aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-06-10 01:26:36 -0400
committerTakashi Iwai <tiwai@suse.de>2009-06-10 01:26:36 -0400
commited8cc176c9d3f8fbc2ddc18b75362be666e6d328 (patch)
treea3a43f4fe421b29a632202aeb506d51f02bc0959
parent03cece06c41431ab71affc540d587e61894d7572 (diff)
parent72cbfd45fac627de4bd38c203baaac40cd26477c (diff)
Merge branch 'topic/maya44' into for-linus
* topic/maya44: ALSA: ice1724 - Add ESI Maya44 support ALSA: ice1724 - Allow spec driver to create own routing controls ALSA: ice1724 - Add PCI postint to reset sequence ALSA: ice1724 - Clean up definitions of DMA records ALSA: ice1724 - Check error in set_rate function
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt3
-rw-r--r--Documentation/sound/alsa/README.maya44163
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/ice1712.h12
-rw-r--r--sound/pci/ice1712/ice1724.c96
-rw-r--r--sound/pci/ice1712/maya44.c779
-rw-r--r--sound/pci/ice1712/maya44.h10
7 files changed, 1025 insertions, 40 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 8cf17fe43003..945de361022f 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -944,6 +944,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
944 * Onkyo SE-90PCI 944 * Onkyo SE-90PCI
945 * Onkyo SE-200PCI 945 * Onkyo SE-200PCI
946 * ESI Juli@ 946 * ESI Juli@
947 * ESI Maya44
947 * Hercules Fortissimo IV 948 * Hercules Fortissimo IV
948 * EGO-SYS WaveTerminal 192M 949 * EGO-SYS WaveTerminal 192M
949 950
@@ -952,7 +953,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
952 prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192, 953 prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
953 juli, aureon51, aureon71, universe, ap192, k8x800, 954 juli, aureon51, aureon71, universe, ap192, k8x800,
954 phase22, phase28, ms300, av710, se200pci, se90pci, 955 phase22, phase28, ms300, av710, se200pci, se90pci,
955 fortissimo4, sn25p, WT192M 956 fortissimo4, sn25p, WT192M, maya44
956 957
957 This module supports multiple cards and autoprobe. 958 This module supports multiple cards and autoprobe.
958 959
diff --git a/Documentation/sound/alsa/README.maya44 b/Documentation/sound/alsa/README.maya44
new file mode 100644
index 000000000000..0e41576fa13e
--- /dev/null
+++ b/Documentation/sound/alsa/README.maya44
@@ -0,0 +1,163 @@
1NOTE: The following is the original document of Rainer's patch that the
2current maya44 code based on. Some contents might be obsoleted, but I
3keep here as reference -- tiwai
4
5----------------------------------------------------------------
6
7STATE OF DEVELOPMENT:
8
9This driver is being developed on the initiative of Piotr Makowski (oponek@gmail.com) and financed by Lars Bergmann.
10Development is carried out by Rainer Zimmermann (mail@lightshed.de).
11
12ESI provided a sample Maya44 card for the development work.
13
14However, unfortunately it has turned out difficult to get detailed programming information, so I (Rainer Zimmermann) had to find out some card-specific information by experiment and conjecture. Some information (in particular, several GPIO bits) is still missing.
15
16This is the first testing version of the Maya44 driver released to the alsa-devel mailing list (Feb 5, 2008).
17
18
19The following functions work, as tested by Rainer Zimmermann and Piotr Makowski:
20
21- playback and capture at all sampling rates
22- input/output level
23- crossmixing
24- line/mic switch
25- phantom power switch
26- analogue monitor a.k.a bypass
27
28
29The following functions *should* work, but are not fully tested:
30
31- Channel 3+4 analogue - S/PDIF input switching
32- S/PDIF output
33- all inputs/outputs on the M/IO/DIO extension card
34- internal/external clock selection
35
36
37*In particular, we would appreciate testing of these functions by anyone who has access to an M/IO/DIO extension card.*
38
39
40Things that do not seem to work:
41
42- The level meters ("multi track") in 'alsamixer' do not seem to react to signals in (if this is a bug, it would probably be in the existing ICE1724 code).
43
44- Ardour 2.1 seems to work only via JACK, not using ALSA directly or via OSS. This still needs to be tracked down.
45
46
47DRIVER DETAILS:
48
49the following files were added:
50
51pci/ice1724/maya44.c - Maya44 specific code
52pci/ice1724/maya44.h
53pci/ice1724/ice1724.patch
54pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
55i2c/other/wm8776.c - low-level access routines for Wolfson WM8776 codecs
56include/wm8776.h
57
58
59Note that the wm8776.c code is meant to be card-independent and does not actually register the codec with the ALSA infrastructure.
60This is done in maya44.c, mainly because some of the WM8776 controls are used in Maya44-specific ways, and should be named appropriately.
61
62
63the following files were created in pci/ice1724, simply #including the corresponding file from the alsa-kernel tree:
64
65wtm.h
66vt1720_mobo.h
67revo.h
68prodigy192.h
69pontis.h
70phase.h
71maya44.h
72juli.h
73aureon.h
74amp.h
75envy24ht.h
76se.h
77prodigy_hifi.h
78
79
80*I hope this is the correct way to do things.*
81
82
83SAMPLING RATES:
84
85The Maya44 card (or more exactly, the Wolfson WM8776 codecs) allow a maximum sampling rate of 192 kHz for playback and 92 kHz for capture.
86
87As the ICE1724 chip only allows one global sampling rate, this is handled as follows:
88
89* setting the sampling rate on any open PCM device on the maya44 card will always set the *global* sampling rate for all playback and capture channels.
90
91* In the current state of the driver, setting rates of up to 192 kHz is permitted even for capture devices.
92
93*AVOID CAPTURING AT RATES ABOVE 96kHz*, even though it may appear to work. The codec cannot actually capture at such rates, meaning poor quality.
94
95
96I propose some additional code for limiting the sampling rate when setting on a capture pcm device. However because of the global sampling rate, this logic would be somewhat problematic.
97
98The proposed code (currently deactivated) is in ice1712.h.patch, ice1724.c and maya44.c (in pci/ice1712).
99
100
101SOUND DEVICES:
102
103PCM devices correspond to inputs/outputs as follows (assuming Maya44 is card #0):
104
105hw:0,0 input - stereo, analog input 1+2
106hw:0,0 output - stereo, analog output 1+2
107hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
108hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
109
110
111NAMING OF MIXER CONTROLS:
112
113(for more information about the signal flow, please refer to the block diagram on p.24 of the ESI Maya44 manual, or in the ESI windows software).
114
115
116PCM: (digital) output level for channel 1+2
117PCM 1: same for channel 3+4
118
119Mic Phantom+48V: switch for +48V phantom power for electrostatic microphones on input 1/2.
120 Make sure this is not turned on while any other source is connected to input 1/2.
121 It might damage the source and/or the maya44 card.
122
123Mic/Line input: if switch is is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
124
125Bypass: analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
126Bypass 1: same for channel 3+4.
127
128Crossmix: cross-mixer from channels 1+2 to channels 3+4
129Crossmix 1: cross-mixer from channels 3+4 to channels 1+2
130
131IEC958 Output: switch for S/PDIF output.
132 This is not supported by the ESI windows driver.
133 S/PDIF should output the same signal as channel 3+4. [untested!]
134
135
136Digitial output selectors:
137
138 These switches allow a direct digital routing from the ADCs to the DACs.
139 Each switch determines where the digital input data to one of the DACs comes from.
140 They are not supported by the ESI windows driver.
141 For normal operation, they should all be set to "PCM out".
142
143H/W: Output source channel 1
144H/W 1: Output source channel 2
145H/W 2: Output source channel 3
146H/W 3: Output source channel 4
147
148H/W 4 ... H/W 9: unknown function, left in to enable testing.
149 Possibly some of these control S/PDIF output(s).
150 If these turn out to be unused, they will go away in later driver versions.
151
152Selectable values for each of the digital output selectors are:
153 "PCM out" -> DAC output of the corresponding channel (default setting)
154 "Input 1"...
155 "Input 4" -> direct routing from ADC output of the selected input channel
156
157
158--------
159
160Feb 14, 2008
161Rainer Zimmermann
162mail@lightshed.de
163
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index f99fe089495d..536eae2ccf94 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
5 5
6snd-ice17xx-ak4xxx-objs := ak4xxx.o 6snd-ice17xx-ak4xxx-objs := ak4xxx.o
7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o 7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
8snd-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 8snd-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 maya44.o
9 9
10# Toplevel Module Dependency 10# Toplevel Module Dependency
11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o 11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index fdae6deba16b..adc909ec125c 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -335,6 +335,7 @@ struct snd_ice1712 {
335 unsigned int force_rdma1:1; /* VT1720/4 - RDMA1 as non-spdif */ 335 unsigned int force_rdma1:1; /* VT1720/4 - RDMA1 as non-spdif */
336 unsigned int midi_output:1; /* VT1720/4: MIDI output triggered */ 336 unsigned int midi_output:1; /* VT1720/4: MIDI output triggered */
337 unsigned int midi_input:1; /* VT1720/4: MIDI input triggered */ 337 unsigned int midi_input:1; /* VT1720/4: MIDI input triggered */
338 unsigned int own_routing:1; /* VT1720/4: use own routing ctls */
338 unsigned int num_total_dacs; /* total DACs */ 339 unsigned int num_total_dacs; /* total DACs */
339 unsigned int num_total_adcs; /* total ADCs */ 340 unsigned int num_total_adcs; /* total ADCs */
340 unsigned int cur_rate; /* current rate */ 341 unsigned int cur_rate; /* current rate */
@@ -458,10 +459,17 @@ static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
458 return snd_ice1712_gpio_read(ice) & mask; 459 return snd_ice1712_gpio_read(ice) & mask;
459} 460}
460 461
462/* route access functions */
463int snd_ice1724_get_route_val(struct snd_ice1712 *ice, int shift);
464int snd_ice1724_put_route_val(struct snd_ice1712 *ice, unsigned int val,
465 int shift);
466
461int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice); 467int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice);
462 468
463int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template, 469int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak,
464 const struct snd_ak4xxx_private *priv, struct snd_ice1712 *ice); 470 const struct snd_akm4xxx *template,
471 const struct snd_ak4xxx_private *priv,
472 struct snd_ice1712 *ice);
465void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice); 473void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice);
466int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice); 474int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice);
467 475
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 128510e77a78..36ade77cf371 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -49,6 +49,7 @@
49#include "prodigy192.h" 49#include "prodigy192.h"
50#include "prodigy_hifi.h" 50#include "prodigy_hifi.h"
51#include "juli.h" 51#include "juli.h"
52#include "maya44.h"
52#include "phase.h" 53#include "phase.h"
53#include "wtm.h" 54#include "wtm.h"
54#include "se.h" 55#include "se.h"
@@ -65,6 +66,7 @@ MODULE_SUPPORTED_DEVICE("{"
65 PRODIGY192_DEVICE_DESC 66 PRODIGY192_DEVICE_DESC
66 PRODIGY_HIFI_DEVICE_DESC 67 PRODIGY_HIFI_DEVICE_DESC
67 JULI_DEVICE_DESC 68 JULI_DEVICE_DESC
69 MAYA44_DEVICE_DESC
68 PHASE_DEVICE_DESC 70 PHASE_DEVICE_DESC
69 WTM_DEVICE_DESC 71 WTM_DEVICE_DESC
70 SE_DEVICE_DESC 72 SE_DEVICE_DESC
@@ -626,7 +628,7 @@ static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
626 return 0; 628 return 0;
627} 629}
628 630
629static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, 631static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
630 int force) 632 int force)
631{ 633{
632 unsigned long flags; 634 unsigned long flags;
@@ -634,17 +636,18 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
634 unsigned int i, old_rate; 636 unsigned int i, old_rate;
635 637
636 if (rate > ice->hw_rates->list[ice->hw_rates->count - 1]) 638 if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
637 return; 639 return -EINVAL;
640
638 spin_lock_irqsave(&ice->reg_lock, flags); 641 spin_lock_irqsave(&ice->reg_lock, flags);
639 if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 642 if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
640 (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { 643 (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
641 /* running? we cannot change the rate now... */ 644 /* running? we cannot change the rate now... */
642 spin_unlock_irqrestore(&ice->reg_lock, flags); 645 spin_unlock_irqrestore(&ice->reg_lock, flags);
643 return; 646 return -EBUSY;
644 } 647 }
645 if (!force && is_pro_rate_locked(ice)) { 648 if (!force && is_pro_rate_locked(ice)) {
646 spin_unlock_irqrestore(&ice->reg_lock, flags); 649 spin_unlock_irqrestore(&ice->reg_lock, flags);
647 return; 650 return (rate == ice->cur_rate) ? 0 : -EBUSY;
648 } 651 }
649 652
650 old_rate = ice->get_rate(ice); 653 old_rate = ice->get_rate(ice);
@@ -652,7 +655,7 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
652 ice->set_rate(ice, rate); 655 ice->set_rate(ice, rate);
653 else if (rate == ice->cur_rate) { 656 else if (rate == ice->cur_rate) {
654 spin_unlock_irqrestore(&ice->reg_lock, flags); 657 spin_unlock_irqrestore(&ice->reg_lock, flags);
655 return; 658 return 0;
656 } 659 }
657 660
658 ice->cur_rate = rate; 661 ice->cur_rate = rate;
@@ -674,13 +677,15 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
674 } 677 }
675 if (ice->spdif.ops.setup_rate) 678 if (ice->spdif.ops.setup_rate)
676 ice->spdif.ops.setup_rate(ice, rate); 679 ice->spdif.ops.setup_rate(ice, rate);
680
681 return 0;
677} 682}
678 683
679static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, 684static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
680 struct snd_pcm_hw_params *hw_params) 685 struct snd_pcm_hw_params *hw_params)
681{ 686{
682 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 687 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
683 int i, chs; 688 int i, chs, err;
684 689
685 chs = params_channels(hw_params); 690 chs = params_channels(hw_params);
686 mutex_lock(&ice->open_mutex); 691 mutex_lock(&ice->open_mutex);
@@ -715,7 +720,11 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
715 } 720 }
716 } 721 }
717 mutex_unlock(&ice->open_mutex); 722 mutex_unlock(&ice->open_mutex);
718 snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); 723
724 err = snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0);
725 if (err < 0)
726 return err;
727
719 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); 728 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
720} 729}
721 730
@@ -848,20 +857,39 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substr
848#endif 857#endif
849} 858}
850 859
851static const struct vt1724_pcm_reg vt1724_playback_pro_reg = { 860static const struct vt1724_pcm_reg vt1724_pdma0_reg = {
852 .addr = VT1724_MT_PLAYBACK_ADDR, 861 .addr = VT1724_MT_PLAYBACK_ADDR,
853 .size = VT1724_MT_PLAYBACK_SIZE, 862 .size = VT1724_MT_PLAYBACK_SIZE,
854 .count = VT1724_MT_PLAYBACK_COUNT, 863 .count = VT1724_MT_PLAYBACK_COUNT,
855 .start = VT1724_PDMA0_START, 864 .start = VT1724_PDMA0_START,
856}; 865};
857 866
858static const struct vt1724_pcm_reg vt1724_capture_pro_reg = { 867static const struct vt1724_pcm_reg vt1724_pdma4_reg = {
868 .addr = VT1724_MT_PDMA4_ADDR,
869 .size = VT1724_MT_PDMA4_SIZE,
870 .count = VT1724_MT_PDMA4_COUNT,
871 .start = VT1724_PDMA4_START,
872};
873
874static const struct vt1724_pcm_reg vt1724_rdma0_reg = {
859 .addr = VT1724_MT_CAPTURE_ADDR, 875 .addr = VT1724_MT_CAPTURE_ADDR,
860 .size = VT1724_MT_CAPTURE_SIZE, 876 .size = VT1724_MT_CAPTURE_SIZE,
861 .count = VT1724_MT_CAPTURE_COUNT, 877 .count = VT1724_MT_CAPTURE_COUNT,
862 .start = VT1724_RDMA0_START, 878 .start = VT1724_RDMA0_START,
863}; 879};
864 880
881static const struct vt1724_pcm_reg vt1724_rdma1_reg = {
882 .addr = VT1724_MT_RDMA1_ADDR,
883 .size = VT1724_MT_RDMA1_SIZE,
884 .count = VT1724_MT_RDMA1_COUNT,
885 .start = VT1724_RDMA1_START,
886};
887
888#define vt1724_playback_pro_reg vt1724_pdma0_reg
889#define vt1724_playback_spdif_reg vt1724_pdma4_reg
890#define vt1724_capture_pro_reg vt1724_rdma0_reg
891#define vt1724_capture_spdif_reg vt1724_rdma1_reg
892
865static const struct snd_pcm_hardware snd_vt1724_playback_pro = { 893static const struct snd_pcm_hardware snd_vt1724_playback_pro = {
866 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 894 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
867 SNDRV_PCM_INFO_BLOCK_TRANSFER | 895 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1077,20 +1105,6 @@ static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
1077 * SPDIF PCM 1105 * SPDIF PCM
1078 */ 1106 */
1079 1107
1080static const struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
1081 .addr = VT1724_MT_PDMA4_ADDR,
1082 .size = VT1724_MT_PDMA4_SIZE,
1083 .count = VT1724_MT_PDMA4_COUNT,
1084 .start = VT1724_PDMA4_START,
1085};
1086
1087static const struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
1088 .addr = VT1724_MT_RDMA1_ADDR,
1089 .size = VT1724_MT_RDMA1_SIZE,
1090 .count = VT1724_MT_RDMA1_COUNT,
1091 .start = VT1724_RDMA1_START,
1092};
1093
1094/* update spdif control bits; call with reg_lock */ 1108/* update spdif control bits; call with reg_lock */
1095static void update_spdif_bits(struct snd_ice1712 *ice, unsigned int val) 1109static void update_spdif_bits(struct snd_ice1712 *ice, unsigned int val)
1096{ 1110{
@@ -1963,7 +1977,7 @@ static inline int digital_route_shift(int idx)
1963 return idx * 3; 1977 return idx * 3;
1964} 1978}
1965 1979
1966static int get_route_val(struct snd_ice1712 *ice, int shift) 1980int snd_ice1724_get_route_val(struct snd_ice1712 *ice, int shift)
1967{ 1981{
1968 unsigned long val; 1982 unsigned long val;
1969 unsigned char eitem; 1983 unsigned char eitem;
@@ -1982,7 +1996,8 @@ static int get_route_val(struct snd_ice1712 *ice, int shift)
1982 return eitem; 1996 return eitem;
1983} 1997}
1984 1998
1985static int put_route_val(struct snd_ice1712 *ice, unsigned int val, int shift) 1999int snd_ice1724_put_route_val(struct snd_ice1712 *ice, unsigned int val,
2000 int shift)
1986{ 2001{
1987 unsigned int old_val, nval; 2002 unsigned int old_val, nval;
1988 int change; 2003 int change;
@@ -2010,7 +2025,7 @@ static int snd_vt1724_pro_route_analog_get(struct snd_kcontrol *kcontrol,
2010 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2025 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2011 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 2026 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2012 ucontrol->value.enumerated.item[0] = 2027 ucontrol->value.enumerated.item[0] =
2013 get_route_val(ice, analog_route_shift(idx)); 2028 snd_ice1724_get_route_val(ice, analog_route_shift(idx));
2014 return 0; 2029 return 0;
2015} 2030}
2016 2031
@@ -2019,8 +2034,9 @@ static int snd_vt1724_pro_route_analog_put(struct snd_kcontrol *kcontrol,
2019{ 2034{
2020 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2035 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2021 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 2036 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2022 return put_route_val(ice, ucontrol->value.enumerated.item[0], 2037 return snd_ice1724_put_route_val(ice,
2023 analog_route_shift(idx)); 2038 ucontrol->value.enumerated.item[0],
2039 analog_route_shift(idx));
2024} 2040}
2025 2041
2026static int snd_vt1724_pro_route_spdif_get(struct snd_kcontrol *kcontrol, 2042static int snd_vt1724_pro_route_spdif_get(struct snd_kcontrol *kcontrol,
@@ -2029,7 +2045,7 @@ static int snd_vt1724_pro_route_spdif_get(struct snd_kcontrol *kcontrol,
2029 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2045 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2030 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 2046 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2031 ucontrol->value.enumerated.item[0] = 2047 ucontrol->value.enumerated.item[0] =
2032 get_route_val(ice, digital_route_shift(idx)); 2048 snd_ice1724_get_route_val(ice, digital_route_shift(idx));
2033 return 0; 2049 return 0;
2034} 2050}
2035 2051
@@ -2038,11 +2054,13 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
2038{ 2054{
2039 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 2055 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
2040 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 2056 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2041 return put_route_val(ice, ucontrol->value.enumerated.item[0], 2057 return snd_ice1724_put_route_val(ice,
2042 digital_route_shift(idx)); 2058 ucontrol->value.enumerated.item[0],
2059 digital_route_shift(idx));
2043} 2060}
2044 2061
2045static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = { 2062static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
2063{
2046 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2064 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2047 .name = "H/W Playback Route", 2065 .name = "H/W Playback Route",
2048 .info = snd_vt1724_pro_route_info, 2066 .info = snd_vt1724_pro_route_info,
@@ -2109,6 +2127,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
2109 snd_vt1724_prodigy_hifi_cards, 2127 snd_vt1724_prodigy_hifi_cards,
2110 snd_vt1724_prodigy192_cards, 2128 snd_vt1724_prodigy192_cards,
2111 snd_vt1724_juli_cards, 2129 snd_vt1724_juli_cards,
2130 snd_vt1724_maya44_cards,
2112 snd_vt1724_phase_cards, 2131 snd_vt1724_phase_cards,
2113 snd_vt1724_wtm_cards, 2132 snd_vt1724_wtm_cards,
2114 snd_vt1724_se_cards, 2133 snd_vt1724_se_cards,
@@ -2246,8 +2265,10 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
2246static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice) 2265static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
2247{ 2266{
2248 outb(VT1724_RESET , ICEREG1724(ice, CONTROL)); 2267 outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
2268 inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */
2249 msleep(10); 2269 msleep(10);
2250 outb(0, ICEREG1724(ice, CONTROL)); 2270 outb(0, ICEREG1724(ice, CONTROL));
2271 inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */
2251 msleep(10); 2272 msleep(10);
2252} 2273}
2253 2274
@@ -2277,9 +2298,12 @@ static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
2277 if (snd_BUG_ON(!ice->pcm)) 2298 if (snd_BUG_ON(!ice->pcm))
2278 return -EIO; 2299 return -EIO;
2279 2300
2280 err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice)); 2301 if (!ice->own_routing) {
2281 if (err < 0) 2302 err = snd_ctl_add(ice->card,
2282 return err; 2303 snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice));
2304 if (err < 0)
2305 return err;
2306 }
2283 2307
2284 err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_spdif_switch, ice)); 2308 err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_spdif_switch, ice));
2285 if (err < 0) 2309 if (err < 0)
@@ -2326,7 +2350,7 @@ static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice)
2326 if (err < 0) 2350 if (err < 0)
2327 return err; 2351 return err;
2328 2352
2329 if (ice->num_total_dacs > 0) { 2353 if (!ice->own_routing && ice->num_total_dacs > 0) {
2330 struct snd_kcontrol_new tmp = snd_vt1724_mixer_pro_analog_route; 2354 struct snd_kcontrol_new tmp = snd_vt1724_mixer_pro_analog_route;
2331 tmp.count = ice->num_total_dacs; 2355 tmp.count = ice->num_total_dacs;
2332 if (ice->vt1720 && tmp.count > 2) 2356 if (ice->vt1720 && tmp.count > 2)
diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c
new file mode 100644
index 000000000000..3e1c20ae2f1c
--- /dev/null
+++ b/sound/pci/ice1712/maya44.c
@@ -0,0 +1,779 @@
1/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for ESI Maya44 cards
5 *
6 * Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
7 * Based on the patches by Rainer Zimmermann <mail@lightshed.de>
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 <linux/init.h>
26#include <linux/slab.h>
27#include <linux/io.h>
28#include <sound/core.h>
29#include <sound/control.h>
30#include <sound/pcm.h>
31#include <sound/tlv.h>
32
33#include "ice1712.h"
34#include "envy24ht.h"
35#include "maya44.h"
36
37/* WM8776 register indexes */
38#define WM8776_REG_HEADPHONE_L 0x00
39#define WM8776_REG_HEADPHONE_R 0x01
40#define WM8776_REG_HEADPHONE_MASTER 0x02
41#define WM8776_REG_DAC_ATTEN_L 0x03
42#define WM8776_REG_DAC_ATTEN_R 0x04
43#define WM8776_REG_DAC_ATTEN_MASTER 0x05
44#define WM8776_REG_DAC_PHASE 0x06
45#define WM8776_REG_DAC_CONTROL 0x07
46#define WM8776_REG_DAC_MUTE 0x08
47#define WM8776_REG_DAC_DEEMPH 0x09
48#define WM8776_REG_DAC_IF_CONTROL 0x0a
49#define WM8776_REG_ADC_IF_CONTROL 0x0b
50#define WM8776_REG_MASTER_MODE_CONTROL 0x0c
51#define WM8776_REG_POWERDOWN 0x0d
52#define WM8776_REG_ADC_ATTEN_L 0x0e
53#define WM8776_REG_ADC_ATTEN_R 0x0f
54#define WM8776_REG_ADC_ALC1 0x10
55#define WM8776_REG_ADC_ALC2 0x11
56#define WM8776_REG_ADC_ALC3 0x12
57#define WM8776_REG_ADC_NOISE_GATE 0x13
58#define WM8776_REG_ADC_LIMITER 0x14
59#define WM8776_REG_ADC_MUX 0x15
60#define WM8776_REG_OUTPUT_MUX 0x16
61#define WM8776_REG_RESET 0x17
62
63#define WM8776_NUM_REGS 0x18
64
65/* clock ratio identifiers for snd_wm8776_set_rate() */
66#define WM8776_CLOCK_RATIO_128FS 0
67#define WM8776_CLOCK_RATIO_192FS 1
68#define WM8776_CLOCK_RATIO_256FS 2
69#define WM8776_CLOCK_RATIO_384FS 3
70#define WM8776_CLOCK_RATIO_512FS 4
71#define WM8776_CLOCK_RATIO_768FS 5
72
73enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
74enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
75
76struct snd_wm8776 {
77 unsigned char addr;
78 unsigned short regs[WM8776_NUM_REGS];
79 unsigned char volumes[WM_NUM_VOLS][2];
80 unsigned int switch_bits;
81};
82
83struct snd_maya44 {
84 struct snd_ice1712 *ice;
85 struct snd_wm8776 wm[2];
86 struct mutex mutex;
87};
88
89
90/* write the given register and save the data to the cache */
91static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
92 unsigned char reg, unsigned short val)
93{
94 /*
95 * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
96 * of the address field
97 */
98 snd_vt1724_write_i2c(ice, wm->addr,
99 (reg << 1) | ((val >> 8) & 1),
100 val & 0xff);
101 wm->regs[reg] = val;
102}
103
104/*
105 * update the given register with and/or mask and save the data to the cache
106 */
107static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
108 unsigned char reg,
109 unsigned short mask, unsigned short val)
110{
111 val |= wm->regs[reg] & ~mask;
112 if (val != wm->regs[reg]) {
113 wm8776_write(ice, wm, reg, val);
114 return 1;
115 }
116 return 0;
117}
118
119
120/*
121 * WM8776 volume controls
122 */
123
124struct maya_vol_info {
125 unsigned int maxval; /* volume range: 0..maxval */
126 unsigned char regs[2]; /* left and right registers */
127 unsigned short mask; /* value mask */
128 unsigned short offset; /* zero-value offset */
129 unsigned short mute; /* mute bit */
130 unsigned short update; /* update bits */
131 unsigned char mux_bits[2]; /* extra bits for ADC mute */
132};
133
134static struct maya_vol_info vol_info[WM_NUM_VOLS] = {
135 [WM_VOL_HP] = {
136 .maxval = 80,
137 .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
138 .mask = 0x7f,
139 .offset = 0x30,
140 .mute = 0x00,
141 .update = 0x180, /* update and zero-cross enable */
142 },
143 [WM_VOL_DAC] = {
144 .maxval = 255,
145 .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
146 .mask = 0xff,
147 .offset = 0x01,
148 .mute = 0x00,
149 .update = 0x100, /* zero-cross enable */
150 },
151 [WM_VOL_ADC] = {
152 .maxval = 91,
153 .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
154 .mask = 0xff,
155 .offset = 0xa5,
156 .mute = 0xa5,
157 .update = 0x100, /* update */
158 .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
159 },
160};
161
162/*
163 * dB tables
164 */
165/* headphone output: mute, -73..+6db (1db step) */
166static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
167/* DAC output: mute, -127..0db (0.5db step) */
168static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
169/* ADC gain: mute, -21..+24db (0.5db step) */
170static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
171
172static int maya_vol_info(struct snd_kcontrol *kcontrol,
173 struct snd_ctl_elem_info *uinfo)
174{
175 unsigned int idx = kcontrol->private_value;
176 struct maya_vol_info *vol = &vol_info[idx];
177
178 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
179 uinfo->count = 2;
180 uinfo->value.integer.min = 0;
181 uinfo->value.integer.max = vol->maxval;
182 return 0;
183}
184
185static int maya_vol_get(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_value *ucontrol)
187{
188 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
189 struct snd_wm8776 *wm =
190 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
191 unsigned int idx = kcontrol->private_value;
192
193 mutex_lock(&chip->mutex);
194 ucontrol->value.integer.value[0] = wm->volumes[idx][0];
195 ucontrol->value.integer.value[1] = wm->volumes[idx][1];
196 mutex_unlock(&chip->mutex);
197 return 0;
198}
199
200static int maya_vol_put(struct snd_kcontrol *kcontrol,
201 struct snd_ctl_elem_value *ucontrol)
202{
203 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
204 struct snd_wm8776 *wm =
205 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
206 unsigned int idx = kcontrol->private_value;
207 struct maya_vol_info *vol = &vol_info[idx];
208 unsigned int val, data;
209 int ch, changed = 0;
210
211 mutex_lock(&chip->mutex);
212 for (ch = 0; ch < 2; ch++) {
213 val = ucontrol->value.integer.value[ch];
214 if (val > vol->maxval)
215 val = vol->maxval;
216 if (val == wm->volumes[idx][ch])
217 continue;
218 if (!val)
219 data = vol->mute;
220 else
221 data = (val - 1) + vol->offset;
222 data |= vol->update;
223 changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
224 vol->mask | vol->update, data);
225 if (vol->mux_bits[ch])
226 wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
227 vol->mux_bits[ch],
228 val ? 0 : vol->mux_bits[ch]);
229 wm->volumes[idx][ch] = val;
230 }
231 mutex_unlock(&chip->mutex);
232 return changed;
233}
234
235/*
236 * WM8776 switch controls
237 */
238
239#define COMPOSE_SW_VAL(idx, reg, mask) ((idx) | ((reg) << 8) | ((mask) << 16))
240#define GET_SW_VAL_IDX(val) ((val) & 0xff)
241#define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff)
242#define GET_SW_VAL_MASK(val) (((val) >> 16) & 0xff)
243
244#define maya_sw_info snd_ctl_boolean_mono_info
245
246static int maya_sw_get(struct snd_kcontrol *kcontrol,
247 struct snd_ctl_elem_value *ucontrol)
248{
249 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
250 struct snd_wm8776 *wm =
251 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
252 unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
253
254 ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
255 return 0;
256}
257
258static int maya_sw_put(struct snd_kcontrol *kcontrol,
259 struct snd_ctl_elem_value *ucontrol)
260{
261 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
262 struct snd_wm8776 *wm =
263 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
264 unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
265 unsigned int mask, val;
266 int changed;
267
268 mutex_lock(&chip->mutex);
269 mask = 1 << idx;
270 wm->switch_bits &= ~mask;
271 val = ucontrol->value.integer.value[0];
272 if (val)
273 wm->switch_bits |= mask;
274 mask = GET_SW_VAL_MASK(kcontrol->private_value);
275 changed = wm8776_write_bits(chip->ice, wm,
276 GET_SW_VAL_REG(kcontrol->private_value),
277 mask, val ? mask : 0);
278 mutex_unlock(&chip->mutex);
279 return changed;
280}
281
282/*
283 * GPIO pins (known ones for maya44)
284 */
285#define GPIO_PHANTOM_OFF 2
286#define GPIO_MIC_RELAY 4
287#define GPIO_SPDIF_IN_INV 5
288#define GPIO_MUST_BE_0 7
289
290/*
291 * GPIO switch controls
292 */
293
294#define COMPOSE_GPIO_VAL(shift, inv) ((shift) | ((inv) << 8))
295#define GET_GPIO_VAL_SHIFT(val) ((val) & 0xff)
296#define GET_GPIO_VAL_INV(val) (((val) >> 8) & 1)
297
298static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
299 unsigned int bits)
300{
301 unsigned int data;
302 data = snd_ice1712_gpio_read(ice);
303 if ((data & mask) == bits)
304 return 0;
305 snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
306 return 1;
307}
308
309#define maya_gpio_sw_info snd_ctl_boolean_mono_info
310
311static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
312 struct snd_ctl_elem_value *ucontrol)
313{
314 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
315 unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
316 unsigned int val;
317
318 val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
319 if (GET_GPIO_VAL_INV(kcontrol->private_value))
320 val = !val;
321 ucontrol->value.integer.value[0] = val;
322 return 0;
323}
324
325static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
326 struct snd_ctl_elem_value *ucontrol)
327{
328 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
329 unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
330 unsigned int val, mask;
331 int changed;
332
333 mutex_lock(&chip->mutex);
334 mask = 1 << shift;
335 val = ucontrol->value.integer.value[0];
336 if (GET_GPIO_VAL_INV(kcontrol->private_value))
337 val = !val;
338 val = val ? mask : 0;
339 changed = maya_set_gpio_bits(chip->ice, mask, val);
340 mutex_unlock(&chip->mutex);
341 return changed;
342}
343
344/*
345 * capture source selection
346 */
347
348/* known working input slots (0-4) */
349#define MAYA_LINE_IN 1 /* in-2 */
350#define MAYA_MIC_IN 4 /* in-5 */
351
352static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
353{
354 wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
355 0x1f, 1 << line);
356}
357
358static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
359 struct snd_ctl_elem_info *uinfo)
360{
361 static char *texts[] = { "Line", "Mic" };
362
363 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
364 uinfo->count = 1;
365 uinfo->value.enumerated.items = ARRAY_SIZE(texts);
366 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
367 uinfo->value.enumerated.item =
368 uinfo->value.enumerated.items - 1;
369 strcpy(uinfo->value.enumerated.name,
370 texts[uinfo->value.enumerated.item]);
371 return 0;
372}
373
374static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
375 struct snd_ctl_elem_value *ucontrol)
376{
377 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
378 int sel;
379
380 if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
381 sel = 1;
382 else
383 sel = 0;
384 ucontrol->value.enumerated.item[0] = sel;
385 return 0;
386}
387
388static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
389 struct snd_ctl_elem_value *ucontrol)
390{
391 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
392 int sel = ucontrol->value.enumerated.item[0];
393 int changed;
394
395 mutex_lock(&chip->mutex);
396 changed = maya_set_gpio_bits(chip->ice, GPIO_MIC_RELAY,
397 sel ? GPIO_MIC_RELAY : 0);
398 wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
399 mutex_unlock(&chip->mutex);
400 return changed;
401}
402
403/*
404 * Maya44 routing switch settings have different meanings than the standard
405 * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
406 */
407static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
408 struct snd_ctl_elem_info *uinfo)
409{
410 static char *texts[] = {
411 "PCM Out", /* 0 */
412 "Input 1", "Input 2", "Input 3", "Input 4"
413 };
414
415 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
416 uinfo->count = 1;
417 uinfo->value.enumerated.items = ARRAY_SIZE(texts);
418 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
419 uinfo->value.enumerated.item =
420 uinfo->value.enumerated.items - 1;
421 strcpy(uinfo->value.enumerated.name,
422 texts[uinfo->value.enumerated.item]);
423 return 0;
424}
425
426static int maya_pb_route_shift(int idx)
427{
428 static const unsigned char shift[10] =
429 { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
430 return shift[idx % 10];
431}
432
433static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
434 struct snd_ctl_elem_value *ucontrol)
435{
436 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
437 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
438 ucontrol->value.enumerated.item[0] =
439 snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
440 return 0;
441}
442
443static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
444 struct snd_ctl_elem_value *ucontrol)
445{
446 struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
447 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
448 return snd_ice1724_put_route_val(chip->ice,
449 ucontrol->value.enumerated.item[0],
450 maya_pb_route_shift(idx));
451}
452
453
454/*
455 * controls to be added
456 */
457
458static struct snd_kcontrol_new maya_controls[] __devinitdata = {
459 {
460 .name = "Crossmix Playback Volume",
461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
462 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
463 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
464 .info = maya_vol_info,
465 .get = maya_vol_get,
466 .put = maya_vol_put,
467 .tlv = { .p = db_scale_hp },
468 .private_value = WM_VOL_HP,
469 .count = 2,
470 },
471 {
472 .name = "PCM Playback Volume",
473 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
474 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
475 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
476 .info = maya_vol_info,
477 .get = maya_vol_get,
478 .put = maya_vol_put,
479 .tlv = { .p = db_scale_dac },
480 .private_value = WM_VOL_DAC,
481 .count = 2,
482 },
483 {
484 .name = "Line Capture Volume",
485 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
486 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
487 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
488 .info = maya_vol_info,
489 .get = maya_vol_get,
490 .put = maya_vol_put,
491 .tlv = { .p = db_scale_adc },
492 .private_value = WM_VOL_ADC,
493 .count = 2,
494 },
495 {
496 .name = "PCM Playback Switch",
497 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
498 .info = maya_sw_info,
499 .get = maya_sw_get,
500 .put = maya_sw_put,
501 .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
502 WM8776_REG_OUTPUT_MUX, 0x01),
503 .count = 2,
504 },
505 {
506 .name = "Bypass Playback Switch",
507 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
508 .info = maya_sw_info,
509 .get = maya_sw_get,
510 .put = maya_sw_put,
511 .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
512 WM8776_REG_OUTPUT_MUX, 0x04),
513 .count = 2,
514 },
515 {
516 .name = "Capture Source",
517 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
518 .info = maya_rec_src_info,
519 .get = maya_rec_src_get,
520 .put = maya_rec_src_put,
521 },
522 {
523 .name = "Mic Phantom Power Switch",
524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
525 .info = maya_gpio_sw_info,
526 .get = maya_gpio_sw_get,
527 .put = maya_gpio_sw_put,
528 .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
529 },
530 {
531 .name = "SPDIF Capture Switch",
532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
533 .info = maya_gpio_sw_info,
534 .get = maya_gpio_sw_get,
535 .put = maya_gpio_sw_put,
536 .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
537 },
538 {
539 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
540 .name = "H/W Playback Route",
541 .info = maya_pb_route_info,
542 .get = maya_pb_route_get,
543 .put = maya_pb_route_put,
544 .count = 4, /* FIXME: do controls 5-9 have any meaning? */
545 },
546};
547
548static int __devinit maya44_add_controls(struct snd_ice1712 *ice)
549{
550 int err, i;
551
552 for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
553 err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
554 ice->spec));
555 if (err < 0)
556 return err;
557 }
558 return 0;
559}
560
561
562/*
563 * initialize a wm8776 chip
564 */
565static void __devinit wm8776_init(struct snd_ice1712 *ice,
566 struct snd_wm8776 *wm, unsigned int addr)
567{
568 static const unsigned short inits_wm8776[] = {
569 0x02, 0x100, /* R2: headphone L+R muted + update */
570 0x05, 0x100, /* R5: DAC output L+R muted + update */
571 0x06, 0x000, /* R6: DAC output phase normal */
572 0x07, 0x091, /* R7: DAC enable zero cross detection,
573 normal output */
574 0x08, 0x000, /* R8: DAC soft mute off */
575 0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
576 0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
577 0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
578 highpass filter enabled */
579 0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
580 0x0d, 0x000, /* R13: all power up */
581 0x0e, 0x100, /* R14: ADC left muted,
582 enable zero cross detection */
583 0x0f, 0x100, /* R15: ADC right muted,
584 enable zero cross detection */
585 /* R16: ALC...*/
586 0x11, 0x000, /* R17: disable ALC */
587 /* R18: ALC...*/
588 /* R19: noise gate...*/
589 0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
590 0x16, 0x001, /* R22: output mux, select DAC */
591 0xff, 0xff
592 };
593
594 const unsigned short *ptr;
595 unsigned char reg;
596 unsigned short data;
597
598 wm->addr = addr;
599 /* enable DAC output; mute bypass, aux & all inputs */
600 wm->switch_bits = (1 << WM_SW_DAC);
601
602 ptr = inits_wm8776;
603 while (*ptr != 0xff) {
604 reg = *ptr++;
605 data = *ptr++;
606 wm8776_write(ice, wm, reg, data);
607 }
608}
609
610
611/*
612 * change the rate on the WM8776 codecs.
613 * this assumes that the VT17xx's rate is changed by the calling function.
614 * NOTE: even though the WM8776's are running in slave mode and rate
615 * selection is automatic, we need to call snd_wm8776_set_rate() here
616 * to make sure some flags are set correctly.
617 */
618static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
619{
620 struct snd_maya44 *chip = ice->spec;
621 unsigned int ratio, adc_ratio, val;
622 int i;
623
624 switch (rate) {
625 case 192000:
626 ratio = WM8776_CLOCK_RATIO_128FS;
627 break;
628 case 176400:
629 ratio = WM8776_CLOCK_RATIO_128FS;
630 break;
631 case 96000:
632 ratio = WM8776_CLOCK_RATIO_256FS;
633 break;
634 case 88200:
635 ratio = WM8776_CLOCK_RATIO_384FS;
636 break;
637 case 48000:
638 ratio = WM8776_CLOCK_RATIO_512FS;
639 break;
640 case 44100:
641 ratio = WM8776_CLOCK_RATIO_512FS;
642 break;
643 case 32000:
644 ratio = WM8776_CLOCK_RATIO_768FS;
645 break;
646 case 0:
647 /* no hint - S/PDIF input is master, simply return */
648 return;
649 default:
650 snd_BUG();
651 return;
652 }
653
654 /*
655 * this currently sets the same rate for ADC and DAC, but limits
656 * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
657 * oversampling to 64x, as recommended by WM8776 datasheet.
658 * Setting the rate is not really necessary in slave mode.
659 */
660 adc_ratio = ratio;
661 if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
662 adc_ratio = WM8776_CLOCK_RATIO_256FS;
663
664 val = adc_ratio;
665 if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
666 val |= 8;
667 val |= ratio << 4;
668
669 mutex_lock(&chip->mutex);
670 for (i = 0; i < 2; i++)
671 wm8776_write_bits(ice, &chip->wm[i],
672 WM8776_REG_MASTER_MODE_CONTROL,
673 0x180, val);
674 mutex_unlock(&chip->mutex);
675}
676
677/*
678 * supported sample rates (to override the default one)
679 */
680
681static unsigned int rates[] = {
682 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
683};
684
685/* playback rates: 32..192 kHz */
686static struct snd_pcm_hw_constraint_list dac_rates = {
687 .count = ARRAY_SIZE(rates),
688 .list = rates,
689 .mask = 0
690};
691
692
693/*
694 * chip addresses on I2C bus
695 */
696static unsigned char wm8776_addr[2] __devinitdata = {
697 0x34, 0x36, /* codec 0 & 1 */
698};
699
700/*
701 * initialize the chip
702 */
703static int __devinit maya44_init(struct snd_ice1712 *ice)
704{
705 int i;
706 struct snd_maya44 *chip;
707
708 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
709 if (!chip)
710 return -ENOMEM;
711 mutex_init(&chip->mutex);
712 chip->ice = ice;
713 ice->spec = chip;
714
715 /* initialise codecs */
716 ice->num_total_dacs = 4;
717 ice->num_total_adcs = 4;
718 ice->akm_codecs = 0;
719
720 for (i = 0; i < 2; i++) {
721 wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
722 wm8776_select_input(chip, i, MAYA_LINE_IN);
723 }
724
725 /* set card specific rates */
726 ice->hw_rates = &dac_rates;
727
728 /* register change rate notifier */
729 ice->gpio.set_pro_rate = set_rate;
730
731 /* RDMA1 (2nd input channel) is used for ADC by default */
732 ice->force_rdma1 = 1;
733
734 /* have an own routing control */
735 ice->own_routing = 1;
736
737 return 0;
738}
739
740
741/*
742 * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
743 * hence the driver needs to sets up it properly.
744 */
745
746static unsigned char maya44_eeprom[] __devinitdata = {
747 [ICE_EEP2_SYSCONF] = 0x45,
748 /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
749 [ICE_EEP2_ACLINK] = 0x80,
750 /* I2S */
751 [ICE_EEP2_I2S] = 0xf8,
752 /* vol, 96k, 24bit, 192k */
753 [ICE_EEP2_SPDIF] = 0xc3,
754 /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
755 [ICE_EEP2_GPIO_DIR] = 0xff,
756 [ICE_EEP2_GPIO_DIR1] = 0xff,
757 [ICE_EEP2_GPIO_DIR2] = 0xff,
758 [ICE_EEP2_GPIO_MASK] = 0/*0x9f*/,
759 [ICE_EEP2_GPIO_MASK1] = 0/*0xff*/,
760 [ICE_EEP2_GPIO_MASK2] = 0/*0x7f*/,
761 [ICE_EEP2_GPIO_STATE] = (1 << GPIO_PHANTOM_OFF) |
762 (1 << GPIO_SPDIF_IN_INV),
763 [ICE_EEP2_GPIO_STATE1] = 0x00,
764 [ICE_EEP2_GPIO_STATE2] = 0x00,
765};
766
767/* entry point */
768struct snd_ice1712_card_info snd_vt1724_maya44_cards[] __devinitdata = {
769 {
770 .subvendor = VT1724_SUBDEVICE_MAYA44,
771 .name = "ESI Maya44",
772 .model = "maya44",
773 .chip_init = maya44_init,
774 .build_controls = maya44_add_controls,
775 .eeprom_size = sizeof(maya44_eeprom),
776 .eeprom_data = maya44_eeprom,
777 },
778 { } /* terminator */
779};
diff --git a/sound/pci/ice1712/maya44.h b/sound/pci/ice1712/maya44.h
new file mode 100644
index 000000000000..eafd03a8f4b5
--- /dev/null
+++ b/sound/pci/ice1712/maya44.h
@@ -0,0 +1,10 @@
1#ifndef __SOUND_MAYA44_H
2#define __SOUND_MAYA44_H
3
4#define MAYA44_DEVICE_DESC "{ESI,Maya44},"
5
6#define VT1724_SUBDEVICE_MAYA44 0x34315441 /* Maya44 */
7
8extern struct snd_ice1712_card_info snd_vt1724_maya44_cards[];
9
10#endif /* __SOUND_MAYA44_H */