diff options
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 2 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 11 | ||||
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 40 |
3 files changed, 52 insertions, 1 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index e71c53498995..ad50fb8b206b 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -66,6 +66,7 @@ struct oxygen { | |||
66 | struct snd_pcm_substream *streams[PCM_COUNT]; | 66 | struct snd_pcm_substream *streams[PCM_COUNT]; |
67 | struct snd_kcontrol *controls[CONTROL_COUNT]; | 67 | struct snd_kcontrol *controls[CONTROL_COUNT]; |
68 | struct work_struct spdif_input_bits_work; | 68 | struct work_struct spdif_input_bits_work; |
69 | struct work_struct gpio_work; | ||
69 | wait_queue_head_t ac97_waitqueue; | 70 | wait_queue_head_t ac97_waitqueue; |
70 | }; | 71 | }; |
71 | 72 | ||
@@ -88,6 +89,7 @@ struct oxygen_model { | |||
88 | void (*update_dac_mute)(struct oxygen *chip); | 89 | void (*update_dac_mute)(struct oxygen *chip); |
89 | void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec, | 90 | void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec, |
90 | unsigned int reg, int mute); | 91 | unsigned int reg, int mute); |
92 | void (*gpio_changed)(struct oxygen *chip); | ||
91 | size_t model_data_size; | 93 | size_t model_data_size; |
92 | u8 dac_channels; | 94 | u8 dac_channels; |
93 | u8 used_channels; | 95 | u8 used_channels; |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 540e56b75794..6eb36dd11476 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -85,7 +85,7 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | if (status & OXYGEN_INT_GPIO) | 87 | if (status & OXYGEN_INT_GPIO) |
88 | ; | 88 | schedule_work(&chip->gpio_work); |
89 | 89 | ||
90 | if ((status & OXYGEN_INT_MIDI) && chip->midi) | 90 | if ((status & OXYGEN_INT_MIDI) && chip->midi) |
91 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); | 91 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); |
@@ -157,6 +157,14 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | static void oxygen_gpio_changed(struct work_struct *work) | ||
161 | { | ||
162 | struct oxygen *chip = container_of(work, struct oxygen, gpio_work); | ||
163 | |||
164 | if (chip->model->gpio_changed) | ||
165 | chip->model->gpio_changed(chip); | ||
166 | } | ||
167 | |||
160 | #ifdef CONFIG_PROC_FS | 168 | #ifdef CONFIG_PROC_FS |
161 | static void oxygen_proc_read(struct snd_info_entry *entry, | 169 | static void oxygen_proc_read(struct snd_info_entry *entry, |
162 | struct snd_info_buffer *buffer) | 170 | struct snd_info_buffer *buffer) |
@@ -413,6 +421,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
413 | mutex_init(&chip->mutex); | 421 | mutex_init(&chip->mutex); |
414 | INIT_WORK(&chip->spdif_input_bits_work, | 422 | INIT_WORK(&chip->spdif_input_bits_work, |
415 | oxygen_spdif_input_bits_changed); | 423 | oxygen_spdif_input_bits_changed); |
424 | INIT_WORK(&chip->gpio_work, oxygen_gpio_changed); | ||
416 | init_waitqueue_head(&chip->ac97_waitqueue); | 425 | init_waitqueue_head(&chip->ac97_waitqueue); |
417 | 426 | ||
418 | err = pci_enable_device(pci); | 427 | err = pci_enable_device(pci); |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 2e1a6996fa86..40e92f5cd69c 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -136,6 +136,11 @@ MODULE_DEVICE_TABLE(pci, xonar_ids); | |||
136 | /* register 23 */ | 136 | /* register 23 */ |
137 | #define PCM1796_ID_MASK 0x1f | 137 | #define PCM1796_ID_MASK 0x1f |
138 | 138 | ||
139 | struct xonar_data { | ||
140 | u8 is_d2x; | ||
141 | u8 has_power; | ||
142 | }; | ||
143 | |||
139 | static void pcm1796_write(struct oxygen *chip, unsigned int codec, | 144 | static void pcm1796_write(struct oxygen *chip, unsigned int codec, |
140 | u8 reg, u8 value) | 145 | u8 reg, u8 value) |
141 | { | 146 | { |
@@ -153,8 +158,11 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec, | |||
153 | 158 | ||
154 | static void xonar_init(struct oxygen *chip) | 159 | static void xonar_init(struct oxygen *chip) |
155 | { | 160 | { |
161 | struct xonar_data *data = chip->model_data; | ||
156 | unsigned int i; | 162 | unsigned int i; |
157 | 163 | ||
164 | data->is_d2x = chip->pci->subsystem_device == 0x82b7; | ||
165 | |||
158 | for (i = 0; i < 4; ++i) { | 166 | for (i = 0; i < 4; ++i) { |
159 | pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD); | 167 | pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD); |
160 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); | 168 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); |
@@ -169,6 +177,15 @@ static void xonar_init(struct oxygen *chip) | |||
169 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | 177 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, |
170 | GPIO_CS5381_M_SINGLE, | 178 | GPIO_CS5381_M_SINGLE, |
171 | GPIO_CS5381_M_MASK | GPIO_ALT); | 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 | } | ||
172 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | 189 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); |
173 | oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE); | 190 | oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE); |
174 | msleep(300); | 191 | msleep(300); |
@@ -234,6 +251,27 @@ static void set_cs5381_params(struct oxygen *chip, | |||
234 | value, GPIO_CS5381_M_MASK); | 251 | value, GPIO_CS5381_M_MASK); |
235 | } | 252 | } |
236 | 253 | ||
254 | static void xonar_gpio_changed(struct oxygen *chip) | ||
255 | { | ||
256 | struct xonar_data *data = chip->model_data; | ||
257 | u8 has_power; | ||
258 | |||
259 | if (!data->is_d2x) | ||
260 | return; | ||
261 | has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) | ||
262 | & GPIO_EXT_POWER); | ||
263 | if (has_power != data->has_power) { | ||
264 | data->has_power = has_power; | ||
265 | if (has_power) { | ||
266 | snd_printk(KERN_NOTICE "power restored\n"); | ||
267 | } else { | ||
268 | snd_printk(KERN_CRIT | ||
269 | "Hey! Don't unplug the power cable!\n"); | ||
270 | /* TODO: stop PCMs */ | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
237 | static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) | 275 | static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) |
238 | { | 276 | { |
239 | unsigned int index = chip->controls[control]->private_value & 0xff; | 277 | unsigned int index = chip->controls[control]->private_value & 0xff; |
@@ -360,6 +398,8 @@ static const struct oxygen_model model_xonar = { | |||
360 | .update_dac_volume = update_pcm1796_volume, | 398 | .update_dac_volume = update_pcm1796_volume, |
361 | .update_dac_mute = update_pcm1796_mute, | 399 | .update_dac_mute = update_pcm1796_mute, |
362 | .ac97_switch_hook = xonar_ac97_switch_hook, | 400 | .ac97_switch_hook = xonar_ac97_switch_hook, |
401 | .gpio_changed = xonar_gpio_changed, | ||
402 | .model_data_size = sizeof(struct xonar_data), | ||
363 | .dac_channels = 8, | 403 | .dac_channels = 8, |
364 | .used_channels = OXYGEN_CHANNEL_B | | 404 | .used_channels = OXYGEN_CHANNEL_B | |
365 | OXYGEN_CHANNEL_C | | 405 | OXYGEN_CHANNEL_C | |