diff options
Diffstat (limited to 'sound/pci/emu10k1/emufx.c')
-rw-r--r-- | sound/pci/emu10k1/emufx.c | 204 |
1 files changed, 170 insertions, 34 deletions
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 13cd6ce89811..c02012cccd8e 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for effect processor FX8010 | 4 | * Routines for effect processor FX8010 |
5 | * | 5 | * |
6 | * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> | ||
7 | * Added EMU 1010 support. | ||
8 | * | ||
6 | * BUGS: | 9 | * BUGS: |
7 | * -- | 10 | * -- |
8 | * | 11 | * |
@@ -293,7 +296,7 @@ static const u32 db_table[101] = { | |||
293 | }; | 296 | }; |
294 | 297 | ||
295 | /* EMU10k1/EMU10k2 DSP control db gain */ | 298 | /* EMU10k1/EMU10k2 DSP control db gain */ |
296 | static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); | 299 | static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); |
297 | 300 | ||
298 | static const u32 onoff_table[2] = { | 301 | static const u32 onoff_table[2] = { |
299 | 0x00000000, 0x00000001 | 302 | 0x00000000, 0x00000001 |
@@ -652,13 +655,66 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) | |||
652 | return NULL; | 655 | return NULL; |
653 | } | 656 | } |
654 | 657 | ||
658 | #define MAX_TLV_SIZE 256 | ||
659 | |||
660 | static unsigned int *copy_tlv(const unsigned int __user *_tlv) | ||
661 | { | ||
662 | unsigned int data[2]; | ||
663 | unsigned int *tlv; | ||
664 | |||
665 | if (!_tlv) | ||
666 | return NULL; | ||
667 | if (copy_from_user(data, _tlv, sizeof(data))) | ||
668 | return NULL; | ||
669 | if (data[1] >= MAX_TLV_SIZE) | ||
670 | return NULL; | ||
671 | tlv = kmalloc(data[1] * 4 + sizeof(data), GFP_KERNEL); | ||
672 | if (!tlv) | ||
673 | return NULL; | ||
674 | memcpy(tlv, data, sizeof(data)); | ||
675 | if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { | ||
676 | kfree(tlv); | ||
677 | return NULL; | ||
678 | } | ||
679 | return tlv; | ||
680 | } | ||
681 | |||
682 | static int copy_gctl(struct snd_emu10k1 *emu, | ||
683 | struct snd_emu10k1_fx8010_control_gpr *gctl, | ||
684 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl, | ||
685 | int idx) | ||
686 | { | ||
687 | struct snd_emu10k1_fx8010_control_old_gpr __user *octl; | ||
688 | |||
689 | if (emu->support_tlv) | ||
690 | return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl)); | ||
691 | octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; | ||
692 | if (copy_from_user(gctl, &octl[idx], sizeof(*octl))) | ||
693 | return -EFAULT; | ||
694 | gctl->tlv = NULL; | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int copy_gctl_to_user(struct snd_emu10k1 *emu, | ||
699 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl, | ||
700 | struct snd_emu10k1_fx8010_control_gpr *gctl, | ||
701 | int idx) | ||
702 | { | ||
703 | struct snd_emu10k1_fx8010_control_old_gpr __user *octl; | ||
704 | |||
705 | if (emu->support_tlv) | ||
706 | return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl)); | ||
707 | |||
708 | octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; | ||
709 | return copy_to_user(&octl[idx], gctl, sizeof(*octl)); | ||
710 | } | ||
711 | |||
655 | static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | 712 | static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, |
656 | struct snd_emu10k1_fx8010_code *icode) | 713 | struct snd_emu10k1_fx8010_code *icode) |
657 | { | 714 | { |
658 | unsigned int i; | 715 | unsigned int i; |
659 | struct snd_ctl_elem_id __user *_id; | 716 | struct snd_ctl_elem_id __user *_id; |
660 | struct snd_ctl_elem_id id; | 717 | struct snd_ctl_elem_id id; |
661 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl; | ||
662 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 718 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
663 | int err; | 719 | int err; |
664 | 720 | ||
@@ -673,9 +729,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | |||
673 | if (! gctl) | 729 | if (! gctl) |
674 | return -ENOMEM; | 730 | return -ENOMEM; |
675 | err = 0; | 731 | err = 0; |
676 | for (i = 0, _gctl = icode->gpr_add_controls; | 732 | for (i = 0; i < icode->gpr_add_control_count; i++) { |
677 | i < icode->gpr_add_control_count; i++, _gctl++) { | 733 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { |
678 | if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { | ||
679 | err = -EFAULT; | 734 | err = -EFAULT; |
680 | goto __error; | 735 | goto __error; |
681 | } | 736 | } |
@@ -694,10 +749,9 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | |||
694 | goto __error; | 749 | goto __error; |
695 | } | 750 | } |
696 | } | 751 | } |
697 | for (i = 0, _gctl = icode->gpr_list_controls; | 752 | for (i = 0; i < icode->gpr_list_control_count; i++) { |
698 | i < icode->gpr_list_control_count; i++, _gctl++) { | ||
699 | /* FIXME: we need to check the WRITE access */ | 753 | /* FIXME: we need to check the WRITE access */ |
700 | if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { | 754 | if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) { |
701 | err = -EFAULT; | 755 | err = -EFAULT; |
702 | goto __error; | 756 | goto __error; |
703 | } | 757 | } |
@@ -715,13 +769,14 @@ static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl) | |||
715 | kctl->private_value = 0; | 769 | kctl->private_value = 0; |
716 | list_del(&ctl->list); | 770 | list_del(&ctl->list); |
717 | kfree(ctl); | 771 | kfree(ctl); |
772 | if (kctl->tlv.p) | ||
773 | kfree(kctl->tlv.p); | ||
718 | } | 774 | } |
719 | 775 | ||
720 | static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | 776 | static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, |
721 | struct snd_emu10k1_fx8010_code *icode) | 777 | struct snd_emu10k1_fx8010_code *icode) |
722 | { | 778 | { |
723 | unsigned int i, j; | 779 | unsigned int i, j; |
724 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl; | ||
725 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 780 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
726 | struct snd_emu10k1_fx8010_ctl *ctl, *nctl; | 781 | struct snd_emu10k1_fx8010_ctl *ctl, *nctl; |
727 | struct snd_kcontrol_new knew; | 782 | struct snd_kcontrol_new knew; |
@@ -737,9 +792,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
737 | goto __error; | 792 | goto __error; |
738 | } | 793 | } |
739 | 794 | ||
740 | for (i = 0, _gctl = icode->gpr_add_controls; | 795 | for (i = 0; i < icode->gpr_add_control_count; i++) { |
741 | i < icode->gpr_add_control_count; i++, _gctl++) { | 796 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { |
742 | if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { | ||
743 | err = -EFAULT; | 797 | err = -EFAULT; |
744 | goto __error; | 798 | goto __error; |
745 | } | 799 | } |
@@ -760,11 +814,10 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
760 | knew.device = gctl->id.device; | 814 | knew.device = gctl->id.device; |
761 | knew.subdevice = gctl->id.subdevice; | 815 | knew.subdevice = gctl->id.subdevice; |
762 | knew.info = snd_emu10k1_gpr_ctl_info; | 816 | knew.info = snd_emu10k1_gpr_ctl_info; |
763 | if (gctl->tlv.p) { | 817 | knew.tlv.p = copy_tlv(gctl->tlv); |
764 | knew.tlv.p = gctl->tlv.p; | 818 | if (knew.tlv.p) |
765 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 819 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
766 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 820 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
767 | } | ||
768 | knew.get = snd_emu10k1_gpr_ctl_get; | 821 | knew.get = snd_emu10k1_gpr_ctl_get; |
769 | knew.put = snd_emu10k1_gpr_ctl_put; | 822 | knew.put = snd_emu10k1_gpr_ctl_put; |
770 | memset(nctl, 0, sizeof(*nctl)); | 823 | memset(nctl, 0, sizeof(*nctl)); |
@@ -782,12 +835,14 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
782 | ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); | 835 | ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); |
783 | if (ctl == NULL) { | 836 | if (ctl == NULL) { |
784 | err = -ENOMEM; | 837 | err = -ENOMEM; |
838 | kfree(knew.tlv.p); | ||
785 | goto __error; | 839 | goto __error; |
786 | } | 840 | } |
787 | knew.private_value = (unsigned long)ctl; | 841 | knew.private_value = (unsigned long)ctl; |
788 | *ctl = *nctl; | 842 | *ctl = *nctl; |
789 | if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { | 843 | if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { |
790 | kfree(ctl); | 844 | kfree(ctl); |
845 | kfree(knew.tlv.p); | ||
791 | goto __error; | 846 | goto __error; |
792 | } | 847 | } |
793 | kctl->private_free = snd_emu10k1_ctl_private_free; | 848 | kctl->private_free = snd_emu10k1_ctl_private_free; |
@@ -838,7 +893,6 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
838 | unsigned int i = 0, j; | 893 | unsigned int i = 0, j; |
839 | unsigned int total = 0; | 894 | unsigned int total = 0; |
840 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 895 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
841 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl; | ||
842 | struct snd_emu10k1_fx8010_ctl *ctl; | 896 | struct snd_emu10k1_fx8010_ctl *ctl; |
843 | struct snd_ctl_elem_id *id; | 897 | struct snd_ctl_elem_id *id; |
844 | struct list_head *list; | 898 | struct list_head *list; |
@@ -847,11 +901,11 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
847 | if (! gctl) | 901 | if (! gctl) |
848 | return -ENOMEM; | 902 | return -ENOMEM; |
849 | 903 | ||
850 | _gctl = icode->gpr_list_controls; | ||
851 | list_for_each(list, &emu->fx8010.gpr_ctl) { | 904 | list_for_each(list, &emu->fx8010.gpr_ctl) { |
852 | ctl = emu10k1_gpr_ctl(list); | 905 | ctl = emu10k1_gpr_ctl(list); |
853 | total++; | 906 | total++; |
854 | if (_gctl && i < icode->gpr_list_control_count) { | 907 | if (icode->gpr_list_controls && |
908 | i < icode->gpr_list_control_count) { | ||
855 | memset(gctl, 0, sizeof(*gctl)); | 909 | memset(gctl, 0, sizeof(*gctl)); |
856 | id = &ctl->kcontrol->id; | 910 | id = &ctl->kcontrol->id; |
857 | gctl->id.iface = id->iface; | 911 | gctl->id.iface = id->iface; |
@@ -868,11 +922,11 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
868 | gctl->min = ctl->min; | 922 | gctl->min = ctl->min; |
869 | gctl->max = ctl->max; | 923 | gctl->max = ctl->max; |
870 | gctl->translation = ctl->translation; | 924 | gctl->translation = ctl->translation; |
871 | if (copy_to_user(_gctl, gctl, sizeof(*gctl))) { | 925 | if (copy_gctl_to_user(emu, icode->gpr_list_controls, |
926 | gctl, i)) { | ||
872 | kfree(gctl); | 927 | kfree(gctl); |
873 | return -EFAULT; | 928 | return -EFAULT; |
874 | } | 929 | } |
875 | _gctl++; | ||
876 | i++; | 930 | i++; |
877 | } | 931 | } |
878 | } | 932 | } |
@@ -1023,7 +1077,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, | |||
1023 | ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; | 1077 | ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; |
1024 | ctl->min = 0; | 1078 | ctl->min = 0; |
1025 | ctl->max = 100; | 1079 | ctl->max = 100; |
1026 | ctl->tlv.p = snd_emu10k1_db_scale1; | 1080 | ctl->tlv = snd_emu10k1_db_scale1; |
1027 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; | 1081 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; |
1028 | } | 1082 | } |
1029 | 1083 | ||
@@ -1038,7 +1092,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, | |||
1038 | ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; | 1092 | ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; |
1039 | ctl->min = 0; | 1093 | ctl->min = 0; |
1040 | ctl->max = 100; | 1094 | ctl->max = 100; |
1041 | ctl->tlv.p = snd_emu10k1_db_scale1; | 1095 | ctl->tlv = snd_emu10k1_db_scale1; |
1042 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; | 1096 | ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; |
1043 | } | 1097 | } |
1044 | 1098 | ||
@@ -1069,6 +1123,21 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl | |||
1069 | ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; | 1123 | ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; |
1070 | } | 1124 | } |
1071 | 1125 | ||
1126 | static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( | ||
1127 | struct snd_emu10k1_fx8010_code *icode, | ||
1128 | u32 *ptr, int tmp, int bit_shifter16, | ||
1129 | int reg_in, int reg_out) | ||
1130 | { | ||
1131 | A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000); | ||
1132 | A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000); | ||
1133 | A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2)); | ||
1134 | A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000); | ||
1135 | A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000); | ||
1136 | A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000); | ||
1137 | A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2)); | ||
1138 | A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000); | ||
1139 | return 1; | ||
1140 | } | ||
1072 | 1141 | ||
1073 | /* | 1142 | /* |
1074 | * initial DSP configuration for Audigy | 1143 | * initial DSP configuration for Audigy |
@@ -1077,6 +1146,7 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl | |||
1077 | static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | 1146 | static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) |
1078 | { | 1147 | { |
1079 | int err, i, z, gpr, nctl; | 1148 | int err, i, z, gpr, nctl; |
1149 | int bit_shifter16; | ||
1080 | const int playback = 10; | 1150 | const int playback = 10; |
1081 | const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ | 1151 | const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ |
1082 | const int stereo_mix = capture + 2; | 1152 | const int stereo_mix = capture + 2; |
@@ -1114,17 +1184,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1114 | ptr = 0; | 1184 | ptr = 0; |
1115 | nctl = 0; | 1185 | nctl = 0; |
1116 | gpr = stereo_mix + 10; | 1186 | gpr = stereo_mix + 10; |
1187 | gpr_map[gpr++] = 0x00007fff; | ||
1188 | gpr_map[gpr++] = 0x00008000; | ||
1189 | gpr_map[gpr++] = 0x0000ffff; | ||
1190 | bit_shifter16 = gpr; | ||
1117 | 1191 | ||
1118 | /* stop FX processor */ | 1192 | /* stop FX processor */ |
1119 | snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); | 1193 | snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); |
1120 | 1194 | ||
1121 | #if 0 | ||
1122 | /* FIX: jcd test */ | ||
1123 | for (z = 0; z < 80; z=z+2) { | ||
1124 | A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */ | ||
1125 | A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */ | ||
1126 | } | ||
1127 | #endif /* jcd test */ | ||
1128 | #if 1 | 1195 | #if 1 |
1129 | /* PCM front Playback Volume (independent from stereo mix) */ | 1196 | /* PCM front Playback Volume (independent from stereo mix) */ |
1130 | A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); | 1197 | A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); |
@@ -1182,13 +1249,20 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1182 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); | 1249 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); |
1183 | snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); | 1250 | snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); |
1184 | gpr += 2; | 1251 | gpr += 2; |
1185 | 1252 | ||
1186 | /* | 1253 | /* |
1187 | * inputs | 1254 | * inputs |
1188 | */ | 1255 | */ |
1189 | #define A_ADD_VOLUME_IN(var,vol,input) \ | 1256 | #define A_ADD_VOLUME_IN(var,vol,input) \ |
1190 | A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | 1257 | A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) |
1191 | 1258 | ||
1259 | /* emu1212 DSP 0 and DSP 1 Capture */ | ||
1260 | if (emu->card_capabilities->emu1010) { | ||
1261 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); | ||
1262 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); | ||
1263 | snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); | ||
1264 | gpr += 2; | ||
1265 | } | ||
1192 | /* AC'97 Playback Volume - used only for mic (renamed later) */ | 1266 | /* AC'97 Playback Volume - used only for mic (renamed later) */ |
1193 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L); | 1267 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L); |
1194 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R); | 1268 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R); |
@@ -1429,6 +1503,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1429 | 1503 | ||
1430 | /* digital outputs */ | 1504 | /* digital outputs */ |
1431 | /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ | 1505 | /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ |
1506 | if (emu->card_capabilities->emu1010) { | ||
1507 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ | ||
1508 | snd_printk("EMU outputs on\n"); | ||
1509 | for (z = 0; z < 8; z++) { | ||
1510 | A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | ||
1511 | } | ||
1512 | } | ||
1432 | 1513 | ||
1433 | /* IEC958 Optical Raw Playback Switch */ | 1514 | /* IEC958 Optical Raw Playback Switch */ |
1434 | gpr_map[gpr++] = 0; | 1515 | gpr_map[gpr++] = 0; |
@@ -1466,9 +1547,57 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1466 | A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); | 1547 | A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); |
1467 | #endif | 1548 | #endif |
1468 | 1549 | ||
1469 | /* EFX capture - capture the 16 EXTINs */ | 1550 | if (emu->card_capabilities->emu1010) { |
1470 | for (z = 0; z < 16; z++) { | 1551 | snd_printk("EMU inputs on\n"); |
1471 | A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); | 1552 | /* Capture 8 channels of S32_LE sound */ |
1553 | |||
1554 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ | ||
1555 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ | ||
1556 | /* A_P16VIN(0) is delayed by one sample, | ||
1557 | * so all other A_P16VIN channels will need to also be delayed | ||
1558 | */ | ||
1559 | /* Left ADC in. 1 of 2 */ | ||
1560 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); | ||
1561 | /* Right ADC in 1 of 2 */ | ||
1562 | gpr_map[gpr++] = 0x00000000; | ||
1563 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); | ||
1564 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); | ||
1565 | gpr_map[gpr++] = 0x00000000; | ||
1566 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); | ||
1567 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); | ||
1568 | gpr_map[gpr++] = 0x00000000; | ||
1569 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); | ||
1570 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); | ||
1571 | /* For 96kHz mode */ | ||
1572 | /* Left ADC in. 2 of 2 */ | ||
1573 | gpr_map[gpr++] = 0x00000000; | ||
1574 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); | ||
1575 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); | ||
1576 | /* Right ADC in 2 of 2 */ | ||
1577 | gpr_map[gpr++] = 0x00000000; | ||
1578 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); | ||
1579 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); | ||
1580 | gpr_map[gpr++] = 0x00000000; | ||
1581 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); | ||
1582 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); | ||
1583 | gpr_map[gpr++] = 0x00000000; | ||
1584 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); | ||
1585 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); | ||
1586 | |||
1587 | #if 0 | ||
1588 | for (z = 4; z < 8; z++) { | ||
1589 | A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); | ||
1590 | } | ||
1591 | for (z = 0xc; z < 0x10; z++) { | ||
1592 | A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); | ||
1593 | } | ||
1594 | #endif | ||
1595 | } else { | ||
1596 | /* EFX capture - capture the 16 EXTINs */ | ||
1597 | /* Capture 16 channels of S16_LE sound */ | ||
1598 | for (z = 0; z < 16; z++) { | ||
1599 | A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); | ||
1600 | } | ||
1472 | } | 1601 | } |
1473 | 1602 | ||
1474 | #endif /* JCD test */ | 1603 | #endif /* JCD test */ |
@@ -1488,7 +1617,9 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1488 | seg = snd_enter_user(); | 1617 | seg = snd_enter_user(); |
1489 | icode->gpr_add_control_count = nctl; | 1618 | icode->gpr_add_control_count = nctl; |
1490 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; | 1619 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; |
1620 | emu->support_tlv = 1; /* support TLV */ | ||
1491 | err = snd_emu10k1_icode_poke(emu, icode); | 1621 | err = snd_emu10k1_icode_poke(emu, icode); |
1622 | emu->support_tlv = 0; /* clear again */ | ||
1492 | snd_leave_user(seg); | 1623 | snd_leave_user(seg); |
1493 | 1624 | ||
1494 | __err: | 1625 | __err: |
@@ -2105,7 +2236,9 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
2105 | seg = snd_enter_user(); | 2236 | seg = snd_enter_user(); |
2106 | icode->gpr_add_control_count = i; | 2237 | icode->gpr_add_control_count = i; |
2107 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; | 2238 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; |
2239 | emu->support_tlv = 1; /* support TLV */ | ||
2108 | err = snd_emu10k1_icode_poke(emu, icode); | 2240 | err = snd_emu10k1_icode_poke(emu, icode); |
2241 | emu->support_tlv = 0; /* clear again */ | ||
2109 | snd_leave_user(seg); | 2242 | snd_leave_user(seg); |
2110 | if (err >= 0) | 2243 | if (err >= 0) |
2111 | err = snd_emu10k1_ipcm_poke(emu, ipcm); | 2244 | err = snd_emu10k1_ipcm_poke(emu, ipcm); |
@@ -2138,7 +2271,7 @@ void snd_emu10k1_free_efx(struct snd_emu10k1 *emu) | |||
2138 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP); | 2271 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP); |
2139 | } | 2272 | } |
2140 | 2273 | ||
2141 | #if 0 // FIXME: who use them? | 2274 | #if 0 /* FIXME: who use them? */ |
2142 | int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output) | 2275 | int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output) |
2143 | { | 2276 | { |
2144 | if (output < 0 || output >= 6) | 2277 | if (output < 0 || output >= 6) |
@@ -2249,6 +2382,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un | |||
2249 | int res; | 2382 | int res; |
2250 | 2383 | ||
2251 | switch (cmd) { | 2384 | switch (cmd) { |
2385 | case SNDRV_EMU10K1_IOCTL_PVERSION: | ||
2386 | emu->support_tlv = 1; | ||
2387 | return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp); | ||
2252 | case SNDRV_EMU10K1_IOCTL_INFO: | 2388 | case SNDRV_EMU10K1_IOCTL_INFO: |
2253 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 2389 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
2254 | if (!info) | 2390 | if (!info) |