commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / sound / pci / emu10k1 / emufx.c
index 8039c59..d2683e8 100644 (file)
@@ -945,12 +945,15 @@ static void snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
        snd_emu10k1_fx8010_ctl_t *ctl, nctl;
        snd_kcontrol_new_t knew;
        snd_kcontrol_t *kctl;
-       snd_ctl_elem_value_t val;
+       snd_ctl_elem_value_t *val;
 
+       val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
+       if (!val)
+               return;
        for (i = 0, _gctl = icode->gpr_add_controls;
             i < icode->gpr_add_control_count; i++, _gctl++) {
                if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
-                       return;
+                       break;
                snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
                                  gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, continue);
                snd_runtime_check(gctl.id.name[0] != '\0', continue);
@@ -970,7 +973,7 @@ static void snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
                for (j = 0; j < 32; j++) {
                        nctl.gpr[j] = gctl.gpr[j];
                        nctl.value[j] = ~gctl.value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
-                       val.value.integer.value[j] = gctl.value[j];
+                       val->value.integer.value[j] = gctl.value[j];
                }
                nctl.min = gctl.min;
                nctl.max = gctl.max;
@@ -996,8 +999,9 @@ static void snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
                        snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
                                                  SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
                }
-               snd_emu10k1_gpr_ctl_put(ctl->kcontrol, &val);
+               snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
        }
+       kfree(val);
 }
 
 static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
@@ -1234,7 +1238,10 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
 
 static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
 {
-       int err, i, z, gpr, tmp, playback, capture, nctl;
+       int err, i, z, gpr, nctl;
+       const int playback = 10;
+       const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
+       const int tmp = 0x88;
        u32 ptr;
        emu10k1_fx8010_code_t *icode;
        emu10k1_fx8010_control_gpr_t *controls, *ctl;
@@ -1257,19 +1264,15 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
        strcpy(icode->name, "Audigy DSP code for ALSA");
        ptr = 0;
        nctl = 0;
-       playback = 10;
-       capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
        gpr = capture + 10;
-       tmp = 0x88;
 
        /* stop FX processor */
        snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
 
-       /* Wave Playback */
+       /* Wave Playback Volume */
        A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
        A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
-       snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr,
-                                       emu->revision == 4 ? 50 : 100);
+       snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
        gpr += 2;
 
        /* Wave Surround Playback */
@@ -1493,6 +1496,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
        gpr += 2;
 
+       /* Master volume for audigy2 */
+       if (emu->revision == 4) {
+               A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
+               A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+               snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+               gpr += 2;
+       }
+
        /* digital outputs */
        A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
        A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -1500,7 +1511,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
        /* analog speakers */
-       if (emu->audigy && emu->revision == 4) { /* audigy2 */
+       if (emu->revision == 4) { /* audigy2 */
                A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
        } else {
                A_PUT_STEREO_OUTPUT(A_EXTOUT_AC97_L, A_EXTOUT_AC97_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -2227,7 +2238,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
 static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
        emu10k1_t *emu = snd_magic_cast(emu10k1_t, hw->private_data, return -ENXIO);
-       emu10k1_fx8010_info_t info;
+       emu10k1_fx8010_info_t *info;
        emu10k1_fx8010_code_t *icode;
        emu10k1_fx8010_pcm_t *ipcm;
        unsigned int addr;
@@ -2235,10 +2246,18 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
        
        switch (cmd) {
        case SNDRV_EMU10K1_IOCTL_INFO:
-               if ((res = snd_emu10k1_fx8010_info(emu, &info)) < 0)
+               info = (emu10k1_fx8010_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
+               if (!info)
+                       return -ENOMEM;
+               if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
+                       kfree(info);
                        return res;
-               if (copy_to_user((void *)arg, &info, sizeof(info)))
+               }
+               if (copy_to_user((void *)arg, info, sizeof(*info))) {
+                       kfree(info);
                        return -EFAULT;
+               }
+               kfree(info);
                return 0;
        case SNDRV_EMU10K1_IOCTL_CODE_POKE:
                if (!capable(CAP_SYS_ADMIN))
@@ -2271,9 +2290,13 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
        case SNDRV_EMU10K1_IOCTL_PCM_POKE:
                if (emu->audigy)
                        return -EINVAL;
-               ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
+               ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
                if (ipcm == NULL)
                        return -ENOMEM;
+               if (copy_from_user(ipcm, (void *)arg, sizeof(*ipcm))) {
+                       kfree(ipcm);
+                       return -EFAULT;
+               }
                res = snd_emu10k1_ipcm_poke(emu, ipcm);
                kfree(ipcm);
                return res;
@@ -2283,6 +2306,10 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
                ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
                if (ipcm == NULL)
                        return -ENOMEM;
+               if (copy_from_user(ipcm, (void *)arg, sizeof(*ipcm))) {
+                       kfree(ipcm);
+                       return -EFAULT;
+               }
                res = snd_emu10k1_ipcm_peek(emu, ipcm);
                if (res == 0 && copy_to_user((void *)arg, ipcm, sizeof(*ipcm))) {
                        kfree(ipcm);