]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/pci/hda/hda_codec.c
Merge branch 'for-spi' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[karo-tx-linux.git] / sound / pci / hda / hda_codec.c
index 70bb365a08d2673d383df4c923f41248c89944e6..821aad374a0695a46c4c265365b71a81aa134412 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
-#include <linux/async.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <sound/core.h>
@@ -1477,18 +1475,8 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
 
-/**
- * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
- * @kcontrol: ctl element
- * @op_flag: operation flag
- * @size: byte size of input TLV
- * @_tlv: TLV data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-                         unsigned int size, unsigned int __user *_tlv)
+/* inquiry the amp caps and convert to TLV */
+static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        hda_nid_t nid = get_amp_nid(kcontrol);
@@ -1497,8 +1485,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        bool min_mute = get_amp_min_mute(kcontrol);
        u32 caps, val1, val2;
 
-       if (size < 4 * sizeof(unsigned int))
-               return -ENOMEM;
        caps = query_amp_caps(codec, nid, dir);
        val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
        val2 = (val2 + 1) * 25;
@@ -1507,13 +1493,31 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        val1 = ((int)val1) * ((int)val2);
        if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
                val2 |= TLV_DB_SCALE_MUTE;
-       if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
-               return -EFAULT;
-       if (put_user(2 * sizeof(unsigned int), _tlv + 1))
-               return -EFAULT;
-       if (put_user(val1, _tlv + 2))
-               return -EFAULT;
-       if (put_user(val2, _tlv + 3))
+       tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
+       tlv[1] = 2 * sizeof(unsigned int);
+       tlv[2] = val1;
+       tlv[3] = val2;
+}
+
+/**
+ * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume
+ * @kcontrol: ctl element
+ * @op_flag: operation flag
+ * @size: byte size of input TLV
+ * @_tlv: TLV data
+ *
+ * The control element is supposed to have the private_value field
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
+ */
+int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+                         unsigned int size, unsigned int __user *_tlv)
+{
+       unsigned int tlv[4];
+
+       if (size < 4 * sizeof(unsigned int))
+               return -ENOMEM;
+       get_ctl_amp_tlv(kcontrol, tlv);
+       if (copy_to_user(_tlv, tlv, sizeof(tlv)))
                return -EFAULT;
        return 0;
 }
@@ -1807,13 +1811,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
        const int *tlv = NULL;
        int val = -1;
 
-       if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
-               /* FIXME: set_fs() hack for obtaining user-space TLV data */
-               mm_segment_t fs = get_fs();
-               set_fs(get_ds());
-               if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
-                       tlv = _tlv;
-               set_fs(fs);
+       if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) &&
+           kctl->tlv.c == snd_hda_mixer_amp_tlv) {
+               get_ctl_amp_tlv(kctl, _tlv);
+               tlv = _tlv;
        } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
                tlv = kctl->tlv.p;
        if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
@@ -2117,196 +2118,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
 
-/*
- * bound volume controls
- *
- * bind multiple volumes (# indices, from 0)
- */
-
-#define AMP_VAL_IDX_SHIFT      19
-#define AMP_VAL_IDX_MASK       (0x0f<<19)
-
-/**
- * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_MUTE*() macros.
- */
-int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned long pval;
-       int err;
-
-       mutex_lock(&codec->control_mutex);
-       pval = kcontrol->private_value;
-       kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
-       err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
-       kcontrol->private_value = pval;
-       mutex_unlock(&codec->control_mutex);
-       return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get);
-
-/**
- * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_MUTE*() macros.
- */
-int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned long pval;
-       int i, indices, err = 0, change = 0;
-
-       mutex_lock(&codec->control_mutex);
-       pval = kcontrol->private_value;
-       indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
-       for (i = 0; i < indices; i++) {
-               kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
-                       (i << AMP_VAL_IDX_SHIFT);
-               err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
-               if (err < 0)
-                       break;
-               change |= err;
-       }
-       kcontrol->private_value = pval;
-       mutex_unlock(&codec->control_mutex);
-       return err < 0 ? err : change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put);
-
-/**
- * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
- * @kcontrol: referred ctl element
- * @uinfo: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_info *uinfo)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_bind_ctls *c;
-       int err;
-
-       mutex_lock(&codec->control_mutex);
-       c = (struct hda_bind_ctls *)kcontrol->private_value;
-       kcontrol->private_value = *c->values;
-       err = c->ops->info(kcontrol, uinfo);
-       kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->control_mutex);
-       return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info);
-
-/**
- * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_bind_ctls *c;
-       int err;
-
-       mutex_lock(&codec->control_mutex);
-       c = (struct hda_bind_ctls *)kcontrol->private_value;
-       kcontrol->private_value = *c->values;
-       err = c->ops->get(kcontrol, ucontrol);
-       kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->control_mutex);
-       return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get);
-
-/**
- * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_bind_ctls *c;
-       unsigned long *vals;
-       int err = 0, change = 0;
-
-       mutex_lock(&codec->control_mutex);
-       c = (struct hda_bind_ctls *)kcontrol->private_value;
-       for (vals = c->values; *vals; vals++) {
-               kcontrol->private_value = *vals;
-               err = c->ops->put(kcontrol, ucontrol);
-               if (err < 0)
-                       break;
-               change |= err;
-       }
-       kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->control_mutex);
-       return err < 0 ? err : change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
-
-/**
- * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
- * @kcontrol: ctl element
- * @op_flag: operation flag
- * @size: byte size of input TLV
- * @tlv: TLV data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() macro.
- */
-int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
-                          unsigned int size, unsigned int __user *tlv)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_bind_ctls *c;
-       int err;
-
-       mutex_lock(&codec->control_mutex);
-       c = (struct hda_bind_ctls *)kcontrol->private_value;
-       kcontrol->private_value = *c->values;
-       err = c->ops->tlv(kcontrol, op_flag, size, tlv);
-       kcontrol->private_value = (long)c;
-       mutex_unlock(&codec->control_mutex);
-       return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv);
-
-struct hda_ctl_ops snd_hda_bind_vol = {
-       .info = snd_hda_mixer_amp_volume_info,
-       .get = snd_hda_mixer_amp_volume_get,
-       .put = snd_hda_mixer_amp_volume_put,
-       .tlv = snd_hda_mixer_amp_tlv
-};
-EXPORT_SYMBOL_GPL(snd_hda_bind_vol);
-
-struct hda_ctl_ops snd_hda_bind_sw = {
-       .info = snd_hda_mixer_amp_switch_info,
-       .get = snd_hda_mixer_amp_switch_get,
-       .put = snd_hda_mixer_amp_switch_put,
-       .tlv = snd_hda_mixer_amp_tlv
-};
-EXPORT_SYMBOL_GPL(snd_hda_bind_sw);
-
 /*
  * SPDIF out controls
  */