brintos

brintos / linux-shallow public Read only

0
0
Text · 31.5 KiB · eb3aca1 Raw
1128 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * C-Media CMI8788 driver - mixer code4 *5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>6 */7 8#include <linux/mutex.h>9#include <sound/ac97_codec.h>10#include <sound/asoundef.h>11#include <sound/control.h>12#include <sound/tlv.h>13#include "oxygen.h"14#include "cm9780.h"15 16static int dac_volume_info(struct snd_kcontrol *ctl,17			   struct snd_ctl_elem_info *info)18{19	struct oxygen *chip = ctl->private_data;20 21	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;22	info->count = chip->model.dac_channels_mixer;23	info->value.integer.min = chip->model.dac_volume_min;24	info->value.integer.max = chip->model.dac_volume_max;25	return 0;26}27 28static int dac_volume_get(struct snd_kcontrol *ctl,29			  struct snd_ctl_elem_value *value)30{31	struct oxygen *chip = ctl->private_data;32	unsigned int i;33 34	mutex_lock(&chip->mutex);35	for (i = 0; i < chip->model.dac_channels_mixer; ++i)36		value->value.integer.value[i] = chip->dac_volume[i];37	mutex_unlock(&chip->mutex);38	return 0;39}40 41static int dac_volume_put(struct snd_kcontrol *ctl,42			  struct snd_ctl_elem_value *value)43{44	struct oxygen *chip = ctl->private_data;45	unsigned int i;46	int changed;47 48	changed = 0;49	mutex_lock(&chip->mutex);50	for (i = 0; i < chip->model.dac_channels_mixer; ++i)51		if (value->value.integer.value[i] != chip->dac_volume[i]) {52			chip->dac_volume[i] = value->value.integer.value[i];53			changed = 1;54		}55	if (changed)56		chip->model.update_dac_volume(chip);57	mutex_unlock(&chip->mutex);58	return changed;59}60 61static int dac_mute_get(struct snd_kcontrol *ctl,62			struct snd_ctl_elem_value *value)63{64	struct oxygen *chip = ctl->private_data;65 66	mutex_lock(&chip->mutex);67	value->value.integer.value[0] = !chip->dac_mute;68	mutex_unlock(&chip->mutex);69	return 0;70}71 72static int dac_mute_put(struct snd_kcontrol *ctl,73			  struct snd_ctl_elem_value *value)74{75	struct oxygen *chip = ctl->private_data;76	int changed;77 78	mutex_lock(&chip->mutex);79	changed = (!value->value.integer.value[0]) != chip->dac_mute;80	if (changed) {81		chip->dac_mute = !value->value.integer.value[0];82		chip->model.update_dac_mute(chip);83	}84	mutex_unlock(&chip->mutex);85	return changed;86}87 88static unsigned int upmix_item_count(struct oxygen *chip)89{90	if (chip->model.dac_channels_pcm < 8)91		return 2;92	else if (chip->model.update_center_lfe_mix)93		return 5;94	else95		return 3;96}97 98static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)99{100	static const char *const names[5] = {101		"Front",102		"Front+Surround",103		"Front+Surround+Back",104		"Front+Surround+Center/LFE",105		"Front+Surround+Center/LFE+Back",106	};107	struct oxygen *chip = ctl->private_data;108	unsigned int count = upmix_item_count(chip);109 110	return snd_ctl_enum_info(info, 1, count, names);111}112 113static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)114{115	struct oxygen *chip = ctl->private_data;116 117	mutex_lock(&chip->mutex);118	value->value.enumerated.item[0] = chip->dac_routing;119	mutex_unlock(&chip->mutex);120	return 0;121}122 123void oxygen_update_dac_routing(struct oxygen *chip)124{125	/* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */126	static const unsigned int reg_values[5] = {127		/* stereo -> front */128		(0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |129		(1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |130		(2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |131		(3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),132		/* stereo -> front+surround */133		(0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |134		(0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |135		(2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |136		(3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),137		/* stereo -> front+surround+back */138		(0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |139		(0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |140		(2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |141		(0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),142		/* stereo -> front+surround+center/LFE */143		(0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |144		(0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |145		(0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |146		(3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),147		/* stereo -> front+surround+center/LFE+back */148		(0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |149		(0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |150		(0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |151		(0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT),152	};153	u8 channels;154	unsigned int reg_value;155 156	channels = oxygen_read8(chip, OXYGEN_PLAY_CHANNELS) &157		OXYGEN_PLAY_CHANNELS_MASK;158	if (channels == OXYGEN_PLAY_CHANNELS_2)159		reg_value = reg_values[chip->dac_routing];160	else if (channels == OXYGEN_PLAY_CHANNELS_8)161		/* in 7.1 mode, "rear" channels go to the "back" jack */162		reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |163			    (3 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |164			    (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |165			    (1 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT);166	else167		reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |168			    (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |169			    (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |170			    (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT);171	if (chip->model.adjust_dac_routing)172		reg_value = chip->model.adjust_dac_routing(chip, reg_value);173	oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value,174			      OXYGEN_PLAY_DAC0_SOURCE_MASK |175			      OXYGEN_PLAY_DAC1_SOURCE_MASK |176			      OXYGEN_PLAY_DAC2_SOURCE_MASK |177			      OXYGEN_PLAY_DAC3_SOURCE_MASK);178	if (chip->model.update_center_lfe_mix)179		chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2);180}181EXPORT_SYMBOL(oxygen_update_dac_routing);182 183static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)184{185	struct oxygen *chip = ctl->private_data;186	unsigned int count = upmix_item_count(chip);187	int changed;188 189	if (value->value.enumerated.item[0] >= count)190		return -EINVAL;191	mutex_lock(&chip->mutex);192	changed = value->value.enumerated.item[0] != chip->dac_routing;193	if (changed) {194		chip->dac_routing = value->value.enumerated.item[0];195		oxygen_update_dac_routing(chip);196	}197	mutex_unlock(&chip->mutex);198	return changed;199}200 201static int spdif_switch_get(struct snd_kcontrol *ctl,202			    struct snd_ctl_elem_value *value)203{204	struct oxygen *chip = ctl->private_data;205 206	mutex_lock(&chip->mutex);207	value->value.integer.value[0] = chip->spdif_playback_enable;208	mutex_unlock(&chip->mutex);209	return 0;210}211 212static unsigned int oxygen_spdif_rate(unsigned int oxygen_rate)213{214	switch (oxygen_rate) {215	case OXYGEN_RATE_32000:216		return IEC958_AES3_CON_FS_32000 << OXYGEN_SPDIF_CS_RATE_SHIFT;217	case OXYGEN_RATE_44100:218		return IEC958_AES3_CON_FS_44100 << OXYGEN_SPDIF_CS_RATE_SHIFT;219	default: /* OXYGEN_RATE_48000 */220		return IEC958_AES3_CON_FS_48000 << OXYGEN_SPDIF_CS_RATE_SHIFT;221	case OXYGEN_RATE_64000:222		return 0xb << OXYGEN_SPDIF_CS_RATE_SHIFT;223	case OXYGEN_RATE_88200:224		return IEC958_AES3_CON_FS_88200 << OXYGEN_SPDIF_CS_RATE_SHIFT;225	case OXYGEN_RATE_96000:226		return IEC958_AES3_CON_FS_96000 << OXYGEN_SPDIF_CS_RATE_SHIFT;227	case OXYGEN_RATE_176400:228		return IEC958_AES3_CON_FS_176400 << OXYGEN_SPDIF_CS_RATE_SHIFT;229	case OXYGEN_RATE_192000:230		return IEC958_AES3_CON_FS_192000 << OXYGEN_SPDIF_CS_RATE_SHIFT;231	}232}233 234void oxygen_update_spdif_source(struct oxygen *chip)235{236	u32 old_control, new_control;237	u16 old_routing, new_routing;238	unsigned int oxygen_rate;239 240	old_control = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);241	old_routing = oxygen_read16(chip, OXYGEN_PLAY_ROUTING);242	if (chip->pcm_active & (1 << PCM_SPDIF)) {243		new_control = old_control | OXYGEN_SPDIF_OUT_ENABLE;244		new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK)245			| OXYGEN_PLAY_SPDIF_SPDIF;246		oxygen_rate = (old_control >> OXYGEN_SPDIF_OUT_RATE_SHIFT)247			& OXYGEN_I2S_RATE_MASK;248		/* S/PDIF rate was already set by the caller */249	} else if ((chip->pcm_active & (1 << PCM_MULTICH)) &&250		   chip->spdif_playback_enable) {251		new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK)252			| OXYGEN_PLAY_SPDIF_MULTICH_01;253		oxygen_rate = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT)254			& OXYGEN_I2S_RATE_MASK;255		new_control = (old_control & ~OXYGEN_SPDIF_OUT_RATE_MASK) |256			(oxygen_rate << OXYGEN_SPDIF_OUT_RATE_SHIFT) |257			OXYGEN_SPDIF_OUT_ENABLE;258	} else {259		new_control = old_control & ~OXYGEN_SPDIF_OUT_ENABLE;260		new_routing = old_routing;261		oxygen_rate = OXYGEN_RATE_44100;262	}263	if (old_routing != new_routing) {264		oxygen_write32(chip, OXYGEN_SPDIF_CONTROL,265			       new_control & ~OXYGEN_SPDIF_OUT_ENABLE);266		oxygen_write16(chip, OXYGEN_PLAY_ROUTING, new_routing);267	}268	if (new_control & OXYGEN_SPDIF_OUT_ENABLE)269		oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS,270			       oxygen_spdif_rate(oxygen_rate) |271			       ((chip->pcm_active & (1 << PCM_SPDIF)) ?272				chip->spdif_pcm_bits : chip->spdif_bits));273	oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, new_control);274}275 276static int spdif_switch_put(struct snd_kcontrol *ctl,277			    struct snd_ctl_elem_value *value)278{279	struct oxygen *chip = ctl->private_data;280	int changed;281 282	mutex_lock(&chip->mutex);283	changed = value->value.integer.value[0] != chip->spdif_playback_enable;284	if (changed) {285		chip->spdif_playback_enable = !!value->value.integer.value[0];286		spin_lock_irq(&chip->reg_lock);287		oxygen_update_spdif_source(chip);288		spin_unlock_irq(&chip->reg_lock);289	}290	mutex_unlock(&chip->mutex);291	return changed;292}293 294static int spdif_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)295{296	info->type = SNDRV_CTL_ELEM_TYPE_IEC958;297	info->count = 1;298	return 0;299}300 301static void oxygen_to_iec958(u32 bits, struct snd_ctl_elem_value *value)302{303	value->value.iec958.status[0] =304		bits & (OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C |305			OXYGEN_SPDIF_PREEMPHASIS);306	value->value.iec958.status[1] = /* category and original */307		bits >> OXYGEN_SPDIF_CATEGORY_SHIFT;308}309 310static u32 iec958_to_oxygen(struct snd_ctl_elem_value *value)311{312	u32 bits;313 314	bits = value->value.iec958.status[0] &315		(OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C |316		 OXYGEN_SPDIF_PREEMPHASIS);317	bits |= value->value.iec958.status[1] << OXYGEN_SPDIF_CATEGORY_SHIFT;318	if (bits & OXYGEN_SPDIF_NONAUDIO)319		bits |= OXYGEN_SPDIF_V;320	return bits;321}322 323static inline void write_spdif_bits(struct oxygen *chip, u32 bits)324{325	oxygen_write32_masked(chip, OXYGEN_SPDIF_OUTPUT_BITS, bits,326			      OXYGEN_SPDIF_NONAUDIO |327			      OXYGEN_SPDIF_C |328			      OXYGEN_SPDIF_PREEMPHASIS |329			      OXYGEN_SPDIF_CATEGORY_MASK |330			      OXYGEN_SPDIF_ORIGINAL |331			      OXYGEN_SPDIF_V);332}333 334static int spdif_default_get(struct snd_kcontrol *ctl,335			     struct snd_ctl_elem_value *value)336{337	struct oxygen *chip = ctl->private_data;338 339	mutex_lock(&chip->mutex);340	oxygen_to_iec958(chip->spdif_bits, value);341	mutex_unlock(&chip->mutex);342	return 0;343}344 345static int spdif_default_put(struct snd_kcontrol *ctl,346			     struct snd_ctl_elem_value *value)347{348	struct oxygen *chip = ctl->private_data;349	u32 new_bits;350	int changed;351 352	new_bits = iec958_to_oxygen(value);353	mutex_lock(&chip->mutex);354	changed = new_bits != chip->spdif_bits;355	if (changed) {356		chip->spdif_bits = new_bits;357		if (!(chip->pcm_active & (1 << PCM_SPDIF)))358			write_spdif_bits(chip, new_bits);359	}360	mutex_unlock(&chip->mutex);361	return changed;362}363 364static int spdif_mask_get(struct snd_kcontrol *ctl,365			  struct snd_ctl_elem_value *value)366{367	value->value.iec958.status[0] = IEC958_AES0_NONAUDIO |368		IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS;369	value->value.iec958.status[1] =370		IEC958_AES1_CON_CATEGORY | IEC958_AES1_CON_ORIGINAL;371	return 0;372}373 374static int spdif_pcm_get(struct snd_kcontrol *ctl,375			 struct snd_ctl_elem_value *value)376{377	struct oxygen *chip = ctl->private_data;378 379	mutex_lock(&chip->mutex);380	oxygen_to_iec958(chip->spdif_pcm_bits, value);381	mutex_unlock(&chip->mutex);382	return 0;383}384 385static int spdif_pcm_put(struct snd_kcontrol *ctl,386			 struct snd_ctl_elem_value *value)387{388	struct oxygen *chip = ctl->private_data;389	u32 new_bits;390	int changed;391 392	new_bits = iec958_to_oxygen(value);393	mutex_lock(&chip->mutex);394	changed = new_bits != chip->spdif_pcm_bits;395	if (changed) {396		chip->spdif_pcm_bits = new_bits;397		if (chip->pcm_active & (1 << PCM_SPDIF))398			write_spdif_bits(chip, new_bits);399	}400	mutex_unlock(&chip->mutex);401	return changed;402}403 404static int spdif_input_mask_get(struct snd_kcontrol *ctl,405				struct snd_ctl_elem_value *value)406{407	value->value.iec958.status[0] = 0xff;408	value->value.iec958.status[1] = 0xff;409	value->value.iec958.status[2] = 0xff;410	value->value.iec958.status[3] = 0xff;411	return 0;412}413 414static int spdif_input_default_get(struct snd_kcontrol *ctl,415				   struct snd_ctl_elem_value *value)416{417	struct oxygen *chip = ctl->private_data;418	u32 bits;419 420	bits = oxygen_read32(chip, OXYGEN_SPDIF_INPUT_BITS);421	value->value.iec958.status[0] = bits;422	value->value.iec958.status[1] = bits >> 8;423	value->value.iec958.status[2] = bits >> 16;424	value->value.iec958.status[3] = bits >> 24;425	return 0;426}427 428static int spdif_bit_switch_get(struct snd_kcontrol *ctl,429				struct snd_ctl_elem_value *value)430{431	struct oxygen *chip = ctl->private_data;432	u32 bit = ctl->private_value;433 434	value->value.integer.value[0] =435		!!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit);436	return 0;437}438 439static int spdif_bit_switch_put(struct snd_kcontrol *ctl,440				struct snd_ctl_elem_value *value)441{442	struct oxygen *chip = ctl->private_data;443	u32 bit = ctl->private_value;444	u32 oldreg, newreg;445	int changed;446 447	spin_lock_irq(&chip->reg_lock);448	oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);449	if (value->value.integer.value[0])450		newreg = oldreg | bit;451	else452		newreg = oldreg & ~bit;453	changed = newreg != oldreg;454	if (changed)455		oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg);456	spin_unlock_irq(&chip->reg_lock);457	return changed;458}459 460static int monitor_volume_info(struct snd_kcontrol *ctl,461			       struct snd_ctl_elem_info *info)462{463	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;464	info->count = 1;465	info->value.integer.min = 0;466	info->value.integer.max = 1;467	return 0;468}469 470static int monitor_get(struct snd_kcontrol *ctl,471		       struct snd_ctl_elem_value *value)472{473	struct oxygen *chip = ctl->private_data;474	u8 bit = ctl->private_value;475	int invert = ctl->private_value & (1 << 8);476 477	value->value.integer.value[0] =478		!!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);479	return 0;480}481 482static int monitor_put(struct snd_kcontrol *ctl,483		       struct snd_ctl_elem_value *value)484{485	struct oxygen *chip = ctl->private_data;486	u8 bit = ctl->private_value;487	int invert = ctl->private_value & (1 << 8);488	u8 oldreg, newreg;489	int changed;490 491	spin_lock_irq(&chip->reg_lock);492	oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);493	if ((!!value->value.integer.value[0] ^ !!invert) != 0)494		newreg = oldreg | bit;495	else496		newreg = oldreg & ~bit;497	changed = newreg != oldreg;498	if (changed)499		oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);500	spin_unlock_irq(&chip->reg_lock);501	return changed;502}503 504static int ac97_switch_get(struct snd_kcontrol *ctl,505			   struct snd_ctl_elem_value *value)506{507	struct oxygen *chip = ctl->private_data;508	unsigned int codec = (ctl->private_value >> 24) & 1;509	unsigned int index = ctl->private_value & 0xff;510	unsigned int bitnr = (ctl->private_value >> 8) & 0xff;511	int invert = ctl->private_value & (1 << 16);512	u16 reg;513 514	mutex_lock(&chip->mutex);515	reg = oxygen_read_ac97(chip, codec, index);516	mutex_unlock(&chip->mutex);517	if (!(reg & (1 << bitnr)) ^ !invert)518		value->value.integer.value[0] = 1;519	else520		value->value.integer.value[0] = 0;521	return 0;522}523 524static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)525{526	unsigned int priv_idx;527	u16 value;528 529	if (!chip->controls[control])530		return;531	priv_idx = chip->controls[control]->private_value & 0xff;532	value = oxygen_read_ac97(chip, 0, priv_idx);533	if (!(value & 0x8000)) {534		oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);535		if (chip->model.ac97_switch)536			chip->model.ac97_switch(chip, priv_idx, 0x8000);537		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,538			       &chip->controls[control]->id);539	}540}541 542static int ac97_switch_put(struct snd_kcontrol *ctl,543			   struct snd_ctl_elem_value *value)544{545	struct oxygen *chip = ctl->private_data;546	unsigned int codec = (ctl->private_value >> 24) & 1;547	unsigned int index = ctl->private_value & 0xff;548	unsigned int bitnr = (ctl->private_value >> 8) & 0xff;549	int invert = ctl->private_value & (1 << 16);550	u16 oldreg, newreg;551	int change;552 553	mutex_lock(&chip->mutex);554	oldreg = oxygen_read_ac97(chip, codec, index);555	newreg = oldreg;556	if (!value->value.integer.value[0] ^ !invert)557		newreg |= 1 << bitnr;558	else559		newreg &= ~(1 << bitnr);560	change = newreg != oldreg;561	if (change) {562		oxygen_write_ac97(chip, codec, index, newreg);563		if (codec == 0 && chip->model.ac97_switch)564			chip->model.ac97_switch(chip, index, newreg & 0x8000);565		if (index == AC97_LINE) {566			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,567						 newreg & 0x8000 ?568						 CM9780_GPO0 : 0, CM9780_GPO0);569			if (!(newreg & 0x8000)) {570				mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);571				mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);572				mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);573			}574		} else if ((index == AC97_MIC || index == AC97_CD ||575			    index == AC97_VIDEO || index == AC97_AUX) &&576			   bitnr == 15 && !(newreg & 0x8000)) {577			mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);578			oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,579						 CM9780_GPO0, CM9780_GPO0);580		}581	}582	mutex_unlock(&chip->mutex);583	return change;584}585 586static int ac97_volume_info(struct snd_kcontrol *ctl,587			    struct snd_ctl_elem_info *info)588{589	int stereo = (ctl->private_value >> 16) & 1;590 591	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;592	info->count = stereo ? 2 : 1;593	info->value.integer.min = 0;594	info->value.integer.max = 0x1f;595	return 0;596}597 598static int ac97_volume_get(struct snd_kcontrol *ctl,599			   struct snd_ctl_elem_value *value)600{601	struct oxygen *chip = ctl->private_data;602	unsigned int codec = (ctl->private_value >> 24) & 1;603	int stereo = (ctl->private_value >> 16) & 1;604	unsigned int index = ctl->private_value & 0xff;605	u16 reg;606 607	mutex_lock(&chip->mutex);608	reg = oxygen_read_ac97(chip, codec, index);609	mutex_unlock(&chip->mutex);610	if (!stereo) {611		value->value.integer.value[0] = 31 - (reg & 0x1f);612	} else {613		value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f);614		value->value.integer.value[1] = 31 - (reg & 0x1f);615	}616	return 0;617}618 619static int ac97_volume_put(struct snd_kcontrol *ctl,620			   struct snd_ctl_elem_value *value)621{622	struct oxygen *chip = ctl->private_data;623	unsigned int codec = (ctl->private_value >> 24) & 1;624	int stereo = (ctl->private_value >> 16) & 1;625	unsigned int index = ctl->private_value & 0xff;626	u16 oldreg, newreg;627	int change;628 629	mutex_lock(&chip->mutex);630	oldreg = oxygen_read_ac97(chip, codec, index);631	if (!stereo) {632		newreg = oldreg & ~0x1f;633		newreg |= 31 - (value->value.integer.value[0] & 0x1f);634	} else {635		newreg = oldreg & ~0x1f1f;636		newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8;637		newreg |= 31 - (value->value.integer.value[1] & 0x1f);638	}639	change = newreg != oldreg;640	if (change)641		oxygen_write_ac97(chip, codec, index, newreg);642	mutex_unlock(&chip->mutex);643	return change;644}645 646static int mic_fmic_source_info(struct snd_kcontrol *ctl,647			   struct snd_ctl_elem_info *info)648{649	static const char *const names[] = { "Mic Jack", "Front Panel" };650 651	return snd_ctl_enum_info(info, 1, 2, names);652}653 654static int mic_fmic_source_get(struct snd_kcontrol *ctl,655			       struct snd_ctl_elem_value *value)656{657	struct oxygen *chip = ctl->private_data;658 659	mutex_lock(&chip->mutex);660	value->value.enumerated.item[0] =661		!!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC);662	mutex_unlock(&chip->mutex);663	return 0;664}665 666static int mic_fmic_source_put(struct snd_kcontrol *ctl,667			       struct snd_ctl_elem_value *value)668{669	struct oxygen *chip = ctl->private_data;670	u16 oldreg, newreg;671	int change;672 673	mutex_lock(&chip->mutex);674	oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK);675	if (value->value.enumerated.item[0])676		newreg = oldreg | CM9780_FMIC2MIC;677	else678		newreg = oldreg & ~CM9780_FMIC2MIC;679	change = newreg != oldreg;680	if (change)681		oxygen_write_ac97(chip, 0, CM9780_JACK, newreg);682	mutex_unlock(&chip->mutex);683	return change;684}685 686static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl,687				   struct snd_ctl_elem_info *info)688{689	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;690	info->count = 2;691	info->value.integer.min = 0;692	info->value.integer.max = 7;693	return 0;694}695 696static int ac97_fp_rec_volume_get(struct snd_kcontrol *ctl,697				  struct snd_ctl_elem_value *value)698{699	struct oxygen *chip = ctl->private_data;700	u16 reg;701 702	mutex_lock(&chip->mutex);703	reg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN);704	mutex_unlock(&chip->mutex);705	value->value.integer.value[0] = reg & 7;706	value->value.integer.value[1] = (reg >> 8) & 7;707	return 0;708}709 710static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,711				  struct snd_ctl_elem_value *value)712{713	struct oxygen *chip = ctl->private_data;714	u16 oldreg, newreg;715	int change;716 717	mutex_lock(&chip->mutex);718	oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN);719	newreg = oldreg & ~0x0707;720	newreg = newreg | (value->value.integer.value[0] & 7);721	newreg = newreg | ((value->value.integer.value[1] & 7) << 8);722	change = newreg != oldreg;723	if (change)724		oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg);725	mutex_unlock(&chip->mutex);726	return change;727}728 729#define AC97_SWITCH(xname, codec, index, bitnr, invert) { \730		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \731		.name = xname, \732		.info = snd_ctl_boolean_mono_info, \733		.get = ac97_switch_get, \734		.put = ac97_switch_put, \735		.private_value = ((codec) << 24) | ((invert) << 16) | \736				 ((bitnr) << 8) | (index), \737	}738#define AC97_VOLUME(xname, codec, index, stereo) { \739		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \740		.name = xname, \741		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \742			  SNDRV_CTL_ELEM_ACCESS_TLV_READ, \743		.info = ac97_volume_info, \744		.get = ac97_volume_get, \745		.put = ac97_volume_put, \746		.tlv = { .p = ac97_db_scale, }, \747		.private_value = ((codec) << 24) | ((stereo) << 16) | (index), \748	}749 750static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0);751static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);752static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);753 754static const struct snd_kcontrol_new controls[] = {755	{756		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,757		.name = "Master Playback Volume",758		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,759		.info = dac_volume_info,760		.get = dac_volume_get,761		.put = dac_volume_put,762	},763	{764		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,765		.name = "Master Playback Switch",766		.info = snd_ctl_boolean_mono_info,767		.get = dac_mute_get,768		.put = dac_mute_put,769	},770	{771		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,772		.name = "Stereo Upmixing",773		.info = upmix_info,774		.get = upmix_get,775		.put = upmix_put,776	},777};778 779static const struct snd_kcontrol_new spdif_output_controls[] = {780	{781		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,782		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),783		.info = snd_ctl_boolean_mono_info,784		.get = spdif_switch_get,785		.put = spdif_switch_put,786	},787	{788		.iface = SNDRV_CTL_ELEM_IFACE_PCM,789		.device = 1,790		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),791		.info = spdif_info,792		.get = spdif_default_get,793		.put = spdif_default_put,794	},795	{796		.iface = SNDRV_CTL_ELEM_IFACE_PCM,797		.device = 1,798		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),799		.access = SNDRV_CTL_ELEM_ACCESS_READ,800		.info = spdif_info,801		.get = spdif_mask_get,802	},803	{804		.iface = SNDRV_CTL_ELEM_IFACE_PCM,805		.device = 1,806		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),807		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |808			  SNDRV_CTL_ELEM_ACCESS_INACTIVE,809		.info = spdif_info,810		.get = spdif_pcm_get,811		.put = spdif_pcm_put,812	},813};814 815static const struct snd_kcontrol_new spdif_input_controls[] = {816	{817		.iface = SNDRV_CTL_ELEM_IFACE_PCM,818		.device = 1,819		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),820		.access = SNDRV_CTL_ELEM_ACCESS_READ,821		.info = spdif_info,822		.get = spdif_input_mask_get,823	},824	{825		.iface = SNDRV_CTL_ELEM_IFACE_PCM,826		.device = 1,827		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),828		.access = SNDRV_CTL_ELEM_ACCESS_READ,829		.info = spdif_info,830		.get = spdif_input_default_get,831	},832	{833		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,834		.name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH),835		.info = snd_ctl_boolean_mono_info,836		.get = spdif_bit_switch_get,837		.put = spdif_bit_switch_put,838		.private_value = OXYGEN_SPDIF_LOOPBACK,839	},840	{841		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,842		.name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH),843		.info = snd_ctl_boolean_mono_info,844		.get = spdif_bit_switch_get,845		.put = spdif_bit_switch_put,846		.private_value = OXYGEN_SPDIF_SPDVALID,847	},848};849 850static const struct {851	unsigned int pcm_dev;852	struct snd_kcontrol_new controls[2];853} monitor_controls[] = {854	{855		.pcm_dev = CAPTURE_0_FROM_I2S_1,856		.controls = {857			{858				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,859				.name = "Analog Input Monitor Playback Switch",860				.info = snd_ctl_boolean_mono_info,861				.get = monitor_get,862				.put = monitor_put,863				.private_value = OXYGEN_ADC_MONITOR_A,864			},865			{866				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,867				.name = "Analog Input Monitor Playback Volume",868				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |869					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,870				.info = monitor_volume_info,871				.get = monitor_get,872				.put = monitor_put,873				.private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL874						| (1 << 8),875				.tlv = { .p = monitor_db_scale, },876			},877		},878	},879	{880		.pcm_dev = CAPTURE_0_FROM_I2S_2,881		.controls = {882			{883				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,884				.name = "Analog Input Monitor Playback Switch",885				.info = snd_ctl_boolean_mono_info,886				.get = monitor_get,887				.put = monitor_put,888				.private_value = OXYGEN_ADC_MONITOR_B,889			},890			{891				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,892				.name = "Analog Input Monitor Playback Volume",893				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |894					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,895				.info = monitor_volume_info,896				.get = monitor_get,897				.put = monitor_put,898				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL899						| (1 << 8),900				.tlv = { .p = monitor_db_scale, },901			},902		},903	},904	{905		.pcm_dev = CAPTURE_2_FROM_I2S_2,906		.controls = {907			{908				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,909				.name = "Analog Input Monitor Playback Switch",910				.index = 1,911				.info = snd_ctl_boolean_mono_info,912				.get = monitor_get,913				.put = monitor_put,914				.private_value = OXYGEN_ADC_MONITOR_B,915			},916			{917				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,918				.name = "Analog Input Monitor Playback Volume",919				.index = 1,920				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |921					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,922				.info = monitor_volume_info,923				.get = monitor_get,924				.put = monitor_put,925				.private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL926						| (1 << 8),927				.tlv = { .p = monitor_db_scale, },928			},929		},930	},931	{932		.pcm_dev = CAPTURE_3_FROM_I2S_3,933		.controls = {934			{935				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,936				.name = "Analog Input Monitor Playback Switch",937				.index = 2,938				.info = snd_ctl_boolean_mono_info,939				.get = monitor_get,940				.put = monitor_put,941				.private_value = OXYGEN_ADC_MONITOR_C,942			},943			{944				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,945				.name = "Analog Input Monitor Playback Volume",946				.index = 2,947				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |948					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,949				.info = monitor_volume_info,950				.get = monitor_get,951				.put = monitor_put,952				.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL953						| (1 << 8),954				.tlv = { .p = monitor_db_scale, },955			},956		},957	},958	{959		.pcm_dev = CAPTURE_1_FROM_SPDIF,960		.controls = {961			{962				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,963				.name = "Digital Input Monitor Playback Switch",964				.info = snd_ctl_boolean_mono_info,965				.get = monitor_get,966				.put = monitor_put,967				.private_value = OXYGEN_ADC_MONITOR_C,968			},969			{970				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,971				.name = "Digital Input Monitor Playback Volume",972				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |973					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,974				.info = monitor_volume_info,975				.get = monitor_get,976				.put = monitor_put,977				.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL978						| (1 << 8),979				.tlv = { .p = monitor_db_scale, },980			},981		},982	},983};984 985static const struct snd_kcontrol_new ac97_controls[] = {986	AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0),987	AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),988	AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),989	{990		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,991		.name = "Mic Source Capture Enum",992		.info = mic_fmic_source_info,993		.get = mic_fmic_source_get,994		.put = mic_fmic_source_put,995	},996	AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),997	AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1),998	AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),999	AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX, 1),1000	AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1),1001};1002 1003static const struct snd_kcontrol_new ac97_fp_controls[] = {1004	AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE, 1),1005	AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1),1006	{1007		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,1008		.name = "Front Panel Capture Volume",1009		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |1010			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,1011		.info = ac97_fp_rec_volume_info,1012		.get = ac97_fp_rec_volume_get,1013		.put = ac97_fp_rec_volume_put,1014		.tlv = { .p = ac97_rec_db_scale, },1015	},1016	AC97_SWITCH("Front Panel Capture Switch", 1, AC97_REC_GAIN, 15, 1),1017};1018 1019static void oxygen_any_ctl_free(struct snd_kcontrol *ctl)1020{1021	struct oxygen *chip = ctl->private_data;1022	unsigned int i;1023 1024	/* I'm too lazy to write a function for each control :-) */1025	for (i = 0; i < ARRAY_SIZE(chip->controls); ++i)1026		chip->controls[i] = NULL;1027}1028 1029static int add_controls(struct oxygen *chip,1030			const struct snd_kcontrol_new controls[],1031			unsigned int count)1032{1033	static const char *const known_ctl_names[CONTROL_COUNT] = {1034		[CONTROL_SPDIF_PCM] =1035			SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),1036		[CONTROL_SPDIF_INPUT_BITS] =1037			SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),1038		[CONTROL_MIC_CAPTURE_SWITCH] = "Mic Capture Switch",1039		[CONTROL_LINE_CAPTURE_SWITCH] = "Line Capture Switch",1040		[CONTROL_CD_CAPTURE_SWITCH] = "CD Capture Switch",1041		[CONTROL_AUX_CAPTURE_SWITCH] = "Aux Capture Switch",1042	};1043	unsigned int i;1044	struct snd_kcontrol_new template;1045	struct snd_kcontrol *ctl;1046	int j, err;1047 1048	for (i = 0; i < count; ++i) {1049		template = controls[i];1050		if (chip->model.control_filter) {1051			err = chip->model.control_filter(&template);1052			if (err < 0)1053				return err;1054			if (err == 1)1055				continue;1056		}1057		if (!strcmp(template.name, "Stereo Upmixing") &&1058		    chip->model.dac_channels_pcm == 2)1059			continue;1060		if (!strcmp(template.name, "Mic Source Capture Enum") &&1061		    !(chip->model.device_config & AC97_FMIC_SWITCH))1062			continue;1063		if (!strncmp(template.name, "CD Capture ", 11) &&1064		    !(chip->model.device_config & AC97_CD_INPUT))1065			continue;1066		if (!strcmp(template.name, "Master Playback Volume") &&1067		    chip->model.dac_tlv) {1068			template.tlv.p = chip->model.dac_tlv;1069			template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;1070		}1071		ctl = snd_ctl_new1(&template, chip);1072		if (!ctl)1073			return -ENOMEM;1074		err = snd_ctl_add(chip->card, ctl);1075		if (err < 0)1076			return err;1077		j = match_string(known_ctl_names, CONTROL_COUNT, ctl->id.name);1078		if (j >= 0) {1079			chip->controls[j] = ctl;1080			ctl->private_free = oxygen_any_ctl_free;1081		}1082	}1083	return 0;1084}1085 1086int oxygen_mixer_init(struct oxygen *chip)1087{1088	unsigned int i;1089	int err;1090 1091	err = add_controls(chip, controls, ARRAY_SIZE(controls));1092	if (err < 0)1093		return err;1094	if (chip->model.device_config & PLAYBACK_1_TO_SPDIF) {1095		err = add_controls(chip, spdif_output_controls,1096				   ARRAY_SIZE(spdif_output_controls));1097		if (err < 0)1098			return err;1099	}1100	if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) {1101		err = add_controls(chip, spdif_input_controls,1102				   ARRAY_SIZE(spdif_input_controls));1103		if (err < 0)1104			return err;1105	}1106	for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {1107		if (!(chip->model.device_config & monitor_controls[i].pcm_dev))1108			continue;1109		err = add_controls(chip, monitor_controls[i].controls,1110				   ARRAY_SIZE(monitor_controls[i].controls));1111		if (err < 0)1112			return err;1113	}1114	if (chip->has_ac97_0) {1115		err = add_controls(chip, ac97_controls,1116				   ARRAY_SIZE(ac97_controls));1117		if (err < 0)1118			return err;1119	}1120	if (chip->has_ac97_1) {1121		err = add_controls(chip, ac97_fp_controls,1122				   ARRAY_SIZE(ac97_fp_controls));1123		if (err < 0)1124			return err;1125	}1126	return chip->model.mixer_init ? chip->model.mixer_init(chip) : 0;1127}1128