Commit 968e8e9f authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/line6-cleanup' into for-next

Pull LINE6 driver cleanups and fixes.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parents 213ed4b8 f23a09ee
...@@ -195,17 +195,6 @@ static int line6_send_raw_message_async_part(struct message *msg, ...@@ -195,17 +195,6 @@ static int line6_send_raw_message_async_part(struct message *msg,
return retval; return retval;
} }
/*
Setup and start timer.
*/
void line6_start_timer(struct timer_list *timer, unsigned long msecs,
void (*function)(struct timer_list *t))
{
timer->function = function;
mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
}
EXPORT_SYMBOL_GPL(line6_start_timer);
/* /*
Asynchronously send raw message. Asynchronously send raw message.
*/ */
...@@ -720,6 +709,15 @@ static int line6_init_cap_control(struct usb_line6 *line6) ...@@ -720,6 +709,15 @@ static int line6_init_cap_control(struct usb_line6 *line6)
return 0; return 0;
} }
static void line6_startup_work(struct work_struct *work)
{
struct usb_line6 *line6 =
container_of(work, struct usb_line6, startup_work.work);
if (line6->startup)
line6->startup(line6);
}
/* /*
Probe USB device. Probe USB device.
*/ */
...@@ -755,6 +753,7 @@ int line6_probe(struct usb_interface *interface, ...@@ -755,6 +753,7 @@ int line6_probe(struct usb_interface *interface,
line6->properties = properties; line6->properties = properties;
line6->usbdev = usbdev; line6->usbdev = usbdev;
line6->ifcdev = &interface->dev; line6->ifcdev = &interface->dev;
INIT_DELAYED_WORK(&line6->startup_work, line6_startup_work);
strcpy(card->id, properties->id); strcpy(card->id, properties->id);
strcpy(card->driver, driver_name); strcpy(card->driver, driver_name);
...@@ -825,6 +824,8 @@ void line6_disconnect(struct usb_interface *interface) ...@@ -825,6 +824,8 @@ void line6_disconnect(struct usb_interface *interface)
if (WARN_ON(usbdev != line6->usbdev)) if (WARN_ON(usbdev != line6->usbdev))
return; return;
cancel_delayed_work(&line6->startup_work);
if (line6->urb_listen != NULL) if (line6->urb_listen != NULL)
line6_stop_listen(line6); line6_stop_listen(line6);
......
...@@ -68,13 +68,6 @@ ...@@ -68,13 +68,6 @@
#define LINE6_CHANNEL_MASK 0x0f #define LINE6_CHANNEL_MASK 0x0f
#define CHECK_STARTUP_PROGRESS(x, n) \
do { \
if ((x) >= (n)) \
return; \
x = (n); \
} while (0)
extern const unsigned char line6_midi_id[3]; extern const unsigned char line6_midi_id[3];
static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
...@@ -178,11 +171,15 @@ struct usb_line6 { ...@@ -178,11 +171,15 @@ struct usb_line6 {
fifo; fifo;
} messages; } messages;
/* Work for delayed PCM startup */
struct delayed_work startup_work;
/* If MIDI is supported, buffer_message contains the pre-processed data; /* If MIDI is supported, buffer_message contains the pre-processed data;
* otherwise the data is only in urb_listen (buffer_incoming). * otherwise the data is only in urb_listen (buffer_incoming).
*/ */
void (*process_message)(struct usb_line6 *); void (*process_message)(struct usb_line6 *);
void (*disconnect)(struct usb_line6 *line6); void (*disconnect)(struct usb_line6 *line6);
void (*startup)(struct usb_line6 *line6);
}; };
extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
...@@ -197,8 +194,6 @@ extern int line6_send_sysex_message(struct usb_line6 *line6, ...@@ -197,8 +194,6 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
const char *buffer, int size); const char *buffer, int size);
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count); const char *buf, size_t count);
extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
void (*function)(struct timer_list *t));
extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_version_request_async(struct usb_line6 *line6);
extern int line6_write_data(struct usb_line6 *line6, unsigned address, extern int line6_write_data(struct usb_line6 *line6, unsigned address,
void *data, unsigned datalen); void *data, unsigned datalen);
......
...@@ -39,11 +39,9 @@ ...@@ -39,11 +39,9 @@
Stages of POD startup procedure Stages of POD startup procedure
*/ */
enum { enum {
POD_STARTUP_INIT = 1,
POD_STARTUP_VERSIONREQ, POD_STARTUP_VERSIONREQ,
POD_STARTUP_WORKQUEUE,
POD_STARTUP_SETUP, POD_STARTUP_SETUP,
POD_STARTUP_LAST = POD_STARTUP_SETUP - 1 POD_STARTUP_DONE,
}; };
enum { enum {
...@@ -63,12 +61,6 @@ struct usb_line6_pod { ...@@ -63,12 +61,6 @@ struct usb_line6_pod {
/* Instrument monitor level */ /* Instrument monitor level */
int monitor_level; int monitor_level;
/* Timer for device initialization */
struct timer_list startup_timer;
/* Work handler for device initialization */
struct work_struct startup_work;
/* Current progress in startup procedure */ /* Current progress in startup procedure */
int startup_progress; int startup_progress;
...@@ -82,6 +74,8 @@ struct usb_line6_pod { ...@@ -82,6 +74,8 @@ struct usb_line6_pod {
int device_id; int device_id;
}; };
#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6)
#define POD_SYSEX_CODE 3 #define POD_SYSEX_CODE 3
/* *INDENT-OFF* */ /* *INDENT-OFF* */
...@@ -173,10 +167,6 @@ static const char pod_version_header[] = { ...@@ -173,10 +167,6 @@ static const char pod_version_header[] = {
0xf2, 0x7e, 0x7f, 0x06, 0x02 0xf2, 0x7e, 0x7f, 0x06, 0x02
}; };
/* forward declarations: */
static void pod_startup2(struct timer_list *t);
static void pod_startup3(struct usb_line6_pod *pod);
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
int size) int size)
{ {
...@@ -189,14 +179,17 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, ...@@ -189,14 +179,17 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
*/ */
static void line6_pod_process_message(struct usb_line6 *line6) static void line6_pod_process_message(struct usb_line6 *line6)
{ {
struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; struct usb_line6_pod *pod = line6_to_pod(line6);
const unsigned char *buf = pod->line6.buffer_message; const unsigned char *buf = pod->line6.buffer_message;
if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
(int) buf[10]; (int) buf[10];
pod_startup3(pod); if (pod->startup_progress == POD_STARTUP_VERSIONREQ) {
pod->startup_progress = POD_STARTUP_SETUP;
schedule_delayed_work(&line6->startup_work, 0);
}
return; return;
} }
...@@ -281,47 +274,27 @@ static ssize_t device_id_show(struct device *dev, ...@@ -281,47 +274,27 @@ static ssize_t device_id_show(struct device *dev,
context). After the last one has finished, the device is ready to use. context). After the last one has finished, the device is ready to use.
*/ */
static void pod_startup1(struct usb_line6_pod *pod) static void pod_startup(struct usb_line6 *line6)
{
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
/* delay startup procedure: */
line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2);
}
static void pod_startup2(struct timer_list *t)
{
struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
struct usb_line6 *line6 = &pod->line6;
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
/* request firmware version: */
line6_version_request_async(line6);
}
static void pod_startup3(struct usb_line6_pod *pod)
{
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
/* schedule work for global work queue: */
schedule_work(&pod->startup_work);
}
static void pod_startup4(struct work_struct *work)
{ {
struct usb_line6_pod *pod = struct usb_line6_pod *pod = line6_to_pod(line6);
container_of(work, struct usb_line6_pod, startup_work);
struct usb_line6 *line6 = &pod->line6; switch (pod->startup_progress) {
case POD_STARTUP_VERSIONREQ:
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP); /* request firmware version: */
line6_version_request_async(line6);
/* serial number: */ break;
line6_read_serial_number(&pod->line6, &pod->serial_number); case POD_STARTUP_SETUP:
/* serial number: */
/* ALSA audio interface: */ line6_read_serial_number(&pod->line6, &pod->serial_number);
if (snd_card_register(line6->card))
dev_err(line6->ifcdev, "Failed to register POD card.\n"); /* ALSA audio interface: */
if (snd_card_register(line6->card))
dev_err(line6->ifcdev, "Failed to register POD card.\n");
pod->startup_progress = POD_STARTUP_DONE;
break;
default:
break;
}
} }
/* POD special files: */ /* POD special files: */
...@@ -357,7 +330,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol, ...@@ -357,7 +330,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
ucontrol->value.integer.value[0] = pod->monitor_level; ucontrol->value.integer.value[0] = pod->monitor_level;
return 0; return 0;
...@@ -368,7 +341,7 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, ...@@ -368,7 +341,7 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
if (ucontrol->value.integer.value[0] == pod->monitor_level) if (ucontrol->value.integer.value[0] == pod->monitor_level)
return 0; return 0;
...@@ -390,17 +363,6 @@ static const struct snd_kcontrol_new pod_control_monitor = { ...@@ -390,17 +363,6 @@ static const struct snd_kcontrol_new pod_control_monitor = {
.put = snd_pod_control_monitor_put .put = snd_pod_control_monitor_put
}; };
/*
POD device disconnected.
*/
static void line6_pod_disconnect(struct usb_line6 *line6)
{
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
del_timer_sync(&pod->startup_timer);
cancel_work_sync(&pod->startup_work);
}
/* /*
Try to init POD device. Try to init POD device.
*/ */
...@@ -408,13 +370,10 @@ static int pod_init(struct usb_line6 *line6, ...@@ -408,13 +370,10 @@ static int pod_init(struct usb_line6 *line6,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int err; int err;
struct usb_line6_pod *pod = (struct usb_line6_pod *) line6; struct usb_line6_pod *pod = line6_to_pod(line6);
line6->process_message = line6_pod_process_message; line6->process_message = line6_pod_process_message;
line6->disconnect = line6_pod_disconnect; line6->startup = pod_startup;
timer_setup(&pod->startup_timer, NULL, 0);
INIT_WORK(&pod->startup_work, pod_startup4);
/* create sysfs entries: */ /* create sysfs entries: */
err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group); err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
...@@ -447,7 +406,8 @@ static int pod_init(struct usb_line6 *line6, ...@@ -447,7 +406,8 @@ static int pod_init(struct usb_line6 *line6,
pod->monitor_level = POD_SYSTEM_INVALID; pod->monitor_level = POD_SYSTEM_INVALID;
/* initiate startup procedure: */ /* initiate startup procedure: */
pod_startup1(pod); schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(POD_STARTUP_DELAY));
} }
return 0; return 0;
......
...@@ -22,16 +22,6 @@ ...@@ -22,16 +22,6 @@
#define PODHD_STARTUP_DELAY 500 #define PODHD_STARTUP_DELAY 500
/*
* Stages of POD startup procedure
*/
enum {
PODHD_STARTUP_INIT = 1,
PODHD_STARTUP_SCHEDULE_WORKQUEUE,
PODHD_STARTUP_SETUP,
PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1
};
enum { enum {
LINE6_PODHD300, LINE6_PODHD300,
LINE6_PODHD400, LINE6_PODHD400,
...@@ -47,15 +37,6 @@ struct usb_line6_podhd { ...@@ -47,15 +37,6 @@ struct usb_line6_podhd {
/* Generic Line 6 USB data */ /* Generic Line 6 USB data */
struct usb_line6 line6; struct usb_line6 line6;
/* Timer for device initialization */
struct timer_list startup_timer;
/* Work handler for device initialization */
struct work_struct startup_work;
/* Current progress in startup procedure */
int startup_progress;
/* Serial number of device */ /* Serial number of device */
u32 serial_number; u32 serial_number;
...@@ -63,6 +44,8 @@ struct usb_line6_podhd { ...@@ -63,6 +44,8 @@ struct usb_line6_podhd {
int firmware_version; int firmware_version;
}; };
#define line6_to_podhd(x) container_of(x, struct usb_line6_podhd, line6)
static struct snd_ratden podhd_ratden = { static struct snd_ratden podhd_ratden = {
.num_min = 48000, .num_min = 48000,
.num_max = 48000, .num_max = 48000,
...@@ -158,10 +141,6 @@ static struct line6_pcm_properties podx3_pcm_properties = { ...@@ -158,10 +141,6 @@ static struct line6_pcm_properties podx3_pcm_properties = {
}; };
static struct usb_driver podhd_driver; static struct usb_driver podhd_driver;
static void podhd_startup_start_workqueue(struct timer_list *t);
static void podhd_startup_workqueue(struct work_struct *work);
static int podhd_startup_finalize(struct usb_line6_podhd *pod);
static ssize_t serial_number_show(struct device *dev, static ssize_t serial_number_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -202,26 +181,6 @@ static const struct attribute_group podhd_dev_attr_group = { ...@@ -202,26 +181,6 @@ static const struct attribute_group podhd_dev_attr_group = {
* audio nor bulk interfaces to work. * audio nor bulk interfaces to work.
*/ */
static void podhd_startup(struct usb_line6_podhd *pod)
{
CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
/* delay startup procedure: */
line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
podhd_startup_start_workqueue);
}
static void podhd_startup_start_workqueue(struct timer_list *t)
{
struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer);
CHECK_STARTUP_PROGRESS(pod->startup_progress,
PODHD_STARTUP_SCHEDULE_WORKQUEUE);
/* schedule work for global work queue: */
schedule_work(&pod->startup_work);
}
static int podhd_dev_start(struct usb_line6_podhd *pod) static int podhd_dev_start(struct usb_line6_podhd *pod)
{ {
int ret; int ret;
...@@ -272,37 +231,23 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) ...@@ -272,37 +231,23 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
return ret; return ret;
} }
static void podhd_startup_workqueue(struct work_struct *work) static void podhd_startup(struct usb_line6 *line6)
{ {
struct usb_line6_podhd *pod = struct usb_line6_podhd *pod = line6_to_podhd(line6);
container_of(work, struct usb_line6_podhd, startup_work);
CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
podhd_dev_start(pod); podhd_dev_start(pod);
line6_read_serial_number(&pod->line6, &pod->serial_number); line6_read_serial_number(&pod->line6, &pod->serial_number);
if (snd_card_register(line6->card))
podhd_startup_finalize(pod); dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
}
static int podhd_startup_finalize(struct usb_line6_podhd *pod)
{
struct usb_line6 *line6 = &pod->line6;
/* ALSA audio interface: */
return snd_card_register(line6->card);
} }
static void podhd_disconnect(struct usb_line6 *line6) static void podhd_disconnect(struct usb_line6 *line6)
{ {
struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; struct usb_line6_podhd *pod = line6_to_podhd(line6);
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
struct usb_interface *intf; struct usb_interface *intf;
del_timer_sync(&pod->startup_timer);
cancel_work_sync(&pod->startup_work);
intf = usb_ifnum_to_if(line6->usbdev, intf = usb_ifnum_to_if(line6->usbdev,
pod->line6.properties->ctrl_if); pod->line6.properties->ctrl_if);
if (intf) if (intf)
...@@ -317,13 +262,11 @@ static int podhd_init(struct usb_line6 *line6, ...@@ -317,13 +262,11 @@ static int podhd_init(struct usb_line6 *line6,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int err; int err;
struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; struct usb_line6_podhd *pod = line6_to_podhd(line6);
struct usb_interface *intf; struct usb_interface *intf;
line6->disconnect = podhd_disconnect; line6->disconnect = podhd_disconnect;
line6->startup = podhd_startup;
timer_setup(&pod->startup_timer, NULL, 0);
INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
/* claim the data interface */ /* claim the data interface */
...@@ -362,11 +305,12 @@ static int podhd_init(struct usb_line6 *line6, ...@@ -362,11 +305,12 @@ static int podhd_init(struct usb_line6 *line6,
if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
/* register USB audio system directly */ /* register USB audio system directly */
return podhd_startup_finalize(pod); return snd_card_register(line6->card);
} }
/* init device and delay registering */ /* init device and delay registering */
podhd_startup(pod); schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(PODHD_STARTUP_DELAY));
return 0; return 0;
} }
......
...@@ -54,9 +54,6 @@ struct usb_line6_toneport { ...@@ -54,9 +54,6 @@ struct usb_line6_toneport {
/* Firmware version (x 100) */ /* Firmware version (x 100) */
u8 firmware_version; u8 firmware_version;
/* Work for delayed PCM startup */
struct delayed_work pcm_work;
/* Device type */ /* Device type */
enum line6_device_type type; enum line6_device_type type;
...@@ -64,6 +61,8 @@ struct usb_line6_toneport { ...@@ -64,6 +61,8 @@ struct usb_line6_toneport {
struct toneport_led leds[2]; struct toneport_led leds[2];
}; };
#define line6_to_toneport(x) container_of(x, struct usb_line6_toneport, line6)
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);
#define TONEPORT_PCM_DELAY 1 #define TONEPORT_PCM_DELAY 1
...@@ -214,8 +213,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol, ...@@ -214,8 +213,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
struct usb_line6_toneport *toneport = struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
(struct usb_line6_toneport *)line6pcm->line6;
ucontrol->value.enumerated.item[0] = toneport->source; ucontrol->value.enumerated.item[0] = toneport->source;
return 0; return 0;
} }
...@@ -225,8 +224,7 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, ...@@ -225,8 +224,7 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
struct usb_line6_toneport *toneport = struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
(struct usb_line6_toneport *)line6pcm->line6;
unsigned int source; unsigned int source;
source = ucontrol->value.enumerated.item[0]; source = ucontrol->value.enumerated.item[0];
...@@ -241,12 +239,8 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, ...@@ -241,12 +239,8 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
return 1; return 1;
} }
static void toneport_start_pcm(struct work_struct *work) static void toneport_startup(struct usb_line6 *line6)
{ {
struct usb_line6_toneport *toneport =
container_of(work, struct usb_line6_toneport, pcm_work.work);
struct usb_line6 *line6 = &toneport->line6;
line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true); line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
} }
...@@ -394,7 +388,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport) ...@@ -394,7 +388,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
if (toneport_has_led(toneport)) if (toneport_has_led(toneport))
toneport_update_led(toneport); toneport_update_led(toneport);
schedule_delayed_work(&toneport->pcm_work, schedule_delayed_work(&toneport->line6.startup_work,
msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000)); msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000));
return 0; return 0;
} }
...@@ -404,10 +398,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport) ...@@ -404,10 +398,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
*/ */
static void line6_toneport_disconnect(struct usb_line6 *line6) static void line6_toneport_disconnect(struct usb_line6 *line6)
{ {
struct usb_line6_toneport *toneport = struct usb_line6_toneport *toneport = line6_to_toneport(line6);
(struct usb_line6_toneport *)line6;
cancel_delayed_work_sync(&toneport->pcm_work);
if (toneport_has_led(toneport)) if (toneport_has_led(toneport))
toneport_remove_leds(toneport); toneport_remove_leds(toneport);
...@@ -421,12 +412,12 @@ static int toneport_init(struct usb_line6 *line6, ...@@ -421,12 +412,12 @@ static int toneport_init(struct usb_line6 *line6,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int err; int err;
struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6; struct usb_line6_toneport *toneport = line6_to_toneport(line6);
toneport->type = id->driver_info; toneport->type = id->driver_info;
INIT_DELAYED_WORK(&toneport->pcm_work, toneport_start_pcm);
line6->disconnect = line6_toneport_disconnect; line6->disconnect = line6_toneport_disconnect;
line6->startup = toneport_startup;
/* initialize PCM subsystem: */ /* initialize PCM subsystem: */
err = line6_init_pcm(line6, &toneport_pcm_properties); err = line6_init_pcm(line6, &toneport_pcm_properties);
......
...@@ -26,13 +26,9 @@ ...@@ -26,13 +26,9 @@
Stages of Variax startup procedure Stages of Variax startup procedure
*/ */
enum { enum {
VARIAX_STARTUP_INIT = 1,
VARIAX_STARTUP_VERSIONREQ, VARIAX_STARTUP_VERSIONREQ,
VARIAX_STARTUP_WAIT,
VARIAX_STARTUP_ACTIVATE, VARIAX_STARTUP_ACTIVATE,
VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP, VARIAX_STARTUP_SETUP,
VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
}; };
enum { enum {
...@@ -47,17 +43,12 @@ struct usb_line6_variax { ...@@ -47,17 +43,12 @@ struct usb_line6_variax {
/* Buffer for activation code */ /* Buffer for activation code */
unsigned char *buffer_activate; unsigned char *buffer_activate;
/* Handler for device initialization */
struct work_struct startup_work;
/* Timers for device initialization */
struct timer_list startup_timer1;
struct timer_list startup_timer2;
/* Current progress in startup procedure */ /* Current progress in startup procedure */
int startup_progress; int startup_progress;
}; };
#define line6_to_variax(x) container_of(x, struct usb_line6_variax, line6)
#define VARIAX_OFFSET_ACTIVATE 7 #define VARIAX_OFFSET_ACTIVATE 7
/* /*
...@@ -81,11 +72,6 @@ static const char variax_activate[] = { ...@@ -81,11 +72,6 @@ static const char variax_activate[] = {
0xf7 0xf7
}; };
/* forward declarations: */
static void variax_startup2(struct timer_list *t);
static void variax_startup4(struct timer_list *t);
static void variax_startup5(struct timer_list *t);
static void variax_activate_async(struct usb_line6_variax *variax, int a) static void variax_activate_async(struct usb_line6_variax *variax, int a)
{ {
variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
...@@ -100,74 +86,30 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a) ...@@ -100,74 +86,30 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a)
context). After the last one has finished, the device is ready to use. context). After the last one has finished, the device is ready to use.
*/ */
static void variax_startup1(struct usb_line6_variax *variax) static void variax_startup(struct usb_line6 *line6)
{
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
/* delay startup procedure: */
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
variax_startup2);
}
static void variax_startup2(struct timer_list *t)
{
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1);
struct usb_line6 *line6 = &variax->line6;
/* schedule another startup procedure until startup is complete: */
if (variax->startup_progress >= VARIAX_STARTUP_LAST)
return;
variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
variax_startup2);
/* request firmware version: */
line6_version_request_async(line6);
}
static void variax_startup3(struct usb_line6_variax *variax)
{
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
/* delay startup procedure: */
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
variax_startup4);
}
static void variax_startup4(struct timer_list *t)
{ {
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2); struct usb_line6_variax *variax = line6_to_variax(line6);
CHECK_STARTUP_PROGRESS(variax->startup_progress, switch (variax->startup_progress) {
VARIAX_STARTUP_ACTIVATE); case VARIAX_STARTUP_VERSIONREQ:
/* repeat request until getting the response */
/* activate device: */ schedule_delayed_work(&line6->startup_work,
variax_activate_async(variax, 1); msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4, /* request firmware version: */
variax_startup5); line6_version_request_async(line6);
} break;
case VARIAX_STARTUP_ACTIVATE:
static void variax_startup5(struct timer_list *t) /* activate device: */
{ variax_activate_async(variax, 1);
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2); variax->startup_progress = VARIAX_STARTUP_SETUP;
schedule_delayed_work(&line6->startup_work,
CHECK_STARTUP_PROGRESS(variax->startup_progress, msecs_to_jiffies(VARIAX_STARTUP_DELAY4));
VARIAX_STARTUP_WORKQUEUE); break;
case VARIAX_STARTUP_SETUP:
/* schedule work for global work queue: */ /* ALSA audio interface: */
schedule_work(&variax->startup_work); snd_card_register(variax->line6.card);
} break;
}
static void variax_startup6(struct work_struct *work)
{
struct usb_line6_variax *variax =
container_of(work, struct usb_line6_variax, startup_work);
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
/* ALSA audio interface: */
snd_card_register(variax->line6.card);
} }
/* /*
...@@ -175,7 +117,7 @@ static void variax_startup6(struct work_struct *work) ...@@ -175,7 +117,7 @@ static void variax_startup6(struct work_struct *work)
*/ */
static void line6_variax_process_message(struct usb_line6 *line6) static void line6_variax_process_message(struct usb_line6 *line6)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; struct usb_line6_variax *variax = line6_to_variax(line6);
const unsigned char *buf = variax->line6.buffer_message; const unsigned char *buf = variax->line6.buffer_message;
switch (buf[0]) { switch (buf[0]) {
...@@ -186,11 +128,19 @@ static void line6_variax_process_message(struct usb_line6 *line6) ...@@ -186,11 +128,19 @@ static void line6_variax_process_message(struct usb_line6 *line6)
case LINE6_SYSEX_BEGIN: case LINE6_SYSEX_BEGIN:
if (memcmp(buf + 1, variax_init_version + 1, if (memcmp(buf + 1, variax_init_version + 1,
sizeof(variax_init_version) - 1) == 0) { sizeof(variax_init_version) - 1) == 0) {
variax_startup3(variax); if (variax->startup_progress >= VARIAX_STARTUP_ACTIVATE)
break;
variax->startup_progress = VARIAX_STARTUP_ACTIVATE;
cancel_delayed_work(&line6->startup_work);
schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY3));
} else if (memcmp(buf + 1, variax_init_done + 1, } else if (memcmp(buf + 1, variax_init_done + 1,
sizeof(variax_init_done) - 1) == 0) { sizeof(variax_init_done) - 1) == 0) {
/* notify of complete initialization: */ /* notify of complete initialization: */
variax_startup4(&variax->startup_timer2); if (variax->startup_progress >= VARIAX_STARTUP_SETUP)
break;
cancel_delayed_work(&line6->startup_work);
schedule_delayed_work(&line6->startup_work, 0);
} }
break; break;
} }
...@@ -201,11 +151,7 @@ static void line6_variax_process_message(struct usb_line6 *line6) ...@@ -201,11 +151,7 @@ static void line6_variax_process_message(struct usb_line6 *line6)
*/ */
static void line6_variax_disconnect(struct usb_line6 *line6) static void line6_variax_disconnect(struct usb_line6 *line6)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *)line6; struct usb_line6_variax *variax = line6_to_variax(line6);
del_timer(&variax->startup_timer1);
del_timer(&variax->startup_timer2);
cancel_work_sync(&variax->startup_work);
kfree(variax->buffer_activate); kfree(variax->buffer_activate);
} }
...@@ -216,15 +162,12 @@ static void line6_variax_disconnect(struct usb_line6 *line6) ...@@ -216,15 +162,12 @@ static void line6_variax_disconnect(struct usb_line6 *line6)
static int variax_init(struct usb_line6 *line6, static int variax_init(struct usb_line6 *line6,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *) line6; struct usb_line6_variax *variax = line6_to_variax(line6);
int err; int err;
line6->process_message = line6_variax_process_message; line6->process_message = line6_variax_process_message;
line6->disconnect = line6_variax_disconnect; line6->disconnect = line6_variax_disconnect;
line6->startup = variax_startup;
timer_setup(&variax->startup_timer1, NULL, 0);
timer_setup(&variax->startup_timer2, NULL, 0);
INIT_WORK(&variax->startup_work, variax_startup6);
/* initialize USB buffers: */ /* initialize USB buffers: */
variax->buffer_activate = kmemdup(variax_activate, variax->buffer_activate = kmemdup(variax_activate,
...@@ -239,7 +182,8 @@ static int variax_init(struct usb_line6 *line6, ...@@ -239,7 +182,8 @@ static int variax_init(struct usb_line6 *line6,
return err; return err;
/* initiate startup procedure: */ /* initiate startup procedure: */
variax_startup1(variax); schedule_delayed_work(&line6->startup_work,
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
return 0; return 0;
} }
......
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