Commit ccddbe4a authored by Takashi Iwai's avatar Takashi Iwai

ALSA: line6: Split to each driver

Split to each individual driver for POD, PODHD, TonePort and Variax
with a core LINE6 helper module.  The new modules follow the standard
ALSA naming rule with snd prefix: snd-usb-pod, snd-usb-podhd,
snd-usb-toneport and snd-usb-variax, together with the corresponding
CONFIG_SND_USB_* Kconfig items.
Tested-by: default avatarChris Rorvick <chris@rorvick.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 0f2524b3
...@@ -25,4 +25,4 @@ obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o ...@@ -25,4 +25,4 @@ obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/ obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
obj-$(CONFIG_LINE6_USB) += line6/ obj-$(CONFIG_SND_USB_LINE6) += line6/
menuconfig LINE6_USB config SND_USB_LINE6
tristate "Line6 USB support" tristate
depends on USB && SND
select SND_RAWMIDI select SND_RAWMIDI
select SND_PCM select SND_PCM
config SND_USB_POD
tristate "Line6 POD USB support"
select SND_USB_LINE6
help help
This is a driver for the guitar amp, cab, and effects modeller This is a driver for PODxt and other similar devices,
PODxt Pro by Line6 (and similar devices), supporting the supporting the following features:
following features:
* Reading/writing individual parameters * Reading/writing individual parameters
* Reading/writing complete channel, effects setup, and amp * Reading/writing complete channel, effects setup, and amp
setup data setup data
...@@ -18,14 +20,27 @@ menuconfig LINE6_USB ...@@ -18,14 +20,27 @@ menuconfig LINE6_USB
* Signal routing (record clean/processed guitar signal, * Signal routing (record clean/processed guitar signal,
re-amping) re-amping)
Preliminary support for the Variax Workbench and TonePort config SND_USB_PODHD
devices is included. tristate "Line6 POD HD300/400/500 USB support"
select SND_USB_LINE6
help
This is a driver for POD HD300, 400 and 500 devices.
if LINE6_USB config SND_USB_TONEPORT
tristate "TonePort GX, UX1 and UX2 USB support"
select SND_USB_LINE6
help
This is a driver for TonePort GX, UX1 and UX2 devices.
config SND_USB_VARIAX
tristate "Variax Workbench USB support"
select SND_USB_LINE6
help
This is a driver for Variax Workbench device.
config LINE6_USB_IMPULSE_RESPONSE config LINE6_USB_IMPULSE_RESPONSE
bool "measure impulse response" bool "measure impulse response"
default n depends on SND_USB_LINE6
help help
Say Y here to add code to measure the impulse response of a Line6 Say Y here to add code to measure the impulse response of a Line6
device. This is more accurate than user-space methods since it device. This is more accurate than user-space methods since it
...@@ -35,4 +50,3 @@ config LINE6_USB_IMPULSE_RESPONSE ...@@ -35,4 +50,3 @@ config LINE6_USB_IMPULSE_RESPONSE
If unsure, say N. If unsure, say N.
endif # LINE6_USB
obj-$(CONFIG_LINE6_USB) += line6usb.o snd-usb-line6-y := \
line6usb-y := \
audio.o \ audio.o \
capture.o \ capture.o \
driver.o \ driver.o \
midi.o \ midi.o \
midibuf.o \ midibuf.o \
pcm.o \ pcm.o \
playback.o \ playback.o
pod.o \
toneport.o \ snd-usb-pod-y := pod.o
variax.o \ snd-usb-podhd-y := podhd.o
podhd.o snd-usb-toneport-y := toneport.o
snd-usb-variax-y := variax.o
obj-$(CONFIG_SND_USB_LINE6) += snd-usb-line6.o
obj-$(CONFIG_SND_USB_POD) += snd-usb-pod.o
obj-$(CONFIG_SND_USB_PODHD) += snd-usb-podhd.o
obj-$(CONFIG_SND_USB_TONEPORT) += snd-usb-toneport.o
obj-$(CONFIG_SND_USB_VARIAX) += snd-usb-variax.o
...@@ -40,6 +40,7 @@ int line6_init_audio(struct usb_line6 *line6) ...@@ -40,6 +40,7 @@ int line6_init_audio(struct usb_line6 *line6)
dev_name(line6->ifcdev)); dev_name(line6->ifcdev));
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(line6_init_audio);
/* /*
Register the Line6 USB audio system. Register the Line6 USB audio system.
...@@ -54,6 +55,7 @@ int line6_register_audio(struct usb_line6 *line6) ...@@ -54,6 +55,7 @@ int line6_register_audio(struct usb_line6 *line6)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(line6_register_audio);
/* /*
Cleanup the Line6 USB audio system. Cleanup the Line6 USB audio system.
...@@ -69,3 +71,4 @@ void line6_cleanup_audio(struct usb_line6 *line6) ...@@ -69,3 +71,4 @@ void line6_cleanup_audio(struct usb_line6 *line6)
snd_card_free(card); snd_card_free(card);
line6->card = NULL; line6->card = NULL;
} }
EXPORT_SYMBOL_GPL(line6_cleanup_audio);
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "capture.h" #include "capture.h"
#include "driver.h" #include "driver.h"
#include "pcm.h" #include "pcm.h"
#include "pod.h"
/* /*
Find a free URB and submit it. Find a free URB and submit it.
......
This diff is collapsed.
...@@ -20,29 +20,6 @@ ...@@ -20,29 +20,6 @@
#define DRIVER_NAME "line6usb" #define DRIVER_NAME "line6usb"
enum line6_device_type {
LINE6_BASSPODXT,
LINE6_BASSPODXTLIVE,
LINE6_BASSPODXTPRO,
LINE6_GUITARPORT,
LINE6_POCKETPOD,
LINE6_PODHD300,
LINE6_PODHD400,
LINE6_PODHD500_0,
LINE6_PODHD500_1,
LINE6_PODSTUDIO_GX,
LINE6_PODSTUDIO_UX1,
LINE6_PODSTUDIO_UX2,
LINE6_PODXT,
LINE6_PODXTLIVE_POD,
LINE6_PODXTLIVE_VARIAX,
LINE6_PODXTPRO,
LINE6_TONEPORT_GX,
LINE6_TONEPORT_UX1,
LINE6_TONEPORT_UX2,
LINE6_VARIAX
};
#define LINE6_TIMEOUT 1 #define LINE6_TIMEOUT 1
#define LINE6_BUFSIZE_LISTEN 32 #define LINE6_BUFSIZE_LISTEN 32
#define LINE6_MESSAGE_MAXLEN 256 #define LINE6_MESSAGE_MAXLEN 256
...@@ -134,11 +111,6 @@ struct usb_line6 { ...@@ -134,11 +111,6 @@ struct usb_line6 {
*/ */
struct usb_device *usbdev; struct usb_device *usbdev;
/**
Device type.
*/
enum line6_device_type type;
/** /**
Properties. Properties.
*/ */
...@@ -225,4 +197,15 @@ extern int line6_version_request_async(struct usb_line6 *line6); ...@@ -225,4 +197,15 @@ extern int line6_version_request_async(struct usb_line6 *line6);
extern int line6_write_data(struct usb_line6 *line6, int address, void *data, extern int line6_write_data(struct usb_line6 *line6, int address, void *data,
size_t datalen); size_t datalen);
int line6_probe(struct usb_interface *interface,
struct usb_line6 *line6,
const struct line6_properties *properties,
int (*private_init)(struct usb_interface *, struct usb_line6 *));
void line6_disconnect(struct usb_interface *interface);
#ifdef CONFIG_PM
int line6_suspend(struct usb_interface *interface, pm_message_t message);
int line6_resume(struct usb_interface *interface);
#endif
#endif #endif
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/export.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include "audio.h" #include "audio.h"
#include "driver.h" #include "driver.h"
#include "midi.h" #include "midi.h"
#include "pod.h"
#include "usbdefs.h" #include "usbdefs.h"
#define line6_rawmidi_substream_midi(substream) \ #define line6_rawmidi_substream_midi(substream) \
...@@ -319,3 +319,4 @@ int line6_init_midi(struct usb_line6 *line6) ...@@ -319,3 +319,4 @@ int line6_init_midi(struct usb_line6 *line6)
spin_lock_init(&line6midi->midi_transmit_lock); spin_lock_init(&line6midi->midi_transmit_lock);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(line6_init_midi);
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -19,7 +20,6 @@ ...@@ -19,7 +20,6 @@
#include "capture.h" #include "capture.h"
#include "driver.h" #include "driver.h"
#include "playback.h" #include "playback.h"
#include "pod.h"
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
...@@ -195,6 +195,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels) ...@@ -195,6 +195,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
line6_pcm_release(line6pcm, flags_final & channels); line6_pcm_release(line6pcm, flags_final & channels);
return err; return err;
} }
EXPORT_SYMBOL_GPL(line6_pcm_acquire);
int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
{ {
...@@ -223,6 +224,7 @@ int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) ...@@ -223,6 +224,7 @@ int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(line6_pcm_release);
/* trigger callback */ /* trigger callback */
int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
...@@ -408,6 +410,7 @@ void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) ...@@ -408,6 +410,7 @@ void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
line6_unlink_wait_clear_audio_out_urbs(line6pcm); line6_unlink_wait_clear_audio_out_urbs(line6pcm);
line6_unlink_wait_clear_audio_in_urbs(line6pcm); line6_unlink_wait_clear_audio_in_urbs(line6pcm);
} }
EXPORT_SYMBOL_GPL(line6_pcm_disconnect);
/* /*
Create and register the PCM device and mixer entries. Create and register the PCM device and mixer entries.
...@@ -490,6 +493,7 @@ int line6_init_pcm(struct usb_line6 *line6, ...@@ -490,6 +493,7 @@ int line6_init_pcm(struct usb_line6 *line6,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(line6_init_pcm);
/* prepare pcm callback */ /* prepare pcm callback */
int snd_line6_prepare(struct snd_pcm_substream *substream) int snd_line6_prepare(struct snd_pcm_substream *substream)
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "capture.h" #include "capture.h"
#include "driver.h" #include "driver.h"
#include "pcm.h" #include "pcm.h"
#include "pod.h"
#include "playback.h" #include "playback.h"
/* /*
......
...@@ -11,13 +11,94 @@ ...@@ -11,13 +11,94 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include "audio.h" #include "audio.h"
#include "capture.h" #include "capture.h"
#include "driver.h" #include "driver.h"
#include "playback.h" #include "playback.h"
#include "pod.h" #include "usbdefs.h"
/*
Locate name in binary program dump
*/
#define POD_NAME_OFFSET 0
#define POD_NAME_LENGTH 16
/*
Other constants
*/
#define POD_CONTROL_SIZE 0x80
#define POD_BUFSIZE_DUMPREQ 7
#define POD_STARTUP_DELAY 1000
/*
Stages of POD startup procedure
*/
enum {
POD_STARTUP_INIT = 1,
POD_STARTUP_VERSIONREQ,
POD_STARTUP_WORKQUEUE,
POD_STARTUP_SETUP,
POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
};
enum {
LINE6_BASSPODXT,
LINE6_BASSPODXTLIVE,
LINE6_BASSPODXTPRO,
LINE6_POCKETPOD,
LINE6_PODXT,
LINE6_PODXTLIVE_POD,
LINE6_PODXTPRO,
};
struct usb_line6_pod {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Instrument monitor level.
*/
int monitor_level;
/**
Timer for device initializaton.
*/
struct timer_list startup_timer;
/**
Work handler for device initializaton.
*/
struct work_struct startup_work;
/**
Current progress in startup procedure.
*/
int startup_progress;
/**
Serial number of device.
*/
int serial_number;
/**
Firmware version (x 100).
*/
int firmware_version;
/**
Device ID.
*/
int device_id;
};
#define POD_SYSEX_CODE 3 #define POD_SYSEX_CODE 3
#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ #define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
...@@ -442,7 +523,8 @@ static int pod_try_init(struct usb_interface *interface, ...@@ -442,7 +523,8 @@ static int pod_try_init(struct usb_interface *interface,
/* /*
Init POD device (and clean up in case of failure). Init POD device (and clean up in case of failure).
*/ */
int line6_pod_init(struct usb_interface *interface, struct usb_line6 *line6) static int pod_init(struct usb_interface *interface,
struct usb_line6 *line6)
{ {
int err = pod_try_init(interface, line6); int err = pod_try_init(interface, line6);
...@@ -451,3 +533,141 @@ int line6_pod_init(struct usb_interface *interface, struct usb_line6 *line6) ...@@ -451,3 +533,141 @@ int line6_pod_init(struct usb_interface *interface, struct usb_line6 *line6)
return err; return err;
} }
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static const struct usb_device_id pod_id_table[] = {
{ LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
{ LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
{ LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
{ LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
{ LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
{ LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
{ LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
{}
};
MODULE_DEVICE_TABLE(usb, pod_id_table);
static const struct line6_properties pod_properties_table[] = {
[LINE6_BASSPODXT] = {
.id = "BassPODxt",
.name = "BassPODxt",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_BASSPODXTLIVE] = {
.id = "BassPODxtLive",
.name = "BassPODxt Live",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_BASSPODXTPRO] = {
.id = "BassPODxtPro",
.name = "BassPODxt Pro",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_POCKETPOD] = {
.id = "PocketPOD",
.name = "Pocket POD",
.capabilities = LINE6_CAP_CONTROL,
.altsetting = 0,
.ep_ctrl_r = 0x82,
.ep_ctrl_w = 0x02,
/* no audio channel */
},
[LINE6_PODXT] = {
.id = "PODxt",
.name = "PODxt",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODXTLIVE_POD] = {
.id = "PODxtLive",
.name = "PODxt Live",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODXTPRO] = {
.id = "PODxtPro",
.name = "PODxt Pro",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
};
/*
Probe USB device.
*/
static int pod_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_line6_pod *pod;
int err;
pod = kzalloc(sizeof(*pod), GFP_KERNEL);
if (!pod)
return -ENODEV;
err = line6_probe(interface, &pod->line6,
&pod_properties_table[id->driver_info],
pod_init);
if (err < 0)
kfree(pod);
return err;
}
static struct usb_driver pod_driver = {
.name = KBUILD_MODNAME,
.probe = pod_probe,
.disconnect = line6_disconnect,
#ifdef CONFIG_PM
.suspend = line6_suspend,
.resume = line6_resume,
.reset_resume = line6_resume,
#endif
.id_table = pod_id_table,
};
module_usb_driver(pod_driver);
MODULE_DESCRIPTION("Line6 POD USB driver");
MODULE_LICENSE("GPL");
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/
#ifndef POD_H
#define POD_H
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <sound/core.h>
#include "driver.h"
/*
Locate name in binary program dump
*/
#define POD_NAME_OFFSET 0
#define POD_NAME_LENGTH 16
/*
Other constants
*/
#define POD_CONTROL_SIZE 0x80
#define POD_BUFSIZE_DUMPREQ 7
#define POD_STARTUP_DELAY 1000
/*
Stages of POD startup procedure
*/
enum {
POD_STARTUP_INIT = 1,
POD_STARTUP_VERSIONREQ,
POD_STARTUP_WORKQUEUE,
POD_STARTUP_SETUP,
POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
};
struct usb_line6_pod {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Instrument monitor level.
*/
int monitor_level;
/**
Timer for device initializaton.
*/
struct timer_list startup_timer;
/**
Work handler for device initializaton.
*/
struct work_struct startup_work;
/**
Current progress in startup procedure.
*/
int startup_progress;
/**
Serial number of device.
*/
int serial_number;
/**
Firmware version (x 100).
*/
int firmware_version;
/**
Device ID.
*/
int device_id;
};
extern int line6_pod_init(struct usb_interface *interface,
struct usb_line6 *line6);
#endif
...@@ -9,13 +9,30 @@ ...@@ -9,13 +9,30 @@
* *
*/ */
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include "audio.h" #include "audio.h"
#include "driver.h" #include "driver.h"
#include "pcm.h" #include "pcm.h"
#include "podhd.h" #include "usbdefs.h"
enum {
LINE6_PODHD300,
LINE6_PODHD400,
LINE6_PODHD500_0,
LINE6_PODHD500_1,
};
struct usb_line6_podhd {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
};
#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ #define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
...@@ -141,10 +158,76 @@ static int podhd_try_init(struct usb_interface *interface, ...@@ -141,10 +158,76 @@ static int podhd_try_init(struct usb_interface *interface,
return err; return err;
} }
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static const struct usb_device_id podhd_id_table[] = {
{ LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 },
{ LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 },
{ LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
{ LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
{}
};
MODULE_DEVICE_TABLE(usb, podhd_id_table);
static const struct line6_properties podhd_properties_table[] = {
[LINE6_PODHD300] = {
.id = "PODHD300",
.name = "POD HD300",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODHD400] = {
.id = "PODHD400",
.name = "POD HD400",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 5,
.ep_ctrl_r = 0x84,
.ep_ctrl_w = 0x03,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODHD500_0] = {
.id = "PODHD500",
.name = "POD HD500",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x81,
.ep_ctrl_w = 0x01,
.ep_audio_r = 0x86,
.ep_audio_w = 0x02,
},
[LINE6_PODHD500_1] = {
.id = "PODHD500",
.name = "POD HD500",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x81,
.ep_ctrl_w = 0x01,
.ep_audio_r = 0x86,
.ep_audio_w = 0x02,
},
};
/* /*
Init POD HD device (and clean up in case of failure). Init POD HD device (and clean up in case of failure).
*/ */
int line6_podhd_init(struct usb_interface *interface, struct usb_line6 *line6) static int podhd_init(struct usb_interface *interface,
struct usb_line6 *line6)
{ {
struct usb_line6_podhd *podhd = (struct usb_line6_podhd *) line6; struct usb_line6_podhd *podhd = (struct usb_line6_podhd *) line6;
int err = podhd_try_init(interface, podhd); int err = podhd_try_init(interface, podhd);
...@@ -154,3 +237,40 @@ int line6_podhd_init(struct usb_interface *interface, struct usb_line6 *line6) ...@@ -154,3 +237,40 @@ int line6_podhd_init(struct usb_interface *interface, struct usb_line6 *line6)
return err; return err;
} }
/*
Probe USB device.
*/
static int podhd_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_line6_podhd *podhd;
int err;
podhd = kzalloc(sizeof(*podhd), GFP_KERNEL);
if (!podhd)
return -ENODEV;
err = line6_probe(interface, &podhd->line6,
&podhd_properties_table[id->driver_info],
podhd_init);
if (err < 0)
kfree(podhd);
return err;
}
static struct usb_driver podhd_driver = {
.name = KBUILD_MODNAME,
.probe = podhd_probe,
.disconnect = line6_disconnect,
#ifdef CONFIG_PM
.suspend = line6_suspend,
.resume = line6_resume,
.reset_resume = line6_resume,
#endif
.id_table = podhd_id_table,
};
module_usb_driver(podhd_driver);
MODULE_DESCRIPTION("Line6 PODHD USB driver");
MODULE_LICENSE("GPL");
/*
* Line6 Pod HD
*
* Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/
#ifndef PODHD_H
#define PODHD_H
#include <linux/usb.h>
#include "driver.h"
struct usb_line6_podhd {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
};
extern int line6_podhd_init(struct usb_interface *interface,
struct usb_line6 *line6);
#endif /* PODHD_H */
...@@ -11,13 +11,59 @@ ...@@ -11,13 +11,59 @@
*/ */
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
#include "audio.h" #include "audio.h"
#include "capture.h" #include "capture.h"
#include "driver.h" #include "driver.h"
#include "playback.h" #include "playback.h"
#include "toneport.h" #include "usbdefs.h"
enum line6_device_type {
LINE6_GUITARPORT,
LINE6_PODSTUDIO_GX,
LINE6_PODSTUDIO_UX1,
LINE6_PODSTUDIO_UX2,
LINE6_TONEPORT_GX,
LINE6_TONEPORT_UX1,
LINE6_TONEPORT_UX2,
};
struct usb_line6_toneport {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Source selector.
*/
int source;
/**
Serial number of device.
*/
int serial_number;
/**
Firmware version (x 100).
*/
int firmware_version;
/**
Timer for delayed PCM startup.
*/
struct timer_list timer;
/**
Device type.
*/
enum line6_device_type type;
};
static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
...@@ -319,7 +365,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport) ...@@ -319,7 +365,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport)
toneport_send_cmd(usbdev, 0x0301, 0x0000); toneport_send_cmd(usbdev, 0x0301, 0x0000);
/* initialize source select: */ /* initialize source select: */
switch (line6->type) { switch (toneport->type) {
case LINE6_TONEPORT_UX1: case LINE6_TONEPORT_UX1:
case LINE6_TONEPORT_UX2: case LINE6_TONEPORT_UX2:
case LINE6_PODSTUDIO_UX1: case LINE6_PODSTUDIO_UX1:
...@@ -331,7 +377,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport) ...@@ -331,7 +377,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport)
break; break;
} }
if (toneport_has_led(line6->type)) if (toneport_has_led(toneport->type))
toneport_update_led(&usbdev->dev); toneport_update_led(&usbdev->dev);
} }
...@@ -400,7 +446,7 @@ static int toneport_try_init(struct usb_interface *interface, ...@@ -400,7 +446,7 @@ static int toneport_try_init(struct usb_interface *interface,
return err; return err;
/* register source select control: */ /* register source select control: */
switch (line6->type) { switch (toneport->type) {
case LINE6_TONEPORT_UX1: case LINE6_TONEPORT_UX1:
case LINE6_TONEPORT_UX2: case LINE6_TONEPORT_UX2:
case LINE6_PODSTUDIO_UX1: case LINE6_PODSTUDIO_UX1:
...@@ -424,7 +470,7 @@ static int toneport_try_init(struct usb_interface *interface, ...@@ -424,7 +470,7 @@ static int toneport_try_init(struct usb_interface *interface,
line6_read_serial_number(line6, &toneport->serial_number); line6_read_serial_number(line6, &toneport->serial_number);
line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
if (toneport_has_led(line6->type)) { if (toneport_has_led(toneport->type)) {
CHECK_RETURN(device_create_file CHECK_RETURN(device_create_file
(&interface->dev, &dev_attr_led_red)); (&interface->dev, &dev_attr_led_red));
CHECK_RETURN(device_create_file CHECK_RETURN(device_create_file
...@@ -443,8 +489,8 @@ static int toneport_try_init(struct usb_interface *interface, ...@@ -443,8 +489,8 @@ static int toneport_try_init(struct usb_interface *interface,
/* /*
Init Toneport device (and clean up in case of failure). Init Toneport device (and clean up in case of failure).
*/ */
int line6_toneport_init(struct usb_interface *interface, static int toneport_init(struct usb_interface *interface,
struct usb_line6 *line6) struct usb_line6 *line6)
{ {
int err = toneport_try_init(interface, line6); int err = toneport_try_init(interface, line6);
...@@ -454,10 +500,134 @@ int line6_toneport_init(struct usb_interface *interface, ...@@ -454,10 +500,134 @@ int line6_toneport_init(struct usb_interface *interface,
return err; return err;
} }
#ifdef CONFIG_PM
/* /*
Resume Toneport device after reset. Resume Toneport device after reset.
*/ */
void line6_toneport_reset_resume(struct usb_line6_toneport *toneport) static int toneport_reset_resume(struct usb_interface *interface)
{ {
toneport_setup(toneport); toneport_setup(usb_get_intfdata(interface));
return line6_resume(interface);
} }
#endif
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static const struct usb_device_id toneport_id_table[] = {
{ LINE6_DEVICE(0x4750), .driver_info = LINE6_GUITARPORT },
{ LINE6_DEVICE(0x4153), .driver_info = LINE6_PODSTUDIO_GX },
{ LINE6_DEVICE(0x4150), .driver_info = LINE6_PODSTUDIO_UX1 },
{ LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 },
{ LINE6_DEVICE(0x4147), .driver_info = LINE6_TONEPORT_GX },
{ LINE6_DEVICE(0x4141), .driver_info = LINE6_TONEPORT_UX1 },
{ LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 },
{}
};
MODULE_DEVICE_TABLE(usb, toneport_id_table);
static const struct line6_properties toneport_properties_table[] = {
[LINE6_GUITARPORT] = {
.id = "GuitarPort",
.name = "GuitarPort",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* 1..4 seem to be ok */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODSTUDIO_GX] = {
.id = "PODStudioGX",
.name = "POD Studio GX",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* 1..4 seem to be ok */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODSTUDIO_UX1] = {
.id = "PODStudioUX1",
.name = "POD Studio UX1",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* 1..4 seem to be ok */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_PODSTUDIO_UX2] = {
.id = "PODStudioUX2",
.name = "POD Studio UX2",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* defaults to 44.1kHz, 16-bit */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_TONEPORT_GX] = {
.id = "TonePortGX",
.name = "TonePort GX",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* 1..4 seem to be ok */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_TONEPORT_UX1] = {
.id = "TonePortUX1",
.name = "TonePort UX1",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* 1..4 seem to be ok */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_TONEPORT_UX2] = {
.id = "TonePortUX2",
.name = "TonePort UX2",
.capabilities = LINE6_CAP_PCM,
.altsetting = 2, /* defaults to 44.1kHz, 16-bit */
/* no control channel */
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
};
/*
Probe USB device.
*/
static int toneport_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_line6_toneport *toneport;
int err;
toneport = kzalloc(sizeof(*toneport), GFP_KERNEL);
if (!toneport)
return -ENODEV;
toneport->type = id->driver_info;
err = line6_probe(interface, &toneport->line6,
&toneport_properties_table[id->driver_info],
toneport_init);
if (err < 0)
kfree(toneport);
return err;
}
static struct usb_driver toneport_driver = {
.name = KBUILD_MODNAME,
.probe = toneport_probe,
.disconnect = line6_disconnect,
#ifdef CONFIG_PM
.suspend = line6_suspend,
.resume = line6_resume,
.reset_resume = toneport_reset_resume,
#endif
.id_table = toneport_id_table,
};
module_usb_driver(toneport_driver);
MODULE_DESCRIPTION("TonePort USB driver");
MODULE_LICENSE("GPL");
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/
#ifndef TONEPORT_H
#define TONEPORT_H
#include <linux/usb.h>
#include <sound/core.h>
#include "driver.h"
struct usb_line6_toneport {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Source selector.
*/
int source;
/**
Serial number of device.
*/
int serial_number;
/**
Firmware version (x 100).
*/
int firmware_version;
/**
Timer for delayed PCM startup.
*/
struct timer_list timer;
};
extern int line6_toneport_init(struct usb_interface *interface,
struct usb_line6 *line6);
extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport);
#endif
...@@ -10,10 +10,65 @@ ...@@ -10,10 +10,65 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <sound/core.h>
#include "audio.h" #include "audio.h"
#include "driver.h" #include "driver.h"
#include "variax.h" #include "usbdefs.h"
#define VARIAX_STARTUP_DELAY1 1000
#define VARIAX_STARTUP_DELAY3 100
#define VARIAX_STARTUP_DELAY4 100
/*
Stages of Variax startup procedure
*/
enum {
VARIAX_STARTUP_INIT = 1,
VARIAX_STARTUP_VERSIONREQ,
VARIAX_STARTUP_WAIT,
VARIAX_STARTUP_ACTIVATE,
VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP,
VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
};
enum {
LINE6_PODXTLIVE_VARIAX,
LINE6_VARIAX
};
struct usb_line6_variax {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Buffer for activation code.
*/
unsigned char *buffer_activate;
/**
Handler for device initializaton.
*/
struct work_struct startup_work;
/**
Timers for device initializaton.
*/
struct timer_list startup_timer1;
struct timer_list startup_timer2;
/**
Current progress in startup procedure.
*/
int startup_progress;
};
#define VARIAX_OFFSET_ACTIVATE 7 #define VARIAX_OFFSET_ACTIVATE 7
...@@ -228,7 +283,8 @@ static int variax_try_init(struct usb_interface *interface, ...@@ -228,7 +283,8 @@ static int variax_try_init(struct usb_interface *interface,
/* /*
Init workbench device (and clean up in case of failure). Init workbench device (and clean up in case of failure).
*/ */
int line6_variax_init(struct usb_interface *interface, struct usb_line6 *line6) static int variax_init(struct usb_interface *interface,
struct usb_line6 *line6)
{ {
int err = variax_try_init(interface, line6); int err = variax_try_init(interface, line6);
...@@ -237,3 +293,76 @@ int line6_variax_init(struct usb_interface *interface, struct usb_line6 *line6) ...@@ -237,3 +293,76 @@ int line6_variax_init(struct usb_interface *interface, struct usb_line6 *line6)
return err; return err;
} }
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static const struct usb_device_id variax_id_table[] = {
{ LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
{ LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX },
{}
};
MODULE_DEVICE_TABLE(usb, variax_id_table);
static const struct line6_properties variax_properties_table[] = {
[LINE6_PODXTLIVE_VARIAX] = {
.id = "PODxtLive",
.name = "PODxt Live",
.capabilities = LINE6_CAP_CONTROL
| LINE6_CAP_PCM
| LINE6_CAP_HWMON,
.altsetting = 1,
.ep_ctrl_r = 0x86,
.ep_ctrl_w = 0x05,
.ep_audio_r = 0x82,
.ep_audio_w = 0x01,
},
[LINE6_VARIAX] = {
.id = "Variax",
.name = "Variax Workbench",
.capabilities = LINE6_CAP_CONTROL,
.altsetting = 1,
.ep_ctrl_r = 0x82,
.ep_ctrl_w = 0x01,
/* no audio channel */
}
};
/*
Probe USB device.
*/
static int variax_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_line6_variax *variax;
int err;
variax = kzalloc(sizeof(*variax), GFP_KERNEL);
if (!variax)
return -ENODEV;
err = line6_probe(interface, &variax->line6,
&variax_properties_table[id->driver_info],
variax_init);
if (err < 0)
kfree(variax);
return err;
}
static struct usb_driver variax_driver = {
.name = KBUILD_MODNAME,
.probe = variax_probe,
.disconnect = line6_disconnect,
#ifdef CONFIG_PM
.suspend = line6_suspend,
.resume = line6_resume,
.reset_resume = line6_resume,
#endif
.id_table = variax_id_table,
};
module_usb_driver(variax_driver);
MODULE_DESCRIPTION("Vairax Workbench USB driver");
MODULE_LICENSE("GPL");
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/
#ifndef VARIAX_H
#define VARIAX_H
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <sound/core.h>
#include "driver.h"
#define VARIAX_STARTUP_DELAY1 1000
#define VARIAX_STARTUP_DELAY3 100
#define VARIAX_STARTUP_DELAY4 100
/*
Stages of Variax startup procedure
*/
enum {
VARIAX_STARTUP_INIT = 1,
VARIAX_STARTUP_VERSIONREQ,
VARIAX_STARTUP_WAIT,
VARIAX_STARTUP_ACTIVATE,
VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP,
VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
};
struct usb_line6_variax {
/**
Generic Line6 USB data.
*/
struct usb_line6 line6;
/**
Buffer for activation code.
*/
unsigned char *buffer_activate;
/**
Handler for device initializaton.
*/
struct work_struct startup_work;
/**
Timers for device initializaton.
*/
struct timer_list startup_timer1;
struct timer_list startup_timer2;
/**
Current progress in startup procedure.
*/
int startup_progress;
};
extern int line6_variax_init(struct usb_interface *interface,
struct usb_line6 *line6);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment