diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 77 |
1 files changed, 51 insertions, 26 deletions
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 1627197f1689..95c229acf855 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -79,11 +79,16 @@ MODULE_DEVICE_TABLE(pci, xonar_ids); | |||
79 | #define GPIO_CS53x1_M_DOUBLE 0x0004 | 79 | #define GPIO_CS53x1_M_DOUBLE 0x0004 |
80 | #define GPIO_CS53x1_M_QUAD 0x0008 | 80 | #define GPIO_CS53x1_M_QUAD 0x0008 |
81 | 81 | ||
82 | #define GPIO_EXT_POWER 0x0020 | 82 | #define GPIO_D2X_EXT_POWER 0x0020 |
83 | #define GPIO_ALT 0x0080 | 83 | #define GPIO_D2_ALT 0x0080 |
84 | #define GPIO_OUTPUT_ENABLE 0x0100 | 84 | #define GPIO_D2_OUTPUT_ENABLE 0x0100 |
85 | 85 | ||
86 | struct xonar_data { | 86 | struct xonar_data { |
87 | unsigned int anti_pop_delay; | ||
88 | u16 output_enable_bit; | ||
89 | u8 ext_power_reg; | ||
90 | u8 ext_power_int_reg; | ||
91 | u8 ext_power_bit; | ||
87 | u8 has_power; | 92 | u8 has_power; |
88 | }; | 93 | }; |
89 | 94 | ||
@@ -102,10 +107,34 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec, | |||
102 | (reg << 8) | value); | 107 | (reg << 8) | value); |
103 | } | 108 | } |
104 | 109 | ||
110 | static void xonar_common_init(struct oxygen *chip) | ||
111 | { | ||
112 | struct xonar_data *data = chip->model_data; | ||
113 | |||
114 | if (data->ext_power_reg) { | ||
115 | oxygen_set_bits8(chip, data->ext_power_int_reg, | ||
116 | data->ext_power_bit); | ||
117 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | ||
118 | data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) | ||
119 | & data->ext_power_bit); | ||
120 | } | ||
121 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK); | ||
122 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
123 | GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); | ||
124 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | ||
125 | msleep(data->anti_pop_delay); | ||
126 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit); | ||
127 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); | ||
128 | } | ||
129 | |||
105 | static void xonar_d2_init(struct oxygen *chip) | 130 | static void xonar_d2_init(struct oxygen *chip) |
106 | { | 131 | { |
132 | struct xonar_data *data = chip->model_data; | ||
107 | unsigned int i; | 133 | unsigned int i; |
108 | 134 | ||
135 | data->anti_pop_delay = 300; | ||
136 | data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE; | ||
137 | |||
109 | for (i = 0; i < 4; ++i) { | 138 | for (i = 0; i < 4; ++i) { |
110 | pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD); | 139 | pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD); |
111 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); | 140 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); |
@@ -115,15 +144,10 @@ static void xonar_d2_init(struct oxygen *chip) | |||
115 | pcm1796_write(chip, i, 17, 0xff); | 144 | pcm1796_write(chip, i, 17, 0xff); |
116 | } | 145 | } |
117 | 146 | ||
118 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | 147 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT); |
119 | GPIO_CS53x1_M_MASK | GPIO_ALT); | 148 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT); |
120 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | 149 | |
121 | GPIO_CS53x1_M_SINGLE, | 150 | xonar_common_init(chip); |
122 | GPIO_CS53x1_M_MASK | GPIO_ALT); | ||
123 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | ||
124 | msleep(300); | ||
125 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE); | ||
126 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
127 | 151 | ||
128 | snd_component_add(chip->card, "PCM1796"); | 152 | snd_component_add(chip->card, "PCM1796"); |
129 | snd_component_add(chip->card, "CS5381"); | 153 | snd_component_add(chip->card, "CS5381"); |
@@ -133,17 +157,18 @@ static void xonar_d2x_init(struct oxygen *chip) | |||
133 | { | 157 | { |
134 | struct xonar_data *data = chip->model_data; | 158 | struct xonar_data *data = chip->model_data; |
135 | 159 | ||
160 | data->ext_power_reg = OXYGEN_GPIO_DATA; | ||
161 | data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; | ||
162 | data->ext_power_bit = GPIO_D2X_EXT_POWER; | ||
163 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); | ||
136 | xonar_d2_init(chip); | 164 | xonar_d2_init(chip); |
137 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_EXT_POWER); | ||
138 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_EXT_POWER); | ||
139 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | ||
140 | data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) | ||
141 | & GPIO_EXT_POWER); | ||
142 | } | 165 | } |
143 | 166 | ||
144 | static void xonar_cleanup(struct oxygen *chip) | 167 | static void xonar_cleanup(struct oxygen *chip) |
145 | { | 168 | { |
146 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | 169 | struct xonar_data *data = chip->model_data; |
170 | |||
171 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); | ||
147 | } | 172 | } |
148 | 173 | ||
149 | static void set_pcm1796_params(struct oxygen *chip, | 174 | static void set_pcm1796_params(struct oxygen *chip, |
@@ -201,8 +226,8 @@ static void xonar_gpio_changed(struct oxygen *chip) | |||
201 | struct xonar_data *data = chip->model_data; | 226 | struct xonar_data *data = chip->model_data; |
202 | u8 has_power; | 227 | u8 has_power; |
203 | 228 | ||
204 | has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) | 229 | has_power = !!(oxygen_read8(chip, data->ext_power_reg) |
205 | & GPIO_EXT_POWER); | 230 | & data->ext_power_bit); |
206 | if (has_power != data->has_power) { | 231 | if (has_power != data->has_power) { |
207 | data->has_power = has_power; | 232 | data->has_power = has_power; |
208 | if (has_power) { | 233 | if (has_power) { |
@@ -231,7 +256,7 @@ static int alt_switch_get(struct snd_kcontrol *ctl, | |||
231 | struct oxygen *chip = ctl->private_data; | 256 | struct oxygen *chip = ctl->private_data; |
232 | 257 | ||
233 | value->value.integer.value[0] = | 258 | value->value.integer.value[0] = |
234 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT); | 259 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT); |
235 | return 0; | 260 | return 0; |
236 | } | 261 | } |
237 | 262 | ||
@@ -245,9 +270,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl, | |||
245 | spin_lock_irq(&chip->reg_lock); | 270 | spin_lock_irq(&chip->reg_lock); |
246 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 271 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); |
247 | if (value->value.integer.value[0]) | 272 | if (value->value.integer.value[0]) |
248 | new_bits = old_bits | GPIO_ALT; | 273 | new_bits = old_bits | GPIO_D2_ALT; |
249 | else | 274 | else |
250 | new_bits = old_bits & ~GPIO_ALT; | 275 | new_bits = old_bits & ~GPIO_D2_ALT; |
251 | changed = new_bits != old_bits; | 276 | changed = new_bits != old_bits; |
252 | if (changed) | 277 | if (changed) |
253 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); | 278 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); |
@@ -265,7 +290,7 @@ static const struct snd_kcontrol_new alt_switch = { | |||
265 | 290 | ||
266 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); | 291 | static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0); |
267 | 292 | ||
268 | static int xonar_control_filter(struct snd_kcontrol_new *template) | 293 | static int xonar_d2_control_filter(struct snd_kcontrol_new *template) |
269 | { | 294 | { |
270 | if (!strcmp(template->name, "Master Playback Volume")) { | 295 | if (!strcmp(template->name, "Master Playback Volume")) { |
271 | template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 296 | template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
@@ -290,7 +315,7 @@ static const struct oxygen_model xonar_models[] = { | |||
290 | .chip = "AV200", | 315 | .chip = "AV200", |
291 | .owner = THIS_MODULE, | 316 | .owner = THIS_MODULE, |
292 | .init = xonar_d2_init, | 317 | .init = xonar_d2_init, |
293 | .control_filter = xonar_control_filter, | 318 | .control_filter = xonar_d2_control_filter, |
294 | .mixer_init = xonar_mixer_init, | 319 | .mixer_init = xonar_mixer_init, |
295 | .cleanup = xonar_cleanup, | 320 | .cleanup = xonar_cleanup, |
296 | .set_dac_params = set_pcm1796_params, | 321 | .set_dac_params = set_pcm1796_params, |
@@ -315,7 +340,7 @@ static const struct oxygen_model xonar_models[] = { | |||
315 | .chip = "AV200", | 340 | .chip = "AV200", |
316 | .owner = THIS_MODULE, | 341 | .owner = THIS_MODULE, |
317 | .init = xonar_d2x_init, | 342 | .init = xonar_d2x_init, |
318 | .control_filter = xonar_control_filter, | 343 | .control_filter = xonar_d2_control_filter, |
319 | .mixer_init = xonar_mixer_init, | 344 | .mixer_init = xonar_mixer_init, |
320 | .cleanup = xonar_cleanup, | 345 | .cleanup = xonar_cleanup, |
321 | .set_dac_params = set_pcm1796_params, | 346 | .set_dac_params = set_pcm1796_params, |