diff options
| -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 e71c5349899..ad50fb8b206 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h @@ -66,6 +66,7 @@ struct oxygen {  	struct snd_pcm_substream *streams[PCM_COUNT];  	struct snd_kcontrol *controls[CONTROL_COUNT];  	struct work_struct spdif_input_bits_work; +	struct work_struct gpio_work;  	wait_queue_head_t ac97_waitqueue;  }; @@ -88,6 +89,7 @@ struct oxygen_model {  	void (*update_dac_mute)(struct oxygen *chip);  	void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,  				 unsigned int reg, int mute); +	void (*gpio_changed)(struct oxygen *chip);  	size_t model_data_size;  	u8 dac_channels;  	u8 used_channels; diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 540e56b7579..6eb36dd1147 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)  	}  	if (status & OXYGEN_INT_GPIO) -		; +		schedule_work(&chip->gpio_work);  	if ((status & OXYGEN_INT_MIDI) && chip->midi)  		snd_mpu401_uart_interrupt(0, chip->midi->private_data); @@ -157,6 +157,14 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work)  	}  } +static void oxygen_gpio_changed(struct work_struct *work) +{ +	struct oxygen *chip = container_of(work, struct oxygen, gpio_work); + +	if (chip->model->gpio_changed) +		chip->model->gpio_changed(chip); +} +  #ifdef CONFIG_PROC_FS  static void oxygen_proc_read(struct snd_info_entry *entry,  			     struct snd_info_buffer *buffer) @@ -413,6 +421,7 @@ int __devinit oxygen_pci_probe(struct pci_dev *pci, int index, char *id,  	mutex_init(&chip->mutex);  	INIT_WORK(&chip->spdif_input_bits_work,  		  oxygen_spdif_input_bits_changed); +	INIT_WORK(&chip->gpio_work, oxygen_gpio_changed);  	init_waitqueue_head(&chip->ac97_waitqueue);  	err = pci_enable_device(pci); diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 2e1a6996fa8..40e92f5cd69 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c @@ -136,6 +136,11 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);  /* register 23 */  #define PCM1796_ID_MASK		0x1f +struct xonar_data { +	u8 is_d2x; +	u8 has_power; +}; +  static void pcm1796_write(struct oxygen *chip, unsigned int codec,  			  u8 reg, u8 value)  { @@ -153,8 +158,11 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,  static void xonar_init(struct oxygen *chip)  { +	struct xonar_data *data = chip->model_data;  	unsigned int i; +	data->is_d2x = chip->pci->subsystem_device == 0x82b7; +  	for (i = 0; i < 4; ++i) {  		pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);  		pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); @@ -169,6 +177,15 @@ static void xonar_init(struct oxygen *chip)  	oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,  			      GPIO_CS5381_M_SINGLE,  			      GPIO_CS5381_M_MASK | GPIO_ALT); +	if (data->is_d2x) { +		oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, +				    GPIO_EXT_POWER); +		oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, +				  GPIO_EXT_POWER); +		chip->interrupt_mask |= OXYGEN_INT_GPIO; +		data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) +				     & GPIO_EXT_POWER); +	}  	oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);  	oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);  	msleep(300); @@ -234,6 +251,27 @@ static void set_cs5381_params(struct oxygen *chip,  			      value, GPIO_CS5381_M_MASK);  } +static void xonar_gpio_changed(struct oxygen *chip) +{ +	struct xonar_data *data = chip->model_data; +	u8 has_power; + +	if (!data->is_d2x) +		return; +	has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) +		       & GPIO_EXT_POWER); +	if (has_power != data->has_power) { +		data->has_power = has_power; +		if (has_power) { +			snd_printk(KERN_NOTICE "power restored\n"); +		} else { +			snd_printk(KERN_CRIT +				   "Hey! Don't unplug the power cable!\n"); +			/* TODO: stop PCMs */ +		} +	} +} +  static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)  {  	unsigned int index = chip->controls[control]->private_value & 0xff; @@ -360,6 +398,8 @@ static const struct oxygen_model model_xonar = {  	.update_dac_volume = update_pcm1796_volume,  	.update_dac_mute = update_pcm1796_mute,  	.ac97_switch_hook = xonar_ac97_switch_hook, +	.gpio_changed = xonar_gpio_changed, +	.model_data_size = sizeof(struct xonar_data),  	.dac_channels = 8,  	.used_channels = OXYGEN_CHANNEL_B |  			 OXYGEN_CHANNEL_C |  |