diff options
Diffstat (limited to 'sound/pci/ice1712/ice1724.c')
| -rw-r--r-- | sound/pci/ice1712/ice1724.c | 105 | 
1 files changed, 84 insertions, 21 deletions
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 76b717dae4b..ae29073eea9 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -53,6 +53,7 @@  #include "phase.h"  #include "wtm.h"  #include "se.h" +#include "quartet.h"  MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");  MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); @@ -70,6 +71,7 @@ MODULE_SUPPORTED_DEVICE("{"  	       PHASE_DEVICE_DESC  	       WTM_DEVICE_DESC  	       SE_DEVICE_DESC +	       QTET_DEVICE_DESC  		"{VIA,VT1720},"  		"{VIA,VT1724},"  		"{ICEnsemble,Generic ICE1724}," @@ -104,6 +106,8 @@ static int PRO_RATE_LOCKED;  static int PRO_RATE_RESET = 1;  static unsigned int PRO_RATE_DEFAULT = 44100; +static char *ext_clock_names[1] = { "IEC958 In" }; +  /*   *  Basic I/O   */ @@ -118,9 +122,12 @@ static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)  	return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;  } +/* + * locking rate makes sense only for internal clock mode + */  static inline int is_pro_rate_locked(struct snd_ice1712 *ice)  { -	return ice->is_spdif_master(ice) || PRO_RATE_LOCKED; +	return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED;  }  /* @@ -196,6 +203,12 @@ static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)  	inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */  } +/* get gpio direction 0 = read, 1 = write */ +static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice) +{ +	return inl(ICEREG1724(ice, GPIO_DIRECTION)); +} +  /* set the gpio mask (0 = writable) */  static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)  { @@ -205,6 +218,17 @@ static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)  	inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */  } +static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice) +{ +	unsigned int mask; +	if (!ice->vt1720) +		mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22)); +	else +		mask = 0; +	mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); +	return mask; +} +  static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data)  {  	outw(data, ICEREG1724(ice, GPIO_DATA)); @@ -648,19 +672,25 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,  	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {  		/* running? we cannot change the rate now... */  		spin_unlock_irqrestore(&ice->reg_lock, flags); -		return -EBUSY; +		return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY;  	}  	if (!force && is_pro_rate_locked(ice)) { +		/* comparing required and current rate - makes sense for +		 * internal clock only */  		spin_unlock_irqrestore(&ice->reg_lock, flags);  		return (rate == ice->cur_rate) ? 0 : -EBUSY;  	} -	old_rate = ice->get_rate(ice); -	if (force || (old_rate != rate)) -		ice->set_rate(ice, rate); -	else if (rate == ice->cur_rate) { -		spin_unlock_irqrestore(&ice->reg_lock, flags); -		return 0; +	if (force || !ice->is_spdif_master(ice)) { +		/* force means the rate was switched by ucontrol, otherwise +		 * setting clock rate for internal clock mode */ +		old_rate = ice->get_rate(ice); +		if (force || (old_rate != rate)) +			ice->set_rate(ice, rate); +		else if (rate == ice->cur_rate) { +			spin_unlock_irqrestore(&ice->reg_lock, flags); +			return 0; +		}  	}  	ice->cur_rate = rate; @@ -1016,6 +1046,8 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)  				   VT1724_BUFFER_ALIGN);  	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,  				   VT1724_BUFFER_ALIGN); +	if (ice->pro_open) +		ice->pro_open(ice, substream);  	return 0;  } @@ -1034,6 +1066,8 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)  				   VT1724_BUFFER_ALIGN);  	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,  				   VT1724_BUFFER_ALIGN); +	if (ice->pro_open) +		ice->pro_open(ice, substream);  	return 0;  } @@ -1787,15 +1821,21 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,  					      struct snd_ctl_elem_info *uinfo)  {  	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - +	int hw_rates_count = ice->hw_rates->count;  	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  	uinfo->count = 1; -	uinfo->value.enumerated.items = ice->hw_rates->count + 1; + +	uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count; +	/* upper limit - keep at top */  	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)  		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; -	if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1) -		strcpy(uinfo->value.enumerated.name, "IEC958 Input"); +	if (uinfo->value.enumerated.item >= hw_rates_count) +		/* ext_clock items */ +		strcpy(uinfo->value.enumerated.name, +				ice->ext_clock_names[ +				uinfo->value.enumerated.item - hw_rates_count]);  	else +		/* int clock items */  		sprintf(uinfo->value.enumerated.name, "%d",  			ice->hw_rates->list[uinfo->value.enumerated.item]);  	return 0; @@ -1809,7 +1849,8 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,  	spin_lock_irq(&ice->reg_lock);  	if (ice->is_spdif_master(ice)) { -		ucontrol->value.enumerated.item[0] = ice->hw_rates->count; +		ucontrol->value.enumerated.item[0] = ice->hw_rates->count + +			ice->get_spdif_master_type(ice);  	} else {  		rate = ice->get_rate(ice);  		ucontrol->value.enumerated.item[0] = 0; @@ -1824,8 +1865,14 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,  	return 0;  } +static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) +{ +	/* standard external clock - only single type - SPDIF IN */ +	return 0; +} +  /* setting clock to external - SPDIF */ -static void stdclock_set_spdif_clock(struct snd_ice1712 *ice) +static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type)  {  	unsigned char oval;  	unsigned char i2s_oval; @@ -1834,27 +1881,30 @@ static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)  	/* setting 256fs */  	i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));  	outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); +	return 0;  } +  static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,  					     struct snd_ctl_elem_value *ucontrol)  {  	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);  	unsigned int old_rate, new_rate;  	unsigned int item = ucontrol->value.enumerated.item[0]; -	unsigned int spdif = ice->hw_rates->count; +	unsigned int first_ext_clock = ice->hw_rates->count; -	if (item > spdif) +	if (item >  first_ext_clock + ice->ext_clock_count - 1)  		return -EINVAL; +	/* if rate = 0 => external clock */  	spin_lock_irq(&ice->reg_lock);  	if (ice->is_spdif_master(ice))  		old_rate = 0;  	else  		old_rate = ice->get_rate(ice); -	if (item == spdif) { -		/* switching to external clock via SPDIF */ -		ice->set_spdif_clock(ice); +	if (item >= first_ext_clock) { +		/* switching to external clock */ +		ice->set_spdif_clock(ice, item - first_ext_clock);  		new_rate = 0;  	} else {  		/* internal on-card clock */ @@ -1866,7 +1916,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,  	}  	spin_unlock_irq(&ice->reg_lock); -	/* the first reset to the SPDIF master mode? */ +	/* the first switch to the ext. clock mode? */  	if (old_rate != new_rate && !new_rate) {  		/* notify akm chips as well */  		unsigned int i; @@ -2136,6 +2186,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {  	snd_vt1724_phase_cards,  	snd_vt1724_wtm_cards,  	snd_vt1724_se_cards, +	snd_vt1724_qtet_cards,  	NULL,  }; @@ -2434,7 +2485,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card,  	mutex_init(&ice->open_mutex);  	mutex_init(&ice->i2c_mutex);  	ice->gpio.set_mask = snd_vt1724_set_gpio_mask; +	ice->gpio.get_mask = snd_vt1724_get_gpio_mask;  	ice->gpio.set_dir = snd_vt1724_set_gpio_dir; +	ice->gpio.get_dir = snd_vt1724_get_gpio_dir;  	ice->gpio.set_data = snd_vt1724_set_gpio_data;  	ice->gpio.get_data = snd_vt1724_get_gpio_data;  	ice->card = card; @@ -2522,6 +2575,9 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,  		return err;  	} +	/* field init before calling chip_init */ +	ice->ext_clock_count = 0; +  	for (tbl = card_tables; *tbl; tbl++) {  		for (c = *tbl; c->subvendor; c++) {  			if (c->subvendor == ice->eeprom.subvendor) { @@ -2560,6 +2616,13 @@ __found:  		ice->set_mclk = stdclock_set_mclk;  	if (!ice->set_spdif_clock)  		ice->set_spdif_clock = stdclock_set_spdif_clock; +	if (!ice->get_spdif_master_type) +		ice->get_spdif_master_type = stdclock_get_spdif_master_type; +	if (!ice->ext_clock_names) +		ice->ext_clock_names = ext_clock_names; +	if (!ice->ext_clock_count) +		ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); +  	if (!ice->hw_rates)  		set_std_hw_rates(ice); @@ -2719,7 +2782,7 @@ static int snd_vt1724_resume(struct pci_dev *pci)  	if (ice->pm_saved_is_spdif_master) {  		/* switching to external clock via SPDIF */ -		ice->set_spdif_clock(ice); +		ice->set_spdif_clock(ice, 0);  	} else {  		/* internal on-card clock */  		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);  |