fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / pci / emu10k1 / emufx.c
index 5098372..13cd6ce 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
+
 #include <sound/core.h>
+#include <sound/tlv.h>
 #include <sound/emu10k1.h>
 
 #if 0          /* for testing purposes - digital out -> capture */
@@ -264,6 +267,7 @@ static const u32 treble_table[41][5] = {
        { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
 };
 
+/* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */
 static const u32 db_table[101] = {
        0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540,
        0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8,
@@ -288,6 +292,9 @@ static const u32 db_table[101] = {
        0x7fffffff,
 };
 
+/* EMU10k1/EMU10k2 DSP control db gain */
+static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
+
 static const u32 onoff_table[2] = {
        0x00000000, 0x00000001
 };
@@ -753,6 +760,11 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
                knew.device = gctl->id.device;
                knew.subdevice = gctl->id.subdevice;
                knew.info = snd_emu10k1_gpr_ctl_info;
+               if (gctl->tlv.p) {
+                       knew.tlv.p = gctl->tlv.p;
+                       knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                               SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+               } 
                knew.get = snd_emu10k1_gpr_ctl_get;
                knew.put = snd_emu10k1_gpr_ctl_put;
                memset(nctl, 0, sizeof(*nctl));
@@ -874,7 +886,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
 {
        int err = 0;
 
-       down(&emu->fx8010.lock);
+       mutex_lock(&emu->fx8010.lock);
        if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
                goto __error;
        strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
@@ -897,7 +909,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
        else
                snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
       __error:
-       up(&emu->fx8010.lock);
+       mutex_unlock(&emu->fx8010.lock);
        return err;
 }
 
@@ -906,7 +918,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
 {
        int err;
 
-       down(&emu->fx8010.lock);
+       mutex_lock(&emu->fx8010.lock);
        strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
        /* ok, do the main job */
        err = snd_emu10k1_gpr_peek(emu, icode);
@@ -916,7 +928,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
                err = snd_emu10k1_code_peek(emu, icode);
        if (err >= 0)
                err = snd_emu10k1_list_controls(emu, icode);
-       up(&emu->fx8010.lock);
+       mutex_unlock(&emu->fx8010.lock);
        return err;
 }
 
@@ -932,7 +944,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
        if (ipcm->channels > 32)
                return -EINVAL;
        pcm = &emu->fx8010.pcm[ipcm->substream];
-       down(&emu->fx8010.lock);
+       mutex_lock(&emu->fx8010.lock);
        spin_lock_irq(&emu->reg_lock);
        if (pcm->opened) {
                err = -EBUSY;
@@ -962,7 +974,7 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
        }
       __error:
        spin_unlock_irq(&emu->reg_lock);
-       up(&emu->fx8010.lock);
+       mutex_unlock(&emu->fx8010.lock);
        return err;
 }
 
@@ -976,7 +988,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
        if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
                return -EINVAL;
        pcm = &emu->fx8010.pcm[ipcm->substream];
-       down(&emu->fx8010.lock);
+       mutex_lock(&emu->fx8010.lock);
        spin_lock_irq(&emu->reg_lock);
        ipcm->channels = pcm->channels;
        ipcm->tram_start = pcm->tram_start;
@@ -992,7 +1004,7 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
        ipcm->res1 = ipcm->res2 = 0;
        ipcm->pad = 0;
        spin_unlock_irq(&emu->reg_lock);
-       up(&emu->fx8010.lock);
+       mutex_unlock(&emu->fx8010.lock);
        return err;
 }
 
@@ -1011,6 +1023,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
        ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
        ctl->min = 0;
        ctl->max = 100;
+       ctl->tlv.p = snd_emu10k1_db_scale1;
        ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;    
 }
 
@@ -1025,6 +1038,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
        ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
        ctl->min = 0;
        ctl->max = 100;
+       ctl->tlv.p = snd_emu10k1_db_scale1;
        ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
 }
 
@@ -2308,9 +2322,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
                        return -EPERM;
                if (get_user(addr, (unsigned int __user *)argp))
                        return -EFAULT;
-               down(&emu->fx8010.lock);
+               mutex_lock(&emu->fx8010.lock);
                res = snd_emu10k1_fx8010_tram_setup(emu, addr);
-               up(&emu->fx8010.lock);
+               mutex_unlock(&emu->fx8010.lock);
                return res;
        case SNDRV_EMU10K1_IOCTL_STOP:
                if (!capable(CAP_SYS_ADMIN))