/*** Autogain Switch and Status Controls ***/
 
+/* Forward declarations as phantom power and autogain can disable each other */
+static int scarlett2_check_input_phantom_updated(struct usb_mixer_interface *);
+static int scarlett2_phantom_is_switching(struct scarlett2_data *, int);
+
 /* Set the access mode of a control to read-only (val = 0) or
  * read-write (val = 1).
  */
        return 0;
 }
 
+static int scarlett2_autogain_switch_ctl_info(
+       struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
+{
+       struct usb_mixer_elem_info *elem = kctl->private_data;
+       struct usb_mixer_interface *mixer = elem->head.mixer;
+       struct scarlett2_data *private = mixer->private_data;
+       int err;
+
+       mutex_lock(&private->data_mutex);
+
+       err = scarlett2_check_input_phantom_updated(mixer);
+       if (err < 0)
+               goto unlock;
+
+       err = snd_ctl_boolean_mono_info(kctl, uinfo);
+
+unlock:
+       mutex_unlock(&private->data_mutex);
+       return err;
+}
+
 static int scarlett2_autogain_switch_ctl_get(
        struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
 {
        struct scarlett2_data *private = mixer->private_data;
 
        int index = elem->control;
-       int oval, val, err = 0;
+       int oval, val, err;
 
        mutex_lock(&private->data_mutex);
 
                goto unlock;
        }
 
+       err = scarlett2_check_input_phantom_updated(mixer);
+       if (err < 0)
+               goto unlock;
+
+       if (scarlett2_phantom_is_switching(private, index)) {
+               err = -EPERM;
+               goto unlock;
+       }
+
        oval = private->autogain_switch[index];
        val = !!ucontrol->value.integer.value[0];
 
 static const struct snd_kcontrol_new scarlett2_autogain_switch_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "",
-       .info = snd_ctl_boolean_mono_info,
+       .info = scarlett2_autogain_switch_ctl_info,
        .get  = scarlett2_autogain_switch_ctl_get,
        .put  = scarlett2_autogain_switch_ctl_put
 };
        return 0;
 }
 
+/* Check if phantom power on the given input is currently changing state */
+static int scarlett2_phantom_is_switching(
+       struct scarlett2_data *private, int line_num)
+{
+       const struct scarlett2_device_info *info = private->info;
+       int index = line_num / info->inputs_per_phantom;
+
+       return !!(private->phantom_switch[index] & 0x02);
+}
+
+/* Update autogain controls' access mode when phantom power changes state */
+static void scarlett2_phantom_update_access(struct usb_mixer_interface *mixer)
+{
+       struct scarlett2_data *private = mixer->private_data;
+       const struct scarlett2_device_info *info = private->info;
+       int i;
+
+       /* Disable autogain controls if phantom power is changing state */
+       for (i = 0; i < info->gain_input_count; i++) {
+               int val = !scarlett2_phantom_is_switching(private, i);
+
+               scarlett2_set_ctl_access(private->autogain_ctls[i], val);
+       }
+}
+
+/* Notify of access mode change for autogain which can't be enabled
+ * while phantom power is changing.
+ */
+static void scarlett2_phantom_notify_access(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;
+
+       for (i = 0; i < info->gain_input_count; i++)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
+                              &private->autogain_ctls[i]->id);
+}
+
+/* Call scarlett2_update_input_phantom() and
+ * scarlett2_phantom_update_access() if input_phantom_updated is set.
+ */
+static int scarlett2_check_input_phantom_updated(
+       struct usb_mixer_interface *mixer)
+{
+       struct scarlett2_data *private = mixer->private_data;
+       int err;
+
+       if (!private->input_phantom_updated)
+               return 0;
+
+       err = scarlett2_update_input_phantom(mixer);
+       if (err < 0)
+               return err;
+
+       scarlett2_phantom_update_access(mixer);
+
+       return 0;
+}
+
 static int scarlett2_phantom_ctl_get(struct snd_kcontrol *kctl,
                                     struct snd_ctl_elem_value *ucontrol)
 {
        struct usb_mixer_elem_info *elem = kctl->private_data;
        struct usb_mixer_interface *mixer = elem->head.mixer;
        struct scarlett2_data *private = mixer->private_data;
-       int err = 0;
+       int err;
 
        mutex_lock(&private->data_mutex);
 
                goto unlock;
        }
 
-       if (private->input_phantom_updated) {
-               err = scarlett2_update_input_phantom(mixer);
-               if (err < 0)
-                       goto unlock;
-       }
+       err = scarlett2_check_input_phantom_updated(mixer);
+       if (err < 0)
+               goto unlock;
+
        ucontrol->value.integer.value[0] = scarlett2_decode_muteable(
                private->phantom_switch[elem->control]);
 
        if (err == 0)
                err = 1;
 
+       scarlett2_phantom_update_access(mixer);
+       scarlett2_phantom_notify_access(mixer);
+
 unlock:
        mutex_unlock(&private->data_mutex);
        return err;
        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) */
        if (err < 0)
                return err;
 
-       /* Set the access mode of controls disabled during autogain */
-       if (private->info->gain_input_count)
+       /* Set the access mode of controls disabled during
+        * autogain/phantom power switching.
+        */
+       if (private->info->gain_input_count) {
                scarlett2_autogain_update_access(mixer);
+               scarlett2_phantom_update_access(mixer);
+       }
 
        /* Set up the interrupt polling */
        err = scarlett2_init_notify(mixer);