aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2008-01-28 02:36:55 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:30:18 -0500
commit7c0141591fcf92ddc96a4ee04e35783a15bd68c8 (patch)
tree22b2ce1e76144b5ff0d0fb420668e18820f8adf2 /sound/pci
parent5f7b9b457751efc9f3ad120d0ebdb19fe753e9d0 (diff)
[ALSA] virtuoso: monitor external power on D2X
On the Xonar D2X, monitor the GPIO pin that indicates whether external power is present. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/oxygen/oxygen.h2
-rw-r--r--sound/pci/oxygen/oxygen_lib.c11
-rw-r--r--sound/pci/oxygen/virtuoso.c40
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
160static 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
161static void oxygen_proc_read(struct snd_info_entry *entry, 169static 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
139struct xonar_data {
140 u8 is_d2x;
141 u8 has_power;
142};
143
139static void pcm1796_write(struct oxygen *chip, unsigned int codec, 144static 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
154static void xonar_init(struct oxygen *chip) 159static 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
254static 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
237static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) 275static 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 |