brintos

brintos / linux-shallow public Read only

0
0
Text · 25.0 KiB · b24c804 Raw
893 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK43814 *   AD and DA converters5 *6 *	Copyright (c) 2000-2004 Jaroslav Kysela <perex@perex.cz>,7 *				Takashi Iwai <tiwai@suse.de>8 */9 10#include <linux/io.h>11#include <linux/delay.h>12#include <linux/interrupt.h>13#include <linux/init.h>14#include <linux/module.h>15#include <sound/core.h>16#include <sound/control.h>17#include <sound/tlv.h>18#include <sound/ak4xxx-adda.h>19#include <sound/info.h>20 21MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");22MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx  AD/DA converters");23MODULE_LICENSE("GPL");24 25/* write the given register and save the data to the cache */26void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg,27		       unsigned char val)28{29	ak->ops.lock(ak, chip);30	ak->ops.write(ak, chip, reg, val);31 32	/* save the data */33	snd_akm4xxx_set(ak, chip, reg, val);34	ak->ops.unlock(ak, chip);35}36 37EXPORT_SYMBOL(snd_akm4xxx_write);38 39/* reset procedure for AK4524 and AK4528 */40static void ak4524_reset(struct snd_akm4xxx *ak, int state)41{42	unsigned int chip;43	unsigned char reg;44 45	for (chip = 0; chip < ak->num_dacs/2; chip++) {46		snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03);47		if (state)48			continue;49		/* DAC volumes */50		for (reg = 0x04; reg < ak->total_regs; reg++)51			snd_akm4xxx_write(ak, chip, reg,52					  snd_akm4xxx_get(ak, chip, reg));53	}54}55 56/* reset procedure for AK4355 and AK4358 */57static void ak435X_reset(struct snd_akm4xxx *ak, int state)58{59	unsigned char reg;60 61	if (state) {62		snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */63		return;64	}65	for (reg = 0x00; reg < ak->total_regs; reg++)66		if (reg != 0x01)67			snd_akm4xxx_write(ak, 0, reg,68					  snd_akm4xxx_get(ak, 0, reg));69	snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */70}71 72/* reset procedure for AK4381 */73static void ak4381_reset(struct snd_akm4xxx *ak, int state)74{75	unsigned int chip;76	unsigned char reg;77	for (chip = 0; chip < ak->num_dacs/2; chip++) {78		snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f);79		if (state)80			continue;81		for (reg = 0x01; reg < ak->total_regs; reg++)82			snd_akm4xxx_write(ak, chip, reg,83					  snd_akm4xxx_get(ak, chip, reg));84	}85}86 87/*88 * reset the AKM codecs89 * @state: 1 = reset codec, 0 = restore the registers90 *91 * assert the reset operation and restores the register values to the chips.92 */93void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)94{95	switch (ak->type) {96	case SND_AK4524:97	case SND_AK4528:98	case SND_AK4620:99		ak4524_reset(ak, state);100		break;101	case SND_AK4529:102		/* FIXME: needed for ak4529? */103		break;104	case SND_AK4355:105		ak435X_reset(ak, state);106		break;107	case SND_AK4358:108		ak435X_reset(ak, state);109		break;110	case SND_AK4381:111		ak4381_reset(ak, state);112		break;113	default:114		break;115	}116}117 118EXPORT_SYMBOL(snd_akm4xxx_reset);119 120 121/*122 * Volume conversion table for non-linear volumes123 * from -63.5dB (mute) to 0dB step 0.5dB124 *125 * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and126 * AK5365 input attenuation127 */128static const unsigned char vol_cvt_datt[128] = {129	0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04,130	0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,131	0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a,132	0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f,133	0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14,134	0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c,135	0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23,136	0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d,137	0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,138	0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40,139	0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a,140	0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54,141	0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f,142	0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69,143	0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73,144	0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f,145};146 147/*148 * dB tables149 */150static const DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1);151static const DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1);152static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1);153static const DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0);154 155/*156 * initialize all the ak4xxx chips157 */158void snd_akm4xxx_init(struct snd_akm4xxx *ak)159{160	static const unsigned char inits_ak4524[] = {161		0x00, 0x07, /* 0: all power up */162		0x01, 0x00, /* 1: ADC/DAC reset */163		0x02, 0x60, /* 2: 24bit I2S */164		0x03, 0x19, /* 3: deemphasis off */165		0x01, 0x03, /* 1: ADC/DAC enable */166		0x04, 0x00, /* 4: ADC left muted */167		0x05, 0x00, /* 5: ADC right muted */168		0x06, 0x00, /* 6: DAC left muted */169		0x07, 0x00, /* 7: DAC right muted */170		0xff, 0xff171	};172	static const unsigned char inits_ak4528[] = {173		0x00, 0x07, /* 0: all power up */174		0x01, 0x00, /* 1: ADC/DAC reset */175		0x02, 0x60, /* 2: 24bit I2S */176		0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */177		0x01, 0x03, /* 1: ADC/DAC enable */178		0x04, 0x00, /* 4: ADC left muted */179		0x05, 0x00, /* 5: ADC right muted */180		0xff, 0xff181	};182	static const unsigned char inits_ak4529[] = {183		0x09, 0x01, /* 9: ATS=0, RSTN=1 */184		0x0a, 0x3f, /* A: all power up, no zero/overflow detection */185		0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */186		0x01, 0x00, /* 1: ACKS=0, ADC, loop off */187		0x02, 0xff, /* 2: LOUT1 muted */188		0x03, 0xff, /* 3: ROUT1 muted */189		0x04, 0xff, /* 4: LOUT2 muted */190		0x05, 0xff, /* 5: ROUT2 muted */191		0x06, 0xff, /* 6: LOUT3 muted */192		0x07, 0xff, /* 7: ROUT3 muted */193		0x0b, 0xff, /* B: LOUT4 muted */194		0x0c, 0xff, /* C: ROUT4 muted */195		0x08, 0x55, /* 8: deemphasis all off */196		0xff, 0xff197	};198	static const unsigned char inits_ak4355[] = {199		0x01, 0x02, /* 1: reset and soft-mute */200		0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,201			     * disable DZF, sharp roll-off, RSTN#=0 */202		0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */203		// 0x02, 0x2e, /* quad speed */204		0x03, 0x01, /* 3: de-emphasis off */205		0x04, 0x00, /* 4: LOUT1 volume muted */206		0x05, 0x00, /* 5: ROUT1 volume muted */207		0x06, 0x00, /* 6: LOUT2 volume muted */208		0x07, 0x00, /* 7: ROUT2 volume muted */209		0x08, 0x00, /* 8: LOUT3 volume muted */210		0x09, 0x00, /* 9: ROUT3 volume muted */211		0x0a, 0x00, /* a: DATT speed=0, ignore DZF */212		0x01, 0x01, /* 1: un-reset, unmute */213		0xff, 0xff214	};215	static const unsigned char inits_ak4358[] = {216		0x01, 0x02, /* 1: reset and soft-mute */217		0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,218			     * disable DZF, sharp roll-off, RSTN#=0 */219		0x02, 0x4e, /* 2: DA's power up, normal speed, RSTN#=0 */220		/* 0x02, 0x6e,*/ /* quad speed */221		0x03, 0x01, /* 3: de-emphasis off */222		0x04, 0x00, /* 4: LOUT1 volume muted */223		0x05, 0x00, /* 5: ROUT1 volume muted */224		0x06, 0x00, /* 6: LOUT2 volume muted */225		0x07, 0x00, /* 7: ROUT2 volume muted */226		0x08, 0x00, /* 8: LOUT3 volume muted */227		0x09, 0x00, /* 9: ROUT3 volume muted */228		0x0b, 0x00, /* b: LOUT4 volume muted */229		0x0c, 0x00, /* c: ROUT4 volume muted */230		0x0a, 0x00, /* a: DATT speed=0, ignore DZF */231		0x01, 0x01, /* 1: un-reset, unmute */232		0xff, 0xff233	};234	static const unsigned char inits_ak4381[] = {235		0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */236		0x01, 0x02, /* 1: de-emphasis off, normal speed,237			     * sharp roll-off, DZF off */238		// 0x01, 0x12, /* quad speed */239		0x02, 0x00, /* 2: DZF disabled */240		0x03, 0x00, /* 3: LATT 0 */241		0x04, 0x00, /* 4: RATT 0 */242		0x00, 0x0f, /* 0: power-up, un-reset */243		0xff, 0xff244	};245	static const unsigned char inits_ak4620[] = {246		0x00, 0x07, /* 0: normal */247		0x01, 0x00, /* 0: reset */248		0x01, 0x02, /* 1: RSTAD */249		0x01, 0x03, /* 1: RSTDA */250		0x01, 0x0f, /* 1: normal */251		0x02, 0x60, /* 2: 24bit I2S */252		0x03, 0x01, /* 3: deemphasis off */253		0x04, 0x00, /* 4: LIN muted */254		0x05, 0x00, /* 5: RIN muted */255		0x06, 0x00, /* 6: LOUT muted */256		0x07, 0x00, /* 7: ROUT muted */257		0xff, 0xff258	};259 260	int chip;261	const unsigned char *ptr, *inits;262	unsigned char reg, data;263 264	memset(ak->images, 0, sizeof(ak->images));265	memset(ak->volumes, 0, sizeof(ak->volumes));266 267	switch (ak->type) {268	case SND_AK4524:269		inits = inits_ak4524;270		ak->num_chips = ak->num_dacs / 2;271		ak->name = "ak4524";272		ak->total_regs = 0x08;273		break;274	case SND_AK4528:275		inits = inits_ak4528;276		ak->num_chips = ak->num_dacs / 2;277		ak->name = "ak4528";278		ak->total_regs = 0x06;279		break;280	case SND_AK4529:281		inits = inits_ak4529;282		ak->num_chips = 1;283		ak->name = "ak4529";284		ak->total_regs = 0x0d;285		break;286	case SND_AK4355:287		inits = inits_ak4355;288		ak->num_chips = 1;289		ak->name = "ak4355";290		ak->total_regs = 0x0b;291		break;292	case SND_AK4358:293		inits = inits_ak4358;294		ak->num_chips = 1;295		ak->name = "ak4358";296		ak->total_regs = 0x10;297		break;298	case SND_AK4381:299		inits = inits_ak4381;300		ak->num_chips = ak->num_dacs / 2;301		ak->name = "ak4381";302		ak->total_regs = 0x05;303		break;304	case SND_AK5365:305		/* FIXME: any init sequence? */306		ak->num_chips = 1;307		ak->name = "ak5365";308		ak->total_regs = 0x08;309		return;310	case SND_AK4620:311		inits = inits_ak4620;312		ak->num_chips = ak->num_dacs / 2;313		ak->name = "ak4620";314		ak->total_regs = 0x08;315		break;316	default:317		snd_BUG();318		return;319	}320 321	for (chip = 0; chip < ak->num_chips; chip++) {322		ptr = inits;323		while (*ptr != 0xff) {324			reg = *ptr++;325			data = *ptr++;326			snd_akm4xxx_write(ak, chip, reg, data);327			udelay(10);328		}329	}330}331 332EXPORT_SYMBOL(snd_akm4xxx_init);333 334/*335 * Mixer callbacks336 */337#define AK_IPGA 			(1<<20)	/* including IPGA */338#define AK_VOL_CVT 			(1<<21)	/* need dB conversion */339#define AK_NEEDSMSB 			(1<<22)	/* need MSB update bit */340#define AK_INVERT 			(1<<23)	/* data is inverted */341#define AK_GET_CHIP(val)		(((val) >> 8) & 0xff)342#define AK_GET_ADDR(val)		((val) & 0xff)343#define AK_GET_SHIFT(val)		(((val) >> 16) & 0x0f)344#define AK_GET_VOL_CVT(val)		(((val) >> 21) & 1)345#define AK_GET_IPGA(val)		(((val) >> 20) & 1)346#define AK_GET_NEEDSMSB(val)		(((val) >> 22) & 1)347#define AK_GET_INVERT(val)		(((val) >> 23) & 1)348#define AK_GET_MASK(val)		(((val) >> 24) & 0xff)349#define AK_COMPOSE(chip,addr,shift,mask) \350	(((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))351 352static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol,353				   struct snd_ctl_elem_info *uinfo)354{355	unsigned int mask = AK_GET_MASK(kcontrol->private_value);356 357	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;358	uinfo->count = 1;359	uinfo->value.integer.min = 0;360	uinfo->value.integer.max = mask;361	return 0;362}363 364static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol,365				  struct snd_ctl_elem_value *ucontrol)366{367	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);368	int chip = AK_GET_CHIP(kcontrol->private_value);369	int addr = AK_GET_ADDR(kcontrol->private_value);370 371	ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr);372	return 0;373}374 375static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,376		      unsigned char nval)377{378	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);379	unsigned int mask = AK_GET_MASK(kcontrol->private_value);380	int chip = AK_GET_CHIP(kcontrol->private_value);381 382	if (snd_akm4xxx_get_vol(ak, chip, addr) == nval)383		return 0;384 385	snd_akm4xxx_set_vol(ak, chip, addr, nval);386	if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128)387		nval = vol_cvt_datt[nval];388	if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128)389		nval++; /* need to correct + 1 since both 127 and 128 are 0dB */390	if (AK_GET_INVERT(kcontrol->private_value))391		nval = mask - nval;392	if (AK_GET_NEEDSMSB(kcontrol->private_value))393		nval |= 0x80;394	snd_akm4xxx_write(ak, chip, addr, nval);395	return 1;396}397 398static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,399				  struct snd_ctl_elem_value *ucontrol)400{401	unsigned int mask = AK_GET_MASK(kcontrol->private_value);402	unsigned int val = ucontrol->value.integer.value[0];403	if (val > mask)404		return -EINVAL;405	return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val);406}407 408static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,409					  struct snd_ctl_elem_info *uinfo)410{411	unsigned int mask = AK_GET_MASK(kcontrol->private_value);412 413	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;414	uinfo->count = 2;415	uinfo->value.integer.min = 0;416	uinfo->value.integer.max = mask;417	return 0;418}419 420static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol,421					 struct snd_ctl_elem_value *ucontrol)422{423	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);424	int chip = AK_GET_CHIP(kcontrol->private_value);425	int addr = AK_GET_ADDR(kcontrol->private_value);426 427	ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr);428	ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1);429	return 0;430}431 432static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,433					 struct snd_ctl_elem_value *ucontrol)434{435	int addr = AK_GET_ADDR(kcontrol->private_value);436	unsigned int mask = AK_GET_MASK(kcontrol->private_value);437	unsigned int val[2];438	int change;439 440	val[0] = ucontrol->value.integer.value[0];441	val[1] = ucontrol->value.integer.value[1];442	if (val[0] > mask || val[1] > mask)443		return -EINVAL;444	change = put_ak_reg(kcontrol, addr, val[0]);445	change |= put_ak_reg(kcontrol, addr + 1, val[1]);446	return change;447}448 449static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol,450				       struct snd_ctl_elem_info *uinfo)451{452	static const char * const texts[4] = {453		"44.1kHz", "Off", "48kHz", "32kHz",454	};455	return snd_ctl_enum_info(uinfo, 1, 4, texts);456}457 458static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol,459				      struct snd_ctl_elem_value *ucontrol)460{461	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);462	int chip = AK_GET_CHIP(kcontrol->private_value);463	int addr = AK_GET_ADDR(kcontrol->private_value);464	int shift = AK_GET_SHIFT(kcontrol->private_value);465	ucontrol->value.enumerated.item[0] =466		(snd_akm4xxx_get(ak, chip, addr) >> shift) & 3;467	return 0;468}469 470static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol,471				      struct snd_ctl_elem_value *ucontrol)472{473	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);474	int chip = AK_GET_CHIP(kcontrol->private_value);475	int addr = AK_GET_ADDR(kcontrol->private_value);476	int shift = AK_GET_SHIFT(kcontrol->private_value);477	unsigned char nval = ucontrol->value.enumerated.item[0] & 3;478	int change;479	480	nval = (nval << shift) |481		(snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift));482	change = snd_akm4xxx_get(ak, chip, addr) != nval;483	if (change)484		snd_akm4xxx_write(ak, chip, addr, nval);485	return change;486}487 488#define ak4xxx_switch_info	snd_ctl_boolean_mono_info489 490static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol,491			     struct snd_ctl_elem_value *ucontrol)492{493	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);494	int chip = AK_GET_CHIP(kcontrol->private_value);495	int addr = AK_GET_ADDR(kcontrol->private_value);496	int shift = AK_GET_SHIFT(kcontrol->private_value);497	int invert = AK_GET_INVERT(kcontrol->private_value);498	/* we observe the (1<<shift) bit only */499	unsigned char val = snd_akm4xxx_get(ak, chip, addr) & (1<<shift);500	if (invert)501		val = ! val;502	ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0;503	return 0;504}505 506static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,507			     struct snd_ctl_elem_value *ucontrol)508{509	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);510	int chip = AK_GET_CHIP(kcontrol->private_value);511	int addr = AK_GET_ADDR(kcontrol->private_value);512	int shift = AK_GET_SHIFT(kcontrol->private_value);513	int invert = AK_GET_INVERT(kcontrol->private_value);514	long flag = ucontrol->value.integer.value[0];515	unsigned char val, oval;516	int change;517 518	if (invert)519		flag = ! flag;520	oval = snd_akm4xxx_get(ak, chip, addr);521	if (flag)522		val = oval | (1<<shift);523	else524		val = oval & ~(1<<shift);525	change = (oval != val);526	if (change)527		snd_akm4xxx_write(ak, chip, addr, val);528	return change;529}530 531#define AK5365_NUM_INPUTS 5532 533static int ak4xxx_capture_num_inputs(struct snd_akm4xxx *ak, int mixer_ch)534{535	int num_names;536	const char **input_names;537 538	input_names = ak->adc_info[mixer_ch].input_names;539	num_names = 0;540	while (num_names < AK5365_NUM_INPUTS && input_names[num_names])541		++num_names;542	return num_names;543}544 545static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,546				      struct snd_ctl_elem_info *uinfo)547{548	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);549	int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);550	unsigned int num_names;551 552	num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);553	if (!num_names)554		return -EINVAL;555	return snd_ctl_enum_info(uinfo, 1, num_names,556				 ak->adc_info[mixer_ch].input_names);557}558 559static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol,560				     struct snd_ctl_elem_value *ucontrol)561{562	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);563	int chip = AK_GET_CHIP(kcontrol->private_value);564	int addr = AK_GET_ADDR(kcontrol->private_value);565	int mask = AK_GET_MASK(kcontrol->private_value);566	unsigned char val;567 568	val = snd_akm4xxx_get(ak, chip, addr) & mask;569	ucontrol->value.enumerated.item[0] = val;570	return 0;571}572 573static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,574				     struct snd_ctl_elem_value *ucontrol)575{576	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);577	int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);578	int chip = AK_GET_CHIP(kcontrol->private_value);579	int addr = AK_GET_ADDR(kcontrol->private_value);580	int mask = AK_GET_MASK(kcontrol->private_value);581	unsigned char oval, val;582	int num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);583 584	if (ucontrol->value.enumerated.item[0] >= num_names)585		return -EINVAL;586 587	oval = snd_akm4xxx_get(ak, chip, addr);588	val = oval & ~mask;589	val |= ucontrol->value.enumerated.item[0] & mask;590	if (val != oval) {591		snd_akm4xxx_write(ak, chip, addr, val);592		return 1;593	}594	return 0;595}596 597/*598 * build AK4xxx controls599 */600 601static int build_dac_controls(struct snd_akm4xxx *ak)602{603	int idx, err, mixer_ch, num_stereo;604	struct snd_kcontrol_new knew;605 606	mixer_ch = 0;607	for (idx = 0; idx < ak->num_dacs; ) {608		/* mute control for Revolution 7.1 - AK4381 */609		if (ak->type == SND_AK4381 610				&&  ak->dac_info[mixer_ch].switch_name) {611			memset(&knew, 0, sizeof(knew));612			knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;613			knew.count = 1;614			knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;615			knew.name = ak->dac_info[mixer_ch].switch_name;616			knew.info = ak4xxx_switch_info;617			knew.get = ak4xxx_switch_get;618			knew.put = ak4xxx_switch_put;619			knew.access = 0;620			/* register 1, bit 0 (SMUTE): 0 = normal operation,621			   1 = mute */622			knew.private_value =623				AK_COMPOSE(idx/2, 1, 0, 0) | AK_INVERT;624			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));625			if (err < 0)626				return err;627		}628		memset(&knew, 0, sizeof(knew));629		if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) {630			knew.name = "DAC Volume";631			knew.index = mixer_ch + ak->idx_offset * 2;632			num_stereo = 1;633		} else {634			knew.name = ak->dac_info[mixer_ch].name;635			num_stereo = ak->dac_info[mixer_ch].num_channels;636		}637		knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;638		knew.count = 1;639		knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |640			SNDRV_CTL_ELEM_ACCESS_TLV_READ;641		if (num_stereo == 2) {642			knew.info = snd_akm4xxx_stereo_volume_info;643			knew.get = snd_akm4xxx_stereo_volume_get;644			knew.put = snd_akm4xxx_stereo_volume_put;645		} else {646			knew.info = snd_akm4xxx_volume_info;647			knew.get = snd_akm4xxx_volume_get;648			knew.put = snd_akm4xxx_volume_put;649		}650		switch (ak->type) {651		case SND_AK4524:652			/* register 6 & 7 */653			knew.private_value =654				AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) |655				AK_VOL_CVT;656			knew.tlv.p = db_scale_vol_datt;657			break;658		case SND_AK4528:659			/* register 4 & 5 */660			knew.private_value =661				AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) |662				AK_VOL_CVT;663			knew.tlv.p = db_scale_vol_datt;664			break;665		case SND_AK4529: {666			/* registers 2-7 and b,c */667			int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb;668			knew.private_value =669				AK_COMPOSE(0, val, 0, 255) | AK_INVERT;670			knew.tlv.p = db_scale_8bit;671			break;672		}673		case SND_AK4355:674			/* register 4-9, chip #0 only */675			knew.private_value = AK_COMPOSE(0, idx + 4, 0, 255);676			knew.tlv.p = db_scale_8bit;677			break;678		case SND_AK4358: {679			/* register 4-9 and 11-12, chip #0 only */680			int  addr = idx < 6 ? idx + 4 : idx + 5;681			knew.private_value =682				AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB;683			knew.tlv.p = db_scale_7bit;684			break;685		}686		case SND_AK4381:687			/* register 3 & 4 */688			knew.private_value =689				AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);690			knew.tlv.p = db_scale_linear;691			break;692		case SND_AK4620:693			/* register 6 & 7 */694			knew.private_value =695				AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255);696			knew.tlv.p = db_scale_linear;697			break;698		default:699			return -EINVAL;700		}701 702		err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));703		if (err < 0)704			return err;705 706		idx += num_stereo;707		mixer_ch++;708	}709	return 0;710}711 712static int build_adc_controls(struct snd_akm4xxx *ak)713{714	int idx, err, mixer_ch, num_stereo, max_steps;715	struct snd_kcontrol_new knew;716 717	mixer_ch = 0;718	if (ak->type == SND_AK4528)719		return 0;	/* no controls */720	for (idx = 0; idx < ak->num_adcs;) {721		memset(&knew, 0, sizeof(knew));722		if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) {723			knew.name = "ADC Volume";724			knew.index = mixer_ch + ak->idx_offset * 2;725			num_stereo = 1;726		} else {727			knew.name = ak->adc_info[mixer_ch].name;728			num_stereo = ak->adc_info[mixer_ch].num_channels;729		}730		knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;731		knew.count = 1;732		knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |733			SNDRV_CTL_ELEM_ACCESS_TLV_READ;734		if (num_stereo == 2) {735			knew.info = snd_akm4xxx_stereo_volume_info;736			knew.get = snd_akm4xxx_stereo_volume_get;737			knew.put = snd_akm4xxx_stereo_volume_put;738		} else {739			knew.info = snd_akm4xxx_volume_info;740			knew.get = snd_akm4xxx_volume_get;741			knew.put = snd_akm4xxx_volume_put;742		}743		/* register 4 & 5 */744		if (ak->type == SND_AK5365)745			max_steps = 152;746		else747			max_steps = 164;748		knew.private_value =749			AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) |750			AK_VOL_CVT | AK_IPGA;751		knew.tlv.p = db_scale_vol_datt;752		err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));753		if (err < 0)754			return err;755 756		if (ak->type == SND_AK5365 && (idx % 2) == 0) {757			if (! ak->adc_info || 758			    ! ak->adc_info[mixer_ch].switch_name) {759				knew.name = "Capture Switch";760				knew.index = mixer_ch + ak->idx_offset * 2;761			} else762				knew.name = ak->adc_info[mixer_ch].switch_name;763			knew.info = ak4xxx_switch_info;764			knew.get = ak4xxx_switch_get;765			knew.put = ak4xxx_switch_put;766			knew.access = 0;767			/* register 2, bit 0 (SMUTE): 0 = normal operation,768			   1 = mute */769			knew.private_value =770				AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT;771			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));772			if (err < 0)773				return err;774 775			memset(&knew, 0, sizeof(knew));776			if (!ak->adc_info ||777				!ak->adc_info[mixer_ch].selector_name) {778				knew.name = "Capture Channel";779				knew.index = mixer_ch + ak->idx_offset * 2;780			} else781				knew.name = ak->adc_info[mixer_ch].selector_name;782 783			knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;784			knew.info = ak4xxx_capture_source_info;785			knew.get = ak4xxx_capture_source_get;786			knew.put = ak4xxx_capture_source_put;787			knew.access = 0;788			/* input selector control: reg. 1, bits 0-2.789			 * mis-use 'shift' to pass mixer_ch */790			knew.private_value791				= AK_COMPOSE(idx/2, 1, mixer_ch, 0x07);792			err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));793			if (err < 0)794				return err;795		}796 797		idx += num_stereo;798		mixer_ch++;799	}800	return 0;801}802 803static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)804{805	int idx, err;806	struct snd_kcontrol_new knew;807 808	for (idx = 0; idx < num_emphs; idx++) {809		memset(&knew, 0, sizeof(knew));810		knew.name = "Deemphasis";811		knew.index = idx + ak->idx_offset;812		knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;813		knew.count = 1;814		knew.info = snd_akm4xxx_deemphasis_info;815		knew.get = snd_akm4xxx_deemphasis_get;816		knew.put = snd_akm4xxx_deemphasis_put;817		switch (ak->type) {818		case SND_AK4524:819		case SND_AK4528:820		case SND_AK4620:821			/* register 3 */822			knew.private_value = AK_COMPOSE(idx, 3, 0, 0);823			break;824		case SND_AK4529: {825			int shift = idx == 3 ? 6 : (2 - idx) * 2;826			/* register 8 with shift */827			knew.private_value = AK_COMPOSE(0, 8, shift, 0);828			break;829		}830		case SND_AK4355:831		case SND_AK4358:832			knew.private_value = AK_COMPOSE(idx, 3, 0, 0);833			break;834		case SND_AK4381:835			knew.private_value = AK_COMPOSE(idx, 1, 1, 0);836			break;837		default:838			return -EINVAL;839		}840		err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));841		if (err < 0)842			return err;843	}844	return 0;845}846 847static void proc_regs_read(struct snd_info_entry *entry,848		struct snd_info_buffer *buffer)849{850	struct snd_akm4xxx *ak = entry->private_data;851	int reg, val, chip;852	for (chip = 0; chip < ak->num_chips; chip++) {853		for (reg = 0; reg < ak->total_regs; reg++) {854			val =  snd_akm4xxx_get(ak, chip, reg);855			snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip,856					reg, val);857		}858	}859}860 861static int proc_init(struct snd_akm4xxx *ak)862{863	return snd_card_ro_proc_new(ak->card, ak->name, ak, proc_regs_read);864}865 866int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)867{868	int err, num_emphs;869 870	err = build_dac_controls(ak);871	if (err < 0)872		return err;873 874	err = build_adc_controls(ak);875	if (err < 0)876		return err;877	if (ak->type == SND_AK4355 || ak->type == SND_AK4358)878		num_emphs = 1;879	else if (ak->type == SND_AK4620)880		num_emphs = 0;881	else882		num_emphs = ak->num_dacs / 2;883	err = build_deemphasis(ak, num_emphs);884	if (err < 0)885		return err;886	err = proc_init(ak);887	if (err < 0)888		return err;889 890	return 0;891}892EXPORT_SYMBOL(snd_akm4xxx_build_controls);893