static int sanity_check_int_value(struct snd_card *card,
                                  const struct snd_ctl_elem_value *control,
                                  const struct snd_ctl_elem_info *info,
-                                 int i)
+                                 int i, bool print_error)
 {
        long long lval, lmin, lmax, lstep;
        u64 rem;
        }
 
        if (lval < lmin || lval > lmax) {
-               dev_err(card->dev,
-                       "control %i:%i:%i:%s:%i: value out of range %lld (%lld/%lld) at count %i\n",
-                       control->id.iface, control->id.device,
-                       control->id.subdevice, control->id.name,
-                       control->id.index, lval, lmin, lmax, i);
+               if (print_error)
+                       dev_err(card->dev,
+                               "control %i:%i:%i:%s:%i: value out of range %lld (%lld/%lld) at count %i\n",
+                               control->id.iface, control->id.device,
+                               control->id.subdevice, control->id.name,
+                               control->id.index, lval, lmin, lmax, i);
                return -EINVAL;
        }
        if (lstep) {
                div64_u64_rem(lval, lstep, &rem);
                if (rem) {
-                       dev_err(card->dev,
-                               "control %i:%i:%i:%s:%i: unaligned value %lld (step %lld) at count %i\n",
-                               control->id.iface, control->id.device,
-                               control->id.subdevice, control->id.name,
-                               control->id.index, lval, lstep, i);
+                       if (print_error)
+                               dev_err(card->dev,
+                                       "control %i:%i:%i:%s:%i: unaligned value %lld (step %lld) at count %i\n",
+                                       control->id.iface, control->id.device,
+                                       control->id.subdevice, control->id.name,
+                                       control->id.index, lval, lstep, i);
                        return -EINVAL;
                }
        }
        return 0;
 }
 
-/* perform sanity checks to the given snd_ctl_elem_value object */
-static int sanity_check_elem_value(struct snd_card *card,
-                                  const struct snd_ctl_elem_value *control,
-                                  const struct snd_ctl_elem_info *info,
-                                  u32 pattern)
+/* check whether the all input values are valid for the given elem value */
+static int sanity_check_input_values(struct snd_card *card,
+                                    const struct snd_ctl_elem_value *control,
+                                    const struct snd_ctl_elem_info *info,
+                                    bool print_error)
 {
-       size_t offset;
-       int i, ret = 0;
-       u32 *p;
+       int i, ret;
 
        switch (info->type) {
        case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
        case SNDRV_CTL_ELEM_TYPE_INTEGER64:
        case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
                for (i = 0; i < info->count; i++) {
-                       ret = sanity_check_int_value(card, control, info, i);
+                       ret = sanity_check_int_value(card, control, info, i,
+                                                    print_error);
                        if (ret < 0)
                                return ret;
                }
                break;
        }
 
+       return 0;
+}
+
+/* perform sanity checks to the given snd_ctl_elem_value object */
+static int sanity_check_elem_value(struct snd_card *card,
+                                  const struct snd_ctl_elem_value *control,
+                                  const struct snd_ctl_elem_info *info,
+                                  u32 pattern)
+{
+       size_t offset;
+       int ret;
+       u32 *p;
+
+       ret = sanity_check_input_values(card, control, info, true);
+       if (ret < 0)
+               return ret;
+
        /* check whether the remaining area kept untouched */
        offset = value_sizes[info->type] * info->count;
        offset = DIV_ROUND_UP(offset, sizeof(u32));
 
        snd_ctl_build_ioff(&control->id, kctl, index_offset);
        result = snd_power_ref_and_wait(card);
+       /* validate input values */
+       if (IS_ENABLED(CONFIG_SND_CTL_INPUT_VALIDATION) && !result) {
+               struct snd_ctl_elem_info info;
+
+               memset(&info, 0, sizeof(info));
+               info.id = control->id;
+               result = __snd_ctl_elem_info(card, kctl, &info, NULL);
+               if (!result)
+                       result = sanity_check_input_values(card, control, &info,
+                                                          false);
+       }
        if (!result)
                result = kctl->put(kctl, control);
        snd_power_unref(card);