diff options
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r-- | sound/pci/oxygen/cs4362a.h | 69 | ||||
-rw-r--r-- | sound/pci/oxygen/cs4398.h | 69 | ||||
-rw-r--r-- | sound/pci/oxygen/hifier.c | 36 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 129 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 23 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_io.c | 23 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 113 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_mixer.c | 217 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_pcm.c | 78 | ||||
-rw-r--r-- | sound/pci/oxygen/pcm1796.h | 58 | ||||
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 594 | ||||
-rw-r--r-- | sound/pci/oxygen/wm8785.h | 45 |
12 files changed, 1039 insertions, 415 deletions
diff --git a/sound/pci/oxygen/cs4362a.h b/sound/pci/oxygen/cs4362a.h new file mode 100644 index 000000000000..6a4fedf5e1ec --- /dev/null +++ b/sound/pci/oxygen/cs4362a.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* register 01h */ | ||
2 | #define CS4362A_PDN 0x01 | ||
3 | #define CS4362A_DAC1_DIS 0x02 | ||
4 | #define CS4362A_DAC2_DIS 0x04 | ||
5 | #define CS4362A_DAC3_DIS 0x08 | ||
6 | #define CS4362A_MCLKDIV 0x20 | ||
7 | #define CS4362A_FREEZE 0x40 | ||
8 | #define CS4362A_CPEN 0x80 | ||
9 | /* register 02h */ | ||
10 | #define CS4362A_DIF_MASK 0x70 | ||
11 | #define CS4362A_DIF_LJUST 0x00 | ||
12 | #define CS4362A_DIF_I2S 0x10 | ||
13 | #define CS4362A_DIF_RJUST_16 0x20 | ||
14 | #define CS4362A_DIF_RJUST_24 0x30 | ||
15 | #define CS4362A_DIF_RJUST_20 0x40 | ||
16 | #define CS4362A_DIF_RJUST_18 0x50 | ||
17 | /* register 03h */ | ||
18 | #define CS4362A_MUTEC_MASK 0x03 | ||
19 | #define CS4362A_MUTEC_6 0x00 | ||
20 | #define CS4362A_MUTEC_1 0x01 | ||
21 | #define CS4362A_MUTEC_3 0x03 | ||
22 | #define CS4362A_AMUTE 0x04 | ||
23 | #define CS4362A_MUTEC_POL 0x08 | ||
24 | #define CS4362A_RMP_UP 0x10 | ||
25 | #define CS4362A_SNGLVOL 0x20 | ||
26 | #define CS4362A_ZERO_CROSS 0x40 | ||
27 | #define CS4362A_SOFT_RAMP 0x80 | ||
28 | /* register 04h */ | ||
29 | #define CS4362A_RMP_DN 0x01 | ||
30 | #define CS4362A_DEM_MASK 0x06 | ||
31 | #define CS4362A_DEM_NONE 0x00 | ||
32 | #define CS4362A_DEM_44100 0x02 | ||
33 | #define CS4362A_DEM_48000 0x04 | ||
34 | #define CS4362A_DEM_32000 0x06 | ||
35 | #define CS4362A_FILT_SEL 0x10 | ||
36 | /* register 05h */ | ||
37 | #define CS4362A_INV_A1 0x01 | ||
38 | #define CS4362A_INV_B1 0x02 | ||
39 | #define CS4362A_INV_A2 0x04 | ||
40 | #define CS4362A_INV_B2 0x08 | ||
41 | #define CS4362A_INV_A3 0x10 | ||
42 | #define CS4362A_INV_B3 0x20 | ||
43 | /* register 06h */ | ||
44 | #define CS4362A_FM_MASK 0x03 | ||
45 | #define CS4362A_FM_SINGLE 0x00 | ||
46 | #define CS4362A_FM_DOUBLE 0x01 | ||
47 | #define CS4362A_FM_QUAD 0x02 | ||
48 | #define CS4362A_FM_DSD 0x03 | ||
49 | #define CS4362A_ATAPI_MASK 0x7c | ||
50 | #define CS4362A_ATAPI_B_MUTE 0x00 | ||
51 | #define CS4362A_ATAPI_B_R 0x04 | ||
52 | #define CS4362A_ATAPI_B_L 0x08 | ||
53 | #define CS4362A_ATAPI_B_LR 0x0c | ||
54 | #define CS4362A_ATAPI_A_MUTE 0x00 | ||
55 | #define CS4362A_ATAPI_A_R 0x10 | ||
56 | #define CS4362A_ATAPI_A_L 0x20 | ||
57 | #define CS4362A_ATAPI_A_LR 0x30 | ||
58 | #define CS4362A_ATAPI_MIX_LR_VOL 0x40 | ||
59 | #define CS4362A_A_EQ_B 0x80 | ||
60 | /* register 07h */ | ||
61 | #define CS4362A_VOL_MASK 0x7f | ||
62 | #define CS4362A_MUTE 0x80 | ||
63 | /* register 08h: like 07h */ | ||
64 | /* registers 09h..0Bh: like 06h..08h */ | ||
65 | /* registers 0Ch..0Eh: like 06h..08h */ | ||
66 | /* register 12h */ | ||
67 | #define CS4362A_REV_MASK 0x07 | ||
68 | #define CS4362A_PART_MASK 0xf8 | ||
69 | #define CS4362A_PART_CS4362A 0x50 | ||
diff --git a/sound/pci/oxygen/cs4398.h b/sound/pci/oxygen/cs4398.h new file mode 100644 index 000000000000..5faf5efc8826 --- /dev/null +++ b/sound/pci/oxygen/cs4398.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* register 1 */ | ||
2 | #define CS4398_REV_MASK 0x07 | ||
3 | #define CS4398_PART_MASK 0xf8 | ||
4 | #define CS4398_PART_CS4398 0x70 | ||
5 | /* register 2 */ | ||
6 | #define CS4398_FM_MASK 0x03 | ||
7 | #define CS4398_FM_SINGLE 0x00 | ||
8 | #define CS4398_FM_DOUBLE 0x01 | ||
9 | #define CS4398_FM_QUAD 0x02 | ||
10 | #define CS4398_FM_DSD 0x03 | ||
11 | #define CS4398_DEM_MASK 0x0c | ||
12 | #define CS4398_DEM_NONE 0x00 | ||
13 | #define CS4398_DEM_44100 0x04 | ||
14 | #define CS4398_DEM_48000 0x08 | ||
15 | #define CS4398_DEM_32000 0x0c | ||
16 | #define CS4398_DIF_MASK 0x70 | ||
17 | #define CS4398_DIF_LJUST 0x00 | ||
18 | #define CS4398_DIF_I2S 0x10 | ||
19 | #define CS4398_DIF_RJUST_16 0x20 | ||
20 | #define CS4398_DIF_RJUST_24 0x30 | ||
21 | #define CS4398_DIF_RJUST_20 0x40 | ||
22 | #define CS4398_DIF_RJUST_18 0x50 | ||
23 | #define CS4398_DSD_SRC 0x80 | ||
24 | /* register 3 */ | ||
25 | #define CS4398_ATAPI_MASK 0x1f | ||
26 | #define CS4398_ATAPI_B_MUTE 0x00 | ||
27 | #define CS4398_ATAPI_B_R 0x01 | ||
28 | #define CS4398_ATAPI_B_L 0x02 | ||
29 | #define CS4398_ATAPI_B_LR 0x03 | ||
30 | #define CS4398_ATAPI_A_MUTE 0x00 | ||
31 | #define CS4398_ATAPI_A_R 0x04 | ||
32 | #define CS4398_ATAPI_A_L 0x08 | ||
33 | #define CS4398_ATAPI_A_LR 0x0c | ||
34 | #define CS4398_ATAPI_MIX_LR_VOL 0x10 | ||
35 | #define CS4398_INVERT_B 0x20 | ||
36 | #define CS4398_INVERT_A 0x40 | ||
37 | #define CS4398_VOL_B_EQ_A 0x80 | ||
38 | /* register 4 */ | ||
39 | #define CS4398_MUTEP_MASK 0x03 | ||
40 | #define CS4398_MUTEP_AUTO 0x00 | ||
41 | #define CS4398_MUTEP_LOW 0x02 | ||
42 | #define CS4398_MUTEP_HIGH 0x03 | ||
43 | #define CS4398_MUTE_B 0x08 | ||
44 | #define CS4398_MUTE_A 0x10 | ||
45 | #define CS4398_MUTEC_A_EQ_B 0x20 | ||
46 | #define CS4398_DAMUTE 0x40 | ||
47 | #define CS4398_PAMUTE 0x80 | ||
48 | /* register 5 */ | ||
49 | #define CS4398_VOL_A_MASK 0xff | ||
50 | /* register 6 */ | ||
51 | #define CS4398_VOL_B_MASK 0xff | ||
52 | /* register 7 */ | ||
53 | #define CS4398_DIR_DSD 0x01 | ||
54 | #define CS4398_FILT_SEL 0x04 | ||
55 | #define CS4398_RMP_DN 0x10 | ||
56 | #define CS4398_RMP_UP 0x20 | ||
57 | #define CS4398_ZERO_CROSS 0x40 | ||
58 | #define CS4398_SOFT_RAMP 0x80 | ||
59 | /* register 8 */ | ||
60 | #define CS4398_MCLKDIV3 0x08 | ||
61 | #define CS4398_MCLKDIV2 0x10 | ||
62 | #define CS4398_FREEZE 0x20 | ||
63 | #define CS4398_CPEN 0x40 | ||
64 | #define CS4398_PDN 0x80 | ||
65 | /* register 9 */ | ||
66 | #define CS4398_DSD_PM_EN 0x01 | ||
67 | #define CS4398_DSD_PM_MODE 0x02 | ||
68 | #define CS4398_INVALID_DSD 0x04 | ||
69 | #define CS4398_STATIC_DSD 0x08 | ||
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c index 666f69a3312e..090dd4354a28 100644 --- a/sound/pci/oxygen/hifier.c +++ b/sound/pci/oxygen/hifier.c | |||
@@ -66,12 +66,12 @@ static void hifier_init(struct oxygen *chip) | |||
66 | { | 66 | { |
67 | struct hifier_data *data = chip->model_data; | 67 | struct hifier_data *data = chip->model_data; |
68 | 68 | ||
69 | data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL; | 69 | data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; |
70 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | 70 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); |
71 | ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2); | 71 | ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2); |
72 | ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); | 72 | ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); |
73 | ak4396_write(chip, AK4396_LCH_ATT, 0xff); | 73 | ak4396_write(chip, AK4396_LCH_ATT, 0); |
74 | ak4396_write(chip, AK4396_RCH_ATT, 0xff); | 74 | ak4396_write(chip, AK4396_RCH_ATT, 0); |
75 | 75 | ||
76 | snd_component_add(chip->card, "AK4396"); | 76 | snd_component_add(chip->card, "AK4396"); |
77 | snd_component_add(chip->card, "CS5340"); | 77 | snd_component_add(chip->card, "CS5340"); |
@@ -127,22 +127,8 @@ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | |||
127 | 127 | ||
128 | static int hifier_control_filter(struct snd_kcontrol_new *template) | 128 | static int hifier_control_filter(struct snd_kcontrol_new *template) |
129 | { | 129 | { |
130 | if (!strcmp(template->name, "Master Playback Volume")) { | 130 | if (!strcmp(template->name, "Stereo Upmixing")) |
131 | template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
132 | template->tlv.p = ak4396_db_scale; | ||
133 | } else if (!strcmp(template->name, "Stereo Upmixing")) { | ||
134 | return 1; /* stereo only - we don't need upmixing */ | 131 | return 1; /* stereo only - we don't need upmixing */ |
135 | } else if (!strcmp(template->name, | ||
136 | SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) || | ||
137 | !strcmp(template->name, | ||
138 | SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) { | ||
139 | return 1; /* no digital input */ | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int hifier_mixer_init(struct oxygen *chip) | ||
145 | { | ||
146 | return 0; | 132 | return 0; |
147 | } | 133 | } |
148 | 134 | ||
@@ -153,18 +139,20 @@ static const struct oxygen_model model_hifier = { | |||
153 | .owner = THIS_MODULE, | 139 | .owner = THIS_MODULE, |
154 | .init = hifier_init, | 140 | .init = hifier_init, |
155 | .control_filter = hifier_control_filter, | 141 | .control_filter = hifier_control_filter, |
156 | .mixer_init = hifier_mixer_init, | ||
157 | .cleanup = hifier_cleanup, | 142 | .cleanup = hifier_cleanup, |
158 | .set_dac_params = set_ak4396_params, | 143 | .set_dac_params = set_ak4396_params, |
159 | .set_adc_params = set_cs5340_params, | 144 | .set_adc_params = set_cs5340_params, |
160 | .update_dac_volume = update_ak4396_volume, | 145 | .update_dac_volume = update_ak4396_volume, |
161 | .update_dac_mute = update_ak4396_mute, | 146 | .update_dac_mute = update_ak4396_mute, |
147 | .dac_tlv = ak4396_db_scale, | ||
162 | .model_data_size = sizeof(struct hifier_data), | 148 | .model_data_size = sizeof(struct hifier_data), |
149 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | | ||
150 | PLAYBACK_1_TO_SPDIF | | ||
151 | CAPTURE_0_FROM_I2S_1, | ||
163 | .dac_channels = 2, | 152 | .dac_channels = 2, |
164 | .used_channels = OXYGEN_CHANNEL_A | | 153 | .dac_volume_min = 0, |
165 | OXYGEN_CHANNEL_SPDIF | | 154 | .dac_volume_max = 255, |
166 | OXYGEN_CHANNEL_MULTICH, | 155 | .function_flags = OXYGEN_FUNCTION_SPI, |
167 | .function_flags = 0, | ||
168 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 156 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
169 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 157 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
170 | }; | 158 | }; |
@@ -181,7 +169,7 @@ static int __devinit hifier_probe(struct pci_dev *pci, | |||
181 | ++dev; | 169 | ++dev; |
182 | return -ENOENT; | 170 | return -ENOENT; |
183 | } | 171 | } |
184 | err = oxygen_pci_probe(pci, index[dev], id[dev], 0, &model_hifier); | 172 | err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier); |
185 | if (err >= 0) | 173 | if (err >= 0) |
186 | ++dev; | 174 | ++dev; |
187 | return err; | 175 | return err; |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 9a9941bb0460..63f185c1ed1e 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <sound/tlv.h> | 39 | #include <sound/tlv.h> |
40 | #include "oxygen.h" | 40 | #include "oxygen.h" |
41 | #include "ak4396.h" | 41 | #include "ak4396.h" |
42 | #include "cm9780.h" | 42 | #include "wm8785.h" |
43 | 43 | ||
44 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 44 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
45 | MODULE_DESCRIPTION("C-Media CMI8788 driver"); | 45 | MODULE_DESCRIPTION("C-Media CMI8788 driver"); |
@@ -78,49 +78,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
78 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 | 78 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 |
79 | #define GPIO_AK5385_DFS_QUAD 0x0002 | 79 | #define GPIO_AK5385_DFS_QUAD 0x0002 |
80 | 80 | ||
81 | #define GPIO_LINE_MUTE CM9780_GPO0 | ||
82 | |||
83 | #define WM8785_R0 0 | ||
84 | #define WM8785_R1 1 | ||
85 | #define WM8785_R2 2 | ||
86 | #define WM8785_R7 7 | ||
87 | |||
88 | /* R0 */ | ||
89 | #define WM8785_MCR_MASK 0x007 | ||
90 | #define WM8785_MCR_SLAVE 0x000 | ||
91 | #define WM8785_MCR_MASTER_128 0x001 | ||
92 | #define WM8785_MCR_MASTER_192 0x002 | ||
93 | #define WM8785_MCR_MASTER_256 0x003 | ||
94 | #define WM8785_MCR_MASTER_384 0x004 | ||
95 | #define WM8785_MCR_MASTER_512 0x005 | ||
96 | #define WM8785_MCR_MASTER_768 0x006 | ||
97 | #define WM8785_OSR_MASK 0x018 | ||
98 | #define WM8785_OSR_SINGLE 0x000 | ||
99 | #define WM8785_OSR_DOUBLE 0x008 | ||
100 | #define WM8785_OSR_QUAD 0x010 | ||
101 | #define WM8785_FORMAT_MASK 0x060 | ||
102 | #define WM8785_FORMAT_RJUST 0x000 | ||
103 | #define WM8785_FORMAT_LJUST 0x020 | ||
104 | #define WM8785_FORMAT_I2S 0x040 | ||
105 | #define WM8785_FORMAT_DSP 0x060 | ||
106 | /* R1 */ | ||
107 | #define WM8785_WL_MASK 0x003 | ||
108 | #define WM8785_WL_16 0x000 | ||
109 | #define WM8785_WL_20 0x001 | ||
110 | #define WM8785_WL_24 0x002 | ||
111 | #define WM8785_WL_32 0x003 | ||
112 | #define WM8785_LRP 0x004 | ||
113 | #define WM8785_BCLKINV 0x008 | ||
114 | #define WM8785_LRSWAP 0x010 | ||
115 | #define WM8785_DEVNO_MASK 0x0e0 | ||
116 | /* R2 */ | ||
117 | #define WM8785_HPFR 0x001 | ||
118 | #define WM8785_HPFL 0x002 | ||
119 | #define WM8785_SDODIS 0x004 | ||
120 | #define WM8785_PWRDNR 0x008 | ||
121 | #define WM8785_PWRDNL 0x010 | ||
122 | #define WM8785_TDM_MASK 0x1c0 | ||
123 | |||
124 | struct generic_data { | 81 | struct generic_data { |
125 | u8 ak4396_ctl2; | 82 | u8 ak4396_ctl2; |
126 | }; | 83 | }; |
@@ -155,7 +112,7 @@ static void ak4396_init(struct oxygen *chip) | |||
155 | struct generic_data *data = chip->model_data; | 112 | struct generic_data *data = chip->model_data; |
156 | unsigned int i; | 113 | unsigned int i; |
157 | 114 | ||
158 | data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL; | 115 | data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; |
159 | for (i = 0; i < 4; ++i) { | 116 | for (i = 0; i < 4; ++i) { |
160 | ak4396_write(chip, i, | 117 | ak4396_write(chip, i, |
161 | AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | 118 | AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); |
@@ -163,8 +120,8 @@ static void ak4396_init(struct oxygen *chip) | |||
163 | AK4396_CONTROL_2, data->ak4396_ctl2); | 120 | AK4396_CONTROL_2, data->ak4396_ctl2); |
164 | ak4396_write(chip, i, | 121 | ak4396_write(chip, i, |
165 | AK4396_CONTROL_3, AK4396_PCM); | 122 | AK4396_CONTROL_3, AK4396_PCM); |
166 | ak4396_write(chip, i, AK4396_LCH_ATT, 0xff); | 123 | ak4396_write(chip, i, AK4396_LCH_ATT, 0); |
167 | ak4396_write(chip, i, AK4396_RCH_ATT, 0xff); | 124 | ak4396_write(chip, i, AK4396_RCH_ATT, 0); |
168 | } | 125 | } |
169 | snd_component_add(chip->card, "AK4396"); | 126 | snd_component_add(chip->card, "AK4396"); |
170 | } | 127 | } |
@@ -185,23 +142,16 @@ static void wm8785_init(struct oxygen *chip) | |||
185 | snd_component_add(chip->card, "WM8785"); | 142 | snd_component_add(chip->card, "WM8785"); |
186 | } | 143 | } |
187 | 144 | ||
188 | static void cmi9780_init(struct oxygen *chip) | ||
189 | { | ||
190 | oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE); | ||
191 | } | ||
192 | |||
193 | static void generic_init(struct oxygen *chip) | 145 | static void generic_init(struct oxygen *chip) |
194 | { | 146 | { |
195 | ak4396_init(chip); | 147 | ak4396_init(chip); |
196 | wm8785_init(chip); | 148 | wm8785_init(chip); |
197 | cmi9780_init(chip); | ||
198 | } | 149 | } |
199 | 150 | ||
200 | static void meridian_init(struct oxygen *chip) | 151 | static void meridian_init(struct oxygen *chip) |
201 | { | 152 | { |
202 | ak4396_init(chip); | 153 | ak4396_init(chip); |
203 | ak5385_init(chip); | 154 | ak5385_init(chip); |
204 | cmi9780_init(chip); | ||
205 | } | 155 | } |
206 | 156 | ||
207 | static void generic_cleanup(struct oxygen *chip) | 157 | static void generic_cleanup(struct oxygen *chip) |
@@ -297,59 +247,32 @@ static void set_ak5385_params(struct oxygen *chip, | |||
297 | value, GPIO_AK5385_DFS_MASK); | 247 | value, GPIO_AK5385_DFS_MASK); |
298 | } | 248 | } |
299 | 249 | ||
300 | static void cmi9780_switch_hook(struct oxygen *chip, unsigned int codec, | ||
301 | unsigned int reg, int mute) | ||
302 | { | ||
303 | if (codec != 0) | ||
304 | return; | ||
305 | switch (reg) { | ||
306 | case AC97_LINE: | ||
307 | oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, | ||
308 | mute ? GPIO_LINE_MUTE : 0, | ||
309 | GPIO_LINE_MUTE); | ||
310 | break; | ||
311 | case AC97_MIC: | ||
312 | case AC97_CD: | ||
313 | case AC97_AUX: | ||
314 | if (!mute) | ||
315 | oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS, | ||
316 | GPIO_LINE_MUTE); | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 250 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
322 | 251 | ||
323 | static int ak4396_control_filter(struct snd_kcontrol_new *template) | ||
324 | { | ||
325 | if (!strcmp(template->name, "Master Playback Volume")) { | ||
326 | template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
327 | template->tlv.p = ak4396_db_scale; | ||
328 | } | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static const struct oxygen_model model_generic = { | 252 | static const struct oxygen_model model_generic = { |
333 | .shortname = "C-Media CMI8788", | 253 | .shortname = "C-Media CMI8788", |
334 | .longname = "C-Media Oxygen HD Audio", | 254 | .longname = "C-Media Oxygen HD Audio", |
335 | .chip = "CMI8788", | 255 | .chip = "CMI8788", |
336 | .owner = THIS_MODULE, | 256 | .owner = THIS_MODULE, |
337 | .init = generic_init, | 257 | .init = generic_init, |
338 | .control_filter = ak4396_control_filter, | ||
339 | .cleanup = generic_cleanup, | 258 | .cleanup = generic_cleanup, |
340 | .set_dac_params = set_ak4396_params, | 259 | .set_dac_params = set_ak4396_params, |
341 | .set_adc_params = set_wm8785_params, | 260 | .set_adc_params = set_wm8785_params, |
342 | .update_dac_volume = update_ak4396_volume, | 261 | .update_dac_volume = update_ak4396_volume, |
343 | .update_dac_mute = update_ak4396_mute, | 262 | .update_dac_mute = update_ak4396_mute, |
344 | .ac97_switch_hook = cmi9780_switch_hook, | 263 | .dac_tlv = ak4396_db_scale, |
345 | .model_data_size = sizeof(struct generic_data), | 264 | .model_data_size = sizeof(struct generic_data), |
265 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | | ||
266 | PLAYBACK_1_TO_SPDIF | | ||
267 | PLAYBACK_2_TO_AC97_1 | | ||
268 | CAPTURE_0_FROM_I2S_1 | | ||
269 | CAPTURE_1_FROM_SPDIF | | ||
270 | CAPTURE_2_FROM_AC97_1, | ||
346 | .dac_channels = 8, | 271 | .dac_channels = 8, |
347 | .used_channels = OXYGEN_CHANNEL_A | | 272 | .dac_volume_min = 0, |
348 | OXYGEN_CHANNEL_C | | 273 | .dac_volume_max = 255, |
349 | OXYGEN_CHANNEL_SPDIF | | 274 | .function_flags = OXYGEN_FUNCTION_SPI | |
350 | OXYGEN_CHANNEL_MULTICH | | 275 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
351 | OXYGEN_CHANNEL_AC97, | ||
352 | .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5, | ||
353 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 276 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
354 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 277 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
355 | }; | 278 | }; |
@@ -359,21 +282,25 @@ static const struct oxygen_model model_meridian = { | |||
359 | .chip = "CMI8788", | 282 | .chip = "CMI8788", |
360 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
361 | .init = meridian_init, | 284 | .init = meridian_init, |
362 | .control_filter = ak4396_control_filter, | ||
363 | .cleanup = generic_cleanup, | 285 | .cleanup = generic_cleanup, |
364 | .set_dac_params = set_ak4396_params, | 286 | .set_dac_params = set_ak4396_params, |
365 | .set_adc_params = set_ak5385_params, | 287 | .set_adc_params = set_ak5385_params, |
366 | .update_dac_volume = update_ak4396_volume, | 288 | .update_dac_volume = update_ak4396_volume, |
367 | .update_dac_mute = update_ak4396_mute, | 289 | .update_dac_mute = update_ak4396_mute, |
368 | .ac97_switch_hook = cmi9780_switch_hook, | 290 | .dac_tlv = ak4396_db_scale, |
369 | .model_data_size = sizeof(struct generic_data), | 291 | .model_data_size = sizeof(struct generic_data), |
292 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | | ||
293 | PLAYBACK_1_TO_SPDIF | | ||
294 | PLAYBACK_2_TO_AC97_1 | | ||
295 | CAPTURE_0_FROM_I2S_2 | | ||
296 | CAPTURE_1_FROM_SPDIF | | ||
297 | CAPTURE_2_FROM_AC97_1, | ||
370 | .dac_channels = 8, | 298 | .dac_channels = 8, |
371 | .used_channels = OXYGEN_CHANNEL_B | | 299 | .dac_volume_min = 0, |
372 | OXYGEN_CHANNEL_C | | 300 | .dac_volume_max = 255, |
373 | OXYGEN_CHANNEL_SPDIF | | 301 | .misc_flags = OXYGEN_MISC_MIDI, |
374 | OXYGEN_CHANNEL_MULTICH | | 302 | .function_flags = OXYGEN_FUNCTION_SPI | |
375 | OXYGEN_CHANNEL_AC97, | 303 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
376 | .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5, | ||
377 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 304 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
378 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 305 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
379 | }; | 306 | }; |
@@ -392,7 +319,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci, | |||
392 | return -ENOENT; | 319 | return -ENOENT; |
393 | } | 320 | } |
394 | is_meridian = pci_id->driver_data; | 321 | is_meridian = pci_id->driver_data; |
395 | err = oxygen_pci_probe(pci, index[dev], id[dev], is_meridian, | 322 | err = oxygen_pci_probe(pci, index[dev], id[dev], |
396 | is_meridian ? &model_meridian : &model_generic); | 323 | is_meridian ? &model_meridian : &model_generic); |
397 | if (err >= 0) | 324 | if (err >= 0) |
398 | ++dev; | 325 | ++dev; |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index ad50fb8b206b..a71c6e059260 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -16,6 +16,16 @@ | |||
16 | #define PCM_AC97 5 | 16 | #define PCM_AC97 5 |
17 | #define PCM_COUNT 6 | 17 | #define PCM_COUNT 6 |
18 | 18 | ||
19 | /* model-specific configuration of outputs/inputs */ | ||
20 | #define PLAYBACK_0_TO_I2S 0x001 | ||
21 | #define PLAYBACK_1_TO_SPDIF 0x004 | ||
22 | #define PLAYBACK_2_TO_AC97_1 0x008 | ||
23 | #define CAPTURE_0_FROM_I2S_1 0x010 | ||
24 | #define CAPTURE_0_FROM_I2S_2 0x020 | ||
25 | #define CAPTURE_1_FROM_SPDIF 0x080 | ||
26 | #define CAPTURE_2_FROM_I2S_2 0x100 | ||
27 | #define CAPTURE_2_FROM_AC97_1 0x200 | ||
28 | |||
19 | enum { | 29 | enum { |
20 | CONTROL_SPDIF_PCM, | 30 | CONTROL_SPDIF_PCM, |
21 | CONTROL_SPDIF_INPUT_BITS, | 31 | CONTROL_SPDIF_INPUT_BITS, |
@@ -87,12 +97,16 @@ struct oxygen_model { | |||
87 | struct snd_pcm_hw_params *params); | 97 | struct snd_pcm_hw_params *params); |
88 | void (*update_dac_volume)(struct oxygen *chip); | 98 | void (*update_dac_volume)(struct oxygen *chip); |
89 | void (*update_dac_mute)(struct oxygen *chip); | 99 | void (*update_dac_mute)(struct oxygen *chip); |
90 | void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec, | ||
91 | unsigned int reg, int mute); | ||
92 | void (*gpio_changed)(struct oxygen *chip); | 100 | void (*gpio_changed)(struct oxygen *chip); |
101 | void (*ac97_switch)(struct oxygen *chip, | ||
102 | unsigned int reg, unsigned int mute); | ||
103 | const unsigned int *dac_tlv; | ||
93 | size_t model_data_size; | 104 | size_t model_data_size; |
105 | unsigned int pcm_dev_cfg; | ||
94 | u8 dac_channels; | 106 | u8 dac_channels; |
95 | u8 used_channels; | 107 | u8 dac_volume_min; |
108 | u8 dac_volume_max; | ||
109 | u8 misc_flags; | ||
96 | u8 function_flags; | 110 | u8 function_flags; |
97 | u16 dac_i2s_format; | 111 | u16 dac_i2s_format; |
98 | u16 adc_i2s_format; | 112 | u16 adc_i2s_format; |
@@ -100,7 +114,7 @@ struct oxygen_model { | |||
100 | 114 | ||
101 | /* oxygen_lib.c */ | 115 | /* oxygen_lib.c */ |
102 | 116 | ||
103 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, int midi, | 117 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
104 | const struct oxygen_model *model); | 118 | const struct oxygen_model *model); |
105 | void oxygen_pci_remove(struct pci_dev *pci); | 119 | void oxygen_pci_remove(struct pci_dev *pci); |
106 | 120 | ||
@@ -137,6 +151,7 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, | |||
137 | unsigned int index, u16 data, u16 mask); | 151 | unsigned int index, u16 data, u16 mask); |
138 | 152 | ||
139 | void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); | 153 | void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); |
154 | void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); | ||
140 | 155 | ||
141 | static inline void oxygen_set_bits8(struct oxygen *chip, | 156 | static inline void oxygen_set_bits8(struct oxygen *chip, |
142 | unsigned int reg, u8 value) | 157 | unsigned int reg, u8 value) |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 74e23ef9c946..5569606ee87f 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
@@ -190,12 +190,31 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data) | |||
190 | --count; | 190 | --count; |
191 | } | 191 | } |
192 | 192 | ||
193 | spin_lock_irq(&chip->reg_lock); | ||
194 | oxygen_write8(chip, OXYGEN_SPI_DATA1, data); | 193 | oxygen_write8(chip, OXYGEN_SPI_DATA1, data); |
195 | oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8); | 194 | oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8); |
196 | if (control & OXYGEN_SPI_DATA_LENGTH_3) | 195 | if (control & OXYGEN_SPI_DATA_LENGTH_3) |
197 | oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16); | 196 | oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16); |
198 | oxygen_write8(chip, OXYGEN_SPI_CONTROL, control); | 197 | oxygen_write8(chip, OXYGEN_SPI_CONTROL, control); |
199 | spin_unlock_irq(&chip->reg_lock); | ||
200 | } | 198 | } |
201 | EXPORT_SYMBOL(oxygen_write_spi); | 199 | EXPORT_SYMBOL(oxygen_write_spi); |
200 | |||
201 | void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data) | ||
202 | { | ||
203 | unsigned long timeout; | ||
204 | |||
205 | /* should not need more than about 300 us */ | ||
206 | timeout = jiffies + msecs_to_jiffies(1); | ||
207 | do { | ||
208 | if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS) | ||
209 | & OXYGEN_2WIRE_BUSY)) | ||
210 | break; | ||
211 | udelay(1); | ||
212 | cond_resched(); | ||
213 | } while (time_after_eq(timeout, jiffies)); | ||
214 | |||
215 | oxygen_write8(chip, OXYGEN_2WIRE_MAP, map); | ||
216 | oxygen_write8(chip, OXYGEN_2WIRE_DATA, data); | ||
217 | oxygen_write8(chip, OXYGEN_2WIRE_CONTROL, | ||
218 | device | OXYGEN_2WIRE_DIR_WRITE); | ||
219 | } | ||
220 | EXPORT_SYMBOL(oxygen_write_i2c); | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 78c21155218e..897697d43506 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -221,7 +221,8 @@ static void oxygen_init(struct oxygen *chip) | |||
221 | 221 | ||
222 | chip->dac_routing = 1; | 222 | chip->dac_routing = 1; |
223 | for (i = 0; i < 8; ++i) | 223 | for (i = 0; i < 8; ++i) |
224 | chip->dac_volume[i] = 0xff; | 224 | chip->dac_volume[i] = chip->model->dac_volume_min; |
225 | chip->dac_mute = 1; | ||
225 | chip->spdif_playback_enable = 1; | 226 | chip->spdif_playback_enable = 1; |
226 | chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | | 227 | chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | |
227 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); | 228 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); |
@@ -240,12 +241,12 @@ static void oxygen_init(struct oxygen *chip) | |||
240 | chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0; | 241 | chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0; |
241 | chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0; | 242 | chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0; |
242 | 243 | ||
243 | oxygen_set_bits8(chip, OXYGEN_FUNCTION, | ||
244 | OXYGEN_FUNCTION_RESET_CODEC | | ||
245 | chip->model->function_flags); | ||
246 | oxygen_write8_masked(chip, OXYGEN_FUNCTION, | 244 | oxygen_write8_masked(chip, OXYGEN_FUNCTION, |
247 | OXYGEN_FUNCTION_SPI, | 245 | OXYGEN_FUNCTION_RESET_CODEC | |
248 | OXYGEN_FUNCTION_2WIRE_SPI_MASK); | 246 | chip->model->function_flags, |
247 | OXYGEN_FUNCTION_RESET_CODEC | | ||
248 | OXYGEN_FUNCTION_2WIRE_SPI_MASK | | ||
249 | OXYGEN_FUNCTION_ENABLE_SPI_4_5); | ||
249 | oxygen_write8(chip, OXYGEN_DMA_STATUS, 0); | 250 | oxygen_write8(chip, OXYGEN_DMA_STATUS, 0); |
250 | oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0); | 251 | oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0); |
251 | oxygen_write8(chip, OXYGEN_PLAY_CHANNELS, | 252 | oxygen_write8(chip, OXYGEN_PLAY_CHANNELS, |
@@ -253,11 +254,13 @@ static void oxygen_init(struct oxygen *chip) | |||
253 | OXYGEN_DMA_A_BURST_8 | | 254 | OXYGEN_DMA_A_BURST_8 | |
254 | OXYGEN_DMA_MULTICH_BURST_8); | 255 | OXYGEN_DMA_MULTICH_BURST_8); |
255 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); | 256 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); |
256 | oxygen_write8_masked(chip, OXYGEN_MISC, 0, | 257 | oxygen_write8_masked(chip, OXYGEN_MISC, |
258 | chip->model->misc_flags, | ||
257 | OXYGEN_MISC_WRITE_PCI_SUBID | | 259 | OXYGEN_MISC_WRITE_PCI_SUBID | |
258 | OXYGEN_MISC_REC_C_FROM_SPDIF | | 260 | OXYGEN_MISC_REC_C_FROM_SPDIF | |
259 | OXYGEN_MISC_REC_B_FROM_AC97 | | 261 | OXYGEN_MISC_REC_B_FROM_AC97 | |
260 | OXYGEN_MISC_REC_A_FROM_MULTICH); | 262 | OXYGEN_MISC_REC_A_FROM_MULTICH | |
263 | OXYGEN_MISC_MIDI); | ||
261 | oxygen_write8(chip, OXYGEN_REC_FORMAT, | 264 | oxygen_write8(chip, OXYGEN_REC_FORMAT, |
262 | (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) | | 265 | (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) | |
263 | (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) | | 266 | (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) | |
@@ -267,35 +270,49 @@ static void oxygen_init(struct oxygen *chip) | |||
267 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); | 270 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); |
268 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); | 271 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); |
269 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, | 272 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, |
270 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | | 273 | OXYGEN_RATE_48000 | chip->model->dac_i2s_format | |
271 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | 274 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | |
272 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | ||
273 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
274 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | | ||
275 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | ||
276 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | ||
277 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | ||
278 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | | ||
279 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | ||
280 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 275 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); |
276 | if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1) | ||
277 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
278 | OXYGEN_RATE_48000 | chip->model->adc_i2s_format | | ||
279 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | ||
280 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | ||
281 | else | ||
282 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
283 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | ||
284 | if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 | | ||
285 | CAPTURE_2_FROM_I2S_2)) | ||
286 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | ||
287 | OXYGEN_RATE_48000 | chip->model->adc_i2s_format | | ||
288 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | ||
289 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | ||
290 | else | ||
291 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | ||
292 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | ||
281 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, | 293 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, |
282 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | | 294 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); |
283 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | 295 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
284 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 296 | OXYGEN_SPDIF_OUT_ENABLE | |
285 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, | 297 | OXYGEN_SPDIF_LOOPBACK); |
286 | OXYGEN_SPDIF_SENSE_MASK | | 298 | if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) |
287 | OXYGEN_SPDIF_LOCK_MASK | | 299 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, |
288 | OXYGEN_SPDIF_RATE_MASK | | 300 | OXYGEN_SPDIF_SENSE_MASK | |
289 | OXYGEN_SPDIF_LOCK_PAR | | 301 | OXYGEN_SPDIF_LOCK_MASK | |
290 | OXYGEN_SPDIF_IN_CLOCK_96, | 302 | OXYGEN_SPDIF_RATE_MASK | |
291 | OXYGEN_SPDIF_OUT_ENABLE | | 303 | OXYGEN_SPDIF_LOCK_PAR | |
292 | OXYGEN_SPDIF_LOOPBACK | | 304 | OXYGEN_SPDIF_IN_CLOCK_96, |
293 | OXYGEN_SPDIF_SENSE_MASK | | 305 | OXYGEN_SPDIF_SENSE_MASK | |
294 | OXYGEN_SPDIF_LOCK_MASK | | 306 | OXYGEN_SPDIF_LOCK_MASK | |
295 | OXYGEN_SPDIF_RATE_MASK | | 307 | OXYGEN_SPDIF_RATE_MASK | |
296 | OXYGEN_SPDIF_SENSE_PAR | | 308 | OXYGEN_SPDIF_SENSE_PAR | |
297 | OXYGEN_SPDIF_LOCK_PAR | | 309 | OXYGEN_SPDIF_LOCK_PAR | |
298 | OXYGEN_SPDIF_IN_CLOCK_MASK); | 310 | OXYGEN_SPDIF_IN_CLOCK_MASK); |
311 | else | ||
312 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | ||
313 | OXYGEN_SPDIF_SENSE_MASK | | ||
314 | OXYGEN_SPDIF_LOCK_MASK | | ||
315 | OXYGEN_SPDIF_RATE_MASK); | ||
299 | oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); | 316 | oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); |
300 | oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK); | 317 | oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK); |
301 | oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0); | 318 | oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0); |
@@ -318,9 +335,12 @@ static void oxygen_init(struct oxygen *chip) | |||
318 | (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) | | 335 | (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) | |
319 | (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT)); | 336 | (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT)); |
320 | 337 | ||
321 | oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, | 338 | if (chip->has_ac97_0 | chip->has_ac97_1) |
322 | OXYGEN_AC97_INT_READ_DONE | | 339 | oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, |
323 | OXYGEN_AC97_INT_WRITE_DONE); | 340 | OXYGEN_AC97_INT_READ_DONE | |
341 | OXYGEN_AC97_INT_WRITE_DONE); | ||
342 | else | ||
343 | oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0); | ||
324 | oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0); | 344 | oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0); |
325 | oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0); | 345 | oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0); |
326 | if (!(chip->has_ac97_0 | chip->has_ac97_1)) | 346 | if (!(chip->has_ac97_0 | chip->has_ac97_1)) |
@@ -351,6 +371,8 @@ static void oxygen_init(struct oxygen *chip) | |||
351 | oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000); | 371 | oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000); |
352 | oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080); | 372 | oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080); |
353 | oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080); | 373 | oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080); |
374 | oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, | ||
375 | CM9780_GPO0); | ||
354 | /* power down unused ADCs and DACs */ | 376 | /* power down unused ADCs and DACs */ |
355 | oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN, | 377 | oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN, |
356 | AC97_PD_PR0 | AC97_PD_PR1); | 378 | AC97_PD_PR0 | AC97_PD_PR1); |
@@ -388,10 +410,8 @@ static void oxygen_card_free(struct snd_card *card) | |||
388 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); | 410 | oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); |
389 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); | 411 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); |
390 | spin_unlock_irq(&chip->reg_lock); | 412 | spin_unlock_irq(&chip->reg_lock); |
391 | if (chip->irq >= 0) { | 413 | if (chip->irq >= 0) |
392 | free_irq(chip->irq, chip); | 414 | free_irq(chip->irq, chip); |
393 | synchronize_irq(chip->irq); | ||
394 | } | ||
395 | flush_scheduled_work(); | 415 | flush_scheduled_work(); |
396 | chip->model->cleanup(chip); | 416 | chip->model->cleanup(chip); |
397 | mutex_destroy(&chip->mutex); | 417 | mutex_destroy(&chip->mutex); |
@@ -400,7 +420,7 @@ static void oxygen_card_free(struct snd_card *card) | |||
400 | } | 420 | } |
401 | 421 | ||
402 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | 422 | int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, |
403 | int midi, const struct oxygen_model *model) | 423 | const struct oxygen_model *model) |
404 | { | 424 | { |
405 | struct snd_card *card; | 425 | struct snd_card *card; |
406 | struct oxygen *chip; | 426 | struct oxygen *chip; |
@@ -472,9 +492,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
472 | if (err < 0) | 492 | if (err < 0) |
473 | goto err_card; | 493 | goto err_card; |
474 | 494 | ||
475 | oxygen_write8_masked(chip, OXYGEN_MISC, | 495 | if (model->misc_flags & OXYGEN_MISC_MIDI) { |
476 | midi ? OXYGEN_MISC_MIDI : 0, OXYGEN_MISC_MIDI); | ||
477 | if (midi) { | ||
478 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, | 496 | err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, |
479 | chip->addr + OXYGEN_MPU401, | 497 | chip->addr + OXYGEN_MPU401, |
480 | MPU401_INFO_INTEGRATED, 0, 0, | 498 | MPU401_INFO_INTEGRATED, 0, 0, |
@@ -486,7 +504,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
486 | oxygen_proc_init(chip); | 504 | oxygen_proc_init(chip); |
487 | 505 | ||
488 | spin_lock_irq(&chip->reg_lock); | 506 | spin_lock_irq(&chip->reg_lock); |
489 | chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97; | 507 | if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) |
508 | chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; | ||
509 | if (chip->has_ac97_0 | chip->has_ac97_1) | ||
510 | chip->interrupt_mask |= OXYGEN_INT_AC97; | ||
490 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); | 511 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); |
491 | spin_unlock_irq(&chip->reg_lock); | 512 | spin_unlock_irq(&chip->reg_lock); |
492 | 513 | ||
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index a8e4623415d9..cc0cddadd589 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -32,8 +32,8 @@ static int dac_volume_info(struct snd_kcontrol *ctl, | |||
32 | 32 | ||
33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
34 | info->count = chip->model->dac_channels; | 34 | info->count = chip->model->dac_channels; |
35 | info->value.integer.min = 0; | 35 | info->value.integer.min = chip->model->dac_volume_min; |
36 | info->value.integer.max = 0xff; | 36 | info->value.integer.max = chip->model->dac_volume_max; |
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl, | |||
446 | return changed; | 446 | return changed; |
447 | } | 447 | } |
448 | 448 | ||
449 | static int monitor_volume_info(struct snd_kcontrol *ctl, | ||
450 | struct snd_ctl_elem_info *info) | ||
451 | { | ||
452 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
453 | info->count = 1; | ||
454 | info->value.integer.min = 0; | ||
455 | info->value.integer.max = 1; | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int monitor_get(struct snd_kcontrol *ctl, | ||
460 | struct snd_ctl_elem_value *value) | ||
461 | { | ||
462 | struct oxygen *chip = ctl->private_data; | ||
463 | u8 bit = ctl->private_value; | ||
464 | int invert = ctl->private_value & (1 << 8); | ||
465 | |||
466 | value->value.integer.value[0] = | ||
467 | !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int monitor_put(struct snd_kcontrol *ctl, | ||
472 | struct snd_ctl_elem_value *value) | ||
473 | { | ||
474 | struct oxygen *chip = ctl->private_data; | ||
475 | u8 bit = ctl->private_value; | ||
476 | int invert = ctl->private_value & (1 << 8); | ||
477 | u8 oldreg, newreg; | ||
478 | int changed; | ||
479 | |||
480 | spin_lock_irq(&chip->reg_lock); | ||
481 | oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR); | ||
482 | if ((!!value->value.integer.value[0] ^ !!invert) != 0) | ||
483 | newreg = oldreg | bit; | ||
484 | else | ||
485 | newreg = oldreg & ~bit; | ||
486 | changed = newreg != oldreg; | ||
487 | if (changed) | ||
488 | oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg); | ||
489 | spin_unlock_irq(&chip->reg_lock); | ||
490 | return changed; | ||
491 | } | ||
492 | |||
449 | static int ac97_switch_get(struct snd_kcontrol *ctl, | 493 | static int ac97_switch_get(struct snd_kcontrol *ctl, |
450 | struct snd_ctl_elem_value *value) | 494 | struct snd_ctl_elem_value *value) |
451 | { | 495 | { |
@@ -466,6 +510,21 @@ static int ac97_switch_get(struct snd_kcontrol *ctl, | |||
466 | return 0; | 510 | return 0; |
467 | } | 511 | } |
468 | 512 | ||
513 | static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) | ||
514 | { | ||
515 | unsigned int priv_idx = chip->controls[control]->private_value & 0xff; | ||
516 | u16 value; | ||
517 | |||
518 | value = oxygen_read_ac97(chip, 0, priv_idx); | ||
519 | if (!(value & 0x8000)) { | ||
520 | oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000); | ||
521 | if (chip->model->ac97_switch) | ||
522 | chip->model->ac97_switch(chip, priv_idx, 0x8000); | ||
523 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
524 | &chip->controls[control]->id); | ||
525 | } | ||
526 | } | ||
527 | |||
469 | static int ac97_switch_put(struct snd_kcontrol *ctl, | 528 | static int ac97_switch_put(struct snd_kcontrol *ctl, |
470 | struct snd_ctl_elem_value *value) | 529 | struct snd_ctl_elem_value *value) |
471 | { | 530 | { |
@@ -487,9 +546,24 @@ static int ac97_switch_put(struct snd_kcontrol *ctl, | |||
487 | change = newreg != oldreg; | 546 | change = newreg != oldreg; |
488 | if (change) { | 547 | if (change) { |
489 | oxygen_write_ac97(chip, codec, index, newreg); | 548 | oxygen_write_ac97(chip, codec, index, newreg); |
490 | if (bitnr == 15 && chip->model->ac97_switch_hook) | 549 | if (codec == 0 && chip->model->ac97_switch) |
491 | chip->model->ac97_switch_hook(chip, codec, index, | 550 | chip->model->ac97_switch(chip, index, newreg & 0x8000); |
492 | newreg & 0x8000); | 551 | if (index == AC97_LINE) { |
552 | oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, | ||
553 | newreg & 0x8000 ? | ||
554 | CM9780_GPO0 : 0, CM9780_GPO0); | ||
555 | if (!(newreg & 0x8000)) { | ||
556 | mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH); | ||
557 | mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH); | ||
558 | mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH); | ||
559 | } | ||
560 | } else if ((index == AC97_MIC || index == AC97_CD || | ||
561 | index == AC97_VIDEO || index == AC97_AUX) && | ||
562 | bitnr == 15 && !(newreg & 0x8000)) { | ||
563 | mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH); | ||
564 | oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, | ||
565 | CM9780_GPO0, CM9780_GPO0); | ||
566 | } | ||
493 | } | 567 | } |
494 | mutex_unlock(&chip->mutex); | 568 | mutex_unlock(&chip->mutex); |
495 | return change; | 569 | return change; |
@@ -608,6 +682,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, | |||
608 | .private_value = ((codec) << 24) | (index), \ | 682 | .private_value = ((codec) << 24) | (index), \ |
609 | } | 683 | } |
610 | 684 | ||
685 | static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0); | ||
611 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); | 686 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); |
612 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); | 687 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); |
613 | 688 | ||
@@ -667,6 +742,9 @@ static const struct snd_kcontrol_new controls[] = { | |||
667 | .get = spdif_pcm_get, | 742 | .get = spdif_pcm_get, |
668 | .put = spdif_pcm_put, | 743 | .put = spdif_pcm_put, |
669 | }, | 744 | }, |
745 | }; | ||
746 | |||
747 | static const struct snd_kcontrol_new spdif_input_controls[] = { | ||
670 | { | 748 | { |
671 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 749 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
672 | .device = 1, | 750 | .device = 1, |
@@ -692,11 +770,118 @@ static const struct snd_kcontrol_new controls[] = { | |||
692 | }, | 770 | }, |
693 | }; | 771 | }; |
694 | 772 | ||
773 | static const struct { | ||
774 | unsigned int pcm_dev; | ||
775 | struct snd_kcontrol_new controls[2]; | ||
776 | } monitor_controls[] = { | ||
777 | { | ||
778 | .pcm_dev = CAPTURE_0_FROM_I2S_1, | ||
779 | .controls = { | ||
780 | { | ||
781 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
782 | .name = "Analog Input Monitor Switch", | ||
783 | .info = snd_ctl_boolean_mono_info, | ||
784 | .get = monitor_get, | ||
785 | .put = monitor_put, | ||
786 | .private_value = OXYGEN_ADC_MONITOR_A, | ||
787 | }, | ||
788 | { | ||
789 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
790 | .name = "Analog Input Monitor Volume", | ||
791 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
792 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
793 | .info = monitor_volume_info, | ||
794 | .get = monitor_get, | ||
795 | .put = monitor_put, | ||
796 | .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL | ||
797 | | (1 << 8), | ||
798 | .tlv = { .p = monitor_db_scale, }, | ||
799 | }, | ||
800 | }, | ||
801 | }, | ||
802 | { | ||
803 | .pcm_dev = CAPTURE_0_FROM_I2S_2, | ||
804 | .controls = { | ||
805 | { | ||
806 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
807 | .name = "Analog Input Monitor Switch", | ||
808 | .info = snd_ctl_boolean_mono_info, | ||
809 | .get = monitor_get, | ||
810 | .put = monitor_put, | ||
811 | .private_value = OXYGEN_ADC_MONITOR_B, | ||
812 | }, | ||
813 | { | ||
814 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
815 | .name = "Analog Input Monitor Volume", | ||
816 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
817 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
818 | .info = monitor_volume_info, | ||
819 | .get = monitor_get, | ||
820 | .put = monitor_put, | ||
821 | .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | ||
822 | | (1 << 8), | ||
823 | .tlv = { .p = monitor_db_scale, }, | ||
824 | }, | ||
825 | }, | ||
826 | }, | ||
827 | { | ||
828 | .pcm_dev = CAPTURE_2_FROM_I2S_2, | ||
829 | .controls = { | ||
830 | { | ||
831 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
832 | .name = "Analog Input Monitor Switch", | ||
833 | .index = 1, | ||
834 | .info = snd_ctl_boolean_mono_info, | ||
835 | .get = monitor_get, | ||
836 | .put = monitor_put, | ||
837 | .private_value = OXYGEN_ADC_MONITOR_B, | ||
838 | }, | ||
839 | { | ||
840 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
841 | .name = "Analog Input Monitor Volume", | ||
842 | .index = 1, | ||
843 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
844 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
845 | .info = monitor_volume_info, | ||
846 | .get = monitor_get, | ||
847 | .put = monitor_put, | ||
848 | .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL | ||
849 | | (1 << 8), | ||
850 | .tlv = { .p = monitor_db_scale, }, | ||
851 | }, | ||
852 | }, | ||
853 | }, | ||
854 | { | ||
855 | .pcm_dev = CAPTURE_1_FROM_SPDIF, | ||
856 | .controls = { | ||
857 | { | ||
858 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
859 | .name = "Digital Input Monitor Switch", | ||
860 | .info = snd_ctl_boolean_mono_info, | ||
861 | .get = monitor_get, | ||
862 | .put = monitor_put, | ||
863 | .private_value = OXYGEN_ADC_MONITOR_C, | ||
864 | }, | ||
865 | { | ||
866 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
867 | .name = "Digital Input Monitor Volume", | ||
868 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
869 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
870 | .info = monitor_volume_info, | ||
871 | .get = monitor_get, | ||
872 | .put = monitor_put, | ||
873 | .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL | ||
874 | | (1 << 8), | ||
875 | .tlv = { .p = monitor_db_scale, }, | ||
876 | }, | ||
877 | }, | ||
878 | }, | ||
879 | }; | ||
880 | |||
695 | static const struct snd_kcontrol_new ac97_controls[] = { | 881 | static const struct snd_kcontrol_new ac97_controls[] = { |
696 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC), | 882 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC), |
697 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), | 883 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), |
698 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), | 884 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), |
699 | AC97_VOLUME("Line Capture Volume", 0, AC97_LINE), | ||
700 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), | 885 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), |
701 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD), | 886 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD), |
702 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), | 887 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), |
@@ -756,6 +941,11 @@ static int add_controls(struct oxygen *chip, | |||
756 | return err; | 941 | return err; |
757 | if (err == 1) | 942 | if (err == 1) |
758 | continue; | 943 | continue; |
944 | if (!strcmp(template.name, "Master Playback Volume") && | ||
945 | chip->model->dac_tlv) { | ||
946 | template.tlv.p = chip->model->dac_tlv; | ||
947 | template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
948 | } | ||
759 | ctl = snd_ctl_new1(&template, chip); | 949 | ctl = snd_ctl_new1(&template, chip); |
760 | if (!ctl) | 950 | if (!ctl) |
761 | return -ENOMEM; | 951 | return -ENOMEM; |
@@ -773,11 +963,26 @@ static int add_controls(struct oxygen *chip, | |||
773 | 963 | ||
774 | int oxygen_mixer_init(struct oxygen *chip) | 964 | int oxygen_mixer_init(struct oxygen *chip) |
775 | { | 965 | { |
966 | unsigned int i; | ||
776 | int err; | 967 | int err; |
777 | 968 | ||
778 | err = add_controls(chip, controls, ARRAY_SIZE(controls)); | 969 | err = add_controls(chip, controls, ARRAY_SIZE(controls)); |
779 | if (err < 0) | 970 | if (err < 0) |
780 | return err; | 971 | return err; |
972 | if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) { | ||
973 | err = add_controls(chip, spdif_input_controls, | ||
974 | ARRAY_SIZE(spdif_input_controls)); | ||
975 | if (err < 0) | ||
976 | return err; | ||
977 | } | ||
978 | for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) { | ||
979 | if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev)) | ||
980 | continue; | ||
981 | err = add_controls(chip, monitor_controls[i].controls, | ||
982 | ARRAY_SIZE(monitor_controls[i].controls)); | ||
983 | if (err < 0) | ||
984 | return err; | ||
985 | } | ||
781 | if (chip->has_ac97_0) { | 986 | if (chip->has_ac97_0) { |
782 | err = add_controls(chip, ac97_controls, | 987 | err = add_controls(chip, ac97_controls, |
783 | ARRAY_SIZE(ac97_controls)); | 988 | ARRAY_SIZE(ac97_controls)); |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index b70046aca657..b17c405e069d 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -119,7 +119,7 @@ static int oxygen_open(struct snd_pcm_substream *substream, | |||
119 | 119 | ||
120 | runtime->private_data = (void *)(uintptr_t)channel; | 120 | runtime->private_data = (void *)(uintptr_t)channel; |
121 | if (channel == PCM_B && chip->has_ac97_1 && | 121 | if (channel == PCM_B && chip->has_ac97_1 && |
122 | (chip->model->used_channels & OXYGEN_CHANNEL_AC97)) | 122 | (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1)) |
123 | runtime->hw = oxygen_ac97_hardware; | 123 | runtime->hw = oxygen_ac97_hardware; |
124 | else | 124 | else |
125 | runtime->hw = *oxygen_hardware[channel]; | 125 | runtime->hw = *oxygen_hardware[channel]; |
@@ -365,7 +365,7 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, | |||
365 | return err; | 365 | return err; |
366 | 366 | ||
367 | is_ac97 = chip->has_ac97_1 && | 367 | is_ac97 = chip->has_ac97_1 && |
368 | (chip->model->used_channels & OXYGEN_CHANNEL_AC97); | 368 | (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1); |
369 | 369 | ||
370 | spin_lock_irq(&chip->reg_lock); | 370 | spin_lock_irq(&chip->reg_lock); |
371 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, | 371 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, |
@@ -640,34 +640,39 @@ int oxygen_pcm_init(struct oxygen *chip) | |||
640 | int outs, ins; | 640 | int outs, ins; |
641 | int err; | 641 | int err; |
642 | 642 | ||
643 | outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */ | 643 | outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_0_TO_I2S); |
644 | ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A | | 644 | ins = !!(chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_1 | |
645 | OXYGEN_CHANNEL_B)); | 645 | CAPTURE_0_FROM_I2S_2)); |
646 | err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm); | 646 | if (outs | ins) { |
647 | if (err < 0) | 647 | err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm); |
648 | return err; | 648 | if (err < 0) |
649 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops); | 649 | return err; |
650 | if (chip->model->used_channels & OXYGEN_CHANNEL_A) | 650 | if (outs) |
651 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 651 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
652 | &oxygen_rec_a_ops); | 652 | &oxygen_multich_ops); |
653 | else if (chip->model->used_channels & OXYGEN_CHANNEL_B) | 653 | if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1) |
654 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 654 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
655 | &oxygen_rec_b_ops); | 655 | &oxygen_rec_a_ops); |
656 | pcm->private_data = chip; | 656 | else if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_2) |
657 | pcm->private_free = oxygen_pcm_free; | 657 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
658 | strcpy(pcm->name, "Analog"); | 658 | &oxygen_rec_b_ops); |
659 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, | 659 | pcm->private_data = chip; |
660 | SNDRV_DMA_TYPE_DEV, | 660 | pcm->private_free = oxygen_pcm_free; |
661 | snd_dma_pci_data(chip->pci), | 661 | strcpy(pcm->name, "Analog"); |
662 | 512 * 1024, 2048 * 1024); | 662 | if (outs) |
663 | if (ins) | 663 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, |
664 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, | 664 | SNDRV_DMA_TYPE_DEV, |
665 | SNDRV_DMA_TYPE_DEV, | 665 | snd_dma_pci_data(chip->pci), |
666 | snd_dma_pci_data(chip->pci), | 666 | 512 * 1024, 2048 * 1024); |
667 | 128 * 1024, 256 * 1024); | 667 | if (ins) |
668 | 668 | snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, | |
669 | outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF); | 669 | SNDRV_DMA_TYPE_DEV, |
670 | ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C); | 670 | snd_dma_pci_data(chip->pci), |
671 | 128 * 1024, 256 * 1024); | ||
672 | } | ||
673 | |||
674 | outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF); | ||
675 | ins = !!(chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF); | ||
671 | if (outs | ins) { | 676 | if (outs | ins) { |
672 | err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm); | 677 | err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm); |
673 | if (err < 0) | 678 | if (err < 0) |
@@ -686,12 +691,13 @@ int oxygen_pcm_init(struct oxygen *chip) | |||
686 | 128 * 1024, 256 * 1024); | 691 | 128 * 1024, 256 * 1024); |
687 | } | 692 | } |
688 | 693 | ||
689 | outs = chip->has_ac97_1 && | 694 | if (chip->has_ac97_1) { |
690 | (chip->model->used_channels & OXYGEN_CHANNEL_AC97); | 695 | outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_2_TO_AC97_1); |
691 | ins = outs || | 696 | ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1); |
692 | (chip->model->used_channels & (OXYGEN_CHANNEL_A | | 697 | } else { |
693 | OXYGEN_CHANNEL_B)) | 698 | outs = 0; |
694 | == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B); | 699 | ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_I2S_2); |
700 | } | ||
695 | if (outs | ins) { | 701 | if (outs | ins) { |
696 | err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2", | 702 | err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2", |
697 | 2, outs, ins, &pcm); | 703 | 2, outs, ins, &pcm); |
diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h new file mode 100644 index 000000000000..698bf46c710c --- /dev/null +++ b/sound/pci/oxygen/pcm1796.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef PCM1796_H_INCLUDED | ||
2 | #define PCM1796_H_INCLUDED | ||
3 | |||
4 | /* register 16 */ | ||
5 | #define PCM1796_ATL_MASK 0xff | ||
6 | /* register 17 */ | ||
7 | #define PCM1796_ATR_MASK 0xff | ||
8 | /* register 18 */ | ||
9 | #define PCM1796_MUTE 0x01 | ||
10 | #define PCM1796_DME 0x02 | ||
11 | #define PCM1796_DMF_MASK 0x0c | ||
12 | #define PCM1796_DMF_DISABLED 0x00 | ||
13 | #define PCM1796_DMF_48 0x04 | ||
14 | #define PCM1796_DMF_441 0x08 | ||
15 | #define PCM1796_DMF_32 0x0c | ||
16 | #define PCM1796_FMT_MASK 0x70 | ||
17 | #define PCM1796_FMT_16_RJUST 0x00 | ||
18 | #define PCM1796_FMT_20_RJUST 0x10 | ||
19 | #define PCM1796_FMT_24_RJUST 0x20 | ||
20 | #define PCM1796_FMT_24_LJUST 0x30 | ||
21 | #define PCM1796_FMT_16_I2S 0x40 | ||
22 | #define PCM1796_FMT_24_I2S 0x50 | ||
23 | #define PCM1796_ATLD 0x80 | ||
24 | /* register 19 */ | ||
25 | #define PCM1796_INZD 0x01 | ||
26 | #define PCM1796_FLT_MASK 0x02 | ||
27 | #define PCM1796_FLT_SHARP 0x00 | ||
28 | #define PCM1796_FLT_SLOW 0x02 | ||
29 | #define PCM1796_DFMS 0x04 | ||
30 | #define PCM1796_OPE 0x10 | ||
31 | #define PCM1796_ATS_MASK 0x60 | ||
32 | #define PCM1796_ATS_1 0x00 | ||
33 | #define PCM1796_ATS_2 0x20 | ||
34 | #define PCM1796_ATS_4 0x40 | ||
35 | #define PCM1796_ATS_8 0x60 | ||
36 | #define PCM1796_REV 0x80 | ||
37 | /* register 20 */ | ||
38 | #define PCM1796_OS_MASK 0x03 | ||
39 | #define PCM1796_OS_64 0x00 | ||
40 | #define PCM1796_OS_32 0x01 | ||
41 | #define PCM1796_OS_128 0x02 | ||
42 | #define PCM1796_CHSL_MASK 0x04 | ||
43 | #define PCM1796_CHSL_LEFT 0x00 | ||
44 | #define PCM1796_CHSL_RIGHT 0x04 | ||
45 | #define PCM1796_MONO 0x08 | ||
46 | #define PCM1796_DFTH 0x10 | ||
47 | #define PCM1796_DSD 0x20 | ||
48 | #define PCM1796_SRST 0x40 | ||
49 | /* register 21 */ | ||
50 | #define PCM1796_PCMZ 0x01 | ||
51 | #define PCM1796_DZ_MASK 0x06 | ||
52 | /* register 22 */ | ||
53 | #define PCM1796_ZFGL 0x01 | ||
54 | #define PCM1796_ZFGR 0x02 | ||
55 | /* register 23 */ | ||
56 | #define PCM1796_ID_MASK 0x1f | ||
57 | |||
58 | #endif | ||
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index d163397b85cc..7f84fa5deca2 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -18,6 +18,9 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * Xonar D2/D2X | ||
22 | * ------------ | ||
23 | * | ||
21 | * CMI8788: | 24 | * CMI8788: |
22 | * | 25 | * |
23 | * SPI 0 -> 1st PCM1796 (front) | 26 | * SPI 0 -> 1st PCM1796 (front) |
@@ -30,10 +33,33 @@ | |||
30 | * GPIO 5 <- external power present (D2X only) | 33 | * GPIO 5 <- external power present (D2X only) |
31 | * GPIO 7 -> ALT | 34 | * GPIO 7 -> ALT |
32 | * GPIO 8 -> enable output to speakers | 35 | * GPIO 8 -> enable output to speakers |
36 | */ | ||
37 | |||
38 | /* | ||
39 | * Xonar DX | ||
40 | * -------- | ||
41 | * | ||
42 | * CMI8788: | ||
43 | * | ||
44 | * I²C <-> CS4398 (front) | ||
45 | * <-> CS4362A (surround, center/LFE, back) | ||
46 | * | ||
47 | * GPI 0 <- external power present | ||
33 | * | 48 | * |
34 | * CM9780: | 49 | * GPIO 0 -> enable output to speakers |
50 | * GPIO 1 -> enable front panel I/O | ||
51 | * GPIO 2 -> M0 of CS5361 | ||
52 | * GPIO 3 -> M1 of CS5361 | ||
53 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
35 | * | 54 | * |
36 | * GPIO 0 -> enable AC'97 bypass (line in -> ADC) | 55 | * CS4398: |
56 | * | ||
57 | * AD0 <- 1 | ||
58 | * AD1 <- 1 | ||
59 | * | ||
60 | * CS4362A: | ||
61 | * | ||
62 | * AD0 <- 0 | ||
37 | */ | 63 | */ |
38 | 64 | ||
39 | #include <linux/pci.h> | 65 | #include <linux/pci.h> |
@@ -47,11 +73,14 @@ | |||
47 | #include <sound/tlv.h> | 73 | #include <sound/tlv.h> |
48 | #include "oxygen.h" | 74 | #include "oxygen.h" |
49 | #include "cm9780.h" | 75 | #include "cm9780.h" |
76 | #include "pcm1796.h" | ||
77 | #include "cs4398.h" | ||
78 | #include "cs4362a.h" | ||
50 | 79 | ||
51 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 80 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
52 | MODULE_DESCRIPTION("Asus AV200 driver"); | 81 | MODULE_DESCRIPTION("Asus AVx00 driver"); |
53 | MODULE_LICENSE("GPL"); | 82 | MODULE_LICENSE("GPL"); |
54 | MODULE_SUPPORTED_DEVICE("{{Asus,AV200}}"); | 83 | MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}"); |
55 | 84 | ||
56 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 85 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
57 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 86 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -64,80 +93,44 @@ MODULE_PARM_DESC(id, "ID string"); | |||
64 | module_param_array(enable, bool, NULL, 0444); | 93 | module_param_array(enable, bool, NULL, 0444); |
65 | MODULE_PARM_DESC(enable, "enable card"); | 94 | MODULE_PARM_DESC(enable, "enable card"); |
66 | 95 | ||
96 | enum { | ||
97 | MODEL_D2, | ||
98 | MODEL_D2X, | ||
99 | MODEL_DX, | ||
100 | }; | ||
101 | |||
67 | static struct pci_device_id xonar_ids[] __devinitdata = { | 102 | static struct pci_device_id xonar_ids[] __devinitdata = { |
68 | { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, /* Asus Xonar D2 */ | 103 | { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 }, |
69 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, /* Asus Xonar D2X */ | 104 | { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX }, |
105 | { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X }, | ||
70 | { } | 106 | { } |
71 | }; | 107 | }; |
72 | MODULE_DEVICE_TABLE(pci, xonar_ids); | 108 | MODULE_DEVICE_TABLE(pci, xonar_ids); |
73 | 109 | ||
74 | 110 | ||
75 | #define GPIO_CS5381_M_MASK 0x000c | 111 | #define GPIO_CS53x1_M_MASK 0x000c |
76 | #define GPIO_CS5381_M_SINGLE 0x0000 | 112 | #define GPIO_CS53x1_M_SINGLE 0x0000 |
77 | #define GPIO_CS5381_M_DOUBLE 0x0004 | 113 | #define GPIO_CS53x1_M_DOUBLE 0x0004 |
78 | #define GPIO_CS5381_M_QUAD 0x0008 | 114 | #define GPIO_CS53x1_M_QUAD 0x0008 |
79 | #define GPIO_EXT_POWER 0x0020 | 115 | |
80 | #define GPIO_ALT 0x0080 | 116 | #define GPIO_D2X_EXT_POWER 0x0020 |
81 | #define GPIO_OUTPUT_ENABLE 0x0100 | 117 | #define GPIO_D2_ALT 0x0080 |
82 | 118 | #define GPIO_D2_OUTPUT_ENABLE 0x0100 | |
83 | #define GPIO_LINE_MUTE CM9780_GPO0 | 119 | |
84 | 120 | #define GPI_DX_EXT_POWER 0x01 | |
85 | /* register 16 */ | 121 | #define GPIO_DX_OUTPUT_ENABLE 0x0001 |
86 | #define PCM1796_ATL_MASK 0xff | 122 | #define GPIO_DX_FRONT_PANEL 0x0002 |
87 | /* register 17 */ | 123 | #define GPIO_DX_INPUT_ROUTE 0x0100 |
88 | #define PCM1796_ATR_MASK 0xff | 124 | |
89 | /* register 18 */ | 125 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ |
90 | #define PCM1796_MUTE 0x01 | 126 | #define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ |
91 | #define PCM1796_DME 0x02 | ||
92 | #define PCM1796_DMF_MASK 0x0c | ||
93 | #define PCM1796_DMF_DISABLED 0x00 | ||
94 | #define PCM1796_DMF_48 0x04 | ||
95 | #define PCM1796_DMF_441 0x08 | ||
96 | #define PCM1796_DMF_32 0x0c | ||
97 | #define PCM1796_FMT_MASK 0x70 | ||
98 | #define PCM1796_FMT_16_RJUST 0x00 | ||
99 | #define PCM1796_FMT_20_RJUST 0x10 | ||
100 | #define PCM1796_FMT_24_RJUST 0x20 | ||
101 | #define PCM1796_FMT_24_LJUST 0x30 | ||
102 | #define PCM1796_FMT_16_I2S 0x40 | ||
103 | #define PCM1796_FMT_24_I2S 0x50 | ||
104 | #define PCM1796_ATLD 0x80 | ||
105 | /* register 19 */ | ||
106 | #define PCM1796_INZD 0x01 | ||
107 | #define PCM1796_FLT_MASK 0x02 | ||
108 | #define PCM1796_FLT_SHARP 0x00 | ||
109 | #define PCM1796_FLT_SLOW 0x02 | ||
110 | #define PCM1796_DFMS 0x04 | ||
111 | #define PCM1796_OPE 0x10 | ||
112 | #define PCM1796_ATS_MASK 0x60 | ||
113 | #define PCM1796_ATS_1 0x00 | ||
114 | #define PCM1796_ATS_2 0x20 | ||
115 | #define PCM1796_ATS_4 0x40 | ||
116 | #define PCM1796_ATS_8 0x60 | ||
117 | #define PCM1796_REV 0x80 | ||
118 | /* register 20 */ | ||
119 | #define PCM1796_OS_MASK 0x03 | ||
120 | #define PCM1796_OS_64 0x00 | ||
121 | #define PCM1796_OS_32 0x01 | ||
122 | #define PCM1796_OS_128 0x02 | ||
123 | #define PCM1796_CHSL_MASK 0x04 | ||
124 | #define PCM1796_CHSL_LEFT 0x00 | ||
125 | #define PCM1796_CHSL_RIGHT 0x04 | ||
126 | #define PCM1796_MONO 0x08 | ||
127 | #define PCM1796_DFTH 0x10 | ||
128 | #define PCM1796_DSD 0x20 | ||
129 | #define PCM1796_SRST 0x40 | ||
130 | /* register 21 */ | ||
131 | #define PCM1796_PCMZ 0x01 | ||
132 | #define PCM1796_DZ_MASK 0x06 | ||
133 | /* register 22 */ | ||
134 | #define PCM1796_ZFGL 0x01 | ||
135 | #define PCM1796_ZFGR 0x02 | ||
136 | /* register 23 */ | ||
137 | #define PCM1796_ID_MASK 0x1f | ||
138 | 127 | ||
139 | struct xonar_data { | 128 | struct xonar_data { |
140 | u8 is_d2x; | 129 | unsigned int anti_pop_delay; |
130 | u16 output_enable_bit; | ||
131 | u8 ext_power_reg; | ||
132 | u8 ext_power_int_reg; | ||
133 | u8 ext_power_bit; | ||
141 | u8 has_power; | 134 | u8 has_power; |
142 | }; | 135 | }; |
143 | 136 | ||
@@ -156,62 +149,157 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec, | |||
156 | (reg << 8) | value); | 149 | (reg << 8) | value); |
157 | } | 150 | } |
158 | 151 | ||
159 | static void xonar_init(struct oxygen *chip) | 152 | static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) |
153 | { | ||
154 | oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value); | ||
155 | } | ||
156 | |||
157 | static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value) | ||
158 | { | ||
159 | oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value); | ||
160 | } | ||
161 | |||
162 | static void xonar_common_init(struct oxygen *chip) | ||
163 | { | ||
164 | struct xonar_data *data = chip->model_data; | ||
165 | |||
166 | if (data->ext_power_reg) { | ||
167 | oxygen_set_bits8(chip, data->ext_power_int_reg, | ||
168 | data->ext_power_bit); | ||
169 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | ||
170 | data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) | ||
171 | & data->ext_power_bit); | ||
172 | } | ||
173 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK); | ||
174 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
175 | GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); | ||
176 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | ||
177 | msleep(data->anti_pop_delay); | ||
178 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit); | ||
179 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); | ||
180 | } | ||
181 | |||
182 | static void xonar_d2_init(struct oxygen *chip) | ||
160 | { | 183 | { |
161 | struct xonar_data *data = chip->model_data; | 184 | struct xonar_data *data = chip->model_data; |
162 | unsigned int i; | 185 | unsigned int i; |
163 | 186 | ||
164 | data->is_d2x = chip->pci->subsystem_device == 0x82b7; | 187 | data->anti_pop_delay = 300; |
188 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; | ||
165 | 189 | ||
166 | for (i = 0; i < 4; ++i) { | 190 | for (i = 0; i < 4; ++i) { |
167 | pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD); | 191 | pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED | |
192 | PCM1796_FMT_24_LJUST | PCM1796_ATLD); | ||
168 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); | 193 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); |
169 | pcm1796_write(chip, i, 20, PCM1796_OS_64); | 194 | pcm1796_write(chip, i, 20, PCM1796_OS_64); |
170 | pcm1796_write(chip, i, 21, 0); | 195 | pcm1796_write(chip, i, 21, 0); |
171 | pcm1796_write(chip, i, 16, 0xff); /* set ATL/ATR after ATLD */ | 196 | pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */ |
172 | pcm1796_write(chip, i, 17, 0xff); | 197 | pcm1796_write(chip, i, 17, 0x0f); |
173 | } | 198 | } |
174 | 199 | ||
175 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | 200 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT); |
176 | GPIO_CS5381_M_MASK | GPIO_ALT); | 201 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT); |
177 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | 202 | |
178 | GPIO_CS5381_M_SINGLE, | 203 | xonar_common_init(chip); |
179 | GPIO_CS5381_M_MASK | GPIO_ALT); | ||
180 | if (data->is_d2x) { | ||
181 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
182 | GPIO_EXT_POWER); | ||
183 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, | ||
184 | GPIO_EXT_POWER); | ||
185 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | ||
186 | data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) | ||
187 | & GPIO_EXT_POWER); | ||
188 | } | ||
189 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | ||
190 | oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE); | ||
191 | msleep(300); | ||
192 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE); | ||
193 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
194 | 204 | ||
195 | snd_component_add(chip->card, "PCM1796"); | 205 | snd_component_add(chip->card, "PCM1796"); |
196 | snd_component_add(chip->card, "CS5381"); | 206 | snd_component_add(chip->card, "CS5381"); |
197 | } | 207 | } |
198 | 208 | ||
209 | static void xonar_d2x_init(struct oxygen *chip) | ||
210 | { | ||
211 | struct xonar_data *data = chip->model_data; | ||
212 | |||
213 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
214 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
215 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
216 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); | ||
217 | xonar_d2_init(chip); | ||
218 | } | ||
219 | |||
220 | static void xonar_dx_init(struct oxygen *chip) | ||
221 | { | ||
222 | struct xonar_data *data = chip->model_data; | ||
223 | |||
224 | data->anti_pop_delay = 800; | ||
225 | data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE; | ||
226 | data->ext_power_reg = OXYGEN_GPI_DATA; | ||
227 | data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | ||
228 | data->ext_power_bit = GPI_DX_EXT_POWER; | ||
229 | |||
230 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | ||
231 | OXYGEN_2WIRE_LENGTH_8 | | ||
232 | OXYGEN_2WIRE_INTERRUPT_MASK | | ||
233 | OXYGEN_2WIRE_SPEED_FAST); | ||
234 | |||
235 | /* set CPEN (control port mode) and power down */ | ||
236 | cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN); | ||
237 | cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); | ||
238 | /* configure */ | ||
239 | cs4398_write(chip, 2, CS4398_FM_SINGLE | | ||
240 | CS4398_DEM_NONE | CS4398_DIF_LJUST); | ||
241 | cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L); | ||
242 | cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE); | ||
243 | cs4398_write(chip, 5, 0xfe); | ||
244 | cs4398_write(chip, 6, 0xfe); | ||
245 | cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP | | ||
246 | CS4398_ZERO_CROSS | CS4398_SOFT_RAMP); | ||
247 | cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST); | ||
248 | cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE | | ||
249 | CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP); | ||
250 | cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE); | ||
251 | cs4362a_write(chip, 0x05, 0); | ||
252 | cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE | | ||
253 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L); | ||
254 | cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE); | ||
255 | cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE); | ||
256 | cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE | | ||
257 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L); | ||
258 | cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE); | ||
259 | cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE); | ||
260 | cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE | | ||
261 | CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L); | ||
262 | cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE); | ||
263 | cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE); | ||
264 | /* clear power down */ | ||
265 | cs4398_write(chip, 8, CS4398_CPEN); | ||
266 | cs4362a_write(chip, 0x01, CS4362A_CPEN); | ||
267 | |||
268 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
269 | GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE); | ||
270 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
271 | GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE); | ||
272 | |||
273 | xonar_common_init(chip); | ||
274 | |||
275 | snd_component_add(chip->card, "CS4398"); | ||
276 | snd_component_add(chip->card, "CS4362A"); | ||
277 | snd_component_add(chip->card, "CS5361"); | ||
278 | } | ||
279 | |||
199 | static void xonar_cleanup(struct oxygen *chip) | 280 | static void xonar_cleanup(struct oxygen *chip) |
200 | { | 281 | { |
201 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | 282 | struct xonar_data *data = chip->model_data; |
283 | |||
284 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); | ||
285 | } | ||
286 | |||
287 | static void xonar_dx_cleanup(struct oxygen *chip) | ||
288 | { | ||
289 | xonar_cleanup(chip); | ||
290 | cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); | ||
291 | oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); | ||
202 | } | 292 | } |
203 | 293 | ||
204 | static void set_pcm1796_params(struct oxygen *chip, | 294 | static void set_pcm1796_params(struct oxygen *chip, |
205 | struct snd_pcm_hw_params *params) | 295 | struct snd_pcm_hw_params *params) |
206 | { | 296 | { |
207 | #if 0 | ||
208 | unsigned int i; | 297 | unsigned int i; |
209 | u8 value; | 298 | u8 value; |
210 | 299 | ||
211 | value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; | 300 | value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; |
212 | for (i = 0; i < 4; ++i) | 301 | for (i = 0; i < 4; ++i) |
213 | pcm1796_write(chip, i, 20, value); | 302 | pcm1796_write(chip, i, 20, value); |
214 | #endif | ||
215 | } | 303 | } |
216 | 304 | ||
217 | static void update_pcm1796_volume(struct oxygen *chip) | 305 | static void update_pcm1796_volume(struct oxygen *chip) |
@@ -236,19 +324,73 @@ static void update_pcm1796_mute(struct oxygen *chip) | |||
236 | pcm1796_write(chip, i, 18, value); | 324 | pcm1796_write(chip, i, 18, value); |
237 | } | 325 | } |
238 | 326 | ||
239 | static void set_cs5381_params(struct oxygen *chip, | 327 | static void set_cs53x1_params(struct oxygen *chip, |
240 | struct snd_pcm_hw_params *params) | 328 | struct snd_pcm_hw_params *params) |
241 | { | 329 | { |
242 | unsigned int value; | 330 | unsigned int value; |
243 | 331 | ||
244 | if (params_rate(params) <= 54000) | 332 | if (params_rate(params) <= 54000) |
245 | value = GPIO_CS5381_M_SINGLE; | 333 | value = GPIO_CS53x1_M_SINGLE; |
246 | else if (params_rate(params) <= 108000) | 334 | else if (params_rate(params) <= 108000) |
247 | value = GPIO_CS5381_M_DOUBLE; | 335 | value = GPIO_CS53x1_M_DOUBLE; |
248 | else | 336 | else |
249 | value = GPIO_CS5381_M_QUAD; | 337 | value = GPIO_CS53x1_M_QUAD; |
250 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | 338 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, |
251 | value, GPIO_CS5381_M_MASK); | 339 | value, GPIO_CS53x1_M_MASK); |
340 | } | ||
341 | |||
342 | static void set_cs43xx_params(struct oxygen *chip, | ||
343 | struct snd_pcm_hw_params *params) | ||
344 | { | ||
345 | u8 fm_cs4398, fm_cs4362a; | ||
346 | |||
347 | fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST; | ||
348 | fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; | ||
349 | if (params_rate(params) <= 50000) { | ||
350 | fm_cs4398 |= CS4398_FM_SINGLE; | ||
351 | fm_cs4362a |= CS4362A_FM_SINGLE; | ||
352 | } else if (params_rate(params) <= 100000) { | ||
353 | fm_cs4398 |= CS4398_FM_DOUBLE; | ||
354 | fm_cs4362a |= CS4362A_FM_DOUBLE; | ||
355 | } else { | ||
356 | fm_cs4398 |= CS4398_FM_QUAD; | ||
357 | fm_cs4362a |= CS4362A_FM_QUAD; | ||
358 | } | ||
359 | cs4398_write(chip, 2, fm_cs4398); | ||
360 | cs4362a_write(chip, 0x06, fm_cs4362a); | ||
361 | cs4362a_write(chip, 0x09, fm_cs4362a); | ||
362 | cs4362a_write(chip, 0x0c, fm_cs4362a); | ||
363 | } | ||
364 | |||
365 | static void update_cs4362a_volumes(struct oxygen *chip) | ||
366 | { | ||
367 | u8 mute; | ||
368 | |||
369 | mute = chip->dac_mute ? CS4362A_MUTE : 0; | ||
370 | cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute); | ||
371 | cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute); | ||
372 | cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute); | ||
373 | cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute); | ||
374 | cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute); | ||
375 | cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute); | ||
376 | } | ||
377 | |||
378 | static void update_cs43xx_volume(struct oxygen *chip) | ||
379 | { | ||
380 | cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2); | ||
381 | cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2); | ||
382 | update_cs4362a_volumes(chip); | ||
383 | } | ||
384 | |||
385 | static void update_cs43xx_mute(struct oxygen *chip) | ||
386 | { | ||
387 | u8 reg; | ||
388 | |||
389 | reg = CS4398_MUTEP_LOW | CS4398_PAMUTE; | ||
390 | if (chip->dac_mute) | ||
391 | reg |= CS4398_MUTE_B | CS4398_MUTE_A; | ||
392 | cs4398_write(chip, 4, reg); | ||
393 | update_cs4362a_volumes(chip); | ||
252 | } | 394 | } |
253 | 395 | ||
254 | static void xonar_gpio_changed(struct oxygen *chip) | 396 | static void xonar_gpio_changed(struct oxygen *chip) |
@@ -256,10 +398,8 @@ static void xonar_gpio_changed(struct oxygen *chip) | |||
256 | struct xonar_data *data = chip->model_data; | 398 | struct xonar_data *data = chip->model_data; |
257 | u8 has_power; | 399 | u8 has_power; |
258 | 400 | ||
259 | if (!data->is_d2x) | 401 | has_power = !!(oxygen_read8(chip, data->ext_power_reg) |
260 | return; | 402 | & data->ext_power_bit); |
261 | has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) | ||
262 | & GPIO_EXT_POWER); | ||
263 | if (has_power != data->has_power) { | 403 | if (has_power != data->has_power) { |
264 | data->has_power = has_power; | 404 | data->has_power = has_power; |
265 | if (has_power) { | 405 | if (has_power) { |
@@ -272,66 +412,13 @@ static void xonar_gpio_changed(struct oxygen *chip) | |||
272 | } | 412 | } |
273 | } | 413 | } |
274 | 414 | ||
275 | static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) | ||
276 | { | ||
277 | unsigned int index = chip->controls[control]->private_value & 0xff; | ||
278 | u16 value; | ||
279 | |||
280 | value = oxygen_read_ac97(chip, 0, index); | ||
281 | if (!(value & 0x8000)) { | ||
282 | oxygen_write_ac97(chip, 0, index, value | 0x8000); | ||
283 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
284 | &chip->controls[control]->id); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec, | ||
289 | unsigned int reg, int mute) | ||
290 | { | ||
291 | if (codec != 0) | ||
292 | return; | ||
293 | /* line-in is exclusive */ | ||
294 | switch (reg) { | ||
295 | case AC97_LINE: | ||
296 | oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, | ||
297 | mute ? GPIO_LINE_MUTE : 0, | ||
298 | GPIO_LINE_MUTE); | ||
299 | if (!mute) { | ||
300 | mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH); | ||
301 | mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH); | ||
302 | mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH); | ||
303 | } | ||
304 | break; | ||
305 | case AC97_MIC: | ||
306 | case AC97_CD: | ||
307 | case AC97_VIDEO: | ||
308 | case AC97_AUX: | ||
309 | if (!mute) { | ||
310 | oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS, | ||
311 | GPIO_LINE_MUTE); | ||
312 | mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH); | ||
313 | } | ||
314 | break; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static int pcm1796_volume_info(struct snd_kcontrol *ctl, | ||
319 | struct snd_ctl_elem_info *info) | ||
320 | { | ||
321 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
322 | info->count = 8; | ||
323 | info->value.integer.min = 0x0f; | ||
324 | info->value.integer.max = 0xff; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int alt_switch_get(struct snd_kcontrol *ctl, | 415 | static int alt_switch_get(struct snd_kcontrol *ctl, |
329 | struct snd_ctl_elem_value *value) | 416 | struct snd_ctl_elem_value *value) |
330 | { | 417 | { |
331 | struct oxygen *chip = ctl->private_data; | 418 | struct oxygen *chip = ctl->private_data; |
332 | 419 | ||
333 | value->value.integer.value[0] = | 420 | value->value.integer.value[0] = |
334 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT); | 421 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT); |
335 | return 0; | 422 | return 0; |
336 | } | 423 | } |
337 | 424 | ||
@@ -345,9 +432,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl, | |||
345 | spin_lock_irq(&chip->reg_lock); | 432 | spin_lock_irq(&chip->reg_lock); |
346 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 433 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); |
347 | if (value->value.integer.value[0]) | 434 | if (value->value.integer.value[0]) |
348 | new_bits = old_bits | GPIO_ALT; | 435 | new_bits = old_bits | GPIO_D2_ALT; |
349 | else | 436 | else |
350 | new_bits = old_bits & ~GPIO_ALT; | 437 | new_bits = old_bits & ~GPIO_D2_ALT; |
351 | changed = new_bits != old_bits; | 438 | changed = new_bits != old_bits; |
352 | if (changed) | 439 | if (changed) |
353 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); | 440 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); |
@@ -363,20 +450,68 @@ static const struct snd_kcontrol_new alt_switch = { | |||
363 | .put = alt_switch_put, | 450 | .put = alt_switch_put, |
364 | }; | 451 | }; |
365 | 452 | ||
453 | static int front_panel_get(struct snd_kcontrol *ctl, | ||
454 | struct snd_ctl_elem_value *value) | ||
455 | { | ||
456 | struct oxygen *chip = ctl->private_data; | ||
457 | |||
458 | value->value.integer.value[0] = | ||
459 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_FRONT_PANEL); | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int front_panel_put(struct snd_kcontrol *ctl, | ||
464 | struct snd_ctl_elem_value *value) | ||
465 | { | ||
466 | struct oxygen *chip = ctl->private_data; | ||
467 | u16 old_reg, new_reg; | ||
468 | |||
469 | spin_lock_irq(&chip->reg_lock); | ||
470 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
471 | if (value->value.integer.value[0]) | ||
472 | new_reg = old_reg | GPIO_DX_FRONT_PANEL; | ||
473 | else | ||
474 | new_reg = old_reg & ~GPIO_DX_FRONT_PANEL; | ||
475 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); | ||
476 | spin_unlock_irq(&chip->reg_lock); | ||
477 | return old_reg != new_reg; | ||
478 | } | ||
479 | |||
480 | static const struct snd_kcontrol_new front_panel_switch = { | ||
481 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
482 | .name = "Front Panel Switch", | ||
483 | .info = snd_ctl_boolean_mono_info, | ||
484 | .get = front_panel_get, | ||
485 | .put = front_panel_put, | ||
486 | }; | ||
487 | |||
488 | static void xonar_dx_ac97_switch(struct oxygen *chip, | ||
489 | unsigned int reg, unsigned int mute) | ||
490 | { | ||
491 | if (reg == AC97_LINE) { | ||
492 | spin_lock_irq(&chip->reg_lock); | ||
493 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
494 | mute ? GPIO_DX_INPUT_ROUTE : 0, | ||
495 | GPIO_DX_INPUT_ROUTE); | ||
496 | spin_unlock_irq(&chip->reg_lock); | ||
497 | } | ||
498 | } | ||
499 | |||
366 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); | 500 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); |
501 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0); | ||
367 | 502 | ||
368 | static int xonar_control_filter(struct snd_kcontrol_new *template) | 503 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) |
369 | { | 504 | { |
370 | if (!strcmp(template->name, "Master Playback Volume")) { | 505 | if (!strncmp(template->name, "CD Capture ", 11)) |
371 | template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
372 | template->info = pcm1796_volume_info, | ||
373 | template->tlv.p = pcm1796_db_scale; | ||
374 | } else if (!strncmp(template->name, "CD Capture ", 11)) { | ||
375 | /* CD in is actually connected to the video in pin */ | 506 | /* CD in is actually connected to the video in pin */ |
376 | template->private_value ^= AC97_CD ^ AC97_VIDEO; | 507 | template->private_value ^= AC97_CD ^ AC97_VIDEO; |
377 | } else if (!strcmp(template->name, "Line Capture Volume")) { | 508 | return 0; |
378 | return 1; /* line-in bypasses the AC'97 mixer */ | 509 | } |
379 | } | 510 | |
511 | static int xonar_dx_control_filter(struct snd_kcontrol_new *template) | ||
512 | { | ||
513 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
514 | return 1; /* no CD input */ | ||
380 | return 0; | 515 | return 0; |
381 | } | 516 | } |
382 | 517 | ||
@@ -385,30 +520,96 @@ static int xonar_mixer_init(struct oxygen *chip) | |||
385 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); | 520 | return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); |
386 | } | 521 | } |
387 | 522 | ||
388 | static const struct oxygen_model model_xonar = { | 523 | static int xonar_dx_mixer_init(struct oxygen *chip) |
389 | .shortname = "Asus AV200", | 524 | { |
390 | .longname = "Asus Virtuoso 200", | 525 | return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); |
391 | .chip = "AV200", | 526 | } |
392 | .owner = THIS_MODULE, | 527 | |
393 | .init = xonar_init, | 528 | static const struct oxygen_model xonar_models[] = { |
394 | .control_filter = xonar_control_filter, | 529 | [MODEL_D2] = { |
395 | .mixer_init = xonar_mixer_init, | 530 | .shortname = "Xonar D2", |
396 | .cleanup = xonar_cleanup, | 531 | .longname = "Asus Virtuoso 200", |
397 | .set_dac_params = set_pcm1796_params, | 532 | .chip = "AV200", |
398 | .set_adc_params = set_cs5381_params, | 533 | .owner = THIS_MODULE, |
399 | .update_dac_volume = update_pcm1796_volume, | 534 | .init = xonar_d2_init, |
400 | .update_dac_mute = update_pcm1796_mute, | 535 | .control_filter = xonar_d2_control_filter, |
401 | .ac97_switch_hook = xonar_ac97_switch_hook, | 536 | .mixer_init = xonar_mixer_init, |
402 | .gpio_changed = xonar_gpio_changed, | 537 | .cleanup = xonar_cleanup, |
403 | .model_data_size = sizeof(struct xonar_data), | 538 | .set_dac_params = set_pcm1796_params, |
404 | .dac_channels = 8, | 539 | .set_adc_params = set_cs53x1_params, |
405 | .used_channels = OXYGEN_CHANNEL_B | | 540 | .update_dac_volume = update_pcm1796_volume, |
406 | OXYGEN_CHANNEL_C | | 541 | .update_dac_mute = update_pcm1796_mute, |
407 | OXYGEN_CHANNEL_SPDIF | | 542 | .dac_tlv = pcm1796_db_scale, |
408 | OXYGEN_CHANNEL_MULTICH, | 543 | .model_data_size = sizeof(struct xonar_data), |
409 | .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5, | 544 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | |
410 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 545 | PLAYBACK_1_TO_SPDIF | |
411 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 546 | CAPTURE_0_FROM_I2S_2 | |
547 | CAPTURE_1_FROM_SPDIF, | ||
548 | .dac_channels = 8, | ||
549 | .dac_volume_min = 0x0f, | ||
550 | .dac_volume_max = 0xff, | ||
551 | .misc_flags = OXYGEN_MISC_MIDI, | ||
552 | .function_flags = OXYGEN_FUNCTION_SPI | | ||
553 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | ||
554 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
555 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
556 | }, | ||
557 | [MODEL_D2X] = { | ||
558 | .shortname = "Xonar D2X", | ||
559 | .longname = "Asus Virtuoso 200", | ||
560 | .chip = "AV200", | ||
561 | .owner = THIS_MODULE, | ||
562 | .init = xonar_d2x_init, | ||
563 | .control_filter = xonar_d2_control_filter, | ||
564 | .mixer_init = xonar_mixer_init, | ||
565 | .cleanup = xonar_cleanup, | ||
566 | .set_dac_params = set_pcm1796_params, | ||
567 | .set_adc_params = set_cs53x1_params, | ||
568 | .update_dac_volume = update_pcm1796_volume, | ||
569 | .update_dac_mute = update_pcm1796_mute, | ||
570 | .gpio_changed = xonar_gpio_changed, | ||
571 | .dac_tlv = pcm1796_db_scale, | ||
572 | .model_data_size = sizeof(struct xonar_data), | ||
573 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | | ||
574 | PLAYBACK_1_TO_SPDIF | | ||
575 | CAPTURE_0_FROM_I2S_2 | | ||
576 | CAPTURE_1_FROM_SPDIF, | ||
577 | .dac_channels = 8, | ||
578 | .dac_volume_min = 0x0f, | ||
579 | .dac_volume_max = 0xff, | ||
580 | .misc_flags = OXYGEN_MISC_MIDI, | ||
581 | .function_flags = OXYGEN_FUNCTION_SPI | | ||
582 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | ||
583 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
584 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
585 | }, | ||
586 | [MODEL_DX] = { | ||
587 | .shortname = "Xonar DX", | ||
588 | .longname = "Asus Virtuoso 100", | ||
589 | .chip = "AV200", | ||
590 | .owner = THIS_MODULE, | ||
591 | .init = xonar_dx_init, | ||
592 | .control_filter = xonar_dx_control_filter, | ||
593 | .mixer_init = xonar_dx_mixer_init, | ||
594 | .cleanup = xonar_dx_cleanup, | ||
595 | .set_dac_params = set_cs43xx_params, | ||
596 | .set_adc_params = set_cs53x1_params, | ||
597 | .update_dac_volume = update_cs43xx_volume, | ||
598 | .update_dac_mute = update_cs43xx_mute, | ||
599 | .gpio_changed = xonar_gpio_changed, | ||
600 | .ac97_switch = xonar_dx_ac97_switch, | ||
601 | .dac_tlv = cs4362a_db_scale, | ||
602 | .model_data_size = sizeof(struct xonar_data), | ||
603 | .pcm_dev_cfg = PLAYBACK_0_TO_I2S | | ||
604 | PLAYBACK_1_TO_SPDIF | | ||
605 | CAPTURE_0_FROM_I2S_2, | ||
606 | .dac_channels = 8, | ||
607 | .dac_volume_min = 0, | ||
608 | .dac_volume_max = 127, | ||
609 | .function_flags = OXYGEN_FUNCTION_2WIRE, | ||
610 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
611 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
612 | }, | ||
412 | }; | 613 | }; |
413 | 614 | ||
414 | static int __devinit xonar_probe(struct pci_dev *pci, | 615 | static int __devinit xonar_probe(struct pci_dev *pci, |
@@ -423,7 +624,8 @@ static int __devinit xonar_probe(struct pci_dev *pci, | |||
423 | ++dev; | 624 | ++dev; |
424 | return -ENOENT; | 625 | return -ENOENT; |
425 | } | 626 | } |
426 | err = oxygen_pci_probe(pci, index[dev], id[dev], 1, &model_xonar); | 627 | err = oxygen_pci_probe(pci, index[dev], id[dev], |
628 | &xonar_models[pci_id->driver_data]); | ||
427 | if (err >= 0) | 629 | if (err >= 0) |
428 | ++dev; | 630 | ++dev; |
429 | return err; | 631 | return err; |
diff --git a/sound/pci/oxygen/wm8785.h b/sound/pci/oxygen/wm8785.h new file mode 100644 index 000000000000..8c23e315ae66 --- /dev/null +++ b/sound/pci/oxygen/wm8785.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef WM8785_H_INCLUDED | ||
2 | #define WM8785_H_INCLUDED | ||
3 | |||
4 | #define WM8785_R0 0 | ||
5 | #define WM8785_R1 1 | ||
6 | #define WM8785_R2 2 | ||
7 | #define WM8785_R7 7 | ||
8 | |||
9 | /* R0 */ | ||
10 | #define WM8785_MCR_MASK 0x007 | ||
11 | #define WM8785_MCR_SLAVE 0x000 | ||
12 | #define WM8785_MCR_MASTER_128 0x001 | ||
13 | #define WM8785_MCR_MASTER_192 0x002 | ||
14 | #define WM8785_MCR_MASTER_256 0x003 | ||
15 | #define WM8785_MCR_MASTER_384 0x004 | ||
16 | #define WM8785_MCR_MASTER_512 0x005 | ||
17 | #define WM8785_MCR_MASTER_768 0x006 | ||
18 | #define WM8785_OSR_MASK 0x018 | ||
19 | #define WM8785_OSR_SINGLE 0x000 | ||
20 | #define WM8785_OSR_DOUBLE 0x008 | ||
21 | #define WM8785_OSR_QUAD 0x010 | ||
22 | #define WM8785_FORMAT_MASK 0x060 | ||
23 | #define WM8785_FORMAT_RJUST 0x000 | ||
24 | #define WM8785_FORMAT_LJUST 0x020 | ||
25 | #define WM8785_FORMAT_I2S 0x040 | ||
26 | #define WM8785_FORMAT_DSP 0x060 | ||
27 | /* R1 */ | ||
28 | #define WM8785_WL_MASK 0x003 | ||
29 | #define WM8785_WL_16 0x000 | ||
30 | #define WM8785_WL_20 0x001 | ||
31 | #define WM8785_WL_24 0x002 | ||
32 | #define WM8785_WL_32 0x003 | ||
33 | #define WM8785_LRP 0x004 | ||
34 | #define WM8785_BCLKINV 0x008 | ||
35 | #define WM8785_LRSWAP 0x010 | ||
36 | #define WM8785_DEVNO_MASK 0x0e0 | ||
37 | /* R2 */ | ||
38 | #define WM8785_HPFR 0x001 | ||
39 | #define WM8785_HPFL 0x002 | ||
40 | #define WM8785_SDODIS 0x004 | ||
41 | #define WM8785_PWRDNR 0x008 | ||
42 | #define WM8785_PWRDNL 0x010 | ||
43 | #define WM8785_TDM_MASK 0x1c0 | ||
44 | |||
45 | #endif | ||