diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen_mixer.c')
| -rw-r--r-- | sound/pci/oxygen/oxygen_mixer.c | 138 | 
1 files changed, 104 insertions, 34 deletions
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 2849b36f5f7..5988e044c51 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -31,7 +31,7 @@ static int dac_volume_info(struct snd_kcontrol *ctl,  	struct oxygen *chip = ctl->private_data;  	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -	info->count = chip->model.dac_channels; +	info->count = chip->model.dac_channels_mixer;  	info->value.integer.min = chip->model.dac_volume_min;  	info->value.integer.max = chip->model.dac_volume_max;  	return 0; @@ -44,7 +44,7 @@ static int dac_volume_get(struct snd_kcontrol *ctl,  	unsigned int i;  	mutex_lock(&chip->mutex); -	for (i = 0; i < chip->model.dac_channels; ++i) +	for (i = 0; i < chip->model.dac_channels_mixer; ++i)  		value->value.integer.value[i] = chip->dac_volume[i];  	mutex_unlock(&chip->mutex);  	return 0; @@ -59,7 +59,7 @@ static int dac_volume_put(struct snd_kcontrol *ctl,  	changed = 0;  	mutex_lock(&chip->mutex); -	for (i = 0; i < chip->model.dac_channels; ++i) +	for (i = 0; i < chip->model.dac_channels_mixer; ++i)  		if (value->value.integer.value[i] != chip->dac_volume[i]) {  			chip->dac_volume[i] = value->value.integer.value[i];  			changed = 1; @@ -97,6 +97,16 @@ static int dac_mute_put(struct snd_kcontrol *ctl,  	return changed;  } +static unsigned int upmix_item_count(struct oxygen *chip) +{ +	if (chip->model.dac_channels_pcm < 8) +		return 2; +	else if (chip->model.update_center_lfe_mix) +		return 5; +	else +		return 3; +} +  static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)  {  	static const char *const names[5] = { @@ -107,15 +117,9 @@ static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)  		"Front+Surround+Center/LFE+Back",  	};  	struct oxygen *chip = ctl->private_data; -	unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; +	unsigned int count = upmix_item_count(chip); -	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -	info->count = 1; -	info->value.enumerated.items = count; -	if (info->value.enumerated.item >= count) -		info->value.enumerated.item = count - 1; -	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); -	return 0; +	return snd_ctl_enum_info(info, 1, count, names);  }  static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) @@ -176,6 +180,8 @@ void oxygen_update_dac_routing(struct oxygen *chip)  			    (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |  			    (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |  			    (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); +	if (chip->model.adjust_dac_routing) +		reg_value = chip->model.adjust_dac_routing(chip, reg_value);  	oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value,  			      OXYGEN_PLAY_DAC0_SOURCE_MASK |  			      OXYGEN_PLAY_DAC1_SOURCE_MASK | @@ -184,11 +190,12 @@ void oxygen_update_dac_routing(struct oxygen *chip)  	if (chip->model.update_center_lfe_mix)  		chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2);  } +EXPORT_SYMBOL(oxygen_update_dac_routing);  static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)  {  	struct oxygen *chip = ctl->private_data; -	unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; +	unsigned int count = upmix_item_count(chip);  	int changed;  	if (value->value.enumerated.item[0] >= count) @@ -430,30 +437,31 @@ static int spdif_input_default_get(struct snd_kcontrol *ctl,  	return 0;  } -static int spdif_loopback_get(struct snd_kcontrol *ctl, -			      struct snd_ctl_elem_value *value) +static int spdif_bit_switch_get(struct snd_kcontrol *ctl, +				struct snd_ctl_elem_value *value)  {  	struct oxygen *chip = ctl->private_data; +	u32 bit = ctl->private_value;  	value->value.integer.value[0] = -		!!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) -		   & OXYGEN_SPDIF_LOOPBACK); +		!!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit);  	return 0;  } -static int spdif_loopback_put(struct snd_kcontrol *ctl, -			      struct snd_ctl_elem_value *value) +static int spdif_bit_switch_put(struct snd_kcontrol *ctl, +				struct snd_ctl_elem_value *value)  {  	struct oxygen *chip = ctl->private_data; +	u32 bit = ctl->private_value;  	u32 oldreg, newreg;  	int changed;  	spin_lock_irq(&chip->reg_lock);  	oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);  	if (value->value.integer.value[0]) -		newreg = oldreg | OXYGEN_SPDIF_LOOPBACK; +		newreg = oldreg | bit;  	else -		newreg = oldreg & ~OXYGEN_SPDIF_LOOPBACK; +		newreg = oldreg & ~bit;  	changed = newreg != oldreg;  	if (changed)  		oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); @@ -611,9 +619,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,  	mutex_lock(&chip->mutex);  	reg = oxygen_read_ac97(chip, codec, index);  	mutex_unlock(&chip->mutex); -	value->value.integer.value[0] = 31 - (reg & 0x1f); -	if (stereo) -		value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); +	if (!stereo) { +		value->value.integer.value[0] = 31 - (reg & 0x1f); +	} else { +		value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); +		value->value.integer.value[1] = 31 - (reg & 0x1f); +	}  	return 0;  } @@ -629,14 +640,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,  	mutex_lock(&chip->mutex);  	oldreg = oxygen_read_ac97(chip, codec, index); -	newreg = oldreg; -	newreg = (newreg & ~0x1f) | -		(31 - (value->value.integer.value[0] & 0x1f)); -	if (stereo) -		newreg = (newreg & ~0x1f00) | -			((31 - (value->value.integer.value[1] & 0x1f)) << 8); -	else -		newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8); +	if (!stereo) { +		newreg = oldreg & ~0x1f; +		newreg |= 31 - (value->value.integer.value[0] & 0x1f); +	} else { +		newreg = oldreg & ~0x1f1f; +		newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; +		newreg |= 31 - (value->value.integer.value[1] & 0x1f); +	}  	change = newreg != oldreg;  	if (change)  		oxygen_write_ac97(chip, codec, index, newreg); @@ -644,6 +655,46 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,  	return change;  } +static int mic_fmic_source_info(struct snd_kcontrol *ctl, +			   struct snd_ctl_elem_info *info) +{ +	static const char *const names[] = { "Mic Jack", "Front Panel" }; + +	return snd_ctl_enum_info(info, 1, 2, names); +} + +static int mic_fmic_source_get(struct snd_kcontrol *ctl, +			       struct snd_ctl_elem_value *value) +{ +	struct oxygen *chip = ctl->private_data; + +	mutex_lock(&chip->mutex); +	value->value.enumerated.item[0] = +		!!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); +	mutex_unlock(&chip->mutex); +	return 0; +} + +static int mic_fmic_source_put(struct snd_kcontrol *ctl, +			       struct snd_ctl_elem_value *value) +{ +	struct oxygen *chip = ctl->private_data; +	u16 oldreg, newreg; +	int change; + +	mutex_lock(&chip->mutex); +	oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); +	if (value->value.enumerated.item[0]) +		newreg = oldreg | CM9780_FMIC2MIC; +	else +		newreg = oldreg & ~CM9780_FMIC2MIC; +	change = newreg != oldreg; +	if (change) +		oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); +	mutex_unlock(&chip->mutex); +	return change; +} +  static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl,  				   struct snd_ctl_elem_info *info)  { @@ -791,8 +842,17 @@ static const struct snd_kcontrol_new spdif_input_controls[] = {  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  		.name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH),  		.info = snd_ctl_boolean_mono_info, -		.get = spdif_loopback_get, -		.put = spdif_loopback_put, +		.get = spdif_bit_switch_get, +		.put = spdif_bit_switch_put, +		.private_value = OXYGEN_SPDIF_LOOPBACK, +	}, +	{ +		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, +		.name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH), +		.info = snd_ctl_boolean_mono_info, +		.get = spdif_bit_switch_get, +		.put = spdif_bit_switch_put, +		.private_value = OXYGEN_SPDIF_SPDVALID,  	},  }; @@ -908,6 +968,13 @@ static const struct snd_kcontrol_new ac97_controls[] = {  	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0),  	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),  	AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), +	{ +		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, +		.name = "Mic Source Capture Enum", +		.info = mic_fmic_source_info, +		.get = mic_fmic_source_get, +		.put = mic_fmic_source_put, +	},  	AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),  	AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1),  	AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), @@ -970,7 +1037,10 @@ static int add_controls(struct oxygen *chip,  				continue;  		}  		if (!strcmp(template.name, "Stereo Upmixing") && -		    chip->model.dac_channels == 2) +		    chip->model.dac_channels_pcm == 2) +			continue; +		if (!strcmp(template.name, "Mic Source Capture Enum") && +		    !(chip->model.device_config & AC97_FMIC_SWITCH))  			continue;  		if (!strncmp(template.name, "CD Capture ", 11) &&  		    !(chip->model.device_config & AC97_CD_INPUT))  | 
