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

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
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -195,17 +195,6 @@ static int line6_send_raw_message_async_part(struct message *msg,
	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.
*/
@@ -720,6 +709,15 @@ static int line6_init_cap_control(struct usb_line6 *line6)
	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.
*/
@@ -755,6 +753,7 @@ int line6_probe(struct usb_interface *interface,
	line6->properties = properties;
	line6->usbdev = usbdev;
	line6->ifcdev = &interface->dev;
	INIT_DELAYED_WORK(&line6->startup_work, line6_startup_work);

	strcpy(card->id, properties->id);
	strcpy(card->driver, driver_name);
@@ -825,6 +824,8 @@ void line6_disconnect(struct usb_interface *interface)
	if (WARN_ON(usbdev != line6->usbdev))
		return;

	cancel_delayed_work(&line6->startup_work);

	if (line6->urb_listen != NULL)
		line6_stop_listen(line6);

+4 −9
Original line number Diff line number Diff line
@@ -68,13 +68,6 @@

#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];

static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
@@ -178,11 +171,15 @@ struct usb_line6 {
			fifo;
	} messages;

	/* Work for delayed PCM startup */
	struct delayed_work startup_work;

	/* If MIDI is supported, buffer_message contains the pre-processed data;
	 * otherwise the data is only in urb_listen (buffer_incoming).
	 */
	void (*process_message)(struct usb_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,
@@ -197,8 +194,6 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
				    const char *buffer, int size);
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
			     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_write_data(struct usb_line6 *line6, unsigned address,
			    void *data, unsigned datalen);
+34 −74
Original line number Diff line number Diff line
@@ -39,11 +39,9 @@
	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
	POD_STARTUP_DONE,
};

enum {
@@ -63,12 +61,6 @@ struct usb_line6_pod {
	/* Instrument 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 */
	int startup_progress;

@@ -82,6 +74,8 @@ struct usb_line6_pod {
	int device_id;
};

#define line6_to_pod(x)		container_of(x, struct usb_line6_pod, line6)

#define POD_SYSEX_CODE 3

/* *INDENT-OFF* */
@@ -173,10 +167,6 @@ static const char pod_version_header[] = {
	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,
				    int size)
{
@@ -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)
{
	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;

	if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
		pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
		pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
				 (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;
	}

@@ -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.
*/

static void pod_startup1(struct usb_line6_pod *pod)
{
	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)
static void pod_startup(struct usb_line6 *line6)
{
	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);
	struct usb_line6_pod *pod = line6_to_pod(line6);

	switch (pod->startup_progress) {
	case 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 =
	    container_of(work, struct usb_line6_pod, startup_work);
	struct usb_line6 *line6 = &pod->line6;

	CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);

		break;
	case POD_STARTUP_SETUP:
		/* serial number: */
		line6_read_serial_number(&pod->line6, &pod->serial_number);

		/* 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: */
@@ -357,7 +330,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{
	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;
	return 0;
@@ -368,7 +341,7 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{
	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)
		return 0;
@@ -390,17 +363,6 @@ static const struct snd_kcontrol_new pod_control_monitor = {
	.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.
*/
@@ -408,13 +370,10 @@ static int pod_init(struct usb_line6 *line6,
		    const struct usb_device_id *id)
{
	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->disconnect = line6_pod_disconnect;

	timer_setup(&pod->startup_timer, NULL, 0);
	INIT_WORK(&pod->startup_work, pod_startup4);
	line6->startup = pod_startup;

	/* create sysfs entries: */
	err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
@@ -447,7 +406,8 @@ static int pod_init(struct usb_line6 *line6,
		pod->monitor_level = POD_SYSTEM_INVALID;

		/* initiate startup procedure: */
		pod_startup1(pod);
		schedule_delayed_work(&line6->startup_work,
				      msecs_to_jiffies(POD_STARTUP_DELAY));
	}

	return 0;
+12 −68
Original line number Diff line number Diff line
@@ -22,16 +22,6 @@

#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 {
	LINE6_PODHD300,
	LINE6_PODHD400,
@@ -47,15 +37,6 @@ struct usb_line6_podhd {
	/* Generic Line 6 USB data */
	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 */
	u32 serial_number;

@@ -63,6 +44,8 @@ struct usb_line6_podhd {
	int firmware_version;
};

#define line6_to_podhd(x)	container_of(x, struct usb_line6_podhd, line6)

static struct snd_ratden podhd_ratden = {
	.num_min = 48000,
	.num_max = 48000,
@@ -158,10 +141,6 @@ static struct line6_pcm_properties podx3_pcm_properties = {
};
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,
				  struct device_attribute *attr, char *buf)
{
@@ -202,26 +181,6 @@ static const struct attribute_group podhd_dev_attr_group = {
 * 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)
{
	int ret;
@@ -272,37 +231,23 @@ exit:
	return ret;
}

static void podhd_startup_workqueue(struct work_struct *work)
static void podhd_startup(struct usb_line6 *line6)
{
	struct usb_line6_podhd *pod =
	    container_of(work, struct usb_line6_podhd, startup_work);

	CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
	struct usb_line6_podhd *pod = line6_to_podhd(line6);

	podhd_dev_start(pod);
	line6_read_serial_number(&pod->line6, &pod->serial_number);

	podhd_startup_finalize(pod);
}

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);
	if (snd_card_register(line6->card))
		dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
}

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) {
		struct usb_interface *intf;

		del_timer_sync(&pod->startup_timer);
		cancel_work_sync(&pod->startup_work);

		intf = usb_ifnum_to_if(line6->usbdev,
					pod->line6.properties->ctrl_if);
		if (intf)
@@ -317,13 +262,11 @@ static int podhd_init(struct usb_line6 *line6,
		      const struct usb_device_id *id)
{
	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;

	line6->disconnect = podhd_disconnect;

	timer_setup(&pod->startup_timer, NULL, 0);
	INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
	line6->startup = podhd_startup;

	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
		/* claim the data interface */
@@ -362,11 +305,12 @@ static int podhd_init(struct usb_line6 *line6,

	if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
		/* register USB audio system directly */
		return podhd_startup_finalize(pod);
		return snd_card_register(line6->card);
	}

	/* init device and delay registering */
	podhd_startup(pod);
	schedule_delayed_work(&line6->startup_work,
			      msecs_to_jiffies(PODHD_STARTUP_DELAY));
	return 0;
}

+10 −19
Original line number Diff line number Diff line
@@ -54,9 +54,6 @@ struct usb_line6_toneport {
	/* Firmware version (x 100) */
	u8 firmware_version;

	/* Work for delayed PCM startup */
	struct delayed_work pcm_work;

	/* Device type */
	enum line6_device_type type;

@@ -64,6 +61,8 @@ struct usb_line6_toneport {
	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);

#define TONEPORT_PCM_DELAY 1
@@ -214,8 +213,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	struct usb_line6_toneport *toneport =
	    (struct usb_line6_toneport *)line6pcm->line6;
	struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);

	ucontrol->value.enumerated.item[0] = toneport->source;
	return 0;
}
@@ -225,8 +224,7 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
	struct usb_line6_toneport *toneport =
	    (struct usb_line6_toneport *)line6pcm->line6;
	struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
	unsigned int source;

	source = ucontrol->value.enumerated.item[0];
@@ -241,12 +239,8 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
	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);
}

@@ -394,7 +388,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
	if (toneport_has_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));
	return 0;
}
@@ -404,10 +398,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
*/
static void line6_toneport_disconnect(struct usb_line6 *line6)
{
	struct usb_line6_toneport *toneport =
		(struct usb_line6_toneport *)line6;

	cancel_delayed_work_sync(&toneport->pcm_work);
	struct usb_line6_toneport *toneport = line6_to_toneport(line6);

	if (toneport_has_led(toneport))
		toneport_remove_leds(toneport);
@@ -421,12 +412,12 @@ static int toneport_init(struct usb_line6 *line6,
			 const struct usb_device_id *id)
{
	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;
	INIT_DELAYED_WORK(&toneport->pcm_work, toneport_start_pcm);

	line6->disconnect = line6_toneport_disconnect;
	line6->startup = toneport_startup;

	/* initialize PCM subsystem: */
	err = line6_init_pcm(line6, &toneport_pcm_properties);
Loading