summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/usb/mixer_scarlett2.c777
1 files changed, 390 insertions, 387 deletions
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index bd114be537d7..8390b646c0ae 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -6383,6 +6383,364 @@ static int scarlett2_add_power_status_ctl(struct usb_mixer_interface *mixer)
&private->power_status_ctl);
}
+/*** Notification Handlers ***/
+
+/* Notify on sync change */
+static void scarlett2_notify_sync(struct usb_mixer_interface *mixer)
+{
+ struct scarlett2_data *private = mixer->private_data;
+
+ private->sync_updated = 1;
+
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->sync_ctl->id);
+}
+
+/* Notify on monitor change (Gen 2/3) */
+static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ int i;
+
+ if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH))
+ return;
+
+ private->vol_updated = 1;
+
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->master_vol_ctl->id);
+
+ for (i = 0; i < private->num_line_out; i++)
+ if (private->vol_sw_hw_switch[line_out_remap(private, i)])
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->vol_ctls[i]->id);
+}
+
+/* Notify on volume change (Gen 4) */
+static void scarlett2_notify_volume(struct usb_mixer_interface *mixer)
+{
+ struct scarlett2_data *private = mixer->private_data;
+
+ private->vol_updated = 1;
+
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->master_vol_ctl->id);
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->headphone_vol_ctl->id);
+}
+
+/* Notify on dim/mute change */
+static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ int i;
+
+ if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH))
+ return;
+
+ private->dim_mute_updated = 1;
+
+ for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->dim_mute_ctls[i]->id);
+
+ for (i = 0; i < private->num_line_out; i++)
+ if (private->vol_sw_hw_switch[line_out_remap(private, i)])
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->mute_ctls[i]->id);
+}
+
+/* Notify on input level switch change */
+static void scarlett2_notify_input_level(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ private->input_level_updated = 1;
+
+ for (i = 0; i < info->level_input_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->level_ctls[i]->id);
+}
+
+/* Notify on input pad switch change */
+static void scarlett2_notify_input_pad(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ private->input_pad_updated = 1;
+
+ for (i = 0; i < info->pad_input_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->pad_ctls[i]->id);
+}
+
+/* Notify on input air switch change */
+static void scarlett2_notify_input_air(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ private->input_air_updated = 1;
+
+ for (i = 0; i < info->air_input_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->air_ctls[i]->id);
+}
+
+/* Notify on input phantom switch change */
+static void scarlett2_notify_input_phantom(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ private->input_phantom_updated = 1;
+
+ for (i = 0; i < info->phantom_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->phantom_ctls[i]->id);
+
+ scarlett2_phantom_notify_access(mixer);
+}
+
+/* Notify on "input other" change (level/pad/air/phantom) */
+static void scarlett2_notify_input_other(struct usb_mixer_interface *mixer)
+{
+ scarlett2_notify_input_level(mixer);
+ scarlett2_notify_input_pad(mixer);
+ scarlett2_notify_input_air(mixer);
+ scarlett2_notify_input_phantom(mixer);
+}
+
+/* Notify on input select change */
+static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ if (!info->gain_input_count)
+ return;
+
+ private->input_select_updated = 1;
+
+ snd_ctl_notify(card,
+ SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
+ &private->input_select_ctl->id);
+
+ for (i = 0; i < info->gain_input_count / 2; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->input_link_ctls[i]->id);
+}
+
+/* Notify on input gain change */
+static void scarlett2_notify_input_gain(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ if (!info->gain_input_count)
+ return;
+
+ private->input_gain_updated = 1;
+
+ for (i = 0; i < info->gain_input_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->input_gain_ctls[i]->id);
+}
+
+/* Notify on autogain change */
+static void scarlett2_notify_autogain(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ if (!info->gain_input_count)
+ return;
+
+ private->autogain_updated = 1;
+
+ for (i = 0; i < info->gain_input_count; i++) {
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->autogain_ctls[i]->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->autogain_status_ctls[i]->id);
+ }
+
+ scarlett2_autogain_notify_access(mixer);
+}
+
+/* Notify on input safe switch change */
+static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+ int i;
+
+ if (!info->gain_input_count)
+ return;
+
+ private->input_safe_updated = 1;
+
+ for (i = 0; i < info->gain_input_count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->safe_ctls[i]->id);
+}
+
+/* Notify on "monitor other" change (speaker switching, talkback) */
+static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_device_info *info = private->info;
+
+ private->monitor_other_updated = 1;
+
+ if (info->has_speaker_switching)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->speaker_switching_ctl->id);
+
+ if (info->has_talkback)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->talkback_ctl->id);
+
+ /* if speaker switching was recently enabled or disabled,
+ * invalidate the dim/mute and mux enum controls
+ */
+ if (private->speaker_switching_switched) {
+ int i;
+
+ scarlett2_notify_dim_mute(mixer);
+
+ private->speaker_switching_switched = 0;
+ private->mux_updated = 1;
+
+ for (i = 0; i < private->num_mux_dsts; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->mux_ctls[i]->id);
+ }
+}
+
+/* Notify on direct monitor switch change */
+static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ int count = private->num_mix_in * private->num_mix_out;
+ int i;
+
+ private->direct_monitor_updated = 1;
+
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->direct_monitor_ctl->id);
+
+ if (!scarlett2_has_mixer(private))
+ return;
+
+ private->mix_updated = 1;
+
+ /* Notify of change to the mix controls */
+ for (i = 0; i < count; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->mix_ctls[i]->id);
+}
+
+/* Notify on power change */
+static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+
+ private->power_status_updated = 1;
+
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->power_status_ctl->id);
+}
+
+/* Notify on mux change */
+static void scarlett2_notify_mux(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+ int i;
+
+ private->mux_updated = 1;
+
+ for (i = 0; i < private->num_mux_dsts; i++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->mux_ctls[i]->id);
+}
+
+/* Notify on PCM input switch change */
+static void scarlett2_notify_pcm_input_switch(struct usb_mixer_interface *mixer)
+{
+ struct snd_card *card = mixer->chip->card;
+ struct scarlett2_data *private = mixer->private_data;
+
+ private->pcm_input_switch_updated = 1;
+
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &private->pcm_input_switch_ctl->id);
+
+ scarlett2_notify_mux(mixer);
+}
+
+/* Interrupt callback */
+static void scarlett2_notify(struct urb *urb)
+{
+ struct usb_mixer_interface *mixer = urb->context;
+ int len = urb->actual_length;
+ int ustatus = urb->status;
+ u32 data;
+ struct scarlett2_data *private = mixer->private_data;
+ const struct scarlett2_notification *notifications =
+ private->config_set->notifications;
+
+ if (ustatus != 0 || len != 8)
+ goto requeue;
+
+ data = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
+
+ while (data && notifications->mask) {
+ if (data & notifications->mask) {
+ data &= ~notifications->mask;
+ if (notifications->func)
+ notifications->func(mixer);
+ }
+ notifications++;
+ }
+
+ if (data)
+ usb_audio_warn(mixer->chip,
+ "%s: Unhandled notification: 0x%08x\n",
+ __func__, data);
+
+requeue:
+ if (ustatus != -ENOENT &&
+ ustatus != -ECONNRESET &&
+ ustatus != -ESHUTDOWN) {
+ urb->dev = mixer->chip->dev;
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+}
+
/*** Cleanup/Suspend Callbacks ***/
static void scarlett2_private_free(struct usb_mixer_interface *mixer)
@@ -6502,6 +6860,38 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
return scarlett2_find_fc_interface(mixer->chip->dev, private);
}
+/* Submit a URB to receive notifications from the device */
+static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
+{
+ struct usb_device *dev = mixer->chip->dev;
+ struct scarlett2_data *private = mixer->private_data;
+ unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress);
+ void *transfer_buffer;
+
+ if (mixer->urb) {
+ usb_audio_err(mixer->chip,
+ "%s: mixer urb already in use!\n", __func__);
+ return 0;
+ }
+
+ if (usb_pipe_type_check(dev, pipe))
+ return -EINVAL;
+
+ mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!mixer->urb)
+ return -ENOMEM;
+
+ transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL);
+ if (!transfer_buffer)
+ return -ENOMEM;
+
+ usb_fill_int_urb(mixer->urb, dev, pipe,
+ transfer_buffer, private->wMaxPacketSize,
+ scarlett2_notify, mixer, private->bInterval);
+
+ return usb_submit_urb(mixer->urb, GFP_KERNEL);
+}
+
/* Cargo cult proprietary initialisation sequence */
static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
{
@@ -6790,393 +7180,6 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
return scarlett2_usb_get_mux(mixer);
}
-/* Notify on sync change */
-static void scarlett2_notify_sync(struct usb_mixer_interface *mixer)
-{
- struct scarlett2_data *private = mixer->private_data;
-
- private->sync_updated = 1;
-
- snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->sync_ctl->id);
-}
-
-/* Notify on monitor change (Gen 2/3) */
-static void scarlett2_notify_monitor(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- int i;
-
- if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH))
- return;
-
- private->vol_updated = 1;
-
- snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->master_vol_ctl->id);
-
- for (i = 0; i < private->num_line_out; i++)
- if (private->vol_sw_hw_switch[line_out_remap(private, i)])
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->vol_ctls[i]->id);
-}
-
-/* Notify on volume change (Gen 4) */
-static void scarlett2_notify_volume(struct usb_mixer_interface *mixer)
-{
- struct scarlett2_data *private = mixer->private_data;
-
- private->vol_updated = 1;
-
- snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->master_vol_ctl->id);
- snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->headphone_vol_ctl->id);
-}
-
-/* Notify on dim/mute change */
-static void scarlett2_notify_dim_mute(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- int i;
-
- if (!scarlett2_has_config_item(private, SCARLETT2_CONFIG_SW_HW_SWITCH))
- return;
-
- private->dim_mute_updated = 1;
-
- for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->dim_mute_ctls[i]->id);
-
- for (i = 0; i < private->num_line_out; i++)
- if (private->vol_sw_hw_switch[line_out_remap(private, i)])
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->mute_ctls[i]->id);
-}
-
-/* Notify on input level switch change */
-static void scarlett2_notify_input_level(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- private->input_level_updated = 1;
-
- for (i = 0; i < info->level_input_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->level_ctls[i]->id);
-}
-
-/* Notify on input pad switch change */
-static void scarlett2_notify_input_pad(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- private->input_pad_updated = 1;
-
- for (i = 0; i < info->pad_input_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->pad_ctls[i]->id);
-}
-
-/* Notify on input air switch change */
-static void scarlett2_notify_input_air(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- private->input_air_updated = 1;
-
- for (i = 0; i < info->air_input_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->air_ctls[i]->id);
-}
-
-/* Notify on input phantom switch change */
-static void scarlett2_notify_input_phantom(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- private->input_phantom_updated = 1;
-
- for (i = 0; i < info->phantom_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->phantom_ctls[i]->id);
-
- scarlett2_phantom_notify_access(mixer);
-}
-
-/* Notify on "input other" change (level/pad/air/phantom) */
-static void scarlett2_notify_input_other(struct usb_mixer_interface *mixer)
-{
- scarlett2_notify_input_level(mixer);
- scarlett2_notify_input_pad(mixer);
- scarlett2_notify_input_air(mixer);
- scarlett2_notify_input_phantom(mixer);
-}
-
-/* Notify on input select change */
-static void scarlett2_notify_input_select(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- if (!info->gain_input_count)
- return;
-
- private->input_select_updated = 1;
-
- snd_ctl_notify(card,
- SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
- &private->input_select_ctl->id);
-
- for (i = 0; i < info->gain_input_count / 2; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->input_link_ctls[i]->id);
-}
-
-/* Notify on input gain change */
-static void scarlett2_notify_input_gain(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- if (!info->gain_input_count)
- return;
-
- private->input_gain_updated = 1;
-
- for (i = 0; i < info->gain_input_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->input_gain_ctls[i]->id);
-}
-
-/* Notify on autogain change */
-static void scarlett2_notify_autogain(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- if (!info->gain_input_count)
- return;
-
- private->autogain_updated = 1;
-
- for (i = 0; i < info->gain_input_count; i++) {
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->autogain_ctls[i]->id);
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->autogain_status_ctls[i]->id);
- }
-
- scarlett2_autogain_notify_access(mixer);
-}
-
-/* Notify on input safe switch change */
-static void scarlett2_notify_input_safe(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
- int i;
-
- if (!info->gain_input_count)
- return;
-
- private->input_safe_updated = 1;
-
- for (i = 0; i < info->gain_input_count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->safe_ctls[i]->id);
-}
-
-/* Notify on "monitor other" change (speaker switching, talkback) */
-static void scarlett2_notify_monitor_other(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_device_info *info = private->info;
-
- private->monitor_other_updated = 1;
-
- if (info->has_speaker_switching)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->speaker_switching_ctl->id);
-
- if (info->has_talkback)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->talkback_ctl->id);
-
- /* if speaker switching was recently enabled or disabled,
- * invalidate the dim/mute and mux enum controls
- */
- if (private->speaker_switching_switched) {
- int i;
-
- scarlett2_notify_dim_mute(mixer);
-
- private->speaker_switching_switched = 0;
- private->mux_updated = 1;
-
- for (i = 0; i < private->num_mux_dsts; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->mux_ctls[i]->id);
- }
-}
-
-/* Notify on direct monitor switch change */
-static void scarlett2_notify_direct_monitor(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- int count = private->num_mix_in * private->num_mix_out;
- int i;
-
- private->direct_monitor_updated = 1;
-
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->direct_monitor_ctl->id);
-
- if (!scarlett2_has_mixer(private))
- return;
-
- private->mix_updated = 1;
-
- /* Notify of change to the mix controls */
- for (i = 0; i < count; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->mix_ctls[i]->id);
-}
-
-/* Notify on power change */
-static void scarlett2_notify_power_status(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
-
- private->power_status_updated = 1;
-
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->power_status_ctl->id);
-}
-
-/* Notify on mux change */
-static void scarlett2_notify_mux(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
- int i;
-
- private->mux_updated = 1;
-
- for (i = 0; i < private->num_mux_dsts; i++)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->mux_ctls[i]->id);
-}
-
-/* Notify on PCM input switch change */
-static void scarlett2_notify_pcm_input_switch(struct usb_mixer_interface *mixer)
-{
- struct snd_card *card = mixer->chip->card;
- struct scarlett2_data *private = mixer->private_data;
-
- private->pcm_input_switch_updated = 1;
-
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
- &private->pcm_input_switch_ctl->id);
-
- scarlett2_notify_mux(mixer);
-}
-
-/* Interrupt callback */
-static void scarlett2_notify(struct urb *urb)
-{
- struct usb_mixer_interface *mixer = urb->context;
- int len = urb->actual_length;
- int ustatus = urb->status;
- u32 data;
- struct scarlett2_data *private = mixer->private_data;
- const struct scarlett2_notification *notifications =
- private->config_set->notifications;
-
- if (ustatus != 0 || len != 8)
- goto requeue;
-
- data = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
-
- while (data && notifications->mask) {
- if (data & notifications->mask) {
- data &= ~notifications->mask;
- if (notifications->func)
- notifications->func(mixer);
- }
- notifications++;
- }
-
- if (data)
- usb_audio_warn(mixer->chip,
- "%s: Unhandled notification: 0x%08x\n",
- __func__, data);
-
-requeue:
- if (ustatus != -ENOENT &&
- ustatus != -ECONNRESET &&
- ustatus != -ESHUTDOWN) {
- urb->dev = mixer->chip->dev;
- usb_submit_urb(urb, GFP_ATOMIC);
- }
-}
-
-static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
-{
- struct usb_device *dev = mixer->chip->dev;
- struct scarlett2_data *private = mixer->private_data;
- unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress);
- void *transfer_buffer;
-
- if (mixer->urb) {
- usb_audio_err(mixer->chip,
- "%s: mixer urb already in use!\n", __func__);
- return 0;
- }
-
- if (usb_pipe_type_check(dev, pipe))
- return -EINVAL;
-
- mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!mixer->urb)
- return -ENOMEM;
-
- transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL);
- if (!transfer_buffer)
- return -ENOMEM;
-
- usb_fill_int_urb(mixer->urb, dev, pipe,
- transfer_buffer, private->wMaxPacketSize,
- scarlett2_notify, mixer, private->bInterval);
-
- return usb_submit_urb(mixer->urb, GFP_KERNEL);
-}
-
static const struct scarlett2_device_entry *get_scarlett2_device_entry(
struct usb_mixer_interface *mixer)
{