diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-31 18:16:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-31 18:16:28 -0500 |
commit | e1a9c9872dd004617555dff079b357a6ffd945e9 (patch) | |
tree | c34779e59712ff345f8e4ee97e74086a85b34974 /sound/pci/ice1712 | |
parent | fcc3ff4f9d695a80dc6e6058e0d631a3026ed4c3 (diff) | |
parent | 2ecba4ffbbc6c85fce8c3878514be415edace413 (diff) |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa: (299 commits)
[ALSA] version 1.0.16rc2
[ALSA] hda: fix Mic in as output
[ALSA] emu10k1 - Another EMU0404 Board ID
[ALSA] emu10k1 - Fix kthread handling at resume
[ALSA] emu10k1: General cleanup, add new locks, fix alsa bug#3501, kernel bug#9304.
[ALSA] emu10k1 - Use enum for emu_model types
[ALSA] emu10k1 - Don't create emu1010 controls for non-emu boards
[ALSA] emu10k1 - 1616(M) cardbus improvements
[ALSA] snd:emu10k1: E-Mu updates. Fixes to firmware loading and support for 0404.
[ALSA] emu10k1: Add comments regarding E-Mu ins and outs.
[ALSA] oxygen: revert SPI clock frequency change for AK4396/WM8785
[ALSA] es1938 - improve capture hw pointer reads
[ALSA] HDA-Intel - Add support for Intel SCH
[ALSA] hda: Add GPIO mute support to STAC9205
[ALSA] hda-codec - Add Dell T3400 support
[ALSA] hda-codec - Add model for HP DV9553EG laptop
[ALSA] hda-codec - Control SPDIF as slave
[ALSA] hda_intel: ALSA HD Audio patch for Intel ICH10 DeviceID's
[ALSA] Fix Oops with PCM OSS sync
[ALSA] hda-codec - Add speaker automute to ALC262 HP models
...
Diffstat (limited to 'sound/pci/ice1712')
-rw-r--r-- | sound/pci/ice1712/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/ice1712/ak4xxx.c | 1 | ||||
-rw-r--r-- | sound/pci/ice1712/amp.c | 1 | ||||
-rw-r--r-- | sound/pci/ice1712/aureon.c | 133 | ||||
-rw-r--r-- | sound/pci/ice1712/delta.c | 3 | ||||
-rw-r--r-- | sound/pci/ice1712/ews.c | 92 | ||||
-rw-r--r-- | sound/pci/ice1712/hoontech.c | 188 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.c | 2 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1712.h | 37 | ||||
-rw-r--r-- | sound/pci/ice1712/ice1724.c | 9 | ||||
-rw-r--r-- | sound/pci/ice1712/juli.c | 23 | ||||
-rw-r--r-- | sound/pci/ice1712/phase.c | 96 | ||||
-rw-r--r-- | sound/pci/ice1712/pontis.c | 1 | ||||
-rw-r--r-- | sound/pci/ice1712/prodigy192.c | 297 | ||||
-rw-r--r-- | sound/pci/ice1712/prodigy_hifi.c | 1210 | ||||
-rw-r--r-- | sound/pci/ice1712/prodigy_hifi.h | 38 | ||||
-rw-r--r-- | sound/pci/ice1712/revo.c | 24 | ||||
-rw-r--r-- | sound/pci/ice1712/se.c | 774 | ||||
-rw-r--r-- | sound/pci/ice1712/se.h | 15 | ||||
-rw-r--r-- | sound/pci/ice1712/vt1720_mobo.c | 1 | ||||
-rw-r--r-- | sound/pci/ice1712/wtm.c | 9 |
21 files changed, 2547 insertions, 409 deletions
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 65ce66adba5a..f99fe089495d 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o | 7 | snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o |
8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o | 8 | snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o |
9 | 9 | ||
10 | # Toplevel Module Dependency | 10 | # Toplevel Module Dependency |
11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o | 11 | obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o |
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index a1aba0d7d0e4..dab31b2756a6 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 6e13d758bb5d..37564300b50d 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index ec0699c89952..868ae291b960 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -47,7 +47,6 @@ | |||
47 | * | 47 | * |
48 | */ | 48 | */ |
49 | 49 | ||
50 | #include <sound/driver.h> | ||
51 | #include <asm/io.h> | 50 | #include <asm/io.h> |
52 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
53 | #include <linux/interrupt.h> | 52 | #include <linux/interrupt.h> |
@@ -62,6 +61,15 @@ | |||
62 | #include "aureon.h" | 61 | #include "aureon.h" |
63 | #include <sound/tlv.h> | 62 | #include <sound/tlv.h> |
64 | 63 | ||
64 | /* AC97 register cache for Aureon */ | ||
65 | struct aureon_spec { | ||
66 | unsigned short stac9744[64]; | ||
67 | unsigned int cs8415_mux; | ||
68 | unsigned short master[2]; | ||
69 | unsigned short vol[8]; | ||
70 | unsigned char pca9554_out; | ||
71 | }; | ||
72 | |||
65 | /* WM8770 registers */ | 73 | /* WM8770 registers */ |
66 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ | 74 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ |
67 | #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ | 75 | #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ |
@@ -205,7 +213,8 @@ static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol, | |||
205 | struct snd_ctl_elem_value *ucontrol) | 213 | struct snd_ctl_elem_value *ucontrol) |
206 | { | 214 | { |
207 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 215 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
208 | ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out; | 216 | struct aureon_spec *spec = ice->spec; |
217 | ucontrol->value.enumerated.item[0] = spec->pca9554_out; | ||
209 | return 0; | 218 | return 0; |
210 | } | 219 | } |
211 | 220 | ||
@@ -213,16 +222,18 @@ static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol, | |||
213 | struct snd_ctl_elem_value *ucontrol) | 222 | struct snd_ctl_elem_value *ucontrol) |
214 | { | 223 | { |
215 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 224 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
225 | struct aureon_spec *spec = ice->spec; | ||
216 | unsigned char oval, nval; | 226 | unsigned char oval, nval; |
217 | int change; | 227 | int change; |
218 | 228 | ||
229 | nval = ucontrol->value.enumerated.item[0]; | ||
230 | if (nval >= 3) | ||
231 | return -EINVAL; | ||
219 | snd_ice1712_save_gpio_status(ice); | 232 | snd_ice1712_save_gpio_status(ice); |
220 | 233 | oval = spec->pca9554_out; | |
221 | oval = ice->spec.aureon.pca9554_out; | ||
222 | nval = ucontrol->value.integer.value[0]; | ||
223 | if ((change = (oval != nval))) { | 234 | if ((change = (oval != nval))) { |
224 | aureon_pca9554_write(ice, PCA9554_OUT, nval); | 235 | aureon_pca9554_write(ice, PCA9554_OUT, nval); |
225 | ice->spec.aureon.pca9554_out = nval; | 236 | spec->pca9554_out = nval; |
226 | } | 237 | } |
227 | snd_ice1712_restore_gpio_status(ice); | 238 | snd_ice1712_restore_gpio_status(ice); |
228 | 239 | ||
@@ -233,6 +244,7 @@ static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol, | |||
233 | static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, | 244 | static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, |
234 | unsigned short val) | 245 | unsigned short val) |
235 | { | 246 | { |
247 | struct aureon_spec *spec = ice->spec; | ||
236 | unsigned int tmp; | 248 | unsigned int tmp; |
237 | 249 | ||
238 | /* Send address to XILINX chip */ | 250 | /* Send address to XILINX chip */ |
@@ -280,12 +292,13 @@ static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, | |||
280 | udelay(10); | 292 | udelay(10); |
281 | 293 | ||
282 | /* Store the data in out private buffer */ | 294 | /* Store the data in out private buffer */ |
283 | ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val; | 295 | spec->stac9744[(reg & 0x7F) >> 1] = val; |
284 | } | 296 | } |
285 | 297 | ||
286 | static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg) | 298 | static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg) |
287 | { | 299 | { |
288 | return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1]; | 300 | struct aureon_spec *spec = ice->spec; |
301 | return spec->stac9744[(reg & 0x7F) >> 1]; | ||
289 | } | 302 | } |
290 | 303 | ||
291 | /* | 304 | /* |
@@ -293,6 +306,7 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r | |||
293 | */ | 306 | */ |
294 | static int aureon_ac97_init (struct snd_ice1712 *ice) | 307 | static int aureon_ac97_init (struct snd_ice1712 *ice) |
295 | { | 308 | { |
309 | struct aureon_spec *spec = ice->spec; | ||
296 | int i; | 310 | int i; |
297 | static const unsigned short ac97_defaults[] = { | 311 | static const unsigned short ac97_defaults[] = { |
298 | 0x00, 0x9640, | 312 | 0x00, 0x9640, |
@@ -330,9 +344,9 @@ static int aureon_ac97_init (struct snd_ice1712 *ice) | |||
330 | snd_ice1712_gpio_write(ice, tmp); | 344 | snd_ice1712_gpio_write(ice, tmp); |
331 | udelay(3); | 345 | udelay(3); |
332 | 346 | ||
333 | memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744)); | 347 | memset(&spec->stac9744, 0, sizeof(spec->stac9744)); |
334 | for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2) | 348 | for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2) |
335 | ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1]; | 349 | spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1]; |
336 | 350 | ||
337 | aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770 | 351 | aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770 |
338 | 352 | ||
@@ -744,27 +758,33 @@ static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
744 | static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 758 | static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
745 | { | 759 | { |
746 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 760 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
761 | struct aureon_spec *spec = ice->spec; | ||
747 | int i; | 762 | int i; |
748 | for (i=0; i<2; i++) | 763 | for (i=0; i<2; i++) |
749 | ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE; | 764 | ucontrol->value.integer.value[i] = |
765 | spec->master[i] & ~WM_VOL_MUTE; | ||
750 | return 0; | 766 | return 0; |
751 | } | 767 | } |
752 | 768 | ||
753 | static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 769 | static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
754 | { | 770 | { |
755 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 771 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
772 | struct aureon_spec *spec = ice->spec; | ||
756 | int ch, change = 0; | 773 | int ch, change = 0; |
757 | 774 | ||
758 | snd_ice1712_save_gpio_status(ice); | 775 | snd_ice1712_save_gpio_status(ice); |
759 | for (ch = 0; ch < 2; ch++) { | 776 | for (ch = 0; ch < 2; ch++) { |
760 | if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) { | 777 | unsigned int vol = ucontrol->value.integer.value[ch]; |
778 | if (vol > WM_VOL_MAX) | ||
779 | continue; | ||
780 | vol |= spec->master[ch] & WM_VOL_MUTE; | ||
781 | if (vol != spec->master[ch]) { | ||
761 | int dac; | 782 | int dac; |
762 | ice->spec.aureon.master[ch] &= WM_VOL_MUTE; | 783 | spec->master[ch] = vol; |
763 | ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch]; | ||
764 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | 784 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) |
765 | wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, | 785 | wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, |
766 | ice->spec.aureon.vol[dac + ch], | 786 | spec->vol[dac + ch], |
767 | ice->spec.aureon.master[ch]); | 787 | spec->master[ch]); |
768 | change = 1; | 788 | change = 1; |
769 | } | 789 | } |
770 | } | 790 | } |
@@ -788,18 +808,21 @@ static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info * | |||
788 | static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 808 | static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
789 | { | 809 | { |
790 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 810 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
811 | struct aureon_spec *spec = ice->spec; | ||
791 | int i, ofs, voices; | 812 | int i, ofs, voices; |
792 | 813 | ||
793 | voices = kcontrol->private_value >> 8; | 814 | voices = kcontrol->private_value >> 8; |
794 | ofs = kcontrol->private_value & 0xff; | 815 | ofs = kcontrol->private_value & 0xff; |
795 | for (i = 0; i < voices; i++) | 816 | for (i = 0; i < voices; i++) |
796 | ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE; | 817 | ucontrol->value.integer.value[i] = |
818 | spec->vol[ofs+i] & ~WM_VOL_MUTE; | ||
797 | return 0; | 819 | return 0; |
798 | } | 820 | } |
799 | 821 | ||
800 | static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 822 | static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
801 | { | 823 | { |
802 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 824 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
825 | struct aureon_spec *spec = ice->spec; | ||
803 | int i, idx, ofs, voices; | 826 | int i, idx, ofs, voices; |
804 | int change = 0; | 827 | int change = 0; |
805 | 828 | ||
@@ -807,12 +830,15 @@ static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value * | |||
807 | ofs = kcontrol->private_value & 0xff; | 830 | ofs = kcontrol->private_value & 0xff; |
808 | snd_ice1712_save_gpio_status(ice); | 831 | snd_ice1712_save_gpio_status(ice); |
809 | for (i = 0; i < voices; i++) { | 832 | for (i = 0; i < voices; i++) { |
810 | idx = WM_DAC_ATTEN + ofs + i; | 833 | unsigned int vol = ucontrol->value.integer.value[i]; |
811 | if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) { | 834 | if (vol > 0x7f) |
812 | ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE; | 835 | continue; |
813 | ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i]; | 836 | vol |= spec->vol[ofs+i]; |
814 | wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i], | 837 | if (vol != spec->vol[ofs+i]) { |
815 | ice->spec.aureon.master[i]); | 838 | spec->vol[ofs+i] = vol; |
839 | idx = WM_DAC_ATTEN + ofs + i; | ||
840 | wm_set_vol(ice, idx, spec->vol[ofs + i], | ||
841 | spec->master[i]); | ||
816 | change = 1; | 842 | change = 1; |
817 | } | 843 | } |
818 | } | 844 | } |
@@ -834,19 +860,22 @@ static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info | |||
834 | static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 860 | static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
835 | { | 861 | { |
836 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 862 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
863 | struct aureon_spec *spec = ice->spec; | ||
837 | int voices, ofs, i; | 864 | int voices, ofs, i; |
838 | 865 | ||
839 | voices = kcontrol->private_value >> 8; | 866 | voices = kcontrol->private_value >> 8; |
840 | ofs = kcontrol->private_value & 0xFF; | 867 | ofs = kcontrol->private_value & 0xFF; |
841 | 868 | ||
842 | for (i = 0; i < voices; i++) | 869 | for (i = 0; i < voices; i++) |
843 | ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; | 870 | ucontrol->value.integer.value[i] = |
871 | (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; | ||
844 | return 0; | 872 | return 0; |
845 | } | 873 | } |
846 | 874 | ||
847 | static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 875 | static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
848 | { | 876 | { |
849 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 877 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
878 | struct aureon_spec *spec = ice->spec; | ||
850 | int change = 0, voices, ofs, i; | 879 | int change = 0, voices, ofs, i; |
851 | 880 | ||
852 | voices = kcontrol->private_value >> 8; | 881 | voices = kcontrol->private_value >> 8; |
@@ -854,13 +883,13 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
854 | 883 | ||
855 | snd_ice1712_save_gpio_status(ice); | 884 | snd_ice1712_save_gpio_status(ice); |
856 | for (i = 0; i < voices; i++) { | 885 | for (i = 0; i < voices; i++) { |
857 | int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; | 886 | int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; |
858 | if (ucontrol->value.integer.value[i] != val) { | 887 | if (ucontrol->value.integer.value[i] != val) { |
859 | ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE; | 888 | spec->vol[ofs + i] &= ~WM_VOL_MUTE; |
860 | ice->spec.aureon.vol[ofs + i] |= | 889 | spec->vol[ofs + i] |= |
861 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | 890 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; |
862 | wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i], | 891 | wm_set_vol(ice, ofs + i, spec->vol[ofs + i], |
863 | ice->spec.aureon.master[i]); | 892 | spec->master[i]); |
864 | change = 1; | 893 | change = 1; |
865 | } | 894 | } |
866 | } | 895 | } |
@@ -877,29 +906,33 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
877 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 906 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
878 | { | 907 | { |
879 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 908 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
909 | struct aureon_spec *spec = ice->spec; | ||
880 | 910 | ||
881 | ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1; | 911 | ucontrol->value.integer.value[0] = |
882 | ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1; | 912 | (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; |
913 | ucontrol->value.integer.value[1] = | ||
914 | (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; | ||
883 | return 0; | 915 | return 0; |
884 | } | 916 | } |
885 | 917 | ||
886 | static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 918 | static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
887 | { | 919 | { |
888 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 920 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
921 | struct aureon_spec *spec = ice->spec; | ||
889 | int change = 0, i; | 922 | int change = 0, i; |
890 | 923 | ||
891 | snd_ice1712_save_gpio_status(ice); | 924 | snd_ice1712_save_gpio_status(ice); |
892 | for (i = 0; i < 2; i++) { | 925 | for (i = 0; i < 2; i++) { |
893 | int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1; | 926 | int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; |
894 | if (ucontrol->value.integer.value[i] != val) { | 927 | if (ucontrol->value.integer.value[i] != val) { |
895 | int dac; | 928 | int dac; |
896 | ice->spec.aureon.master[i] &= ~WM_VOL_MUTE; | 929 | spec->master[i] &= ~WM_VOL_MUTE; |
897 | ice->spec.aureon.master[i] |= | 930 | spec->master[i] |= |
898 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | 931 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; |
899 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | 932 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) |
900 | wm_set_vol(ice, WM_DAC_ATTEN + dac + i, | 933 | wm_set_vol(ice, WM_DAC_ATTEN + dac + i, |
901 | ice->spec.aureon.vol[dac + i], | 934 | spec->vol[dac + i], |
902 | ice->spec.aureon.master[i]); | 935 | spec->master[i]); |
903 | change = 1; | 936 | change = 1; |
904 | } | 937 | } |
905 | } | 938 | } |
@@ -940,8 +973,10 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
940 | unsigned short ovol, nvol; | 973 | unsigned short ovol, nvol; |
941 | int change = 0; | 974 | int change = 0; |
942 | 975 | ||
943 | snd_ice1712_save_gpio_status(ice); | ||
944 | nvol = ucontrol->value.integer.value[0]; | 976 | nvol = ucontrol->value.integer.value[0]; |
977 | if (nvol > PCM_RES) | ||
978 | return -EINVAL; | ||
979 | snd_ice1712_save_gpio_status(ice); | ||
945 | nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; | 980 | nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; |
946 | ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | 981 | ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; |
947 | if (ovol != nvol) { | 982 | if (ovol != nvol) { |
@@ -1031,7 +1066,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
1031 | snd_ice1712_save_gpio_status(ice); | 1066 | snd_ice1712_save_gpio_status(ice); |
1032 | for (i = 0; i < 2; i++) { | 1067 | for (i = 0; i < 2; i++) { |
1033 | idx = WM_ADC_GAIN + i; | 1068 | idx = WM_ADC_GAIN + i; |
1034 | nvol = ucontrol->value.integer.value[i]; | 1069 | nvol = ucontrol->value.integer.value[i] & 0x1f; |
1035 | ovol = wm_get(ice, idx); | 1070 | ovol = wm_get(ice, idx); |
1036 | if ((ovol & 0x1f) != nvol) { | 1071 | if ((ovol & 0x1f) != nvol) { |
1037 | wm_put(ice, idx, nvol | (ovol & ~0x1f)); | 1072 | wm_put(ice, idx, nvol | (ovol & ~0x1f)); |
@@ -1143,10 +1178,11 @@ static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1143 | static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1178 | static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1144 | { | 1179 | { |
1145 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1180 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1181 | struct aureon_spec *spec = ice->spec; | ||
1146 | 1182 | ||
1147 | //snd_ice1712_save_gpio_status(ice); | 1183 | //snd_ice1712_save_gpio_status(ice); |
1148 | //val = aureon_cs8415_get(ice, CS8415_CTRL2); | 1184 | //val = aureon_cs8415_get(ice, CS8415_CTRL2); |
1149 | ucontrol->value.enumerated.item[0] = ice->spec.aureon.cs8415_mux; | 1185 | ucontrol->value.enumerated.item[0] = spec->cs8415_mux; |
1150 | //snd_ice1712_restore_gpio_status(ice); | 1186 | //snd_ice1712_restore_gpio_status(ice); |
1151 | return 0; | 1187 | return 0; |
1152 | } | 1188 | } |
@@ -1154,6 +1190,7 @@ static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1154 | static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1190 | static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1155 | { | 1191 | { |
1156 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 1192 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
1193 | struct aureon_spec *spec = ice->spec; | ||
1157 | unsigned short oval, nval; | 1194 | unsigned short oval, nval; |
1158 | int change; | 1195 | int change; |
1159 | 1196 | ||
@@ -1165,7 +1202,7 @@ static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1165 | if (change) | 1202 | if (change) |
1166 | aureon_cs8415_put(ice, CS8415_CTRL2, nval); | 1203 | aureon_cs8415_put(ice, CS8415_CTRL2, nval); |
1167 | snd_ice1712_restore_gpio_status(ice); | 1204 | snd_ice1712_restore_gpio_status(ice); |
1168 | ice->spec.aureon.cs8415_mux = ucontrol->value.enumerated.item[0]; | 1205 | spec->cs8415_mux = ucontrol->value.enumerated.item[0]; |
1169 | return change; | 1206 | return change; |
1170 | } | 1207 | } |
1171 | 1208 | ||
@@ -2001,10 +2038,16 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
2001 | 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ | 2038 | 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ |
2002 | (unsigned short)-1 | 2039 | (unsigned short)-1 |
2003 | }; | 2040 | }; |
2041 | struct aureon_spec *spec; | ||
2004 | unsigned int tmp; | 2042 | unsigned int tmp; |
2005 | const unsigned short *p; | 2043 | const unsigned short *p; |
2006 | int err, i; | 2044 | int err, i; |
2007 | 2045 | ||
2046 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
2047 | if (!spec) | ||
2048 | return -ENOMEM; | ||
2049 | ice->spec = spec; | ||
2050 | |||
2008 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { | 2051 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { |
2009 | ice->num_total_dacs = 6; | 2052 | ice->num_total_dacs = 6; |
2010 | ice->num_total_adcs = 2; | 2053 | ice->num_total_adcs = 2; |
@@ -2055,7 +2098,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
2055 | ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { | 2098 | ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { |
2056 | for (p = cs_inits; *p != (unsigned short)-1; p++) | 2099 | for (p = cs_inits; *p != (unsigned short)-1; p++) |
2057 | aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); | 2100 | aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); |
2058 | ice->spec.aureon.cs8415_mux = 1; | 2101 | spec->cs8415_mux = 1; |
2059 | 2102 | ||
2060 | aureon_set_headphone_amp(ice, 1); | 2103 | aureon_set_headphone_amp(ice, 1); |
2061 | } | 2104 | } |
@@ -2066,11 +2109,11 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
2066 | aureon_pca9554_write(ice, PCA9554_DIR, 0x00); | 2109 | aureon_pca9554_write(ice, PCA9554_DIR, 0x00); |
2067 | aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ | 2110 | aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ |
2068 | 2111 | ||
2069 | ice->spec.aureon.master[0] = WM_VOL_MUTE; | 2112 | spec->master[0] = WM_VOL_MUTE; |
2070 | ice->spec.aureon.master[1] = WM_VOL_MUTE; | 2113 | spec->master[1] = WM_VOL_MUTE; |
2071 | for (i = 0; i < ice->num_total_dacs; i++) { | 2114 | for (i = 0; i < ice->num_total_dacs; i++) { |
2072 | ice->spec.aureon.vol[i] = WM_VOL_MUTE; | 2115 | spec->vol[i] = WM_VOL_MUTE; |
2073 | wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]); | 2116 | wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); |
2074 | } | 2117 | } |
2075 | 2118 | ||
2076 | return 0; | 2119 | return 0; |
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 371f78461db4..efd180b40e56 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <sound/driver.h> | ||
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
@@ -405,7 +404,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco | |||
405 | if (snd_i2c_sendbytes(ice->cs8427, ®, 1) != 1) | 404 | if (snd_i2c_sendbytes(ice->cs8427, ®, 1) != 1) |
406 | snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); | 405 | snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); |
407 | snd_i2c_readbytes(ice->cs8427, ®, 1); | 406 | snd_i2c_readbytes(ice->cs8427, ®, 1); |
408 | ucontrol->value.integer.value[0] = (reg ? 1 : 0); | 407 | ucontrol->value.integer.value[0] = (reg & CS8427_UNLOCK) ? 1 : 0; |
409 | return 0; | 408 | return 0; |
410 | } | 409 | } |
411 | 410 | ||
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 75e4e5e0f1e4..064760d2a027 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <sound/driver.h> | ||
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
@@ -45,6 +44,11 @@ enum { | |||
45 | }; | 44 | }; |
46 | 45 | ||
47 | 46 | ||
47 | /* additional i2c devices for EWS boards */ | ||
48 | struct ews_spec { | ||
49 | struct snd_i2c_device *i2cdevs[3]; | ||
50 | }; | ||
51 | |||
48 | /* | 52 | /* |
49 | * access via i2c mode (for EWX 24/96, EWS 88MT&D) | 53 | * access via i2c mode (for EWX 24/96, EWS 88MT&D) |
50 | */ | 54 | */ |
@@ -142,15 +146,17 @@ static struct snd_i2c_bit_ops snd_ice1712_ewx_cs8427_bit_ops = { | |||
142 | /* AK4524 chip select; address 0x48 bit 0-3 */ | 146 | /* AK4524 chip select; address 0x48 bit 0-3 */ |
143 | static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mask) | 147 | static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mask) |
144 | { | 148 | { |
149 | struct ews_spec *spec = ice->spec; | ||
145 | unsigned char data, ndata; | 150 | unsigned char data, ndata; |
146 | 151 | ||
147 | snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL); | 152 | snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL); |
148 | snd_i2c_lock(ice->i2c); | 153 | snd_i2c_lock(ice->i2c); |
149 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) | 154 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) |
150 | goto __error; | 155 | goto __error; |
151 | ndata = (data & 0xf0) | chip_mask; | 156 | ndata = (data & 0xf0) | chip_mask; |
152 | if (ndata != data) | 157 | if (ndata != data) |
153 | if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &ndata, 1) != 1) | 158 | if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF2], &ndata, 1) |
159 | != 1) | ||
154 | goto __error; | 160 | goto __error; |
155 | snd_i2c_unlock(ice->i2c); | 161 | snd_i2c_unlock(ice->i2c); |
156 | return 0; | 162 | return 0; |
@@ -224,6 +230,7 @@ static void dmx6fire_ak4524_lock(struct snd_akm4xxx *ak, int chip) | |||
224 | 230 | ||
225 | static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned char bits) | 231 | static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned char bits) |
226 | { | 232 | { |
233 | struct ews_spec *spec = ice->spec; | ||
227 | unsigned char bytes[2]; | 234 | unsigned char bytes[2]; |
228 | 235 | ||
229 | snd_i2c_lock(ice->i2c); | 236 | snd_i2c_lock(ice->i2c); |
@@ -231,15 +238,18 @@ static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned | |||
231 | case ICE1712_SUBDEVICE_EWS88MT: | 238 | case ICE1712_SUBDEVICE_EWS88MT: |
232 | case ICE1712_SUBDEVICE_EWS88MT_NEW: | 239 | case ICE1712_SUBDEVICE_EWS88MT_NEW: |
233 | case ICE1712_SUBDEVICE_PHASE88: | 240 | case ICE1712_SUBDEVICE_PHASE88: |
234 | if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_CS8404], &bits, 1) != 1) | 241 | if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1) |
242 | != 1) | ||
235 | goto _error; | 243 | goto _error; |
236 | break; | 244 | break; |
237 | case ICE1712_SUBDEVICE_EWS88D: | 245 | case ICE1712_SUBDEVICE_EWS88D: |
238 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], bytes, 2) != 2) | 246 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], bytes, 2) |
247 | != 2) | ||
239 | goto _error; | 248 | goto _error; |
240 | if (bits != bytes[1]) { | 249 | if (bits != bytes[1]) { |
241 | bytes[1] = bits; | 250 | bytes[1] = bits; |
242 | if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_88D], bytes, 2) != 2) | 251 | if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_88D], |
252 | bytes, 2) != 2) | ||
243 | goto _error; | 253 | goto _error; |
244 | } | 254 | } |
245 | break; | 255 | break; |
@@ -412,6 +422,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) | |||
412 | { | 422 | { |
413 | int err; | 423 | int err; |
414 | struct snd_akm4xxx *ak; | 424 | struct snd_akm4xxx *ak; |
425 | struct ews_spec *spec; | ||
415 | 426 | ||
416 | /* set the analog DACs */ | 427 | /* set the analog DACs */ |
417 | switch (ice->eeprom.subvendor) { | 428 | switch (ice->eeprom.subvendor) { |
@@ -436,6 +447,11 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) | |||
436 | break; | 447 | break; |
437 | } | 448 | } |
438 | 449 | ||
450 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
451 | if (!spec) | ||
452 | return -ENOMEM; | ||
453 | ice->spec = spec; | ||
454 | |||
439 | /* create i2c */ | 455 | /* create i2c */ |
440 | if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { | 456 | if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { |
441 | snd_printk(KERN_ERR "unable to create I2C bus\n"); | 457 | snd_printk(KERN_ERR "unable to create I2C bus\n"); |
@@ -447,7 +463,10 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) | |||
447 | /* create i2c devices */ | 463 | /* create i2c devices */ |
448 | switch (ice->eeprom.subvendor) { | 464 | switch (ice->eeprom.subvendor) { |
449 | case ICE1712_SUBDEVICE_DMX6FIRE: | 465 | case ICE1712_SUBDEVICE_DMX6FIRE: |
450 | if ((err = snd_i2c_device_create(ice->i2c, "PCF9554", ICE1712_6FIRE_PCF9554_ADDR, &ice->spec.i2cdevs[EWS_I2C_6FIRE])) < 0) { | 466 | err = snd_i2c_device_create(ice->i2c, "PCF9554", |
467 | ICE1712_6FIRE_PCF9554_ADDR, | ||
468 | &spec->i2cdevs[EWS_I2C_6FIRE]); | ||
469 | if (err < 0) { | ||
451 | snd_printk(KERN_ERR "PCF9554 initialization failed\n"); | 470 | snd_printk(KERN_ERR "PCF9554 initialization failed\n"); |
452 | return err; | 471 | return err; |
453 | } | 472 | } |
@@ -456,18 +475,30 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) | |||
456 | case ICE1712_SUBDEVICE_EWS88MT: | 475 | case ICE1712_SUBDEVICE_EWS88MT: |
457 | case ICE1712_SUBDEVICE_EWS88MT_NEW: | 476 | case ICE1712_SUBDEVICE_EWS88MT_NEW: |
458 | case ICE1712_SUBDEVICE_PHASE88: | 477 | case ICE1712_SUBDEVICE_PHASE88: |
459 | if ((err = snd_i2c_device_create(ice->i2c, "CS8404", ICE1712_EWS88MT_CS8404_ADDR, &ice->spec.i2cdevs[EWS_I2C_CS8404])) < 0) | 478 | err = snd_i2c_device_create(ice->i2c, "CS8404", |
479 | ICE1712_EWS88MT_CS8404_ADDR, | ||
480 | &spec->i2cdevs[EWS_I2C_CS8404]); | ||
481 | if (err < 0) | ||
460 | return err; | 482 | return err; |
461 | if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", ICE1712_EWS88MT_INPUT_ADDR, &ice->spec.i2cdevs[EWS_I2C_PCF1])) < 0) | 483 | err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", |
484 | ICE1712_EWS88MT_INPUT_ADDR, | ||
485 | &spec->i2cdevs[EWS_I2C_PCF1]); | ||
486 | if (err < 0) | ||
462 | return err; | 487 | return err; |
463 | if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (2nd)", ICE1712_EWS88MT_OUTPUT_ADDR, &ice->spec.i2cdevs[EWS_I2C_PCF2])) < 0) | 488 | err = snd_i2c_device_create(ice->i2c, "PCF8574 (2nd)", |
489 | ICE1712_EWS88MT_OUTPUT_ADDR, | ||
490 | &spec->i2cdevs[EWS_I2C_PCF2]); | ||
491 | if (err < 0) | ||
464 | return err; | 492 | return err; |
465 | /* Check if the front module is connected */ | 493 | /* Check if the front module is connected */ |
466 | if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0) | 494 | if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0) |
467 | return err; | 495 | return err; |
468 | break; | 496 | break; |
469 | case ICE1712_SUBDEVICE_EWS88D: | 497 | case ICE1712_SUBDEVICE_EWS88D: |
470 | if ((err = snd_i2c_device_create(ice->i2c, "PCF8575", ICE1712_EWS88D_PCF_ADDR, &ice->spec.i2cdevs[EWS_I2C_88D])) < 0) | 498 | err = snd_i2c_device_create(ice->i2c, "PCF8575", |
499 | ICE1712_EWS88D_PCF_ADDR, | ||
500 | &spec->i2cdevs[EWS_I2C_88D]); | ||
501 | if (err < 0) | ||
471 | return err; | 502 | return err; |
472 | break; | 503 | break; |
473 | } | 504 | } |
@@ -507,7 +538,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) | |||
507 | } | 538 | } |
508 | 539 | ||
509 | /* analog section */ | 540 | /* analog section */ |
510 | ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); | 541 | ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); |
511 | if (! ak) | 542 | if (! ak) |
512 | return -ENOMEM; | 543 | return -ENOMEM; |
513 | ice->akm_codecs = 1; | 544 | ice->akm_codecs = 1; |
@@ -605,10 +636,11 @@ static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = { | |||
605 | static int snd_ice1712_ews88mt_output_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 636 | static int snd_ice1712_ews88mt_output_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
606 | { | 637 | { |
607 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 638 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
639 | struct ews_spec *spec = ice->spec; | ||
608 | unsigned char data; | 640 | unsigned char data; |
609 | 641 | ||
610 | snd_i2c_lock(ice->i2c); | 642 | snd_i2c_lock(ice->i2c); |
611 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { | 643 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { |
612 | snd_i2c_unlock(ice->i2c); | 644 | snd_i2c_unlock(ice->i2c); |
613 | return -EIO; | 645 | return -EIO; |
614 | } | 646 | } |
@@ -621,15 +653,17 @@ static int snd_ice1712_ews88mt_output_sense_get(struct snd_kcontrol *kcontrol, s | |||
621 | static int snd_ice1712_ews88mt_output_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 653 | static int snd_ice1712_ews88mt_output_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
622 | { | 654 | { |
623 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 655 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
656 | struct ews_spec *spec = ice->spec; | ||
624 | unsigned char data, ndata; | 657 | unsigned char data, ndata; |
625 | 658 | ||
626 | snd_i2c_lock(ice->i2c); | 659 | snd_i2c_lock(ice->i2c); |
627 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { | 660 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { |
628 | snd_i2c_unlock(ice->i2c); | 661 | snd_i2c_unlock(ice->i2c); |
629 | return -EIO; | 662 | return -EIO; |
630 | } | 663 | } |
631 | ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0); | 664 | ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0); |
632 | if (ndata != data && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &ndata, 1) != 1) { | 665 | if (ndata != data && snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF2], |
666 | &ndata, 1) != 1) { | ||
633 | snd_i2c_unlock(ice->i2c); | 667 | snd_i2c_unlock(ice->i2c); |
634 | return -EIO; | 668 | return -EIO; |
635 | } | 669 | } |
@@ -641,12 +675,13 @@ static int snd_ice1712_ews88mt_output_sense_put(struct snd_kcontrol *kcontrol, s | |||
641 | static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 675 | static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
642 | { | 676 | { |
643 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 677 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
678 | struct ews_spec *spec = ice->spec; | ||
644 | int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 679 | int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
645 | unsigned char data; | 680 | unsigned char data; |
646 | 681 | ||
647 | snd_assert(channel >= 0 && channel <= 7, return 0); | 682 | snd_assert(channel >= 0 && channel <= 7, return 0); |
648 | snd_i2c_lock(ice->i2c); | 683 | snd_i2c_lock(ice->i2c); |
649 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { | 684 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { |
650 | snd_i2c_unlock(ice->i2c); | 685 | snd_i2c_unlock(ice->i2c); |
651 | return -EIO; | 686 | return -EIO; |
652 | } | 687 | } |
@@ -660,17 +695,19 @@ static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, st | |||
660 | static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 695 | static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
661 | { | 696 | { |
662 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 697 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
698 | struct ews_spec *spec = ice->spec; | ||
663 | int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 699 | int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
664 | unsigned char data, ndata; | 700 | unsigned char data, ndata; |
665 | 701 | ||
666 | snd_assert(channel >= 0 && channel <= 7, return 0); | 702 | snd_assert(channel >= 0 && channel <= 7, return 0); |
667 | snd_i2c_lock(ice->i2c); | 703 | snd_i2c_lock(ice->i2c); |
668 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { | 704 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { |
669 | snd_i2c_unlock(ice->i2c); | 705 | snd_i2c_unlock(ice->i2c); |
670 | return -EIO; | 706 | return -EIO; |
671 | } | 707 | } |
672 | ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel)); | 708 | ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel)); |
673 | if (ndata != data && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &ndata, 1) != 1) { | 709 | if (ndata != data && snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF1], |
710 | &ndata, 1) != 1) { | ||
674 | snd_i2c_unlock(ice->i2c); | 711 | snd_i2c_unlock(ice->i2c); |
675 | return -EIO; | 712 | return -EIO; |
676 | } | 713 | } |
@@ -705,12 +742,13 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = | |||
705 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 742 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
706 | { | 743 | { |
707 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 744 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
745 | struct ews_spec *spec = ice->spec; | ||
708 | int shift = kcontrol->private_value & 0xff; | 746 | int shift = kcontrol->private_value & 0xff; |
709 | int invert = (kcontrol->private_value >> 8) & 1; | 747 | int invert = (kcontrol->private_value >> 8) & 1; |
710 | unsigned char data[2]; | 748 | unsigned char data[2]; |
711 | 749 | ||
712 | snd_i2c_lock(ice->i2c); | 750 | snd_i2c_lock(ice->i2c); |
713 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) { | 751 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { |
714 | snd_i2c_unlock(ice->i2c); | 752 | snd_i2c_unlock(ice->i2c); |
715 | return -EIO; | 753 | return -EIO; |
716 | } | 754 | } |
@@ -725,13 +763,14 @@ static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct | |||
725 | static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 763 | static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
726 | { | 764 | { |
727 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 765 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
766 | struct ews_spec *spec = ice->spec; | ||
728 | int shift = kcontrol->private_value & 0xff; | 767 | int shift = kcontrol->private_value & 0xff; |
729 | int invert = (kcontrol->private_value >> 8) & 1; | 768 | int invert = (kcontrol->private_value >> 8) & 1; |
730 | unsigned char data[2], ndata[2]; | 769 | unsigned char data[2], ndata[2]; |
731 | int change; | 770 | int change; |
732 | 771 | ||
733 | snd_i2c_lock(ice->i2c); | 772 | snd_i2c_lock(ice->i2c); |
734 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) { | 773 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { |
735 | snd_i2c_unlock(ice->i2c); | 774 | snd_i2c_unlock(ice->i2c); |
736 | return -EIO; | 775 | return -EIO; |
737 | } | 776 | } |
@@ -744,7 +783,8 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct | |||
744 | ndata[shift >> 3] |= (1 << (shift & 7)); | 783 | ndata[shift >> 3] |= (1 << (shift & 7)); |
745 | } | 784 | } |
746 | change = (data[shift >> 3] != ndata[shift >> 3]); | 785 | change = (data[shift >> 3] != ndata[shift >> 3]); |
747 | if (change && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) { | 786 | if (change && |
787 | snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { | ||
748 | snd_i2c_unlock(ice->i2c); | 788 | snd_i2c_unlock(ice->i2c); |
749 | return -EIO; | 789 | return -EIO; |
750 | } | 790 | } |
@@ -778,11 +818,13 @@ static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { | |||
778 | static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg) | 818 | static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg) |
779 | { | 819 | { |
780 | unsigned char byte; | 820 | unsigned char byte; |
821 | struct ews_spec *spec = ice->spec; | ||
822 | |||
781 | snd_i2c_lock(ice->i2c); | 823 | snd_i2c_lock(ice->i2c); |
782 | byte = reg; | 824 | byte = reg; |
783 | snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], &byte, 1); | 825 | snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1); |
784 | byte = 0; | 826 | byte = 0; |
785 | if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) { | 827 | if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) { |
786 | snd_i2c_unlock(ice->i2c); | 828 | snd_i2c_unlock(ice->i2c); |
787 | printk(KERN_ERR "cannot read pca\n"); | 829 | printk(KERN_ERR "cannot read pca\n"); |
788 | return -EIO; | 830 | return -EIO; |
@@ -794,10 +836,12 @@ static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg | |||
794 | static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data) | 836 | static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data) |
795 | { | 837 | { |
796 | unsigned char bytes[2]; | 838 | unsigned char bytes[2]; |
839 | struct ews_spec *spec = ice->spec; | ||
840 | |||
797 | snd_i2c_lock(ice->i2c); | 841 | snd_i2c_lock(ice->i2c); |
798 | bytes[0] = reg; | 842 | bytes[0] = reg; |
799 | bytes[1] = data; | 843 | bytes[1] = data; |
800 | if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], bytes, 2) != 2) { | 844 | if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], bytes, 2) != 2) { |
801 | snd_i2c_unlock(ice->i2c); | 845 | snd_i2c_unlock(ice->i2c); |
802 | return -EIO; | 846 | return -EIO; |
803 | } | 847 | } |
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index abcfd1da6587..cf5c7c0898fd 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
@@ -34,6 +33,12 @@ | |||
34 | #include "ice1712.h" | 33 | #include "ice1712.h" |
35 | #include "hoontech.h" | 34 | #include "hoontech.h" |
36 | 35 | ||
36 | /* Hoontech-specific setting */ | ||
37 | struct hoontech_spec { | ||
38 | unsigned char boxbits[4]; | ||
39 | unsigned int config; | ||
40 | unsigned short boxconfig[4]; | ||
41 | }; | ||
37 | 42 | ||
38 | static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte) | 43 | static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte) |
39 | { | 44 | { |
@@ -50,169 +55,182 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, un | |||
50 | 55 | ||
51 | static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) | 56 | static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) |
52 | { | 57 | { |
58 | struct hoontech_spec *spec = ice->spec; | ||
53 | mutex_lock(&ice->gpio_mutex); | 59 | mutex_lock(&ice->gpio_mutex); |
54 | ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate); | 60 | ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate); |
55 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); | 61 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); |
56 | mutex_unlock(&ice->gpio_mutex); | 62 | mutex_unlock(&ice->gpio_mutex); |
57 | } | 63 | } |
58 | 64 | ||
59 | static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) | 65 | static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) |
60 | { | 66 | { |
67 | struct hoontech_spec *spec = ice->spec; | ||
61 | mutex_lock(&ice->gpio_mutex); | 68 | mutex_lock(&ice->gpio_mutex); |
62 | ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate); | 69 | ICE1712_STDSP24_3_MUTE(spec->boxbits, activate); |
63 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 70 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); |
64 | mutex_unlock(&ice->gpio_mutex); | 71 | mutex_unlock(&ice->gpio_mutex); |
65 | } | 72 | } |
66 | 73 | ||
67 | static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) | 74 | static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) |
68 | { | 75 | { |
76 | struct hoontech_spec *spec = ice->spec; | ||
69 | mutex_lock(&ice->gpio_mutex); | 77 | mutex_lock(&ice->gpio_mutex); |
70 | ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate); | 78 | ICE1712_STDSP24_3_INSEL(spec->boxbits, activate); |
71 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 79 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); |
72 | mutex_unlock(&ice->gpio_mutex); | 80 | mutex_unlock(&ice->gpio_mutex); |
73 | } | 81 | } |
74 | 82 | ||
75 | static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) | 83 | static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) |
76 | { | 84 | { |
85 | struct hoontech_spec *spec = ice->spec; | ||
86 | |||
77 | mutex_lock(&ice->gpio_mutex); | 87 | mutex_lock(&ice->gpio_mutex); |
78 | 88 | ||
79 | /* select box */ | 89 | /* select box */ |
80 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); | 90 | ICE1712_STDSP24_0_BOX(spec->boxbits, box); |
81 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); | 91 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); |
82 | 92 | ||
83 | /* prepare for write */ | 93 | /* prepare for write */ |
84 | if (chn == 3) | 94 | if (chn == 3) |
85 | ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 0); | 95 | ICE1712_STDSP24_2_CHN4(spec->boxbits, 0); |
86 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, activate); | 96 | ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate); |
87 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 97 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
88 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 98 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); |
89 | 99 | ||
90 | ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1); | 100 | ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); |
91 | ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1); | 101 | ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); |
92 | ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1); | 102 | ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); |
93 | ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1); | 103 | ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); |
94 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]); | 104 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); |
95 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 105 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
96 | udelay(100); | 106 | udelay(100); |
97 | if (chn == 3) { | 107 | if (chn == 3) { |
98 | ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 0); | 108 | ICE1712_STDSP24_2_CHN4(spec->boxbits, 0); |
99 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 109 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
100 | } else { | 110 | } else { |
101 | switch (chn) { | 111 | switch (chn) { |
102 | case 0: ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 0); break; | 112 | case 0: ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break; |
103 | case 1: ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 0); break; | 113 | case 1: ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break; |
104 | case 2: ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 0); break; | 114 | case 2: ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break; |
105 | } | 115 | } |
106 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]); | 116 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); |
107 | } | 117 | } |
108 | udelay(100); | 118 | udelay(100); |
109 | ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1); | 119 | ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); |
110 | ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1); | 120 | ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); |
111 | ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1); | 121 | ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); |
112 | ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1); | 122 | ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); |
113 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]); | 123 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); |
114 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 124 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
115 | udelay(100); | 125 | udelay(100); |
116 | 126 | ||
117 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0); | 127 | ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0); |
118 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 128 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
119 | 129 | ||
120 | mutex_unlock(&ice->gpio_mutex); | 130 | mutex_unlock(&ice->gpio_mutex); |
121 | } | 131 | } |
122 | 132 | ||
123 | static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) | 133 | static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) |
124 | { | 134 | { |
135 | struct hoontech_spec *spec = ice->spec; | ||
136 | |||
125 | mutex_lock(&ice->gpio_mutex); | 137 | mutex_lock(&ice->gpio_mutex); |
126 | 138 | ||
127 | /* select box */ | 139 | /* select box */ |
128 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box); | 140 | ICE1712_STDSP24_0_BOX(spec->boxbits, box); |
129 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]); | 141 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); |
130 | 142 | ||
131 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); | 143 | ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); |
132 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, master); | 144 | ICE1712_STDSP24_2_MIDI1(spec->boxbits, master); |
133 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 145 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
134 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 146 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); |
135 | 147 | ||
136 | udelay(100); | 148 | udelay(100); |
137 | 149 | ||
138 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 0); | 150 | ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0); |
139 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 151 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
140 | 152 | ||
141 | mdelay(10); | 153 | mdelay(10); |
142 | 154 | ||
143 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); | 155 | ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); |
144 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]); | 156 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); |
145 | 157 | ||
146 | mutex_unlock(&ice->gpio_mutex); | 158 | mutex_unlock(&ice->gpio_mutex); |
147 | } | 159 | } |
148 | 160 | ||
149 | static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) | 161 | static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) |
150 | { | 162 | { |
163 | struct hoontech_spec *spec = ice->spec; | ||
151 | mutex_lock(&ice->gpio_mutex); | 164 | mutex_lock(&ice->gpio_mutex); |
152 | ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate); | 165 | ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate); |
153 | snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]); | 166 | snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); |
154 | mutex_unlock(&ice->gpio_mutex); | 167 | mutex_unlock(&ice->gpio_mutex); |
155 | } | 168 | } |
156 | 169 | ||
157 | static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) | 170 | static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) |
158 | { | 171 | { |
172 | struct hoontech_spec *spec; | ||
159 | int box, chn; | 173 | int box, chn; |
160 | 174 | ||
161 | ice->num_total_dacs = 8; | 175 | ice->num_total_dacs = 8; |
162 | ice->num_total_adcs = 8; | 176 | ice->num_total_adcs = 8; |
163 | 177 | ||
164 | ice->spec.hoontech.boxbits[0] = | 178 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
165 | ice->spec.hoontech.boxbits[1] = | 179 | if (!spec) |
166 | ice->spec.hoontech.boxbits[2] = | 180 | return -ENOMEM; |
167 | ice->spec.hoontech.boxbits[3] = 0; /* should be already */ | 181 | ice->spec = spec; |
168 | 182 | ||
169 | ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 0); | 183 | ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0); |
170 | ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 0, 1); | 184 | ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1); |
171 | ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, 0); | 185 | ICE1712_STDSP24_0_BOX(spec->boxbits, 0); |
172 | ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, 0); | 186 | ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0); |
173 | 187 | ||
174 | ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 1); | 188 | ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1); |
175 | ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 1, 1); | 189 | ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1); |
176 | ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1); | 190 | ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); |
177 | ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1); | 191 | ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); |
178 | ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1); | 192 | ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); |
179 | 193 | ||
180 | ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 2); | 194 | ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2); |
181 | ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 2, 1); | 195 | ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1); |
182 | ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1); | 196 | ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); |
183 | ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1); | 197 | ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); |
184 | ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0); | 198 | ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0); |
185 | 199 | ||
186 | ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 3); | 200 | ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3); |
187 | ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 3, 1); | 201 | ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1); |
188 | ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, 0); | 202 | ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0); |
189 | ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, 1); | 203 | ICE1712_STDSP24_3_MUTE(spec->boxbits, 1); |
190 | ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, 0); | 204 | ICE1712_STDSP24_3_INSEL(spec->boxbits, 0); |
191 | 205 | ||
192 | /* let's go - activate only functions in first box */ | 206 | /* let's go - activate only functions in first box */ |
193 | ice->spec.hoontech.config = 0; | 207 | spec->config = 0; |
194 | /* ICE1712_STDSP24_MUTE | | 208 | /* ICE1712_STDSP24_MUTE | |
195 | ICE1712_STDSP24_INSEL | | 209 | ICE1712_STDSP24_INSEL | |
196 | ICE1712_STDSP24_DAREAR; */ | 210 | ICE1712_STDSP24_DAREAR; */ |
197 | ice->spec.hoontech.boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 | | 211 | spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 | |
198 | ICE1712_STDSP24_BOX_CHN2 | | 212 | ICE1712_STDSP24_BOX_CHN2 | |
199 | ICE1712_STDSP24_BOX_CHN3 | | 213 | ICE1712_STDSP24_BOX_CHN3 | |
200 | ICE1712_STDSP24_BOX_CHN4 | | 214 | ICE1712_STDSP24_BOX_CHN4 | |
201 | ICE1712_STDSP24_BOX_MIDI1 | | 215 | ICE1712_STDSP24_BOX_MIDI1 | |
202 | ICE1712_STDSP24_BOX_MIDI2; | 216 | ICE1712_STDSP24_BOX_MIDI2; |
203 | ice->spec.hoontech.boxconfig[1] = | 217 | spec->boxconfig[1] = |
204 | ice->spec.hoontech.boxconfig[2] = | 218 | spec->boxconfig[2] = |
205 | ice->spec.hoontech.boxconfig[3] = 0; | 219 | spec->boxconfig[3] = 0; |
206 | snd_ice1712_stdsp24_darear(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_DAREAR) ? 1 : 0); | 220 | snd_ice1712_stdsp24_darear(ice, |
207 | snd_ice1712_stdsp24_mute(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_MUTE) ? 1 : 0); | 221 | (spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0); |
208 | snd_ice1712_stdsp24_insel(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_INSEL) ? 1 : 0); | 222 | snd_ice1712_stdsp24_mute(ice, |
209 | for (box = 0; box < 4; box++) { | 223 | (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0); |
224 | snd_ice1712_stdsp24_insel(ice, | ||
225 | (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0); | ||
226 | for (box = 0; box < 1; box++) { | ||
227 | if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2) | ||
228 | snd_ice1712_stdsp24_midi2(ice, 1); | ||
210 | for (chn = 0; chn < 4; chn++) | 229 | for (chn = 0; chn < 4; chn++) |
211 | snd_ice1712_stdsp24_box_channel(ice, box, chn, (ice->spec.hoontech.boxconfig[box] & (1 << chn)) ? 1 : 0); | 230 | snd_ice1712_stdsp24_box_channel(ice, box, chn, |
231 | (spec->boxconfig[box] & (1 << chn)) ? 1 : 0); | ||
212 | snd_ice1712_stdsp24_box_midi(ice, box, | 232 | snd_ice1712_stdsp24_box_midi(ice, box, |
213 | (ice->spec.hoontech.boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0); | 233 | (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0); |
214 | if (ice->spec.hoontech.boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2) | ||
215 | snd_ice1712_stdsp24_midi2(ice, 1); | ||
216 | } | 234 | } |
217 | 235 | ||
218 | return 0; | 236 | return 0; |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 052fc3cb3272..df292af67381 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -47,7 +47,6 @@ | |||
47 | */ | 47 | */ |
48 | 48 | ||
49 | 49 | ||
50 | #include <sound/driver.h> | ||
51 | #include <asm/io.h> | 50 | #include <asm/io.h> |
52 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
53 | #include <linux/interrupt.h> | 52 | #include <linux/interrupt.h> |
@@ -2491,6 +2490,7 @@ static int snd_ice1712_free(struct snd_ice1712 *ice) | |||
2491 | pci_release_regions(ice->pci); | 2490 | pci_release_regions(ice->pci); |
2492 | snd_ice1712_akm4xxx_free(ice); | 2491 | snd_ice1712_akm4xxx_free(ice); |
2493 | pci_disable_device(ice->pci); | 2492 | pci_disable_device(ice->pci); |
2493 | kfree(ice->spec); | ||
2494 | kfree(ice); | 2494 | kfree(ice); |
2495 | return 0; | 2495 | return 0; |
2496 | } | 2496 | } |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 58640afa5404..303cffe08bd8 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -366,42 +366,7 @@ struct snd_ice1712 { | |||
366 | struct mutex gpio_mutex; | 366 | struct mutex gpio_mutex; |
367 | 367 | ||
368 | /* other board-specific data */ | 368 | /* other board-specific data */ |
369 | union { | 369 | void *spec; |
370 | /* additional i2c devices for EWS boards */ | ||
371 | struct snd_i2c_device *i2cdevs[3]; | ||
372 | /* AC97 register cache for Aureon */ | ||
373 | struct aureon_spec { | ||
374 | unsigned short stac9744[64]; | ||
375 | unsigned int cs8415_mux; | ||
376 | unsigned short master[2]; | ||
377 | unsigned short vol[8]; | ||
378 | unsigned char pca9554_out; | ||
379 | } aureon; | ||
380 | /* AC97 register cache for Phase28 */ | ||
381 | struct phase28_spec { | ||
382 | unsigned short master[2]; | ||
383 | unsigned short vol[8]; | ||
384 | } phase28; | ||
385 | /* a non-standard I2C device for revo51 */ | ||
386 | struct revo51_spec { | ||
387 | struct snd_i2c_device *dev; | ||
388 | struct snd_pt2258 *pt2258; | ||
389 | } revo51; | ||
390 | /* Hoontech-specific setting */ | ||
391 | struct hoontech_spec { | ||
392 | unsigned char boxbits[4]; | ||
393 | unsigned int config; | ||
394 | unsigned short boxconfig[4]; | ||
395 | } hoontech; | ||
396 | struct { | ||
397 | struct ak4114 *ak4114; | ||
398 | unsigned int analog: 1; | ||
399 | } juli; | ||
400 | struct { | ||
401 | struct ak4114 *ak4114; | ||
402 | } prodigy192; | ||
403 | } spec; | ||
404 | |||
405 | }; | 370 | }; |
406 | 371 | ||
407 | 372 | ||
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 0b0bbb0d96b9..f533850ec6e7 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <sound/driver.h> | ||
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
@@ -48,9 +47,11 @@ | |||
48 | #include "vt1720_mobo.h" | 47 | #include "vt1720_mobo.h" |
49 | #include "pontis.h" | 48 | #include "pontis.h" |
50 | #include "prodigy192.h" | 49 | #include "prodigy192.h" |
50 | #include "prodigy_hifi.h" | ||
51 | #include "juli.h" | 51 | #include "juli.h" |
52 | #include "phase.h" | 52 | #include "phase.h" |
53 | #include "wtm.h" | 53 | #include "wtm.h" |
54 | #include "se.h" | ||
54 | 55 | ||
55 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 56 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
56 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 57 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
@@ -62,9 +63,11 @@ MODULE_SUPPORTED_DEVICE("{" | |||
62 | VT1720_MOBO_DEVICE_DESC | 63 | VT1720_MOBO_DEVICE_DESC |
63 | PONTIS_DEVICE_DESC | 64 | PONTIS_DEVICE_DESC |
64 | PRODIGY192_DEVICE_DESC | 65 | PRODIGY192_DEVICE_DESC |
66 | PRODIGY_HIFI_DEVICE_DESC | ||
65 | JULI_DEVICE_DESC | 67 | JULI_DEVICE_DESC |
66 | PHASE_DEVICE_DESC | 68 | PHASE_DEVICE_DESC |
67 | WTM_DEVICE_DESC | 69 | WTM_DEVICE_DESC |
70 | SE_DEVICE_DESC | ||
68 | "{VIA,VT1720}," | 71 | "{VIA,VT1720}," |
69 | "{VIA,VT1724}," | 72 | "{VIA,VT1724}," |
70 | "{ICEnsemble,Generic ICE1724}," | 73 | "{ICEnsemble,Generic ICE1724}," |
@@ -1929,10 +1932,12 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = { | |||
1929 | snd_vt1724_aureon_cards, | 1932 | snd_vt1724_aureon_cards, |
1930 | snd_vt1720_mobo_cards, | 1933 | snd_vt1720_mobo_cards, |
1931 | snd_vt1720_pontis_cards, | 1934 | snd_vt1720_pontis_cards, |
1935 | snd_vt1724_prodigy_hifi_cards, | ||
1932 | snd_vt1724_prodigy192_cards, | 1936 | snd_vt1724_prodigy192_cards, |
1933 | snd_vt1724_juli_cards, | 1937 | snd_vt1724_juli_cards, |
1934 | snd_vt1724_phase_cards, | 1938 | snd_vt1724_phase_cards, |
1935 | snd_vt1724_wtm_cards, | 1939 | snd_vt1724_wtm_cards, |
1940 | snd_vt1724_se_cards, | ||
1936 | NULL, | 1941 | NULL, |
1937 | }; | 1942 | }; |
1938 | 1943 | ||
@@ -1955,6 +1960,7 @@ unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, | |||
1955 | unsigned char val; | 1960 | unsigned char val; |
1956 | 1961 | ||
1957 | mutex_lock(&ice->i2c_mutex); | 1962 | mutex_lock(&ice->i2c_mutex); |
1963 | wait_i2c_busy(ice); | ||
1958 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); | 1964 | outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); |
1959 | outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); | 1965 | outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); |
1960 | wait_i2c_busy(ice); | 1966 | wait_i2c_busy(ice); |
@@ -2170,6 +2176,7 @@ static int snd_vt1724_free(struct snd_ice1712 *ice) | |||
2170 | pci_release_regions(ice->pci); | 2176 | pci_release_regions(ice->pci); |
2171 | snd_ice1712_akm4xxx_free(ice); | 2177 | snd_ice1712_akm4xxx_free(ice); |
2172 | pci_disable_device(ice->pci); | 2178 | pci_disable_device(ice->pci); |
2179 | kfree(ice->spec); | ||
2173 | kfree(ice); | 2180 | kfree(ice); |
2174 | return 0; | 2181 | return 0; |
2175 | } | 2182 | } |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 1fbe3ef8e60a..e8038c0ceb72 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
@@ -33,6 +32,11 @@ | |||
33 | #include "envy24ht.h" | 32 | #include "envy24ht.h" |
34 | #include "juli.h" | 33 | #include "juli.h" |
35 | 34 | ||
35 | struct juli_spec { | ||
36 | struct ak4114 *ak4114; | ||
37 | unsigned int analog: 1; | ||
38 | }; | ||
39 | |||
36 | /* | 40 | /* |
37 | * chip addresses on I2C bus | 41 | * chip addresses on I2C bus |
38 | */ | 42 | */ |
@@ -138,12 +142,13 @@ static struct snd_akm4xxx akm_juli_dac __devinitdata = { | |||
138 | 142 | ||
139 | static int __devinit juli_add_controls(struct snd_ice1712 *ice) | 143 | static int __devinit juli_add_controls(struct snd_ice1712 *ice) |
140 | { | 144 | { |
145 | struct juli_spec *spec = ice->spec; | ||
141 | int err; | 146 | int err; |
142 | err = snd_ice1712_akm4xxx_build_controls(ice); | 147 | err = snd_ice1712_akm4xxx_build_controls(ice); |
143 | if (err < 0) | 148 | if (err < 0) |
144 | return err; | 149 | return err; |
145 | /* only capture SPDIF over AK4114 */ | 150 | /* only capture SPDIF over AK4114 */ |
146 | err = snd_ak4114_build(ice->spec.juli.ak4114, NULL, | 151 | err = snd_ak4114_build(spec->ak4114, NULL, |
147 | ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 152 | ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
148 | if (err < 0) | 153 | if (err < 0) |
149 | return err; | 154 | return err; |
@@ -167,13 +172,19 @@ static int __devinit juli_init(struct snd_ice1712 *ice) | |||
167 | 0x41, 0x02, 0x2c, 0x00, 0x00 | 172 | 0x41, 0x02, 0x2c, 0x00, 0x00 |
168 | }; | 173 | }; |
169 | int err; | 174 | int err; |
175 | struct juli_spec *spec; | ||
170 | struct snd_akm4xxx *ak; | 176 | struct snd_akm4xxx *ak; |
171 | 177 | ||
178 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
179 | if (!spec) | ||
180 | return -ENOMEM; | ||
181 | ice->spec = spec; | ||
182 | |||
172 | err = snd_ak4114_create(ice->card, | 183 | err = snd_ak4114_create(ice->card, |
173 | juli_ak4114_read, | 184 | juli_ak4114_read, |
174 | juli_ak4114_write, | 185 | juli_ak4114_write, |
175 | ak4114_init_vals, ak4114_init_txcsb, | 186 | ak4114_init_vals, ak4114_init_txcsb, |
176 | ice, &ice->spec.juli.ak4114); | 187 | ice, &spec->ak4114); |
177 | if (err < 0) | 188 | if (err < 0) |
178 | return err; | 189 | return err; |
179 | 190 | ||
@@ -181,12 +192,12 @@ static int __devinit juli_init(struct snd_ice1712 *ice) | |||
181 | /* it seems that the analog doughter board detection does not work | 192 | /* it seems that the analog doughter board detection does not work |
182 | reliably, so force the analog flag; it should be very rare | 193 | reliably, so force the analog flag; it should be very rare |
183 | to use Juli@ without the analog doughter board */ | 194 | to use Juli@ without the analog doughter board */ |
184 | ice->spec.juli.analog = (ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT) ? 0 : 1; | 195 | spec->analog = (ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT) ? 0 : 1; |
185 | #else | 196 | #else |
186 | ice->spec.juli.analog = 1; | 197 | spec->analog = 1; |
187 | #endif | 198 | #endif |
188 | 199 | ||
189 | if (ice->spec.juli.analog) { | 200 | if (spec->analog) { |
190 | printk(KERN_INFO "juli@: analog I/O detected\n"); | 201 | printk(KERN_INFO "juli@: analog I/O detected\n"); |
191 | ice->num_total_dacs = 2; | 202 | ice->num_total_dacs = 2; |
192 | ice->num_total_adcs = 2; | 203 | ice->num_total_adcs = 2; |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 3ac25058bb58..9ab4a9f383cb 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -33,7 +33,6 @@ | |||
33 | * CDTI may be completely blocked by 74HCT125's gate #1 controlled by GPIO 3 | 33 | * CDTI may be completely blocked by 74HCT125's gate #1 controlled by GPIO 3 |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <sound/driver.h> | ||
37 | #include <asm/io.h> | 36 | #include <asm/io.h> |
38 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
39 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
@@ -48,6 +47,12 @@ | |||
48 | #include "phase.h" | 47 | #include "phase.h" |
49 | #include <sound/tlv.h> | 48 | #include <sound/tlv.h> |
50 | 49 | ||
50 | /* AC97 register cache for Phase28 */ | ||
51 | struct phase28_spec { | ||
52 | unsigned short master[2]; | ||
53 | unsigned short vol[8]; | ||
54 | } phase28; | ||
55 | |||
51 | /* WM8770 registers */ | 56 | /* WM8770 registers */ |
52 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ | 57 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ |
53 | #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ | 58 | #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ |
@@ -313,27 +318,32 @@ static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
313 | static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 318 | static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
314 | { | 319 | { |
315 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 320 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
321 | struct phase28_spec *spec = ice->spec; | ||
316 | int i; | 322 | int i; |
317 | for (i=0; i<2; i++) | 323 | for (i=0; i<2; i++) |
318 | ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE; | 324 | ucontrol->value.integer.value[i] = spec->master[i] & ~WM_VOL_MUTE; |
319 | return 0; | 325 | return 0; |
320 | } | 326 | } |
321 | 327 | ||
322 | static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 328 | static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
323 | { | 329 | { |
324 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 330 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
331 | struct phase28_spec *spec = ice->spec; | ||
325 | int ch, change = 0; | 332 | int ch, change = 0; |
326 | 333 | ||
327 | snd_ice1712_save_gpio_status(ice); | 334 | snd_ice1712_save_gpio_status(ice); |
328 | for (ch = 0; ch < 2; ch++) { | 335 | for (ch = 0; ch < 2; ch++) { |
329 | if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) { | 336 | unsigned int vol = ucontrol->value.integer.value[ch]; |
337 | if (vol > WM_VOL_MAX) | ||
338 | continue; | ||
339 | vol |= spec->master[ch] & WM_VOL_MUTE; | ||
340 | if (vol != spec->master[ch]) { | ||
330 | int dac; | 341 | int dac; |
331 | ice->spec.phase28.master[ch] &= WM_VOL_MUTE; | 342 | spec->master[ch] = vol; |
332 | ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch]; | ||
333 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | 343 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) |
334 | wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, | 344 | wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, |
335 | ice->spec.phase28.vol[dac + ch], | 345 | spec->vol[dac + ch], |
336 | ice->spec.phase28.master[ch]); | 346 | spec->master[ch]); |
337 | change = 1; | 347 | change = 1; |
338 | } | 348 | } |
339 | } | 349 | } |
@@ -382,12 +392,18 @@ static int __devinit phase28_init(struct snd_ice1712 *ice) | |||
382 | 392 | ||
383 | unsigned int tmp; | 393 | unsigned int tmp; |
384 | struct snd_akm4xxx *ak; | 394 | struct snd_akm4xxx *ak; |
395 | struct phase28_spec *spec; | ||
385 | const unsigned short *p; | 396 | const unsigned short *p; |
386 | int i; | 397 | int i; |
387 | 398 | ||
388 | ice->num_total_dacs = 8; | 399 | ice->num_total_dacs = 8; |
389 | ice->num_total_adcs = 2; | 400 | ice->num_total_adcs = 2; |
390 | 401 | ||
402 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
403 | if (!spec) | ||
404 | return -ENOMEM; | ||
405 | ice->spec = spec; | ||
406 | |||
391 | // Initialize analog chips | 407 | // Initialize analog chips |
392 | ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); | 408 | ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); |
393 | if (!ak) | 409 | if (!ak) |
@@ -417,11 +433,11 @@ static int __devinit phase28_init(struct snd_ice1712 *ice) | |||
417 | 433 | ||
418 | snd_ice1712_restore_gpio_status(ice); | 434 | snd_ice1712_restore_gpio_status(ice); |
419 | 435 | ||
420 | ice->spec.phase28.master[0] = WM_VOL_MUTE; | 436 | spec->master[0] = WM_VOL_MUTE; |
421 | ice->spec.phase28.master[1] = WM_VOL_MUTE; | 437 | spec->master[1] = WM_VOL_MUTE; |
422 | for (i = 0; i < ice->num_total_dacs; i++) { | 438 | for (i = 0; i < ice->num_total_dacs; i++) { |
423 | ice->spec.phase28.vol[i] = WM_VOL_MUTE; | 439 | spec->vol[i] = WM_VOL_MUTE; |
424 | wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]); | 440 | wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); |
425 | } | 441 | } |
426 | 442 | ||
427 | return 0; | 443 | return 0; |
@@ -443,18 +459,21 @@ static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info * | |||
443 | static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 459 | static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
444 | { | 460 | { |
445 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 461 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
462 | struct phase28_spec *spec = ice->spec; | ||
446 | int i, ofs, voices; | 463 | int i, ofs, voices; |
447 | 464 | ||
448 | voices = kcontrol->private_value >> 8; | 465 | voices = kcontrol->private_value >> 8; |
449 | ofs = kcontrol->private_value & 0xff; | 466 | ofs = kcontrol->private_value & 0xff; |
450 | for (i = 0; i < voices; i++) | 467 | for (i = 0; i < voices; i++) |
451 | ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE; | 468 | ucontrol->value.integer.value[i] = |
469 | spec->vol[ofs+i] & ~WM_VOL_MUTE; | ||
452 | return 0; | 470 | return 0; |
453 | } | 471 | } |
454 | 472 | ||
455 | static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 473 | static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
456 | { | 474 | { |
457 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 475 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
476 | struct phase28_spec *spec = ice->spec; | ||
458 | int i, idx, ofs, voices; | 477 | int i, idx, ofs, voices; |
459 | int change = 0; | 478 | int change = 0; |
460 | 479 | ||
@@ -462,12 +481,16 @@ static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value * | |||
462 | ofs = kcontrol->private_value & 0xff; | 481 | ofs = kcontrol->private_value & 0xff; |
463 | snd_ice1712_save_gpio_status(ice); | 482 | snd_ice1712_save_gpio_status(ice); |
464 | for (i = 0; i < voices; i++) { | 483 | for (i = 0; i < voices; i++) { |
465 | idx = WM_DAC_ATTEN + ofs + i; | 484 | unsigned int vol; |
466 | if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) { | 485 | vol = ucontrol->value.integer.value[i]; |
467 | ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE; | 486 | if (vol > 0x7f) |
468 | ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i]; | 487 | continue; |
469 | wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i], | 488 | vol |= spec->vol[ofs+i] & WM_VOL_MUTE; |
470 | ice->spec.phase28.master[i]); | 489 | if (vol != spec->vol[ofs+i]) { |
490 | spec->vol[ofs+i] = vol; | ||
491 | idx = WM_DAC_ATTEN + ofs + i; | ||
492 | wm_set_vol(ice, idx, spec->vol[ofs+i], | ||
493 | spec->master[i]); | ||
471 | change = 1; | 494 | change = 1; |
472 | } | 495 | } |
473 | } | 496 | } |
@@ -489,19 +512,22 @@ static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info | |||
489 | static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 512 | static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
490 | { | 513 | { |
491 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 514 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
515 | struct phase28_spec *spec = ice->spec; | ||
492 | int voices, ofs, i; | 516 | int voices, ofs, i; |
493 | 517 | ||
494 | voices = kcontrol->private_value >> 8; | 518 | voices = kcontrol->private_value >> 8; |
495 | ofs = kcontrol->private_value & 0xFF; | 519 | ofs = kcontrol->private_value & 0xFF; |
496 | 520 | ||
497 | for (i = 0; i < voices; i++) | 521 | for (i = 0; i < voices; i++) |
498 | ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; | 522 | ucontrol->value.integer.value[i] = |
523 | (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; | ||
499 | return 0; | 524 | return 0; |
500 | } | 525 | } |
501 | 526 | ||
502 | static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 527 | static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
503 | { | 528 | { |
504 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 529 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
530 | struct phase28_spec *spec = ice->spec; | ||
505 | int change = 0, voices, ofs, i; | 531 | int change = 0, voices, ofs, i; |
506 | 532 | ||
507 | voices = kcontrol->private_value >> 8; | 533 | voices = kcontrol->private_value >> 8; |
@@ -509,13 +535,13 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
509 | 535 | ||
510 | snd_ice1712_save_gpio_status(ice); | 536 | snd_ice1712_save_gpio_status(ice); |
511 | for (i = 0; i < voices; i++) { | 537 | for (i = 0; i < voices; i++) { |
512 | int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; | 538 | int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; |
513 | if (ucontrol->value.integer.value[i] != val) { | 539 | if (ucontrol->value.integer.value[i] != val) { |
514 | ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE; | 540 | spec->vol[ofs + i] &= ~WM_VOL_MUTE; |
515 | ice->spec.phase28.vol[ofs + i] |= | 541 | spec->vol[ofs + i] |= |
516 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | 542 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; |
517 | wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i], | 543 | wm_set_vol(ice, ofs + i, spec->vol[ofs + i], |
518 | ice->spec.phase28.master[i]); | 544 | spec->master[i]); |
519 | change = 1; | 545 | change = 1; |
520 | } | 546 | } |
521 | } | 547 | } |
@@ -532,29 +558,33 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
532 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 558 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
533 | { | 559 | { |
534 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 560 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
561 | struct phase28_spec *spec = ice->spec; | ||
535 | 562 | ||
536 | ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1; | 563 | ucontrol->value.integer.value[0] = |
537 | ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1; | 564 | (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; |
565 | ucontrol->value.integer.value[1] = | ||
566 | (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; | ||
538 | return 0; | 567 | return 0; |
539 | } | 568 | } |
540 | 569 | ||
541 | static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 570 | static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
542 | { | 571 | { |
543 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 572 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
573 | struct phase28_spec *spec = ice->spec; | ||
544 | int change = 0, i; | 574 | int change = 0, i; |
545 | 575 | ||
546 | snd_ice1712_save_gpio_status(ice); | 576 | snd_ice1712_save_gpio_status(ice); |
547 | for (i = 0; i < 2; i++) { | 577 | for (i = 0; i < 2; i++) { |
548 | int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1; | 578 | int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; |
549 | if (ucontrol->value.integer.value[i] != val) { | 579 | if (ucontrol->value.integer.value[i] != val) { |
550 | int dac; | 580 | int dac; |
551 | ice->spec.phase28.master[i] &= ~WM_VOL_MUTE; | 581 | spec->master[i] &= ~WM_VOL_MUTE; |
552 | ice->spec.phase28.master[i] |= | 582 | spec->master[i] |= |
553 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | 583 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; |
554 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | 584 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) |
555 | wm_set_vol(ice, WM_DAC_ATTEN + dac + i, | 585 | wm_set_vol(ice, WM_DAC_ATTEN + dac + i, |
556 | ice->spec.phase28.vol[dac + i], | 586 | spec->vol[dac + i], |
557 | ice->spec.phase28.master[i]); | 587 | spec->master[i]); |
558 | change = 1; | 588 | change = 1; |
559 | } | 589 | } |
560 | } | 590 | } |
@@ -595,8 +625,10 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
595 | unsigned short ovol, nvol; | 625 | unsigned short ovol, nvol; |
596 | int change = 0; | 626 | int change = 0; |
597 | 627 | ||
598 | snd_ice1712_save_gpio_status(ice); | ||
599 | nvol = ucontrol->value.integer.value[0]; | 628 | nvol = ucontrol->value.integer.value[0]; |
629 | if (nvol > PCM_RES) | ||
630 | return -EINVAL; | ||
631 | snd_ice1712_save_gpio_status(ice); | ||
600 | nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; | 632 | nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; |
601 | ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | 633 | ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; |
602 | if (ovol != nvol) { | 634 | if (ovol != nvol) { |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index faefd52c1b80..4945c81e8a96 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 4180f9739ecb..48cf40a8f32a 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -54,7 +54,6 @@ | |||
54 | * | 54 | * |
55 | */ | 55 | */ |
56 | 56 | ||
57 | #include <sound/driver.h> | ||
58 | #include <asm/io.h> | 57 | #include <asm/io.h> |
59 | #include <linux/delay.h> | 58 | #include <linux/delay.h> |
60 | #include <linux/interrupt.h> | 59 | #include <linux/interrupt.h> |
@@ -68,6 +67,12 @@ | |||
68 | #include "stac946x.h" | 67 | #include "stac946x.h" |
69 | #include <sound/tlv.h> | 68 | #include <sound/tlv.h> |
70 | 69 | ||
70 | struct prodigy192_spec { | ||
71 | struct ak4114 *ak4114; | ||
72 | /* rate change needs atomic mute/unmute of all dacs*/ | ||
73 | struct mutex mute_mutex; | ||
74 | }; | ||
75 | |||
71 | static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) | 76 | static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) |
72 | { | 77 | { |
73 | snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val); | 78 | snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val); |
@@ -81,6 +86,24 @@ static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) | |||
81 | /* | 86 | /* |
82 | * DAC mute control | 87 | * DAC mute control |
83 | */ | 88 | */ |
89 | |||
90 | /* | ||
91 | * idx = STAC9460 volume register number, mute: 0 = mute, 1 = unmute | ||
92 | */ | ||
93 | static int stac9460_dac_mute(struct snd_ice1712 *ice, int idx, | ||
94 | unsigned char mute) | ||
95 | { | ||
96 | unsigned char new, old; | ||
97 | int change; | ||
98 | old = stac9460_get(ice, idx); | ||
99 | new = (~mute << 7 & 0x80) | (old & ~0x80); | ||
100 | change = (new != old); | ||
101 | if (change) | ||
102 | /*printk ("Volume register 0x%02x: 0x%02x\n", idx, new);*/ | ||
103 | stac9460_put(ice, idx, new); | ||
104 | return change; | ||
105 | } | ||
106 | |||
84 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info | 107 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info |
85 | 108 | ||
86 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 109 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
@@ -101,20 +124,19 @@ static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
101 | static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 124 | static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
102 | { | 125 | { |
103 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | 126 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); |
104 | unsigned char new, old; | 127 | struct prodigy192_spec *spec = ice->spec; |
105 | int idx; | 128 | int idx, change; |
106 | int change; | ||
107 | 129 | ||
108 | if (kcontrol->private_value) | 130 | if (kcontrol->private_value) |
109 | idx = STAC946X_MASTER_VOLUME; | 131 | idx = STAC946X_MASTER_VOLUME; |
110 | else | 132 | else |
111 | idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; | 133 | idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; |
112 | old = stac9460_get(ice, idx); | 134 | /* due to possible conflicts with stac9460_set_rate_val, mutexing */ |
113 | new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80); | 135 | mutex_lock(&spec->mute_mutex); |
114 | change = (new != old); | 136 | /*printk("Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, |
115 | if (change) | 137 | ucontrol->value.integer.value[0]);*/ |
116 | stac9460_put(ice, idx, new); | 138 | change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); |
117 | 139 | mutex_unlock(&spec->mute_mutex); | |
118 | return change; | 140 | return change; |
119 | } | 141 | } |
120 | 142 | ||
@@ -162,6 +184,8 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
162 | ovol = 0x7f - (tmp & 0x7f); | 184 | ovol = 0x7f - (tmp & 0x7f); |
163 | change = (ovol != nvol); | 185 | change = (ovol != nvol); |
164 | if (change) { | 186 | if (change) { |
187 | ovol = (0x7f - nvol) | (tmp & 0x80); | ||
188 | /*printk("DAC Volume: reg 0x%02x: 0x%02x\n", idx, ovol);*/ | ||
165 | stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); | 189 | stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); |
166 | } | 190 | } |
167 | return change; | 191 | return change; |
@@ -241,7 +265,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
241 | 265 | ||
242 | for (i = 0; i < 2; ++i) { | 266 | for (i = 0; i < 2; ++i) { |
243 | reg = STAC946X_MIC_L_VOLUME + i; | 267 | reg = STAC946X_MIC_L_VOLUME + i; |
244 | nvol = ucontrol->value.integer.value[i]; | 268 | nvol = ucontrol->value.integer.value[i] & 0x0f; |
245 | ovol = 0x0f - stac9460_get(ice, reg); | 269 | ovol = 0x0f - stac9460_get(ice, reg); |
246 | change = ((ovol & 0x0f) != nvol); | 270 | change = ((ovol & 0x0f) != nvol); |
247 | if (change) | 271 | if (change) |
@@ -251,121 +275,6 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
251 | return change; | 275 | return change; |
252 | } | 276 | } |
253 | 277 | ||
254 | #if 0 | ||
255 | /* | ||
256 | * Headphone Amplifier | ||
257 | */ | ||
258 | static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) | ||
259 | { | ||
260 | unsigned int tmp, tmp2; | ||
261 | |||
262 | tmp2 = tmp = snd_ice1712_gpio_read(ice); | ||
263 | if (enable) | ||
264 | tmp |= AUREON_HP_SEL; | ||
265 | else | ||
266 | tmp &= ~ AUREON_HP_SEL; | ||
267 | if (tmp != tmp2) { | ||
268 | snd_ice1712_gpio_write(ice, tmp); | ||
269 | return 1; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int aureon_get_headphone_amp(struct snd_ice1712 *ice) | ||
275 | { | ||
276 | unsigned int tmp = snd_ice1712_gpio_read(ice); | ||
277 | |||
278 | return ( tmp & AUREON_HP_SEL )!= 0; | ||
279 | } | ||
280 | |||
281 | #define aureon_bool_info snd_ctl_boolean_mono_info | ||
282 | |||
283 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
284 | { | ||
285 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
286 | |||
287 | ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | |||
292 | static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
293 | { | ||
294 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
295 | |||
296 | return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]); | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Deemphasis | ||
301 | */ | ||
302 | static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
303 | { | ||
304 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
305 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
310 | { | ||
311 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
312 | int temp, temp2; | ||
313 | temp2 = temp = wm_get(ice, WM_DAC_CTRL2); | ||
314 | if (ucontrol->value.integer.value[0]) | ||
315 | temp |= 0xf; | ||
316 | else | ||
317 | temp &= ~0xf; | ||
318 | if (temp != temp2) { | ||
319 | wm_put(ice, WM_DAC_CTRL2, temp); | ||
320 | return 1; | ||
321 | } | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * ADC Oversampling | ||
327 | */ | ||
328 | static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | ||
329 | { | ||
330 | static char *texts[2] = { "128x", "64x" }; | ||
331 | |||
332 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
333 | uinfo->count = 1; | ||
334 | uinfo->value.enumerated.items = 2; | ||
335 | |||
336 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
337 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
338 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
344 | { | ||
345 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
346 | ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
351 | { | ||
352 | int temp, temp2; | ||
353 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
354 | |||
355 | temp2 = temp = wm_get(ice, WM_MASTER); | ||
356 | |||
357 | if (ucontrol->value.enumerated.item[0]) | ||
358 | temp |= 0x8; | ||
359 | else | ||
360 | temp &= ~0x8; | ||
361 | |||
362 | if (temp != temp2) { | ||
363 | wm_put(ice, WM_MASTER, temp); | ||
364 | return 1; | ||
365 | } | ||
366 | return 0; | ||
367 | } | ||
368 | #endif | ||
369 | static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, | 278 | static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, |
370 | struct snd_ctl_elem_info *uinfo) | 279 | struct snd_ctl_elem_info *uinfo) |
371 | { | 280 | { |
@@ -407,6 +316,57 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, | |||
407 | stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); | 316 | stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); |
408 | return change; | 317 | return change; |
409 | } | 318 | } |
319 | /* | ||
320 | * Handler for setting correct codec rate - called when rate change is detected | ||
321 | */ | ||
322 | static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) | ||
323 | { | ||
324 | unsigned char old, new; | ||
325 | int idx; | ||
326 | unsigned char changed[7]; | ||
327 | struct snd_ice1712 *ice = ak->private_data[0]; | ||
328 | struct prodigy192_spec *spec = ice->spec; | ||
329 | |||
330 | if (rate == 0) /* no hint - S/PDIF input is master, simply return */ | ||
331 | return; | ||
332 | else if (rate <= 48000) | ||
333 | new = 0x08; /* 256x, base rate mode */ | ||
334 | else if (rate <= 96000) | ||
335 | new = 0x11; /* 256x, mid rate mode */ | ||
336 | else | ||
337 | new = 0x12; /* 128x, high rate mode */ | ||
338 | old = stac9460_get(ice, STAC946X_MASTER_CLOCKING); | ||
339 | if (old == new) | ||
340 | return; | ||
341 | /* change detected, setting master clock, muting first */ | ||
342 | /* due to possible conflicts with mute controls - mutexing */ | ||
343 | mutex_lock(&spec->mute_mutex); | ||
344 | /* we have to remember current mute status for each DAC */ | ||
345 | for (idx = 0; idx < 7 ; ++idx) | ||
346 | changed[idx] = stac9460_dac_mute(ice, | ||
347 | STAC946X_MASTER_VOLUME + idx, 0); | ||
348 | /*printk("Rate change: %d, new MC: 0x%02x\n", rate, new);*/ | ||
349 | stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); | ||
350 | udelay(10); | ||
351 | /* unmuting - only originally unmuted dacs - | ||
352 | * i.e. those changed when muting */ | ||
353 | for (idx = 0; idx < 7 ; ++idx) { | ||
354 | if (changed[idx]) | ||
355 | stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1); | ||
356 | } | ||
357 | mutex_unlock(&spec->mute_mutex); | ||
358 | } | ||
359 | |||
360 | /* using akm infrastructure for setting rate of the codec */ | ||
361 | static struct snd_akm4xxx akmlike_stac9460 __devinitdata = { | ||
362 | .type = NON_AKM, /* special value */ | ||
363 | .num_adcs = 6, /* not used in any way, just for completeness */ | ||
364 | .num_dacs = 2, | ||
365 | .ops = { | ||
366 | .set_rate_val = stac9460_set_rate_val | ||
367 | } | ||
368 | }; | ||
369 | |||
410 | 370 | ||
411 | static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); | 371 | static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); |
412 | static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); | 372 | static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); |
@@ -483,39 +443,8 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { | |||
483 | .put = stac9460_mic_sw_put, | 443 | .put = stac9460_mic_sw_put, |
484 | 444 | ||
485 | }, | 445 | }, |
486 | #if 0 | ||
487 | { | ||
488 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
489 | .name = "Capture Route", | ||
490 | .info = wm_adc_mux_info, | ||
491 | .get = wm_adc_mux_get, | ||
492 | .put = wm_adc_mux_put, | ||
493 | }, | ||
494 | { | ||
495 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
496 | .name = "Headphone Amplifier Switch", | ||
497 | .info = aureon_bool_info, | ||
498 | .get = aureon_hpamp_get, | ||
499 | .put = aureon_hpamp_put | ||
500 | }, | ||
501 | { | ||
502 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
503 | .name = "DAC Deemphasis Switch", | ||
504 | .info = aureon_bool_info, | ||
505 | .get = aureon_deemp_get, | ||
506 | .put = aureon_deemp_put | ||
507 | }, | ||
508 | { | ||
509 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
510 | .name = "ADC Oversampling", | ||
511 | .info = aureon_oversampling_info, | ||
512 | .get = aureon_oversampling_get, | ||
513 | .put = aureon_oversampling_put | ||
514 | }, | ||
515 | #endif | ||
516 | }; | 446 | }; |
517 | 447 | ||
518 | |||
519 | /* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ | 448 | /* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ |
520 | /* CDTO (pin 32) -- GPIO11 pin 86 | 449 | /* CDTO (pin 32) -- GPIO11 pin 86 |
521 | * CDTI (pin 33) -- GPIO10 pin 77 | 450 | * CDTI (pin 33) -- GPIO10 pin 77 |
@@ -712,16 +641,39 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice) | |||
712 | static const unsigned char ak4114_init_txcsb[] = { | 641 | static const unsigned char ak4114_init_txcsb[] = { |
713 | 0x41, 0x02, 0x2c, 0x00, 0x00 | 642 | 0x41, 0x02, 0x2c, 0x00, 0x00 |
714 | }; | 643 | }; |
644 | struct prodigy192_spec *spec = ice->spec; | ||
715 | 645 | ||
716 | return snd_ak4114_create(ice->card, | 646 | return snd_ak4114_create(ice->card, |
717 | prodigy192_ak4114_read, | 647 | prodigy192_ak4114_read, |
718 | prodigy192_ak4114_write, | 648 | prodigy192_ak4114_write, |
719 | ak4114_init_vals, ak4114_init_txcsb, | 649 | ak4114_init_vals, ak4114_init_txcsb, |
720 | ice, &ice->spec.prodigy192.ak4114); | 650 | ice, &spec->ak4114); |
651 | } | ||
652 | |||
653 | static void stac9460_proc_regs_read(struct snd_info_entry *entry, | ||
654 | struct snd_info_buffer *buffer) | ||
655 | { | ||
656 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | ||
657 | int reg, val; | ||
658 | /* registers 0x0 - 0x14 */ | ||
659 | for (reg = 0; reg <= 0x15; reg++) { | ||
660 | val = stac9460_get(ice, reg); | ||
661 | snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); | ||
662 | } | ||
663 | } | ||
664 | |||
665 | |||
666 | static void stac9460_proc_init(struct snd_ice1712 *ice) | ||
667 | { | ||
668 | struct snd_info_entry *entry; | ||
669 | if (!snd_card_proc_new(ice->card, "stac9460_codec", &entry)) | ||
670 | snd_info_set_text_ops(entry, ice, stac9460_proc_regs_read); | ||
721 | } | 671 | } |
722 | 672 | ||
673 | |||
723 | static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) | 674 | static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) |
724 | { | 675 | { |
676 | struct prodigy192_spec *spec = ice->spec; | ||
725 | unsigned int i; | 677 | unsigned int i; |
726 | int err; | 678 | int err; |
727 | 679 | ||
@@ -731,7 +683,7 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) | |||
731 | if (err < 0) | 683 | if (err < 0) |
732 | return err; | 684 | return err; |
733 | } | 685 | } |
734 | if (ice->spec.prodigy192.ak4114) { | 686 | if (spec->ak4114) { |
735 | /* ak4114 is connected */ | 687 | /* ak4114 is connected */ |
736 | for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) { | 688 | for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) { |
737 | err = snd_ctl_add(ice->card, | 689 | err = snd_ctl_add(ice->card, |
@@ -740,12 +692,13 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) | |||
740 | if (err < 0) | 692 | if (err < 0) |
741 | return err; | 693 | return err; |
742 | } | 694 | } |
743 | err = snd_ak4114_build(ice->spec.prodigy192.ak4114, | 695 | err = snd_ak4114_build(spec->ak4114, |
744 | NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */ | 696 | NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */ |
745 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); | 697 | ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); |
746 | if (err < 0) | 698 | if (err < 0) |
747 | return err; | 699 | return err; |
748 | } | 700 | } |
701 | stac9460_proc_init(ice); | ||
749 | return 0; | 702 | return 0; |
750 | } | 703 | } |
751 | 704 | ||
@@ -778,6 +731,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice) | |||
778 | { | 731 | { |
779 | static const unsigned short stac_inits_prodigy[] = { | 732 | static const unsigned short stac_inits_prodigy[] = { |
780 | STAC946X_RESET, 0, | 733 | STAC946X_RESET, 0, |
734 | STAC946X_MASTER_CLOCKING, 0x11, | ||
781 | /* STAC946X_MASTER_VOLUME, 0, | 735 | /* STAC946X_MASTER_VOLUME, 0, |
782 | STAC946X_LF_VOLUME, 0, | 736 | STAC946X_LF_VOLUME, 0, |
783 | STAC946X_RF_VOLUME, 0, | 737 | STAC946X_RF_VOLUME, 0, |
@@ -789,22 +743,39 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice) | |||
789 | }; | 743 | }; |
790 | const unsigned short *p; | 744 | const unsigned short *p; |
791 | int err = 0; | 745 | int err = 0; |
746 | struct snd_akm4xxx *ak; | ||
747 | struct prodigy192_spec *spec; | ||
792 | 748 | ||
793 | /* prodigy 192 */ | 749 | /* prodigy 192 */ |
794 | ice->num_total_dacs = 6; | 750 | ice->num_total_dacs = 6; |
795 | ice->num_total_adcs = 2; | 751 | ice->num_total_adcs = 2; |
796 | ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */ | 752 | ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */ |
797 | 753 | ||
754 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
755 | if (!spec) | ||
756 | return -ENOMEM; | ||
757 | ice->spec = spec; | ||
758 | mutex_init(&spec->mute_mutex); | ||
759 | |||
798 | /* initialize codec */ | 760 | /* initialize codec */ |
799 | p = stac_inits_prodigy; | 761 | p = stac_inits_prodigy; |
800 | for (; *p != (unsigned short)-1; p += 2) | 762 | for (; *p != (unsigned short)-1; p += 2) |
801 | stac9460_put(ice, p[0], p[1]); | 763 | stac9460_put(ice, p[0], p[1]); |
764 | /* reusing the akm codecs infrastructure, | ||
765 | * for setting rate on stac9460 */ | ||
766 | ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
767 | if (!ak) | ||
768 | return -ENOMEM; | ||
769 | ice->akm_codecs = 1; | ||
770 | err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice); | ||
771 | if (err < 0) | ||
772 | return err; | ||
802 | 773 | ||
803 | /* MI/ODI/O add on card with AK4114 */ | 774 | /* MI/ODI/O add on card with AK4114 */ |
804 | if (prodigy192_miodio_exists(ice)) { | 775 | if (prodigy192_miodio_exists(ice)) { |
805 | err = prodigy192_ak4114_init(ice); | 776 | err = prodigy192_ak4114_init(ice); |
806 | /* from this moment if err = 0 then | 777 | /* from this moment if err = 0 then |
807 | * ice->spec.prodigy192.ak4114 should not be null | 778 | * spec->ak4114 should not be null |
808 | */ | 779 | */ |
809 | snd_printdd("AK4114 initialized with status %d\n", err); | 780 | snd_printdd("AK4114 initialized with status %d\n", err); |
810 | } else | 781 | } else |
@@ -854,6 +825,10 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { | |||
854 | .build_controls = prodigy192_add_controls, | 825 | .build_controls = prodigy192_add_controls, |
855 | .eeprom_size = sizeof(prodigy71_eeprom), | 826 | .eeprom_size = sizeof(prodigy71_eeprom), |
856 | .eeprom_data = prodigy71_eeprom, | 827 | .eeprom_data = prodigy71_eeprom, |
828 | /* the current MPU401 code loops infinitely | ||
829 | * when opening midi device | ||
830 | */ | ||
831 | .no_mpu401 = 1, | ||
857 | }, | 832 | }, |
858 | { } /* terminator */ | 833 | { } /* terminator */ |
859 | }; | 834 | }; |
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c new file mode 100644 index 000000000000..043a93879bd5 --- /dev/null +++ b/sound/pci/ice1712/prodigy_hifi.c | |||
@@ -0,0 +1,1210 @@ | |||
1 | /* | ||
2 | * ALSA driver for ICEnsemble VT1724 (Envy24HT) | ||
3 | * | ||
4 | * Lowlevel functions for Audiotrak Prodigy 7.1 Hifi | ||
5 | * based on pontis.c | ||
6 | * | ||
7 | * Copyright (c) 2007 Julian Scheel <julian@jusst.de> | ||
8 | * Copyright (c) 2007 allank | ||
9 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | |||
28 | #include <asm/io.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/mutex.h> | ||
34 | |||
35 | #include <sound/core.h> | ||
36 | #include <sound/info.h> | ||
37 | #include <sound/tlv.h> | ||
38 | |||
39 | #include "ice1712.h" | ||
40 | #include "envy24ht.h" | ||
41 | #include "prodigy_hifi.h" | ||
42 | |||
43 | struct prodigy_hifi_spec { | ||
44 | unsigned short master[2]; | ||
45 | unsigned short vol[8]; | ||
46 | }; | ||
47 | |||
48 | /* I2C addresses */ | ||
49 | #define WM_DEV 0x34 | ||
50 | |||
51 | /* WM8776 registers */ | ||
52 | #define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */ | ||
53 | #define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */ | ||
54 | #define WM_HP_MASTER 0x02 /* headphone master (both channels), | ||
55 | override LLR */ | ||
56 | #define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */ | ||
57 | #define WM_DAC_ATTEN_R 0x04 | ||
58 | #define WM_DAC_MASTER 0x05 | ||
59 | #define WM_PHASE_SWAP 0x06 /* DAC phase swap */ | ||
60 | #define WM_DAC_CTRL1 0x07 | ||
61 | #define WM_DAC_MUTE 0x08 | ||
62 | #define WM_DAC_CTRL2 0x09 | ||
63 | #define WM_DAC_INT 0x0a | ||
64 | #define WM_ADC_INT 0x0b | ||
65 | #define WM_MASTER_CTRL 0x0c | ||
66 | #define WM_POWERDOWN 0x0d | ||
67 | #define WM_ADC_ATTEN_L 0x0e | ||
68 | #define WM_ADC_ATTEN_R 0x0f | ||
69 | #define WM_ALC_CTRL1 0x10 | ||
70 | #define WM_ALC_CTRL2 0x11 | ||
71 | #define WM_ALC_CTRL3 0x12 | ||
72 | #define WM_NOISE_GATE 0x13 | ||
73 | #define WM_LIMITER 0x14 | ||
74 | #define WM_ADC_MUX 0x15 | ||
75 | #define WM_OUT_MUX 0x16 | ||
76 | #define WM_RESET 0x17 | ||
77 | |||
78 | /* Analog Recording Source :- Mic, LineIn, CD/Video, */ | ||
79 | |||
80 | /* implement capture source select control for WM8776 */ | ||
81 | |||
82 | #define WM_AIN1 "AIN1" | ||
83 | #define WM_AIN2 "AIN2" | ||
84 | #define WM_AIN3 "AIN3" | ||
85 | #define WM_AIN4 "AIN4" | ||
86 | #define WM_AIN5 "AIN5" | ||
87 | |||
88 | /* GPIO pins of envy24ht connected to wm8766 */ | ||
89 | #define WM8766_SPI_CLK (1<<17) /* CLK, Pin97 on ICE1724 */ | ||
90 | #define WM8766_SPI_MD (1<<16) /* DATA VT1724 -> WM8766, Pin96 */ | ||
91 | #define WM8766_SPI_ML (1<<18) /* Latch, Pin98 */ | ||
92 | |||
93 | /* WM8766 registers */ | ||
94 | #define WM8766_DAC_CTRL 0x02 /* DAC Control */ | ||
95 | #define WM8766_INT_CTRL 0x03 /* Interface Control */ | ||
96 | #define WM8766_DAC_CTRL2 0x09 | ||
97 | #define WM8766_DAC_CTRL3 0x0a | ||
98 | #define WM8766_RESET 0x1f | ||
99 | #define WM8766_LDA1 0x00 | ||
100 | #define WM8766_LDA2 0x04 | ||
101 | #define WM8766_LDA3 0x06 | ||
102 | #define WM8766_RDA1 0x01 | ||
103 | #define WM8766_RDA2 0x05 | ||
104 | #define WM8766_RDA3 0x07 | ||
105 | #define WM8766_MUTE1 0x0C | ||
106 | #define WM8766_MUTE2 0x0F | ||
107 | |||
108 | |||
109 | /* | ||
110 | * Prodigy HD2 | ||
111 | */ | ||
112 | #define AK4396_ADDR 0x00 | ||
113 | #define AK4396_CSN (1 << 8) /* CSN->GPIO8, pin 75 */ | ||
114 | #define AK4396_CCLK (1 << 9) /* CCLK->GPIO9, pin 76 */ | ||
115 | #define AK4396_CDTI (1 << 10) /* CDTI->GPIO10, pin 77 */ | ||
116 | |||
117 | /* ak4396 registers */ | ||
118 | #define AK4396_CTRL1 0x00 | ||
119 | #define AK4396_CTRL2 0x01 | ||
120 | #define AK4396_CTRL3 0x02 | ||
121 | #define AK4396_LCH_ATT 0x03 | ||
122 | #define AK4396_RCH_ATT 0x04 | ||
123 | |||
124 | |||
125 | /* | ||
126 | * get the current register value of WM codec | ||
127 | */ | ||
128 | static unsigned short wm_get(struct snd_ice1712 *ice, int reg) | ||
129 | { | ||
130 | reg <<= 1; | ||
131 | return ((unsigned short)ice->akm[0].images[reg] << 8) | | ||
132 | ice->akm[0].images[reg + 1]; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * set the register value of WM codec and remember it | ||
137 | */ | ||
138 | static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) | ||
139 | { | ||
140 | unsigned short cval; | ||
141 | cval = (reg << 9) | val; | ||
142 | snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); | ||
143 | } | ||
144 | |||
145 | static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) | ||
146 | { | ||
147 | wm_put_nocache(ice, reg, val); | ||
148 | reg <<= 1; | ||
149 | ice->akm[0].images[reg] = val >> 8; | ||
150 | ice->akm[0].images[reg + 1] = val; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * write data in the SPI mode | ||
155 | */ | ||
156 | |||
157 | static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val) | ||
158 | { | ||
159 | unsigned int tmp = snd_ice1712_gpio_read(ice); | ||
160 | if (val) | ||
161 | tmp |= bit; | ||
162 | else | ||
163 | tmp &= ~bit; | ||
164 | snd_ice1712_gpio_write(ice, tmp); | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * SPI implementation for WM8766 codec - only writing supported, no readback | ||
169 | */ | ||
170 | |||
171 | static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data) | ||
172 | { | ||
173 | int i; | ||
174 | for (i = 0; i < 16; i++) { | ||
175 | set_gpio_bit(ice, WM8766_SPI_CLK, 0); | ||
176 | udelay(1); | ||
177 | set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000); | ||
178 | udelay(1); | ||
179 | set_gpio_bit(ice, WM8766_SPI_CLK, 1); | ||
180 | udelay(1); | ||
181 | data <<= 1; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg, | ||
186 | unsigned int data) | ||
187 | { | ||
188 | unsigned int block; | ||
189 | |||
190 | snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD| | ||
191 | WM8766_SPI_CLK|WM8766_SPI_ML); | ||
192 | snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD| | ||
193 | WM8766_SPI_CLK|WM8766_SPI_ML)); | ||
194 | /* latch must be low when writing */ | ||
195 | set_gpio_bit(ice, WM8766_SPI_ML, 0); | ||
196 | block = (reg << 9) | (data & 0x1ff); | ||
197 | wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */ | ||
198 | /* release latch */ | ||
199 | set_gpio_bit(ice, WM8766_SPI_ML, 1); | ||
200 | udelay(1); | ||
201 | /* restore */ | ||
202 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); | ||
203 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); | ||
204 | } | ||
205 | |||
206 | |||
207 | /* | ||
208 | * serial interface for ak4396 - only writing supported, no readback | ||
209 | */ | ||
210 | |||
211 | static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data) | ||
212 | { | ||
213 | int i; | ||
214 | for (i = 0; i < 16; i++) { | ||
215 | set_gpio_bit(ice, AK4396_CCLK, 0); | ||
216 | udelay(1); | ||
217 | set_gpio_bit(ice, AK4396_CDTI, data & 0x8000); | ||
218 | udelay(1); | ||
219 | set_gpio_bit(ice, AK4396_CCLK, 1); | ||
220 | udelay(1); | ||
221 | data <<= 1; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg, | ||
226 | unsigned int data) | ||
227 | { | ||
228 | unsigned int block; | ||
229 | |||
230 | snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI); | ||
231 | snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI)); | ||
232 | /* latch must be low when writing */ | ||
233 | set_gpio_bit(ice, AK4396_CSN, 0); | ||
234 | block = ((AK4396_ADDR & 0x03) << 14) | (1 << 13) | | ||
235 | ((reg & 0x1f) << 8) | (data & 0xff); | ||
236 | ak4396_send_word(ice, block); /* REGISTER ADDRESS */ | ||
237 | /* release latch */ | ||
238 | set_gpio_bit(ice, AK4396_CSN, 1); | ||
239 | udelay(1); | ||
240 | /* restore */ | ||
241 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); | ||
242 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); | ||
243 | } | ||
244 | |||
245 | |||
246 | /* | ||
247 | * ak4396 mixers | ||
248 | */ | ||
249 | |||
250 | |||
251 | |||
252 | /* | ||
253 | * DAC volume attenuation mixer control (-64dB to 0dB) | ||
254 | */ | ||
255 | |||
256 | static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol, | ||
257 | struct snd_ctl_elem_info *uinfo) | ||
258 | { | ||
259 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
260 | uinfo->count = 2; | ||
261 | uinfo->value.integer.min = 0; /* mute */ | ||
262 | uinfo->value.integer.max = 0xFF; /* linear */ | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol, | ||
267 | struct snd_ctl_elem_value *ucontrol) | ||
268 | { | ||
269 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
270 | struct prodigy_hifi_spec *spec = ice->spec; | ||
271 | int i; | ||
272 | |||
273 | for (i = 0; i < 2; i++) | ||
274 | ucontrol->value.integer.value[i] = spec->vol[i]; | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
280 | { | ||
281 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
282 | struct prodigy_hifi_spec *spec = ice->spec; | ||
283 | int i; | ||
284 | int change = 0; | ||
285 | |||
286 | mutex_lock(&ice->gpio_mutex); | ||
287 | for (i = 0; i < 2; i++) { | ||
288 | if (ucontrol->value.integer.value[i] != spec->vol[i]) { | ||
289 | spec->vol[i] = ucontrol->value.integer.value[i]; | ||
290 | ak4396_write(ice, AK4396_LCH_ATT + i, | ||
291 | spec->vol[i] & 0xff); | ||
292 | change = 1; | ||
293 | } | ||
294 | } | ||
295 | mutex_unlock(&ice->gpio_mutex); | ||
296 | return change; | ||
297 | } | ||
298 | |||
299 | static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); | ||
300 | |||
301 | static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { | ||
302 | { | ||
303 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
304 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
305 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
306 | .name = "Front Playback Volume", | ||
307 | .info = ak4396_dac_vol_info, | ||
308 | .get = ak4396_dac_vol_get, | ||
309 | .put = ak4396_dac_vol_put, | ||
310 | .tlv = { .p = db_scale_wm_dac }, | ||
311 | }, | ||
312 | }; | ||
313 | |||
314 | |||
315 | /* --------------- */ | ||
316 | |||
317 | /* | ||
318 | * Logarithmic volume values for WM87*6 | ||
319 | * Computed as 20 * Log10(255 / x) | ||
320 | */ | ||
321 | static const unsigned char wm_vol[256] = { | ||
322 | 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, | ||
323 | 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, | ||
324 | 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, | ||
325 | 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, | ||
326 | 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, | ||
327 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, | ||
328 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | ||
329 | 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, | ||
330 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | ||
331 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
332 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
333 | 0, 0 | ||
334 | }; | ||
335 | |||
336 | #define WM_VOL_MAX (sizeof(wm_vol) - 1) | ||
337 | #define WM_VOL_MUTE 0x8000 | ||
338 | |||
339 | |||
340 | #define DAC_0dB 0xff | ||
341 | #define DAC_RES 128 | ||
342 | #define DAC_MIN (DAC_0dB - DAC_RES) | ||
343 | |||
344 | |||
345 | static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, | ||
346 | unsigned short vol, unsigned short master) | ||
347 | { | ||
348 | unsigned char nvol; | ||
349 | |||
350 | if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) | ||
351 | nvol = 0; | ||
352 | else { | ||
353 | nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128) | ||
354 | & WM_VOL_MAX; | ||
355 | nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff; | ||
356 | } | ||
357 | |||
358 | wm_put(ice, index, nvol); | ||
359 | wm_put_nocache(ice, index, 0x100 | nvol); | ||
360 | } | ||
361 | |||
362 | static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index, | ||
363 | unsigned short vol, unsigned short master) | ||
364 | { | ||
365 | unsigned char nvol; | ||
366 | |||
367 | if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) | ||
368 | nvol = 0; | ||
369 | else { | ||
370 | nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128) | ||
371 | & WM_VOL_MAX; | ||
372 | nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff; | ||
373 | } | ||
374 | |||
375 | wm8766_spi_write(ice, index, (0x0100 | nvol)); | ||
376 | } | ||
377 | |||
378 | |||
379 | /* | ||
380 | * DAC volume attenuation mixer control (-64dB to 0dB) | ||
381 | */ | ||
382 | |||
383 | static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, | ||
384 | struct snd_ctl_elem_info *uinfo) | ||
385 | { | ||
386 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
387 | uinfo->count = 2; | ||
388 | uinfo->value.integer.min = 0; /* mute */ | ||
389 | uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */ | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, | ||
394 | struct snd_ctl_elem_value *ucontrol) | ||
395 | { | ||
396 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
397 | struct prodigy_hifi_spec *spec = ice->spec; | ||
398 | int i; | ||
399 | |||
400 | for (i = 0; i < 2; i++) | ||
401 | ucontrol->value.integer.value[i] = | ||
402 | spec->vol[2 + i] & ~WM_VOL_MUTE; | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
407 | { | ||
408 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
409 | struct prodigy_hifi_spec *spec = ice->spec; | ||
410 | int i, idx, change = 0; | ||
411 | |||
412 | mutex_lock(&ice->gpio_mutex); | ||
413 | for (i = 0; i < 2; i++) { | ||
414 | if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) { | ||
415 | idx = WM_DAC_ATTEN_L + i; | ||
416 | spec->vol[2 + i] &= WM_VOL_MUTE; | ||
417 | spec->vol[2 + i] |= ucontrol->value.integer.value[i]; | ||
418 | wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]); | ||
419 | change = 1; | ||
420 | } | ||
421 | } | ||
422 | mutex_unlock(&ice->gpio_mutex); | ||
423 | return change; | ||
424 | } | ||
425 | |||
426 | |||
427 | /* | ||
428 | * WM8766 DAC volume attenuation mixer control | ||
429 | */ | ||
430 | static int wm8766_vol_info(struct snd_kcontrol *kcontrol, | ||
431 | struct snd_ctl_elem_info *uinfo) | ||
432 | { | ||
433 | int voices = kcontrol->private_value >> 8; | ||
434 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
435 | uinfo->count = voices; | ||
436 | uinfo->value.integer.min = 0; /* mute */ | ||
437 | uinfo->value.integer.max = DAC_RES; /* 0dB */ | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int wm8766_vol_get(struct snd_kcontrol *kcontrol, | ||
442 | struct snd_ctl_elem_value *ucontrol) | ||
443 | { | ||
444 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
445 | struct prodigy_hifi_spec *spec = ice->spec; | ||
446 | int i, ofs, voices; | ||
447 | |||
448 | voices = kcontrol->private_value >> 8; | ||
449 | ofs = kcontrol->private_value & 0xff; | ||
450 | for (i = 0; i < voices; i++) | ||
451 | ucontrol->value.integer.value[i] = spec->vol[ofs + i]; | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
456 | { | ||
457 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
458 | struct prodigy_hifi_spec *spec = ice->spec; | ||
459 | int i, idx, ofs, voices; | ||
460 | int change = 0; | ||
461 | |||
462 | voices = kcontrol->private_value >> 8; | ||
463 | ofs = kcontrol->private_value & 0xff; | ||
464 | mutex_lock(&ice->gpio_mutex); | ||
465 | for (i = 0; i < voices; i++) { | ||
466 | if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) { | ||
467 | idx = WM8766_LDA1 + ofs + i; | ||
468 | spec->vol[ofs + i] &= WM_VOL_MUTE; | ||
469 | spec->vol[ofs + i] |= ucontrol->value.integer.value[i]; | ||
470 | wm8766_set_vol(ice, idx, | ||
471 | spec->vol[ofs + i], spec->master[i]); | ||
472 | change = 1; | ||
473 | } | ||
474 | } | ||
475 | mutex_unlock(&ice->gpio_mutex); | ||
476 | return change; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Master volume attenuation mixer control / applied to WM8776+WM8766 | ||
481 | */ | ||
482 | static int wm_master_vol_info(struct snd_kcontrol *kcontrol, | ||
483 | struct snd_ctl_elem_info *uinfo) | ||
484 | { | ||
485 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
486 | uinfo->count = 2; | ||
487 | uinfo->value.integer.min = 0; | ||
488 | uinfo->value.integer.max = DAC_RES; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int wm_master_vol_get(struct snd_kcontrol *kcontrol, | ||
493 | struct snd_ctl_elem_value *ucontrol) | ||
494 | { | ||
495 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
496 | struct prodigy_hifi_spec *spec = ice->spec; | ||
497 | int i; | ||
498 | for (i = 0; i < 2; i++) | ||
499 | ucontrol->value.integer.value[i] = spec->master[i]; | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static int wm_master_vol_put(struct snd_kcontrol *kcontrol, | ||
504 | struct snd_ctl_elem_value *ucontrol) | ||
505 | { | ||
506 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
507 | struct prodigy_hifi_spec *spec = ice->spec; | ||
508 | int ch, change = 0; | ||
509 | |||
510 | mutex_lock(&ice->gpio_mutex); | ||
511 | for (ch = 0; ch < 2; ch++) { | ||
512 | if (ucontrol->value.integer.value[ch] != spec->master[ch]) { | ||
513 | spec->master[ch] = ucontrol->value.integer.value[ch]; | ||
514 | |||
515 | /* Apply to front DAC */ | ||
516 | wm_set_vol(ice, WM_DAC_ATTEN_L + ch, | ||
517 | spec->vol[2 + ch], spec->master[ch]); | ||
518 | |||
519 | wm8766_set_vol(ice, WM8766_LDA1 + ch, | ||
520 | spec->vol[0 + ch], spec->master[ch]); | ||
521 | |||
522 | wm8766_set_vol(ice, WM8766_LDA2 + ch, | ||
523 | spec->vol[4 + ch], spec->master[ch]); | ||
524 | |||
525 | wm8766_set_vol(ice, WM8766_LDA3 + ch, | ||
526 | spec->vol[6 + ch], spec->master[ch]); | ||
527 | change = 1; | ||
528 | } | ||
529 | } | ||
530 | mutex_unlock(&ice->gpio_mutex); | ||
531 | return change; | ||
532 | } | ||
533 | |||
534 | |||
535 | /* KONSTI */ | ||
536 | |||
537 | static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
538 | struct snd_ctl_elem_info *uinfo) | ||
539 | { | ||
540 | static char* texts[32] = { | ||
541 | "NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2, | ||
542 | WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3, | ||
543 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN3, | ||
544 | WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4, | ||
545 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN4, | ||
546 | WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4, | ||
547 | WM_AIN2 "+" WM_AIN3 "+" WM_AIN4, | ||
548 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4, | ||
549 | WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5, | ||
550 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN5, | ||
551 | WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5, | ||
552 | WM_AIN2 "+" WM_AIN3 "+" WM_AIN5, | ||
553 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5, | ||
554 | WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5, | ||
555 | WM_AIN2 "+" WM_AIN4 "+" WM_AIN5, | ||
556 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5, | ||
557 | WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, | ||
558 | WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, | ||
559 | WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, | ||
560 | WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5 | ||
561 | }; | ||
562 | |||
563 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
564 | uinfo->count = 1; | ||
565 | uinfo->value.enumerated.items = 32; | ||
566 | if (uinfo->value.enumerated.item > 31) | ||
567 | uinfo->value.enumerated.item = 31; | ||
568 | strcpy(uinfo->value.enumerated.name, | ||
569 | texts[uinfo->value.enumerated.item]); | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
574 | struct snd_ctl_elem_value *ucontrol) | ||
575 | { | ||
576 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
577 | |||
578 | mutex_lock(&ice->gpio_mutex); | ||
579 | ucontrol->value.integer.value[0] = wm_get(ice, WM_ADC_MUX) & 0x1f; | ||
580 | mutex_unlock(&ice->gpio_mutex); | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
585 | struct snd_ctl_elem_value *ucontrol) | ||
586 | { | ||
587 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
588 | unsigned short oval, nval; | ||
589 | int change = 0; | ||
590 | |||
591 | mutex_lock(&ice->gpio_mutex); | ||
592 | oval = wm_get(ice, WM_ADC_MUX); | ||
593 | nval = (oval & 0xe0) | ucontrol->value.integer.value[0]; | ||
594 | if (nval != oval) { | ||
595 | wm_put(ice, WM_ADC_MUX, nval); | ||
596 | change = 1; | ||
597 | } | ||
598 | mutex_unlock(&ice->gpio_mutex); | ||
599 | return change; | ||
600 | } | ||
601 | |||
602 | /* KONSTI */ | ||
603 | |||
604 | /* | ||
605 | * ADC gain mixer control (-64dB to 0dB) | ||
606 | */ | ||
607 | |||
608 | #define ADC_0dB 0xcf | ||
609 | #define ADC_RES 128 | ||
610 | #define ADC_MIN (ADC_0dB - ADC_RES) | ||
611 | |||
612 | static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, | ||
613 | struct snd_ctl_elem_info *uinfo) | ||
614 | { | ||
615 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
616 | uinfo->count = 2; | ||
617 | uinfo->value.integer.min = 0; /* mute (-64dB) */ | ||
618 | uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */ | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, | ||
623 | struct snd_ctl_elem_value *ucontrol) | ||
624 | { | ||
625 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
626 | unsigned short val; | ||
627 | int i; | ||
628 | |||
629 | mutex_lock(&ice->gpio_mutex); | ||
630 | for (i = 0; i < 2; i++) { | ||
631 | val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; | ||
632 | val = val > ADC_MIN ? (val - ADC_MIN) : 0; | ||
633 | ucontrol->value.integer.value[i] = val; | ||
634 | } | ||
635 | mutex_unlock(&ice->gpio_mutex); | ||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, | ||
640 | struct snd_ctl_elem_value *ucontrol) | ||
641 | { | ||
642 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
643 | unsigned short ovol, nvol; | ||
644 | int i, idx, change = 0; | ||
645 | |||
646 | mutex_lock(&ice->gpio_mutex); | ||
647 | for (i = 0; i < 2; i++) { | ||
648 | nvol = ucontrol->value.integer.value[i]; | ||
649 | nvol = nvol ? (nvol + ADC_MIN) : 0; | ||
650 | idx = WM_ADC_ATTEN_L + i; | ||
651 | ovol = wm_get(ice, idx) & 0xff; | ||
652 | if (ovol != nvol) { | ||
653 | wm_put(ice, idx, nvol); | ||
654 | change = 1; | ||
655 | } | ||
656 | } | ||
657 | mutex_unlock(&ice->gpio_mutex); | ||
658 | return change; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * ADC input mux mixer control | ||
663 | */ | ||
664 | #define wm_adc_mux_info snd_ctl_boolean_mono_info | ||
665 | |||
666 | static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, | ||
667 | struct snd_ctl_elem_value *ucontrol) | ||
668 | { | ||
669 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
670 | int bit = kcontrol->private_value; | ||
671 | |||
672 | mutex_lock(&ice->gpio_mutex); | ||
673 | ucontrol->value.integer.value[0] = | ||
674 | (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; | ||
675 | mutex_unlock(&ice->gpio_mutex); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, | ||
680 | struct snd_ctl_elem_value *ucontrol) | ||
681 | { | ||
682 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
683 | int bit = kcontrol->private_value; | ||
684 | unsigned short oval, nval; | ||
685 | int change; | ||
686 | |||
687 | mutex_lock(&ice->gpio_mutex); | ||
688 | nval = oval = wm_get(ice, WM_ADC_MUX); | ||
689 | if (ucontrol->value.integer.value[0]) | ||
690 | nval |= (1 << bit); | ||
691 | else | ||
692 | nval &= ~(1 << bit); | ||
693 | change = nval != oval; | ||
694 | if (change) { | ||
695 | wm_put(ice, WM_ADC_MUX, nval); | ||
696 | } | ||
697 | mutex_unlock(&ice->gpio_mutex); | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | /* | ||
702 | * Analog bypass (In -> Out) | ||
703 | */ | ||
704 | #define wm_bypass_info snd_ctl_boolean_mono_info | ||
705 | |||
706 | static int wm_bypass_get(struct snd_kcontrol *kcontrol, | ||
707 | struct snd_ctl_elem_value *ucontrol) | ||
708 | { | ||
709 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
710 | |||
711 | mutex_lock(&ice->gpio_mutex); | ||
712 | ucontrol->value.integer.value[0] = | ||
713 | (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; | ||
714 | mutex_unlock(&ice->gpio_mutex); | ||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static int wm_bypass_put(struct snd_kcontrol *kcontrol, | ||
719 | struct snd_ctl_elem_value *ucontrol) | ||
720 | { | ||
721 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
722 | unsigned short val, oval; | ||
723 | int change = 0; | ||
724 | |||
725 | mutex_lock(&ice->gpio_mutex); | ||
726 | val = oval = wm_get(ice, WM_OUT_MUX); | ||
727 | if (ucontrol->value.integer.value[0]) | ||
728 | val |= 0x04; | ||
729 | else | ||
730 | val &= ~0x04; | ||
731 | if (val != oval) { | ||
732 | wm_put(ice, WM_OUT_MUX, val); | ||
733 | change = 1; | ||
734 | } | ||
735 | mutex_unlock(&ice->gpio_mutex); | ||
736 | return change; | ||
737 | } | ||
738 | |||
739 | /* | ||
740 | * Left/Right swap | ||
741 | */ | ||
742 | #define wm_chswap_info snd_ctl_boolean_mono_info | ||
743 | |||
744 | static int wm_chswap_get(struct snd_kcontrol *kcontrol, | ||
745 | struct snd_ctl_elem_value *ucontrol) | ||
746 | { | ||
747 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
748 | |||
749 | mutex_lock(&ice->gpio_mutex); | ||
750 | ucontrol->value.integer.value[0] = | ||
751 | (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; | ||
752 | mutex_unlock(&ice->gpio_mutex); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static int wm_chswap_put(struct snd_kcontrol *kcontrol, | ||
757 | struct snd_ctl_elem_value *ucontrol) | ||
758 | { | ||
759 | struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); | ||
760 | unsigned short val, oval; | ||
761 | int change = 0; | ||
762 | |||
763 | mutex_lock(&ice->gpio_mutex); | ||
764 | oval = wm_get(ice, WM_DAC_CTRL1); | ||
765 | val = oval & 0x0f; | ||
766 | if (ucontrol->value.integer.value[0]) | ||
767 | val |= 0x60; | ||
768 | else | ||
769 | val |= 0x90; | ||
770 | if (val != oval) { | ||
771 | wm_put(ice, WM_DAC_CTRL1, val); | ||
772 | wm_put_nocache(ice, WM_DAC_CTRL1, val); | ||
773 | change = 1; | ||
774 | } | ||
775 | mutex_unlock(&ice->gpio_mutex); | ||
776 | return change; | ||
777 | } | ||
778 | |||
779 | |||
780 | /* | ||
781 | * mixers | ||
782 | */ | ||
783 | |||
784 | static struct snd_kcontrol_new prodigy_hifi_controls[] __devinitdata = { | ||
785 | { | ||
786 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
787 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
788 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
789 | .name = "Master Playback Volume", | ||
790 | .info = wm_master_vol_info, | ||
791 | .get = wm_master_vol_get, | ||
792 | .put = wm_master_vol_put, | ||
793 | .tlv = { .p = db_scale_wm_dac } | ||
794 | }, | ||
795 | { | ||
796 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
797 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
798 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
799 | .name = "Front Playback Volume", | ||
800 | .info = wm_dac_vol_info, | ||
801 | .get = wm_dac_vol_get, | ||
802 | .put = wm_dac_vol_put, | ||
803 | .tlv = { .p = db_scale_wm_dac }, | ||
804 | }, | ||
805 | { | ||
806 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
807 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
808 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
809 | .name = "Rear Playback Volume", | ||
810 | .info = wm8766_vol_info, | ||
811 | .get = wm8766_vol_get, | ||
812 | .put = wm8766_vol_put, | ||
813 | .private_value = (2 << 8) | 0, | ||
814 | .tlv = { .p = db_scale_wm_dac }, | ||
815 | }, | ||
816 | { | ||
817 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
818 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
819 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
820 | .name = "Center Playback Volume", | ||
821 | .info = wm8766_vol_info, | ||
822 | .get = wm8766_vol_get, | ||
823 | .put = wm8766_vol_put, | ||
824 | .private_value = (1 << 8) | 4, | ||
825 | .tlv = { .p = db_scale_wm_dac } | ||
826 | }, | ||
827 | { | ||
828 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
829 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
830 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
831 | .name = "LFE Playback Volume", | ||
832 | .info = wm8766_vol_info, | ||
833 | .get = wm8766_vol_get, | ||
834 | .put = wm8766_vol_put, | ||
835 | .private_value = (1 << 8) | 5, | ||
836 | .tlv = { .p = db_scale_wm_dac } | ||
837 | }, | ||
838 | { | ||
839 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
840 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
841 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
842 | .name = "Side Playback Volume", | ||
843 | .info = wm8766_vol_info, | ||
844 | .get = wm8766_vol_get, | ||
845 | .put = wm8766_vol_put, | ||
846 | .private_value = (2 << 8) | 6, | ||
847 | .tlv = { .p = db_scale_wm_dac }, | ||
848 | }, | ||
849 | { | ||
850 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
851 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
852 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | ||
853 | .name = "Capture Volume", | ||
854 | .info = wm_adc_vol_info, | ||
855 | .get = wm_adc_vol_get, | ||
856 | .put = wm_adc_vol_put, | ||
857 | .tlv = { .p = db_scale_wm_dac }, | ||
858 | }, | ||
859 | { | ||
860 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
861 | .name = "CD Capture Switch", | ||
862 | .info = wm_adc_mux_info, | ||
863 | .get = wm_adc_mux_get, | ||
864 | .put = wm_adc_mux_put, | ||
865 | .private_value = 0, | ||
866 | }, | ||
867 | { | ||
868 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
869 | .name = "Line Capture Switch", | ||
870 | .info = wm_adc_mux_info, | ||
871 | .get = wm_adc_mux_get, | ||
872 | .put = wm_adc_mux_put, | ||
873 | .private_value = 1, | ||
874 | }, | ||
875 | { | ||
876 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
877 | .name = "Analog Bypass Switch", | ||
878 | .info = wm_bypass_info, | ||
879 | .get = wm_bypass_get, | ||
880 | .put = wm_bypass_put, | ||
881 | }, | ||
882 | { | ||
883 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
884 | .name = "Swap Output Channels", | ||
885 | .info = wm_chswap_info, | ||
886 | .get = wm_chswap_get, | ||
887 | .put = wm_chswap_put, | ||
888 | }, | ||
889 | { | ||
890 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
891 | .name = "Analog Capture Source", | ||
892 | .info = wm_adc_mux_enum_info, | ||
893 | .get = wm_adc_mux_enum_get, | ||
894 | .put = wm_adc_mux_enum_put, | ||
895 | }, | ||
896 | }; | ||
897 | |||
898 | /* | ||
899 | * WM codec registers | ||
900 | */ | ||
901 | static void wm_proc_regs_write(struct snd_info_entry *entry, | ||
902 | struct snd_info_buffer *buffer) | ||
903 | { | ||
904 | struct snd_ice1712 *ice = entry->private_data; | ||
905 | char line[64]; | ||
906 | unsigned int reg, val; | ||
907 | mutex_lock(&ice->gpio_mutex); | ||
908 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
909 | if (sscanf(line, "%x %x", ®, &val) != 2) | ||
910 | continue; | ||
911 | if (reg <= 0x17 && val <= 0xffff) | ||
912 | wm_put(ice, reg, val); | ||
913 | } | ||
914 | mutex_unlock(&ice->gpio_mutex); | ||
915 | } | ||
916 | |||
917 | static void wm_proc_regs_read(struct snd_info_entry *entry, | ||
918 | struct snd_info_buffer *buffer) | ||
919 | { | ||
920 | struct snd_ice1712 *ice = entry->private_data; | ||
921 | int reg, val; | ||
922 | |||
923 | mutex_lock(&ice->gpio_mutex); | ||
924 | for (reg = 0; reg <= 0x17; reg++) { | ||
925 | val = wm_get(ice, reg); | ||
926 | snd_iprintf(buffer, "%02x = %04x\n", reg, val); | ||
927 | } | ||
928 | mutex_unlock(&ice->gpio_mutex); | ||
929 | } | ||
930 | |||
931 | static void wm_proc_init(struct snd_ice1712 *ice) | ||
932 | { | ||
933 | struct snd_info_entry *entry; | ||
934 | if (!snd_card_proc_new(ice->card, "wm_codec", &entry)) { | ||
935 | snd_info_set_text_ops(entry, ice, wm_proc_regs_read); | ||
936 | entry->mode |= S_IWUSR; | ||
937 | entry->c.text.write = wm_proc_regs_write; | ||
938 | } | ||
939 | } | ||
940 | |||
941 | static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice) | ||
942 | { | ||
943 | unsigned int i; | ||
944 | int err; | ||
945 | |||
946 | for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) { | ||
947 | err = snd_ctl_add(ice->card, | ||
948 | snd_ctl_new1(&prodigy_hifi_controls[i], ice)); | ||
949 | if (err < 0) | ||
950 | return err; | ||
951 | } | ||
952 | |||
953 | wm_proc_init(ice); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice) | ||
959 | { | ||
960 | unsigned int i; | ||
961 | int err; | ||
962 | |||
963 | for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) { | ||
964 | err = snd_ctl_add(ice->card, | ||
965 | snd_ctl_new1(&prodigy_hd2_controls[i], ice)); | ||
966 | if (err < 0) | ||
967 | return err; | ||
968 | } | ||
969 | |||
970 | wm_proc_init(ice); | ||
971 | |||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | |||
976 | /* | ||
977 | * initialize the chip | ||
978 | */ | ||
979 | static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice) | ||
980 | { | ||
981 | static unsigned short wm_inits[] = { | ||
982 | /* These come first to reduce init pop noise */ | ||
983 | WM_ADC_MUX, 0x0003, /* ADC mute */ | ||
984 | /* 0x00c0 replaced by 0x0003 */ | ||
985 | |||
986 | WM_DAC_MUTE, 0x0001, /* DAC softmute */ | ||
987 | WM_DAC_CTRL1, 0x0000, /* DAC mute */ | ||
988 | |||
989 | WM_POWERDOWN, 0x0008, /* All power-up except HP */ | ||
990 | WM_RESET, 0x0000, /* reset */ | ||
991 | }; | ||
992 | static unsigned short wm_inits2[] = { | ||
993 | WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ | ||
994 | WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ | ||
995 | WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ | ||
996 | WM_DAC_CTRL1, 0x0090, /* DAC L/R */ | ||
997 | WM_OUT_MUX, 0x0001, /* OUT DAC */ | ||
998 | WM_HP_ATTEN_L, 0x0179, /* HP 0dB */ | ||
999 | WM_HP_ATTEN_R, 0x0179, /* HP 0dB */ | ||
1000 | WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */ | ||
1001 | WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */ | ||
1002 | WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */ | ||
1003 | WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */ | ||
1004 | WM_PHASE_SWAP, 0x0000, /* phase normal */ | ||
1005 | #if 0 | ||
1006 | WM_DAC_MASTER, 0x0100, /* DAC master muted */ | ||
1007 | #endif | ||
1008 | WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */ | ||
1009 | WM_ADC_ATTEN_L, 0x0000, /* ADC muted */ | ||
1010 | WM_ADC_ATTEN_R, 0x0000, /* ADC muted */ | ||
1011 | #if 1 | ||
1012 | WM_ALC_CTRL1, 0x007b, /* */ | ||
1013 | WM_ALC_CTRL2, 0x0000, /* */ | ||
1014 | WM_ALC_CTRL3, 0x0000, /* */ | ||
1015 | WM_NOISE_GATE, 0x0000, /* */ | ||
1016 | #endif | ||
1017 | WM_DAC_MUTE, 0x0000, /* DAC unmute */ | ||
1018 | WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ | ||
1019 | }; | ||
1020 | static unsigned short wm8766_inits[] = { | ||
1021 | WM8766_RESET, 0x0000, | ||
1022 | WM8766_DAC_CTRL, 0x0120, | ||
1023 | WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */ | ||
1024 | WM8766_DAC_CTRL2, 0x0001, | ||
1025 | WM8766_DAC_CTRL3, 0x0080, | ||
1026 | WM8766_LDA1, 0x0100, | ||
1027 | WM8766_LDA2, 0x0100, | ||
1028 | WM8766_LDA3, 0x0100, | ||
1029 | WM8766_RDA1, 0x0100, | ||
1030 | WM8766_RDA2, 0x0100, | ||
1031 | WM8766_RDA3, 0x0100, | ||
1032 | WM8766_MUTE1, 0x0000, | ||
1033 | WM8766_MUTE2, 0x0000, | ||
1034 | }; | ||
1035 | |||
1036 | struct prodigy_hifi_spec *spec; | ||
1037 | unsigned int i; | ||
1038 | |||
1039 | ice->vt1720 = 0; | ||
1040 | ice->vt1724 = 1; | ||
1041 | |||
1042 | ice->num_total_dacs = 8; | ||
1043 | ice->num_total_adcs = 1; | ||
1044 | |||
1045 | /* HACK - use this as the SPDIF source. | ||
1046 | * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten | ||
1047 | */ | ||
1048 | ice->gpio.saved[0] = 0; | ||
1049 | /* to remeber the register values */ | ||
1050 | |||
1051 | ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
1052 | if (! ice->akm) | ||
1053 | return -ENOMEM; | ||
1054 | ice->akm_codecs = 1; | ||
1055 | |||
1056 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1057 | if (!spec) | ||
1058 | return -ENOMEM; | ||
1059 | ice->spec = spec; | ||
1060 | |||
1061 | /* initialize WM8776 codec */ | ||
1062 | for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) | ||
1063 | wm_put(ice, wm_inits[i], wm_inits[i+1]); | ||
1064 | schedule_timeout_uninterruptible(1); | ||
1065 | for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) | ||
1066 | wm_put(ice, wm_inits2[i], wm_inits2[i+1]); | ||
1067 | |||
1068 | /* initialize WM8766 codec */ | ||
1069 | for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2) | ||
1070 | wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]); | ||
1071 | |||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /* | ||
1078 | * initialize the chip | ||
1079 | */ | ||
1080 | static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | ||
1081 | { | ||
1082 | static unsigned short ak4396_inits[] = { | ||
1083 | AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */ | ||
1084 | AK4396_CTRL2, 0x02, | ||
1085 | AK4396_CTRL3, 0x00, | ||
1086 | AK4396_LCH_ATT, 0x00, | ||
1087 | AK4396_RCH_ATT, 0x00, | ||
1088 | }; | ||
1089 | |||
1090 | struct prodigy_hifi_spec *spec; | ||
1091 | unsigned int i; | ||
1092 | |||
1093 | ice->vt1720 = 0; | ||
1094 | ice->vt1724 = 1; | ||
1095 | |||
1096 | ice->num_total_dacs = 1; | ||
1097 | ice->num_total_adcs = 1; | ||
1098 | |||
1099 | /* HACK - use this as the SPDIF source. | ||
1100 | * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten | ||
1101 | */ | ||
1102 | ice->gpio.saved[0] = 0; | ||
1103 | /* to remeber the register values */ | ||
1104 | |||
1105 | ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); | ||
1106 | if (! ice->akm) | ||
1107 | return -ENOMEM; | ||
1108 | ice->akm_codecs = 1; | ||
1109 | |||
1110 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1111 | if (!spec) | ||
1112 | return -ENOMEM; | ||
1113 | ice->spec = spec; | ||
1114 | |||
1115 | /* initialize ak4396 codec */ | ||
1116 | /* reset codec */ | ||
1117 | ak4396_write(ice, AK4396_CTRL1, 0x86); | ||
1118 | msleep(100); | ||
1119 | ak4396_write(ice, AK4396_CTRL1, 0x87); | ||
1120 | |||
1121 | for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2) | ||
1122 | ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); | ||
1123 | |||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | static unsigned char prodigy71hifi_eeprom[] __devinitdata = { | ||
1129 | 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ | ||
1130 | 0x80, /* ACLINK: I2S */ | ||
1131 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | ||
1132 | 0xc3, /* SPDIF: out-en, out-int, spdif-in */ | ||
1133 | 0xff, /* GPIO_DIR */ | ||
1134 | 0xff, /* GPIO_DIR1 */ | ||
1135 | 0x5f, /* GPIO_DIR2 */ | ||
1136 | 0x00, /* GPIO_MASK */ | ||
1137 | 0x00, /* GPIO_MASK1 */ | ||
1138 | 0x00, /* GPIO_MASK2 */ | ||
1139 | 0x00, /* GPIO_STATE */ | ||
1140 | 0x00, /* GPIO_STATE1 */ | ||
1141 | 0x00, /* GPIO_STATE2 */ | ||
1142 | }; | ||
1143 | |||
1144 | static unsigned char prodigyhd2_eeprom[] __devinitdata = { | ||
1145 | 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ | ||
1146 | 0x80, /* ACLINK: I2S */ | ||
1147 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | ||
1148 | 0xc3, /* SPDIF: out-en, out-int, spdif-in */ | ||
1149 | 0xff, /* GPIO_DIR */ | ||
1150 | 0xff, /* GPIO_DIR1 */ | ||
1151 | 0x5f, /* GPIO_DIR2 */ | ||
1152 | 0x00, /* GPIO_MASK */ | ||
1153 | 0x00, /* GPIO_MASK1 */ | ||
1154 | 0x00, /* GPIO_MASK2 */ | ||
1155 | 0x00, /* GPIO_STATE */ | ||
1156 | 0x00, /* GPIO_STATE1 */ | ||
1157 | 0x00, /* GPIO_STATE2 */ | ||
1158 | }; | ||
1159 | |||
1160 | static unsigned char fortissimo4_eeprom[] __devinitdata = { | ||
1161 | 0x43, /* SYSCONF: clock 512, ADC, 4DACs */ | ||
1162 | 0x80, /* ACLINK: I2S */ | ||
1163 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | ||
1164 | 0xc1, /* SPDIF: out-en, out-int */ | ||
1165 | 0xff, /* GPIO_DIR */ | ||
1166 | 0xff, /* GPIO_DIR1 */ | ||
1167 | 0x5f, /* GPIO_DIR2 */ | ||
1168 | 0x00, /* GPIO_MASK */ | ||
1169 | 0x00, /* GPIO_MASK1 */ | ||
1170 | 0x00, /* GPIO_MASK2 */ | ||
1171 | 0x00, /* GPIO_STATE */ | ||
1172 | 0x00, /* GPIO_STATE1 */ | ||
1173 | 0x00, /* GPIO_STATE2 */ | ||
1174 | }; | ||
1175 | |||
1176 | /* entry point */ | ||
1177 | struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] __devinitdata = { | ||
1178 | { | ||
1179 | .subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI, | ||
1180 | .name = "Audiotrak Prodigy 7.1 HiFi", | ||
1181 | .model = "prodigy71hifi", | ||
1182 | .chip_init = prodigy_hifi_init, | ||
1183 | .build_controls = prodigy_hifi_add_controls, | ||
1184 | .eeprom_size = sizeof(prodigy71hifi_eeprom), | ||
1185 | .eeprom_data = prodigy71hifi_eeprom, | ||
1186 | .driver = "Prodigy71HIFI", | ||
1187 | }, | ||
1188 | { | ||
1189 | .subvendor = VT1724_SUBDEVICE_PRODIGY_HD2, | ||
1190 | .name = "Audiotrak Prodigy HD2", | ||
1191 | .model = "prodigyhd2", | ||
1192 | .chip_init = prodigy_hd2_init, | ||
1193 | .build_controls = prodigy_hd2_add_controls, | ||
1194 | .eeprom_size = sizeof(prodigyhd2_eeprom), | ||
1195 | .eeprom_data = prodigyhd2_eeprom, | ||
1196 | .driver = "Prodigy71HD2", | ||
1197 | }, | ||
1198 | { | ||
1199 | .subvendor = VT1724_SUBDEVICE_FORTISSIMO4, | ||
1200 | .name = "Hercules Fortissimo IV", | ||
1201 | .model = "fortissimo4", | ||
1202 | .chip_init = prodigy_hifi_init, | ||
1203 | .build_controls = prodigy_hifi_add_controls, | ||
1204 | .eeprom_size = sizeof(fortissimo4_eeprom), | ||
1205 | .eeprom_data = fortissimo4_eeprom, | ||
1206 | .driver = "Fortissimo4", | ||
1207 | }, | ||
1208 | { } /* terminator */ | ||
1209 | }; | ||
1210 | |||
diff --git a/sound/pci/ice1712/prodigy_hifi.h b/sound/pci/ice1712/prodigy_hifi.h new file mode 100644 index 000000000000..a4415d455d9e --- /dev/null +++ b/sound/pci/ice1712/prodigy_hifi.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef __SOUND_PRODIGY_HIFI_H | ||
2 | #define __SOUND_PRODIGY_HIFI_H | ||
3 | |||
4 | /* | ||
5 | * ALSA driver for VIA VT1724 (Envy24HT) | ||
6 | * | ||
7 | * Lowlevel functions for Audiotrak Prodigy Hifi | ||
8 | * | ||
9 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #define PRODIGY_HIFI_DEVICE_DESC "{Audiotrak,Prodigy 7.1 HIFI},"\ | ||
28 | "{Audiotrak Prodigy HD2},"\ | ||
29 | "{Hercules Fortissimo IV}," | ||
30 | |||
31 | #define VT1724_SUBDEVICE_PRODIGY_HIFI 0x38315441 /* PRODIGY 7.1 HIFI */ | ||
32 | #define VT1724_SUBDEVICE_PRODIGY_HD2 0x37315441 /* PRODIGY HD2 */ | ||
33 | #define VT1724_SUBDEVICE_FORTISSIMO4 0x81160100 /* Fortissimo IV */ | ||
34 | |||
35 | |||
36 | extern struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[]; | ||
37 | |||
38 | #endif /* __SOUND_PRODIGY_HIFI_H */ | ||
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index d18a31e188a9..ddd5fc8d4fe1 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
@@ -33,6 +32,12 @@ | |||
33 | #include "envy24ht.h" | 32 | #include "envy24ht.h" |
34 | #include "revo.h" | 33 | #include "revo.h" |
35 | 34 | ||
35 | /* a non-standard I2C device for revo51 */ | ||
36 | struct revo51_spec { | ||
37 | struct snd_i2c_device *dev; | ||
38 | struct snd_pt2258 *pt2258; | ||
39 | } revo51; | ||
40 | |||
36 | static void revo_i2s_mclk_changed(struct snd_ice1712 *ice) | 41 | static void revo_i2s_mclk_changed(struct snd_ice1712 *ice) |
37 | { | 42 | { |
38 | /* assert PRST# to converters; MT05 bit 7 */ | 43 | /* assert PRST# to converters; MT05 bit 7 */ |
@@ -153,8 +158,14 @@ static struct snd_i2c_bit_ops revo51_bit_ops = { | |||
153 | static int revo51_i2c_init(struct snd_ice1712 *ice, | 158 | static int revo51_i2c_init(struct snd_ice1712 *ice, |
154 | struct snd_pt2258 *pt) | 159 | struct snd_pt2258 *pt) |
155 | { | 160 | { |
161 | struct revo51_spec *spec; | ||
156 | int err; | 162 | int err; |
157 | 163 | ||
164 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
165 | if (!spec) | ||
166 | return -ENOMEM; | ||
167 | ice->spec = spec; | ||
168 | |||
158 | /* create the I2C bus */ | 169 | /* create the I2C bus */ |
159 | err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c); | 170 | err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c); |
160 | if (err < 0) | 171 | if (err < 0) |
@@ -164,15 +175,14 @@ static int revo51_i2c_init(struct snd_ice1712 *ice, | |||
164 | ice->i2c->hw_ops.bit = &revo51_bit_ops; | 175 | ice->i2c->hw_ops.bit = &revo51_bit_ops; |
165 | 176 | ||
166 | /* create the I2C device */ | 177 | /* create the I2C device */ |
167 | err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40, | 178 | err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40, &spec->dev); |
168 | &ice->spec.revo51.dev); | ||
169 | if (err < 0) | 179 | if (err < 0) |
170 | return err; | 180 | return err; |
171 | 181 | ||
172 | pt->card = ice->card; | 182 | pt->card = ice->card; |
173 | pt->i2c_bus = ice->i2c; | 183 | pt->i2c_bus = ice->i2c; |
174 | pt->i2c_dev = ice->spec.revo51.dev; | 184 | pt->i2c_dev = spec->dev; |
175 | ice->spec.revo51.pt2258 = pt; | 185 | spec->pt2258 = pt; |
176 | 186 | ||
177 | snd_pt2258_reset(pt); | 187 | snd_pt2258_reset(pt); |
178 | 188 | ||
@@ -556,6 +566,7 @@ static int __devinit revo_init(struct snd_ice1712 *ice) | |||
556 | 566 | ||
557 | static int __devinit revo_add_controls(struct snd_ice1712 *ice) | 567 | static int __devinit revo_add_controls(struct snd_ice1712 *ice) |
558 | { | 568 | { |
569 | struct revo51_spec *spec; | ||
559 | int err; | 570 | int err; |
560 | 571 | ||
561 | switch (ice->eeprom.subvendor) { | 572 | switch (ice->eeprom.subvendor) { |
@@ -568,7 +579,8 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice) | |||
568 | err = snd_ice1712_akm4xxx_build_controls(ice); | 579 | err = snd_ice1712_akm4xxx_build_controls(ice); |
569 | if (err < 0) | 580 | if (err < 0) |
570 | return err; | 581 | return err; |
571 | err = snd_pt2258_build_controls(ice->spec.revo51.pt2258); | 582 | spec = ice->spec; |
583 | err = snd_pt2258_build_controls(spec->pt2258); | ||
572 | if (err < 0) | 584 | if (err < 0) |
573 | return err; | 585 | return err; |
574 | break; | 586 | break; |
diff --git a/sound/pci/ice1712/se.c b/sound/pci/ice1712/se.c new file mode 100644 index 000000000000..69673b95869d --- /dev/null +++ b/sound/pci/ice1712/se.c | |||
@@ -0,0 +1,774 @@ | |||
1 | /* | ||
2 | * ALSA driver for ICEnsemble VT1724 (Envy24HT) | ||
3 | * | ||
4 | * Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI | ||
5 | * | ||
6 | * Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp | ||
7 | * (at) -> @ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <asm/io.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/tlv.h> | ||
32 | |||
33 | #include "ice1712.h" | ||
34 | #include "envy24ht.h" | ||
35 | #include "se.h" | ||
36 | |||
37 | struct se_spec { | ||
38 | struct { | ||
39 | unsigned char ch1, ch2; | ||
40 | } vol[8]; | ||
41 | }; | ||
42 | |||
43 | /****************************************************************************/ | ||
44 | /* ONKYO WAVIO SE-200PCI */ | ||
45 | /****************************************************************************/ | ||
46 | /* | ||
47 | * system configuration ICE_EEP2_SYSCONF=0x4b | ||
48 | * XIN1 49.152MHz | ||
49 | * not have UART | ||
50 | * one stereo ADC and a S/PDIF receiver connected | ||
51 | * four stereo DACs connected | ||
52 | * | ||
53 | * AC-Link configuration ICE_EEP2_ACLINK=0x80 | ||
54 | * use I2C, not use AC97 | ||
55 | * | ||
56 | * I2S converters feature ICE_EEP2_I2S=0x78 | ||
57 | * I2S codec has no volume/mute control feature | ||
58 | * I2S codec supports 96KHz and 192KHz | ||
59 | * I2S codec 24bits | ||
60 | * | ||
61 | * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 | ||
62 | * Enable integrated S/PDIF transmitter | ||
63 | * internal S/PDIF out implemented | ||
64 | * S/PDIF is stereo | ||
65 | * External S/PDIF out implemented | ||
66 | * | ||
67 | * | ||
68 | * ** connected chips ** | ||
69 | * | ||
70 | * WM8740 | ||
71 | * A 2ch-DAC of main outputs. | ||
72 | * It setuped as I2S mode by wire, so no way to setup from software. | ||
73 | * The sample-rate are automatically changed. | ||
74 | * ML/I2S (28pin) --------+ | ||
75 | * MC/DM1 (27pin) -- 5V | | ||
76 | * MD/DM0 (26pin) -- GND | | ||
77 | * MUTEB (25pin) -- NC | | ||
78 | * MODE (24pin) -- GND | | ||
79 | * CSBIW (23pin) --------+ | ||
80 | * | | ||
81 | * RSTB (22pin) --R(1K)-+ | ||
82 | * Probably it reduce the noise from the control line. | ||
83 | * | ||
84 | * WM8766 | ||
85 | * A 6ch-DAC for surrounds. | ||
86 | * It's control wire was connected to GPIOxx (3-wire serial interface) | ||
87 | * ML/I2S (11pin) -- GPIO18 | ||
88 | * MC/IWL (12pin) -- GPIO17 | ||
89 | * MD/DM (13pin) -- GPIO16 | ||
90 | * MUTE (14pin) -- GPIO01 | ||
91 | * | ||
92 | * WM8776 | ||
93 | * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC. | ||
94 | * It's control wire was connected to SDA/SCLK (2-wire serial interface) | ||
95 | * MODE (16pin) -- R(1K) -- GND | ||
96 | * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34) | ||
97 | * DI (18pin) -- SDA | ||
98 | * CL (19pin) -- SCLK | ||
99 | * | ||
100 | * | ||
101 | * ** output pins and device names ** | ||
102 | * | ||
103 | * 7.1ch name -- output connector color -- device (-D option) | ||
104 | * | ||
105 | * FRONT 2ch -- green -- plughw:0,0 | ||
106 | * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0 | ||
107 | * SURROUND 2ch -- orange -- plughw:0,2,1 | ||
108 | * SURROUND BACK 2ch -- white -- plughw:0,2,2 | ||
109 | * | ||
110 | */ | ||
111 | |||
112 | |||
113 | /****************************************************************************/ | ||
114 | /* WM8740 interface */ | ||
115 | /****************************************************************************/ | ||
116 | |||
117 | static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice) | ||
118 | { | ||
119 | /* nothing to do */ | ||
120 | } | ||
121 | |||
122 | |||
123 | static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice, | ||
124 | unsigned int rate) | ||
125 | { | ||
126 | /* nothing to do */ | ||
127 | } | ||
128 | |||
129 | |||
130 | /****************************************************************************/ | ||
131 | /* WM8766 interface */ | ||
132 | /****************************************************************************/ | ||
133 | |||
134 | static void se200pci_WM8766_write(struct snd_ice1712 *ice, | ||
135 | unsigned int addr, unsigned int data) | ||
136 | { | ||
137 | unsigned int st; | ||
138 | unsigned int bits; | ||
139 | int i; | ||
140 | const unsigned int DATA = 0x010000; | ||
141 | const unsigned int CLOCK = 0x020000; | ||
142 | const unsigned int LOAD = 0x040000; | ||
143 | const unsigned int ALL_MASK = (DATA | CLOCK | LOAD); | ||
144 | |||
145 | snd_ice1712_save_gpio_status(ice); | ||
146 | |||
147 | st = ((addr & 0x7f) << 9) | (data & 0x1ff); | ||
148 | snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK); | ||
149 | snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK); | ||
150 | bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK; | ||
151 | |||
152 | snd_ice1712_gpio_write(ice, bits); | ||
153 | for (i = 0; i < 16; i++) { | ||
154 | udelay(1); | ||
155 | bits &= ~CLOCK; | ||
156 | st = (st << 1); | ||
157 | if (st & 0x10000) | ||
158 | bits |= DATA; | ||
159 | else | ||
160 | bits &= ~DATA; | ||
161 | |||
162 | snd_ice1712_gpio_write(ice, bits); | ||
163 | |||
164 | udelay(1); | ||
165 | bits |= CLOCK; | ||
166 | snd_ice1712_gpio_write(ice, bits); | ||
167 | } | ||
168 | |||
169 | udelay(1); | ||
170 | bits |= LOAD; | ||
171 | snd_ice1712_gpio_write(ice, bits); | ||
172 | |||
173 | udelay(1); | ||
174 | bits |= (DATA | CLOCK); | ||
175 | snd_ice1712_gpio_write(ice, bits); | ||
176 | |||
177 | snd_ice1712_restore_gpio_status(ice); | ||
178 | } | ||
179 | |||
180 | static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch, | ||
181 | unsigned int vol1, unsigned int vol2) | ||
182 | { | ||
183 | switch (ch) { | ||
184 | case 0: | ||
185 | se200pci_WM8766_write(ice, 0x000, vol1); | ||
186 | se200pci_WM8766_write(ice, 0x001, vol2 | 0x100); | ||
187 | break; | ||
188 | case 1: | ||
189 | se200pci_WM8766_write(ice, 0x004, vol1); | ||
190 | se200pci_WM8766_write(ice, 0x005, vol2 | 0x100); | ||
191 | break; | ||
192 | case 2: | ||
193 | se200pci_WM8766_write(ice, 0x006, vol1); | ||
194 | se200pci_WM8766_write(ice, 0x007, vol2 | 0x100); | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice) | ||
200 | { | ||
201 | se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */ | ||
202 | udelay(10); | ||
203 | |||
204 | se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */ | ||
205 | se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */ | ||
206 | se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */ | ||
207 | |||
208 | se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */ | ||
209 | se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ | ||
210 | se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */ | ||
211 | se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */ | ||
212 | se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */ | ||
213 | |||
214 | se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */ | ||
215 | se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */ | ||
216 | } | ||
217 | |||
218 | static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice, | ||
219 | unsigned int rate) | ||
220 | { | ||
221 | if (rate > 96000) | ||
222 | se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */ | ||
223 | else | ||
224 | se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ | ||
225 | } | ||
226 | |||
227 | |||
228 | /****************************************************************************/ | ||
229 | /* WM8776 interface */ | ||
230 | /****************************************************************************/ | ||
231 | |||
232 | static void se200pci_WM8776_write(struct snd_ice1712 *ice, | ||
233 | unsigned int addr, unsigned int data) | ||
234 | { | ||
235 | unsigned int val; | ||
236 | |||
237 | val = (addr << 9) | data; | ||
238 | snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff); | ||
239 | } | ||
240 | |||
241 | |||
242 | static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice, | ||
243 | unsigned int vol1, unsigned int vol2) | ||
244 | { | ||
245 | se200pci_WM8776_write(ice, 0x03, vol1); | ||
246 | se200pci_WM8776_write(ice, 0x04, vol2 | 0x100); | ||
247 | } | ||
248 | |||
249 | static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice, | ||
250 | unsigned int vol1, unsigned int vol2) | ||
251 | { | ||
252 | se200pci_WM8776_write(ice, 0x0e, vol1); | ||
253 | se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100); | ||
254 | } | ||
255 | |||
256 | static const char *se200pci_sel[] = { | ||
257 | "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL | ||
258 | }; | ||
259 | |||
260 | static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice, | ||
261 | unsigned int sel) | ||
262 | { | ||
263 | static unsigned char vals[] = { | ||
264 | /* LINE, CD, MIC, ALL, GND */ | ||
265 | 0x10, 0x04, 0x08, 0x1c, 0x03 | ||
266 | }; | ||
267 | if (sel > 4) | ||
268 | sel = 4; | ||
269 | se200pci_WM8776_write(ice, 0x15, vals[sel]); | ||
270 | } | ||
271 | |||
272 | static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl) | ||
273 | { | ||
274 | /* AFL -- After Fader Listening */ | ||
275 | if (afl) | ||
276 | se200pci_WM8776_write(ice, 0x16, 0x005); | ||
277 | else | ||
278 | se200pci_WM8776_write(ice, 0x16, 0x001); | ||
279 | } | ||
280 | |||
281 | static const char *se200pci_agc[] = { | ||
282 | "Off", "LimiterMode", "ALCMode", NULL | ||
283 | }; | ||
284 | |||
285 | static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc) | ||
286 | { | ||
287 | /* AGC -- Auto Gain Control of the input */ | ||
288 | switch (agc) { | ||
289 | case 0: | ||
290 | se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */ | ||
291 | break; | ||
292 | case 1: | ||
293 | se200pci_WM8776_write(ice, 0x10, 0x07b); | ||
294 | se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */ | ||
295 | break; | ||
296 | case 2: | ||
297 | se200pci_WM8776_write(ice, 0x10, 0x1fb); | ||
298 | se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */ | ||
299 | break; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice) | ||
304 | { | ||
305 | int i; | ||
306 | static unsigned short __devinitdata default_values[] = { | ||
307 | 0x100, 0x100, 0x100, | ||
308 | 0x100, 0x100, 0x100, | ||
309 | 0x000, 0x090, 0x000, 0x000, | ||
310 | 0x022, 0x022, 0x022, | ||
311 | 0x008, 0x0cf, 0x0cf, 0x07b, 0x000, | ||
312 | 0x032, 0x000, 0x0a6, 0x001, 0x001 | ||
313 | }; | ||
314 | |||
315 | se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */ | ||
316 | /* ADC and DAC interface is I2S 24bits mode */ | ||
317 | /* The sample-rate are automatically changed */ | ||
318 | udelay(10); | ||
319 | /* BUT my board can not do reset all, so I load all by manually. */ | ||
320 | for (i = 0; i < ARRAY_SIZE(default_values); i++) | ||
321 | se200pci_WM8776_write(ice, i, default_values[i]); | ||
322 | |||
323 | se200pci_WM8776_set_input_selector(ice, 0); | ||
324 | se200pci_WM8776_set_afl(ice, 0); | ||
325 | se200pci_WM8776_set_agc(ice, 0); | ||
326 | se200pci_WM8776_set_input_volume(ice, 0, 0); | ||
327 | se200pci_WM8776_set_output_volume(ice, 0, 0); | ||
328 | |||
329 | /* head phone mute and power down */ | ||
330 | se200pci_WM8776_write(ice, 0x00, 0); | ||
331 | se200pci_WM8776_write(ice, 0x01, 0); | ||
332 | se200pci_WM8776_write(ice, 0x02, 0x100); | ||
333 | se200pci_WM8776_write(ice, 0x0d, 0x080); | ||
334 | } | ||
335 | |||
336 | static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice, | ||
337 | unsigned int rate) | ||
338 | { | ||
339 | /* nothing to do */ | ||
340 | } | ||
341 | |||
342 | |||
343 | /****************************************************************************/ | ||
344 | /* runtime interface */ | ||
345 | /****************************************************************************/ | ||
346 | |||
347 | static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate) | ||
348 | { | ||
349 | se200pci_WM8740_set_pro_rate(ice, rate); | ||
350 | se200pci_WM8766_set_pro_rate(ice, rate); | ||
351 | se200pci_WM8776_set_pro_rate(ice, rate); | ||
352 | } | ||
353 | |||
354 | struct se200pci_control { | ||
355 | char *name; | ||
356 | enum { | ||
357 | WM8766, | ||
358 | WM8776in, | ||
359 | WM8776out, | ||
360 | WM8776sel, | ||
361 | WM8776agc, | ||
362 | WM8776afl | ||
363 | } target; | ||
364 | enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type; | ||
365 | int ch; | ||
366 | const char **member; | ||
367 | const char *comment; | ||
368 | }; | ||
369 | |||
370 | static const struct se200pci_control se200pci_cont[] = { | ||
371 | { | ||
372 | .name = "Front Playback Volume", | ||
373 | .target = WM8776out, | ||
374 | .type = VOLUME1, | ||
375 | .comment = "Front(green)" | ||
376 | }, | ||
377 | { | ||
378 | .name = "Side Playback Volume", | ||
379 | .target = WM8766, | ||
380 | .type = VOLUME1, | ||
381 | .ch = 1, | ||
382 | .comment = "Surround(orange)" | ||
383 | }, | ||
384 | { | ||
385 | .name = "Surround Playback Volume", | ||
386 | .target = WM8766, | ||
387 | .type = VOLUME1, | ||
388 | .ch = 2, | ||
389 | .comment = "SurroundBack(white)" | ||
390 | }, | ||
391 | { | ||
392 | .name = "CLFE Playback Volume", | ||
393 | .target = WM8766, | ||
394 | .type = VOLUME1, | ||
395 | .ch = 0, | ||
396 | .comment = "Center(Lch)&SubWoofer(Rch)(black)" | ||
397 | }, | ||
398 | { | ||
399 | .name = "Capture Volume", | ||
400 | .target = WM8776in, | ||
401 | .type = VOLUME2 | ||
402 | }, | ||
403 | { | ||
404 | .name = "Capture Select", | ||
405 | .target = WM8776sel, | ||
406 | .type = ENUM, | ||
407 | .member = se200pci_sel | ||
408 | }, | ||
409 | { | ||
410 | .name = "AGC Capture Mode", | ||
411 | .target = WM8776agc, | ||
412 | .type = ENUM, | ||
413 | .member = se200pci_agc | ||
414 | }, | ||
415 | { | ||
416 | .name = "AFL Bypass Playback Switch", | ||
417 | .target = WM8776afl, | ||
418 | .type = BOOLEAN | ||
419 | } | ||
420 | }; | ||
421 | |||
422 | static int se200pci_get_enum_count(int n) | ||
423 | { | ||
424 | const char **member; | ||
425 | int c; | ||
426 | |||
427 | member = se200pci_cont[n].member; | ||
428 | if (!member) | ||
429 | return 0; | ||
430 | for (c = 0; member[c]; c++) | ||
431 | ; | ||
432 | return c; | ||
433 | } | ||
434 | |||
435 | static int se200pci_cont_volume_info(struct snd_kcontrol *kc, | ||
436 | struct snd_ctl_elem_info *uinfo) | ||
437 | { | ||
438 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
439 | uinfo->count = 2; | ||
440 | uinfo->value.integer.min = 0; /* mute */ | ||
441 | uinfo->value.integer.max = 0xff; /* 0dB */ | ||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | #define se200pci_cont_boolean_info snd_ctl_boolean_mono_info | ||
446 | |||
447 | static int se200pci_cont_enum_info(struct snd_kcontrol *kc, | ||
448 | struct snd_ctl_elem_info *uinfo) | ||
449 | { | ||
450 | int n, c; | ||
451 | |||
452 | n = kc->private_value; | ||
453 | c = se200pci_get_enum_count(n); | ||
454 | if (!c) | ||
455 | return -EINVAL; | ||
456 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
457 | uinfo->count = 1; | ||
458 | uinfo->value.enumerated.items = c; | ||
459 | if (uinfo->value.enumerated.item >= c) | ||
460 | uinfo->value.enumerated.item = c - 1; | ||
461 | strcpy(uinfo->value.enumerated.name, | ||
462 | se200pci_cont[n].member[uinfo->value.enumerated.item]); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int se200pci_cont_volume_get(struct snd_kcontrol *kc, | ||
467 | struct snd_ctl_elem_value *uc) | ||
468 | { | ||
469 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
470 | struct se_spec *spec = ice->spec; | ||
471 | int n = kc->private_value; | ||
472 | uc->value.integer.value[0] = spec->vol[n].ch1; | ||
473 | uc->value.integer.value[1] = spec->vol[n].ch2; | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int se200pci_cont_boolean_get(struct snd_kcontrol *kc, | ||
478 | struct snd_ctl_elem_value *uc) | ||
479 | { | ||
480 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
481 | struct se_spec *spec = ice->spec; | ||
482 | int n = kc->private_value; | ||
483 | uc->value.integer.value[0] = spec->vol[n].ch1; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int se200pci_cont_enum_get(struct snd_kcontrol *kc, | ||
488 | struct snd_ctl_elem_value *uc) | ||
489 | { | ||
490 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
491 | struct se_spec *spec = ice->spec; | ||
492 | int n = kc->private_value; | ||
493 | uc->value.enumerated.item[0] = spec->vol[n].ch1; | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static void se200pci_cont_update(struct snd_ice1712 *ice, int n) | ||
498 | { | ||
499 | struct se_spec *spec = ice->spec; | ||
500 | switch (se200pci_cont[n].target) { | ||
501 | case WM8766: | ||
502 | se200pci_WM8766_set_volume(ice, | ||
503 | se200pci_cont[n].ch, | ||
504 | spec->vol[n].ch1, | ||
505 | spec->vol[n].ch2); | ||
506 | break; | ||
507 | |||
508 | case WM8776in: | ||
509 | se200pci_WM8776_set_input_volume(ice, | ||
510 | spec->vol[n].ch1, | ||
511 | spec->vol[n].ch2); | ||
512 | break; | ||
513 | |||
514 | case WM8776out: | ||
515 | se200pci_WM8776_set_output_volume(ice, | ||
516 | spec->vol[n].ch1, | ||
517 | spec->vol[n].ch2); | ||
518 | break; | ||
519 | |||
520 | case WM8776sel: | ||
521 | se200pci_WM8776_set_input_selector(ice, | ||
522 | spec->vol[n].ch1); | ||
523 | break; | ||
524 | |||
525 | case WM8776agc: | ||
526 | se200pci_WM8776_set_agc(ice, spec->vol[n].ch1); | ||
527 | break; | ||
528 | |||
529 | case WM8776afl: | ||
530 | se200pci_WM8776_set_afl(ice, spec->vol[n].ch1); | ||
531 | break; | ||
532 | |||
533 | default: | ||
534 | break; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | static int se200pci_cont_volume_put(struct snd_kcontrol *kc, | ||
539 | struct snd_ctl_elem_value *uc) | ||
540 | { | ||
541 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
542 | struct se_spec *spec = ice->spec; | ||
543 | int n = kc->private_value; | ||
544 | unsigned int vol1, vol2; | ||
545 | int changed; | ||
546 | |||
547 | changed = 0; | ||
548 | vol1 = uc->value.integer.value[0] & 0xff; | ||
549 | vol2 = uc->value.integer.value[1] & 0xff; | ||
550 | if (spec->vol[n].ch1 != vol1) { | ||
551 | spec->vol[n].ch1 = vol1; | ||
552 | changed = 1; | ||
553 | } | ||
554 | if (spec->vol[n].ch2 != vol2) { | ||
555 | spec->vol[n].ch2 = vol2; | ||
556 | changed = 1; | ||
557 | } | ||
558 | if (changed) | ||
559 | se200pci_cont_update(ice, n); | ||
560 | |||
561 | return changed; | ||
562 | } | ||
563 | |||
564 | static int se200pci_cont_boolean_put(struct snd_kcontrol *kc, | ||
565 | struct snd_ctl_elem_value *uc) | ||
566 | { | ||
567 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
568 | struct se_spec *spec = ice->spec; | ||
569 | int n = kc->private_value; | ||
570 | unsigned int vol1; | ||
571 | |||
572 | vol1 = !!uc->value.integer.value[0]; | ||
573 | if (spec->vol[n].ch1 != vol1) { | ||
574 | spec->vol[n].ch1 = vol1; | ||
575 | se200pci_cont_update(ice, n); | ||
576 | return 1; | ||
577 | } | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int se200pci_cont_enum_put(struct snd_kcontrol *kc, | ||
582 | struct snd_ctl_elem_value *uc) | ||
583 | { | ||
584 | struct snd_ice1712 *ice = snd_kcontrol_chip(kc); | ||
585 | struct se_spec *spec = ice->spec; | ||
586 | int n = kc->private_value; | ||
587 | unsigned int vol1; | ||
588 | |||
589 | vol1 = uc->value.enumerated.item[0]; | ||
590 | if (vol1 >= se200pci_get_enum_count(n)) | ||
591 | return -EINVAL; | ||
592 | if (spec->vol[n].ch1 != vol1) { | ||
593 | spec->vol[n].ch1 = vol1; | ||
594 | se200pci_cont_update(ice, n); | ||
595 | return 1; | ||
596 | } | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1); | ||
601 | static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1); | ||
602 | |||
603 | static int __devinit se200pci_add_controls(struct snd_ice1712 *ice) | ||
604 | { | ||
605 | int i; | ||
606 | struct snd_kcontrol_new cont; | ||
607 | int err; | ||
608 | |||
609 | memset(&cont, 0, sizeof(cont)); | ||
610 | cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
611 | for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) { | ||
612 | cont.private_value = i; | ||
613 | cont.name = se200pci_cont[i].name; | ||
614 | cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
615 | cont.tlv.p = NULL; | ||
616 | switch (se200pci_cont[i].type) { | ||
617 | case VOLUME1: | ||
618 | case VOLUME2: | ||
619 | cont.info = se200pci_cont_volume_info; | ||
620 | cont.get = se200pci_cont_volume_get; | ||
621 | cont.put = se200pci_cont_volume_put; | ||
622 | cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
623 | if (se200pci_cont[i].type == VOLUME1) | ||
624 | cont.tlv.p = db_scale_gain1; | ||
625 | else | ||
626 | cont.tlv.p = db_scale_gain2; | ||
627 | break; | ||
628 | case BOOLEAN: | ||
629 | cont.info = se200pci_cont_boolean_info; | ||
630 | cont.get = se200pci_cont_boolean_get; | ||
631 | cont.put = se200pci_cont_boolean_put; | ||
632 | break; | ||
633 | case ENUM: | ||
634 | cont.info = se200pci_cont_enum_info; | ||
635 | cont.get = se200pci_cont_enum_get; | ||
636 | cont.put = se200pci_cont_enum_put; | ||
637 | break; | ||
638 | default: | ||
639 | snd_BUG(); | ||
640 | return -EINVAL; | ||
641 | } | ||
642 | err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice)); | ||
643 | if (err < 0) | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | |||
651 | /****************************************************************************/ | ||
652 | /* ONKYO WAVIO SE-90PCI */ | ||
653 | /****************************************************************************/ | ||
654 | /* | ||
655 | * system configuration ICE_EEP2_SYSCONF=0x4b | ||
656 | * AC-Link configuration ICE_EEP2_ACLINK=0x80 | ||
657 | * I2S converters feature ICE_EEP2_I2S=0x78 | ||
658 | * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 | ||
659 | * | ||
660 | * ** connected chip ** | ||
661 | * | ||
662 | * WM8716 | ||
663 | * A 2ch-DAC of main outputs. | ||
664 | * It setuped as I2S mode by wire, so no way to setup from software. | ||
665 | * ML/I2S (28pin) -- +5V | ||
666 | * MC/DM1 (27pin) -- GND | ||
667 | * MC/DM0 (26pin) -- GND | ||
668 | * MUTEB (25pin) -- open (internal pull-up) | ||
669 | * MODE (24pin) -- GND | ||
670 | * CSBIWO (23pin) -- +5V | ||
671 | * | ||
672 | */ | ||
673 | |||
674 | /* Nothing to do for this chip. */ | ||
675 | |||
676 | |||
677 | /****************************************************************************/ | ||
678 | /* probe/initialize/setup */ | ||
679 | /****************************************************************************/ | ||
680 | |||
681 | static int __devinit se_init(struct snd_ice1712 *ice) | ||
682 | { | ||
683 | struct se_spec *spec; | ||
684 | |||
685 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
686 | if (!spec) | ||
687 | return -ENOMEM; | ||
688 | ice->spec = spec; | ||
689 | |||
690 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) { | ||
691 | ice->num_total_dacs = 2; | ||
692 | ice->num_total_adcs = 0; | ||
693 | ice->vt1720 = 1; | ||
694 | return 0; | ||
695 | |||
696 | } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) { | ||
697 | ice->num_total_dacs = 8; | ||
698 | ice->num_total_adcs = 2; | ||
699 | se200pci_WM8740_init(ice); | ||
700 | se200pci_WM8766_init(ice); | ||
701 | se200pci_WM8776_init(ice); | ||
702 | ice->gpio.set_pro_rate = se200pci_set_pro_rate; | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | return -ENOENT; | ||
707 | } | ||
708 | |||
709 | static int __devinit se_add_controls(struct snd_ice1712 *ice) | ||
710 | { | ||
711 | int err; | ||
712 | |||
713 | err = 0; | ||
714 | /* nothing to do for VT1724_SUBDEVICE_SE90PCI */ | ||
715 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) | ||
716 | err = se200pci_add_controls(ice); | ||
717 | |||
718 | return err; | ||
719 | } | ||
720 | |||
721 | |||
722 | /****************************************************************************/ | ||
723 | /* entry point */ | ||
724 | /****************************************************************************/ | ||
725 | |||
726 | static unsigned char se200pci_eeprom[] __devinitdata = { | ||
727 | [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ | ||
728 | [ICE_EEP2_ACLINK] = 0x80, /* I2S */ | ||
729 | [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ | ||
730 | [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ | ||
731 | |||
732 | [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */ | ||
733 | [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */ | ||
734 | [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */ | ||
735 | |||
736 | [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */ | ||
737 | [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */ | ||
738 | [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */ | ||
739 | |||
740 | [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */ | ||
741 | [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */ | ||
742 | [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */ | ||
743 | }; | ||
744 | |||
745 | static unsigned char se90pci_eeprom[] __devinitdata = { | ||
746 | [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ | ||
747 | [ICE_EEP2_ACLINK] = 0x80, /* I2S */ | ||
748 | [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ | ||
749 | [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ | ||
750 | |||
751 | /* ALL GPIO bits are in input mode */ | ||
752 | }; | ||
753 | |||
754 | struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = { | ||
755 | { | ||
756 | .subvendor = VT1724_SUBDEVICE_SE200PCI, | ||
757 | .name = "ONKYO SE200PCI", | ||
758 | .model = "se200pci", | ||
759 | .chip_init = se_init, | ||
760 | .build_controls = se_add_controls, | ||
761 | .eeprom_size = sizeof(se200pci_eeprom), | ||
762 | .eeprom_data = se200pci_eeprom, | ||
763 | }, | ||
764 | { | ||
765 | .subvendor = VT1724_SUBDEVICE_SE90PCI, | ||
766 | .name = "ONKYO SE90PCI", | ||
767 | .model = "se90pci", | ||
768 | .chip_init = se_init, | ||
769 | .build_controls = se_add_controls, | ||
770 | .eeprom_size = sizeof(se90pci_eeprom), | ||
771 | .eeprom_data = se90pci_eeprom, | ||
772 | }, | ||
773 | {} /*terminator*/ | ||
774 | }; | ||
diff --git a/sound/pci/ice1712/se.h b/sound/pci/ice1712/se.h new file mode 100644 index 000000000000..0b0a9dabdcfb --- /dev/null +++ b/sound/pci/ice1712/se.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef __SOUND_SE_H | ||
2 | #define __SOUND_SE_H | ||
3 | |||
4 | /* ID */ | ||
5 | #define SE_DEVICE_DESC \ | ||
6 | "{ONKYO INC,SE-90PCI},"\ | ||
7 | "{ONKYO INC,SE-200PCI}," | ||
8 | |||
9 | #define VT1724_SUBDEVICE_SE90PCI 0xb161000 | ||
10 | #define VT1724_SUBDEVICE_SE200PCI 0xb160100 | ||
11 | |||
12 | /* entry struct */ | ||
13 | extern struct snd_ice1712_card_info snd_vt1724_se_cards[]; | ||
14 | |||
15 | #endif /* __SOUND_SE_H */ | ||
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c index 239524158fe7..7f9674b641c0 100644 --- a/sound/pci/ice1712/vt1720_mobo.c +++ b/sound/pci/ice1712/vt1720_mobo.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <sound/driver.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index 7fcce0a506d6..a08d17c7e651 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | 26 | ||
27 | 27 | ||
28 | #include <sound/driver.h> | ||
29 | #include <asm/io.h> | 28 | #include <asm/io.h> |
30 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
31 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
@@ -178,7 +177,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, | |||
178 | 177 | ||
179 | if (kcontrol->private_value) { | 178 | if (kcontrol->private_value) { |
180 | idx = STAC946X_MASTER_VOLUME; | 179 | idx = STAC946X_MASTER_VOLUME; |
181 | nvol = ucontrol->value.integer.value[0]; | 180 | nvol = ucontrol->value.integer.value[0] & 0x7f; |
182 | tmp = stac9460_get(ice, idx); | 181 | tmp = stac9460_get(ice, idx); |
183 | ovol = 0x7f - (tmp & 0x7f); | 182 | ovol = 0x7f - (tmp & 0x7f); |
184 | change = (ovol != nvol); | 183 | change = (ovol != nvol); |
@@ -189,7 +188,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, | |||
189 | } else { | 188 | } else { |
190 | id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 189 | id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
191 | idx = id + STAC946X_LF_VOLUME; | 190 | idx = id + STAC946X_LF_VOLUME; |
192 | nvol = ucontrol->value.integer.value[0]; | 191 | nvol = ucontrol->value.integer.value[0] & 0x7f; |
193 | if (id < 6) | 192 | if (id < 6) |
194 | tmp = stac9460_get(ice, idx); | 193 | tmp = stac9460_get(ice, idx); |
195 | else | 194 | else |
@@ -317,7 +316,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, | |||
317 | if (id == 0) { | 316 | if (id == 0) { |
318 | for (i = 0; i < 2; ++i) { | 317 | for (i = 0; i < 2; ++i) { |
319 | reg = STAC946X_MIC_L_VOLUME + i; | 318 | reg = STAC946X_MIC_L_VOLUME + i; |
320 | nvol = ucontrol->value.integer.value[i]; | 319 | nvol = ucontrol->value.integer.value[i] & 0x0f; |
321 | ovol = 0x0f - stac9460_get(ice, reg); | 320 | ovol = 0x0f - stac9460_get(ice, reg); |
322 | change = ((ovol & 0x0f) != nvol); | 321 | change = ((ovol & 0x0f) != nvol); |
323 | if (change) | 322 | if (change) |
@@ -327,7 +326,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, | |||
327 | } else { | 326 | } else { |
328 | for (i = 0; i < 2; ++i) { | 327 | for (i = 0; i < 2; ++i) { |
329 | reg = STAC946X_MIC_L_VOLUME + i; | 328 | reg = STAC946X_MIC_L_VOLUME + i; |
330 | nvol = ucontrol->value.integer.value[i]; | 329 | nvol = ucontrol->value.integer.value[i] & 0x0f; |
331 | ovol = 0x0f - stac9460_2_get(ice, reg); | 330 | ovol = 0x0f - stac9460_2_get(ice, reg); |
332 | change = ((ovol & 0x0f) != nvol); | 331 | change = ((ovol & 0x0f) != nvol); |
333 | if (change) | 332 | if (change) |