xref: /linux/sound/pci/ice1712/maya44.c (revision 8dd06ef34b6e2f41b29fbf5fc1663780f2524285)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
272cbfd45STakashi Iwai /*
372cbfd45STakashi Iwai  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
472cbfd45STakashi Iwai  *
572cbfd45STakashi Iwai  *   Lowlevel functions for ESI Maya44 cards
672cbfd45STakashi Iwai  *
772cbfd45STakashi Iwai  *	Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
872cbfd45STakashi Iwai  *	Based on the patches by Rainer Zimmermann <mail@lightshed.de>
972cbfd45STakashi Iwai  */
1072cbfd45STakashi Iwai 
1172cbfd45STakashi Iwai #include <linux/init.h>
1272cbfd45STakashi Iwai #include <linux/slab.h>
1372cbfd45STakashi Iwai #include <sound/core.h>
1472cbfd45STakashi Iwai #include <sound/control.h>
1572cbfd45STakashi Iwai #include <sound/pcm.h>
1672cbfd45STakashi Iwai #include <sound/tlv.h>
1772cbfd45STakashi Iwai 
1872cbfd45STakashi Iwai #include "ice1712.h"
1972cbfd45STakashi Iwai #include "envy24ht.h"
2072cbfd45STakashi Iwai #include "maya44.h"
2172cbfd45STakashi Iwai 
2272cbfd45STakashi Iwai /* WM8776 register indexes */
2372cbfd45STakashi Iwai #define WM8776_REG_HEADPHONE_L		0x00
2472cbfd45STakashi Iwai #define WM8776_REG_HEADPHONE_R		0x01
2572cbfd45STakashi Iwai #define WM8776_REG_HEADPHONE_MASTER	0x02
2672cbfd45STakashi Iwai #define WM8776_REG_DAC_ATTEN_L		0x03
2772cbfd45STakashi Iwai #define WM8776_REG_DAC_ATTEN_R		0x04
2872cbfd45STakashi Iwai #define WM8776_REG_DAC_ATTEN_MASTER	0x05
2972cbfd45STakashi Iwai #define WM8776_REG_DAC_PHASE		0x06
3072cbfd45STakashi Iwai #define WM8776_REG_DAC_CONTROL		0x07
3172cbfd45STakashi Iwai #define WM8776_REG_DAC_MUTE		0x08
3272cbfd45STakashi Iwai #define WM8776_REG_DAC_DEEMPH		0x09
3372cbfd45STakashi Iwai #define WM8776_REG_DAC_IF_CONTROL	0x0a
3472cbfd45STakashi Iwai #define WM8776_REG_ADC_IF_CONTROL	0x0b
3572cbfd45STakashi Iwai #define WM8776_REG_MASTER_MODE_CONTROL	0x0c
3672cbfd45STakashi Iwai #define WM8776_REG_POWERDOWN		0x0d
3772cbfd45STakashi Iwai #define WM8776_REG_ADC_ATTEN_L		0x0e
3872cbfd45STakashi Iwai #define WM8776_REG_ADC_ATTEN_R		0x0f
3972cbfd45STakashi Iwai #define WM8776_REG_ADC_ALC1		0x10
4072cbfd45STakashi Iwai #define WM8776_REG_ADC_ALC2		0x11
4172cbfd45STakashi Iwai #define WM8776_REG_ADC_ALC3		0x12
4272cbfd45STakashi Iwai #define WM8776_REG_ADC_NOISE_GATE	0x13
4372cbfd45STakashi Iwai #define WM8776_REG_ADC_LIMITER		0x14
4472cbfd45STakashi Iwai #define WM8776_REG_ADC_MUX		0x15
4572cbfd45STakashi Iwai #define WM8776_REG_OUTPUT_MUX		0x16
4672cbfd45STakashi Iwai #define WM8776_REG_RESET		0x17
4772cbfd45STakashi Iwai 
4872cbfd45STakashi Iwai #define WM8776_NUM_REGS			0x18
4972cbfd45STakashi Iwai 
5072cbfd45STakashi Iwai /* clock ratio identifiers for snd_wm8776_set_rate() */
5172cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_128FS	0
5272cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_192FS	1
5372cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_256FS	2
5472cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_384FS	3
5572cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_512FS	4
5672cbfd45STakashi Iwai #define WM8776_CLOCK_RATIO_768FS	5
5772cbfd45STakashi Iwai 
5872cbfd45STakashi Iwai enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
5972cbfd45STakashi Iwai enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
6072cbfd45STakashi Iwai 
6172cbfd45STakashi Iwai struct snd_wm8776 {
6272cbfd45STakashi Iwai 	unsigned char addr;
6372cbfd45STakashi Iwai 	unsigned short regs[WM8776_NUM_REGS];
6472cbfd45STakashi Iwai 	unsigned char volumes[WM_NUM_VOLS][2];
6572cbfd45STakashi Iwai 	unsigned int switch_bits;
6672cbfd45STakashi Iwai };
6772cbfd45STakashi Iwai 
6872cbfd45STakashi Iwai struct snd_maya44 {
6972cbfd45STakashi Iwai 	struct snd_ice1712 *ice;
7072cbfd45STakashi Iwai 	struct snd_wm8776 wm[2];
7172cbfd45STakashi Iwai 	struct mutex mutex;
7272cbfd45STakashi Iwai };
7372cbfd45STakashi Iwai 
7472cbfd45STakashi Iwai 
7572cbfd45STakashi Iwai /* write the given register and save the data to the cache */
wm8776_write(struct snd_ice1712 * ice,struct snd_wm8776 * wm,unsigned char reg,unsigned short val)7672cbfd45STakashi Iwai static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
7772cbfd45STakashi Iwai 			 unsigned char reg, unsigned short val)
7872cbfd45STakashi Iwai {
7972cbfd45STakashi Iwai 	/*
8072cbfd45STakashi Iwai 	 * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
8172cbfd45STakashi Iwai 	 * of the address field
8272cbfd45STakashi Iwai 	 */
8372cbfd45STakashi Iwai 	snd_vt1724_write_i2c(ice, wm->addr,
8472cbfd45STakashi Iwai 			     (reg << 1) | ((val >> 8) & 1),
8572cbfd45STakashi Iwai 			     val & 0xff);
8672cbfd45STakashi Iwai 	wm->regs[reg] = val;
8772cbfd45STakashi Iwai }
8872cbfd45STakashi Iwai 
8972cbfd45STakashi Iwai /*
9072cbfd45STakashi Iwai  * update the given register with and/or mask and save the data to the cache
9172cbfd45STakashi Iwai  */
wm8776_write_bits(struct snd_ice1712 * ice,struct snd_wm8776 * wm,unsigned char reg,unsigned short mask,unsigned short val)9272cbfd45STakashi Iwai static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
9372cbfd45STakashi Iwai 			     unsigned char reg,
9472cbfd45STakashi Iwai 			     unsigned short mask, unsigned short val)
9572cbfd45STakashi Iwai {
9672cbfd45STakashi Iwai 	val |= wm->regs[reg] & ~mask;
9772cbfd45STakashi Iwai 	if (val != wm->regs[reg]) {
9872cbfd45STakashi Iwai 		wm8776_write(ice, wm, reg, val);
9972cbfd45STakashi Iwai 		return 1;
10072cbfd45STakashi Iwai 	}
10172cbfd45STakashi Iwai 	return 0;
10272cbfd45STakashi Iwai }
10372cbfd45STakashi Iwai 
10472cbfd45STakashi Iwai 
10572cbfd45STakashi Iwai /*
10672cbfd45STakashi Iwai  * WM8776 volume controls
10772cbfd45STakashi Iwai  */
10872cbfd45STakashi Iwai 
10972cbfd45STakashi Iwai struct maya_vol_info {
11072cbfd45STakashi Iwai 	unsigned int maxval;		/* volume range: 0..maxval */
11172cbfd45STakashi Iwai 	unsigned char regs[2];		/* left and right registers */
11272cbfd45STakashi Iwai 	unsigned short mask;		/* value mask */
11372cbfd45STakashi Iwai 	unsigned short offset;		/* zero-value offset */
11472cbfd45STakashi Iwai 	unsigned short mute;		/* mute bit */
11572cbfd45STakashi Iwai 	unsigned short update;		/* update bits */
11672cbfd45STakashi Iwai 	unsigned char mux_bits[2];	/* extra bits for ADC mute */
11772cbfd45STakashi Iwai };
11872cbfd45STakashi Iwai 
119*f16a4e96STakashi Iwai static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
12072cbfd45STakashi Iwai 	[WM_VOL_HP] = {
12172cbfd45STakashi Iwai 		.maxval = 80,
12272cbfd45STakashi Iwai 		.regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
12372cbfd45STakashi Iwai 		.mask = 0x7f,
12472cbfd45STakashi Iwai 		.offset = 0x30,
12572cbfd45STakashi Iwai 		.mute = 0x00,
12672cbfd45STakashi Iwai 		.update = 0x180,	/* update and zero-cross enable */
12772cbfd45STakashi Iwai 	},
12872cbfd45STakashi Iwai 	[WM_VOL_DAC] = {
12972cbfd45STakashi Iwai 		.maxval = 255,
13072cbfd45STakashi Iwai 		.regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
13172cbfd45STakashi Iwai 		.mask = 0xff,
13272cbfd45STakashi Iwai 		.offset = 0x01,
13372cbfd45STakashi Iwai 		.mute = 0x00,
13472cbfd45STakashi Iwai 		.update = 0x100,	/* zero-cross enable */
13572cbfd45STakashi Iwai 	},
13672cbfd45STakashi Iwai 	[WM_VOL_ADC] = {
13772cbfd45STakashi Iwai 		.maxval = 91,
13872cbfd45STakashi Iwai 		.regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
13972cbfd45STakashi Iwai 		.mask = 0xff,
14072cbfd45STakashi Iwai 		.offset = 0xa5,
14172cbfd45STakashi Iwai 		.mute = 0xa5,
14272cbfd45STakashi Iwai 		.update = 0x100,	/* update */
14372cbfd45STakashi Iwai 		.mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
14472cbfd45STakashi Iwai 	},
14572cbfd45STakashi Iwai };
14672cbfd45STakashi Iwai 
14772cbfd45STakashi Iwai /*
14872cbfd45STakashi Iwai  * dB tables
14972cbfd45STakashi Iwai  */
15072cbfd45STakashi Iwai /* headphone output: mute, -73..+6db (1db step) */
15172cbfd45STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
15272cbfd45STakashi Iwai /* DAC output: mute, -127..0db (0.5db step) */
15372cbfd45STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
15472cbfd45STakashi Iwai /* ADC gain: mute, -21..+24db (0.5db step) */
15572cbfd45STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
15672cbfd45STakashi Iwai 
maya_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)15772cbfd45STakashi Iwai static int maya_vol_info(struct snd_kcontrol *kcontrol,
15872cbfd45STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
15972cbfd45STakashi Iwai {
16072cbfd45STakashi Iwai 	unsigned int idx = kcontrol->private_value;
161*f16a4e96STakashi Iwai 	const struct maya_vol_info *vol = &vol_info[idx];
16272cbfd45STakashi Iwai 
16372cbfd45STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
16472cbfd45STakashi Iwai 	uinfo->count = 2;
16572cbfd45STakashi Iwai 	uinfo->value.integer.min = 0;
16672cbfd45STakashi Iwai 	uinfo->value.integer.max = vol->maxval;
16772cbfd45STakashi Iwai 	return 0;
16872cbfd45STakashi Iwai }
16972cbfd45STakashi Iwai 
maya_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)17072cbfd45STakashi Iwai static int maya_vol_get(struct snd_kcontrol *kcontrol,
17172cbfd45STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
17272cbfd45STakashi Iwai {
17372cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
17472cbfd45STakashi Iwai 	struct snd_wm8776 *wm =
17572cbfd45STakashi Iwai 		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
17672cbfd45STakashi Iwai 	unsigned int idx = kcontrol->private_value;
17772cbfd45STakashi Iwai 
17872cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
17972cbfd45STakashi Iwai 	ucontrol->value.integer.value[0] = wm->volumes[idx][0];
18072cbfd45STakashi Iwai 	ucontrol->value.integer.value[1] = wm->volumes[idx][1];
18172cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
18272cbfd45STakashi Iwai 	return 0;
18372cbfd45STakashi Iwai }
18472cbfd45STakashi Iwai 
maya_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)18572cbfd45STakashi Iwai static int maya_vol_put(struct snd_kcontrol *kcontrol,
18672cbfd45STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
18772cbfd45STakashi Iwai {
18872cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
18972cbfd45STakashi Iwai 	struct snd_wm8776 *wm =
19072cbfd45STakashi Iwai 		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
19172cbfd45STakashi Iwai 	unsigned int idx = kcontrol->private_value;
192*f16a4e96STakashi Iwai 	const struct maya_vol_info *vol = &vol_info[idx];
19372cbfd45STakashi Iwai 	unsigned int val, data;
19472cbfd45STakashi Iwai 	int ch, changed = 0;
19572cbfd45STakashi Iwai 
19672cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
19772cbfd45STakashi Iwai 	for (ch = 0; ch < 2; ch++) {
19872cbfd45STakashi Iwai 		val = ucontrol->value.integer.value[ch];
19972cbfd45STakashi Iwai 		if (val > vol->maxval)
20072cbfd45STakashi Iwai 			val = vol->maxval;
20172cbfd45STakashi Iwai 		if (val == wm->volumes[idx][ch])
20272cbfd45STakashi Iwai 			continue;
20372cbfd45STakashi Iwai 		if (!val)
20472cbfd45STakashi Iwai 			data = vol->mute;
20572cbfd45STakashi Iwai 		else
20672cbfd45STakashi Iwai 			data = (val - 1) + vol->offset;
20772cbfd45STakashi Iwai 		data |= vol->update;
20872cbfd45STakashi Iwai 		changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
20972cbfd45STakashi Iwai 					     vol->mask | vol->update, data);
21072cbfd45STakashi Iwai 		if (vol->mux_bits[ch])
21172cbfd45STakashi Iwai 			wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
21272cbfd45STakashi Iwai 					  vol->mux_bits[ch],
21372cbfd45STakashi Iwai 					  val ? 0 : vol->mux_bits[ch]);
21472cbfd45STakashi Iwai 		wm->volumes[idx][ch] = val;
21572cbfd45STakashi Iwai 	}
21672cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
21772cbfd45STakashi Iwai 	return changed;
21872cbfd45STakashi Iwai }
21972cbfd45STakashi Iwai 
22072cbfd45STakashi Iwai /*
22172cbfd45STakashi Iwai  * WM8776 switch controls
22272cbfd45STakashi Iwai  */
22372cbfd45STakashi Iwai 
22472cbfd45STakashi Iwai #define COMPOSE_SW_VAL(idx, reg, mask)	((idx) | ((reg) << 8) | ((mask) << 16))
22572cbfd45STakashi Iwai #define GET_SW_VAL_IDX(val)	((val) & 0xff)
22672cbfd45STakashi Iwai #define GET_SW_VAL_REG(val)	(((val) >> 8) & 0xff)
22772cbfd45STakashi Iwai #define GET_SW_VAL_MASK(val)	(((val) >> 16) & 0xff)
22872cbfd45STakashi Iwai 
22972cbfd45STakashi Iwai #define maya_sw_info	snd_ctl_boolean_mono_info
23072cbfd45STakashi Iwai 
maya_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)23172cbfd45STakashi Iwai static int maya_sw_get(struct snd_kcontrol *kcontrol,
23272cbfd45STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
23372cbfd45STakashi Iwai {
23472cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
23572cbfd45STakashi Iwai 	struct snd_wm8776 *wm =
23672cbfd45STakashi Iwai 		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
23772cbfd45STakashi Iwai 	unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
23872cbfd45STakashi Iwai 
23972cbfd45STakashi Iwai 	ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
24072cbfd45STakashi Iwai 	return 0;
24172cbfd45STakashi Iwai }
24272cbfd45STakashi Iwai 
maya_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)24372cbfd45STakashi Iwai static int maya_sw_put(struct snd_kcontrol *kcontrol,
24472cbfd45STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
24572cbfd45STakashi Iwai {
24672cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
24772cbfd45STakashi Iwai 	struct snd_wm8776 *wm =
24872cbfd45STakashi Iwai 		&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
24972cbfd45STakashi Iwai 	unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
25072cbfd45STakashi Iwai 	unsigned int mask, val;
25172cbfd45STakashi Iwai 	int changed;
25272cbfd45STakashi Iwai 
25372cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
25472cbfd45STakashi Iwai 	mask = 1 << idx;
25572cbfd45STakashi Iwai 	wm->switch_bits &= ~mask;
25672cbfd45STakashi Iwai 	val = ucontrol->value.integer.value[0];
25772cbfd45STakashi Iwai 	if (val)
25872cbfd45STakashi Iwai 		wm->switch_bits |= mask;
25972cbfd45STakashi Iwai 	mask = GET_SW_VAL_MASK(kcontrol->private_value);
26072cbfd45STakashi Iwai 	changed = wm8776_write_bits(chip->ice, wm,
26172cbfd45STakashi Iwai 				    GET_SW_VAL_REG(kcontrol->private_value),
26272cbfd45STakashi Iwai 				    mask, val ? mask : 0);
26372cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
26472cbfd45STakashi Iwai 	return changed;
26572cbfd45STakashi Iwai }
26672cbfd45STakashi Iwai 
26772cbfd45STakashi Iwai /*
26872cbfd45STakashi Iwai  * GPIO pins (known ones for maya44)
26972cbfd45STakashi Iwai  */
27072cbfd45STakashi Iwai #define GPIO_PHANTOM_OFF	2
27172cbfd45STakashi Iwai #define GPIO_MIC_RELAY		4
27272cbfd45STakashi Iwai #define GPIO_SPDIF_IN_INV	5
27372cbfd45STakashi Iwai #define GPIO_MUST_BE_0		7
27472cbfd45STakashi Iwai 
27572cbfd45STakashi Iwai /*
27672cbfd45STakashi Iwai  * GPIO switch controls
27772cbfd45STakashi Iwai  */
27872cbfd45STakashi Iwai 
27972cbfd45STakashi Iwai #define COMPOSE_GPIO_VAL(shift, inv)	((shift) | ((inv) << 8))
28072cbfd45STakashi Iwai #define GET_GPIO_VAL_SHIFT(val)		((val) & 0xff)
28172cbfd45STakashi Iwai #define GET_GPIO_VAL_INV(val)		(((val) >> 8) & 1)
28272cbfd45STakashi Iwai 
maya_set_gpio_bits(struct snd_ice1712 * ice,unsigned int mask,unsigned int bits)28372cbfd45STakashi Iwai static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
28472cbfd45STakashi Iwai 			      unsigned int bits)
28572cbfd45STakashi Iwai {
28672cbfd45STakashi Iwai 	unsigned int data;
28772cbfd45STakashi Iwai 	data = snd_ice1712_gpio_read(ice);
28872cbfd45STakashi Iwai 	if ((data & mask) == bits)
28972cbfd45STakashi Iwai 		return 0;
29072cbfd45STakashi Iwai 	snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
29172cbfd45STakashi Iwai 	return 1;
29272cbfd45STakashi Iwai }
29372cbfd45STakashi Iwai 
29472cbfd45STakashi Iwai #define maya_gpio_sw_info	snd_ctl_boolean_mono_info
29572cbfd45STakashi Iwai 
maya_gpio_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)29672cbfd45STakashi Iwai static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
29772cbfd45STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
29872cbfd45STakashi Iwai {
29972cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
30072cbfd45STakashi Iwai 	unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
30172cbfd45STakashi Iwai 	unsigned int val;
30272cbfd45STakashi Iwai 
30372cbfd45STakashi Iwai 	val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
30472cbfd45STakashi Iwai 	if (GET_GPIO_VAL_INV(kcontrol->private_value))
30572cbfd45STakashi Iwai 		val = !val;
30672cbfd45STakashi Iwai 	ucontrol->value.integer.value[0] = val;
30772cbfd45STakashi Iwai 	return 0;
30872cbfd45STakashi Iwai }
30972cbfd45STakashi Iwai 
maya_gpio_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)31072cbfd45STakashi Iwai static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
31172cbfd45STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
31272cbfd45STakashi Iwai {
31372cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
31472cbfd45STakashi Iwai 	unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
31572cbfd45STakashi Iwai 	unsigned int val, mask;
31672cbfd45STakashi Iwai 	int changed;
31772cbfd45STakashi Iwai 
31872cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
31972cbfd45STakashi Iwai 	mask = 1 << shift;
32072cbfd45STakashi Iwai 	val = ucontrol->value.integer.value[0];
32172cbfd45STakashi Iwai 	if (GET_GPIO_VAL_INV(kcontrol->private_value))
32272cbfd45STakashi Iwai 		val = !val;
32372cbfd45STakashi Iwai 	val = val ? mask : 0;
32472cbfd45STakashi Iwai 	changed = maya_set_gpio_bits(chip->ice, mask, val);
32572cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
32672cbfd45STakashi Iwai 	return changed;
32772cbfd45STakashi Iwai }
32872cbfd45STakashi Iwai 
32972cbfd45STakashi Iwai /*
33072cbfd45STakashi Iwai  * capture source selection
33172cbfd45STakashi Iwai  */
33272cbfd45STakashi Iwai 
33372cbfd45STakashi Iwai /* known working input slots (0-4) */
33472cbfd45STakashi Iwai #define MAYA_LINE_IN	1	/* in-2 */
33582134665STakashi Iwai #define MAYA_MIC_IN	3	/* in-4 */
33672cbfd45STakashi Iwai 
wm8776_select_input(struct snd_maya44 * chip,int idx,int line)33772cbfd45STakashi Iwai static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
33872cbfd45STakashi Iwai {
33972cbfd45STakashi Iwai 	wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
34072cbfd45STakashi Iwai 			  0x1f, 1 << line);
34172cbfd45STakashi Iwai }
34272cbfd45STakashi Iwai 
maya_rec_src_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)34372cbfd45STakashi Iwai static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
34472cbfd45STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
34572cbfd45STakashi Iwai {
346a2af050fSTakashi Iwai 	static const char * const texts[] = { "Line", "Mic" };
34772cbfd45STakashi Iwai 
348597da2e4STakashi Iwai 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
34972cbfd45STakashi Iwai }
35072cbfd45STakashi Iwai 
maya_rec_src_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)35172cbfd45STakashi Iwai static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
35272cbfd45STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
35372cbfd45STakashi Iwai {
35472cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
35572cbfd45STakashi Iwai 	int sel;
35672cbfd45STakashi Iwai 
35772cbfd45STakashi Iwai 	if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
35872cbfd45STakashi Iwai 		sel = 1;
35972cbfd45STakashi Iwai 	else
36072cbfd45STakashi Iwai 		sel = 0;
36172cbfd45STakashi Iwai 	ucontrol->value.enumerated.item[0] = sel;
36272cbfd45STakashi Iwai 	return 0;
36372cbfd45STakashi Iwai }
36472cbfd45STakashi Iwai 
maya_rec_src_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)36572cbfd45STakashi Iwai static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
36672cbfd45STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
36772cbfd45STakashi Iwai {
36872cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
36972cbfd45STakashi Iwai 	int sel = ucontrol->value.enumerated.item[0];
37072cbfd45STakashi Iwai 	int changed;
37172cbfd45STakashi Iwai 
37272cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
37382134665STakashi Iwai 	changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
37482134665STakashi Iwai 				     sel ? (1 << GPIO_MIC_RELAY) : 0);
37572cbfd45STakashi Iwai 	wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
37672cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
37772cbfd45STakashi Iwai 	return changed;
37872cbfd45STakashi Iwai }
37972cbfd45STakashi Iwai 
38072cbfd45STakashi Iwai /*
38172cbfd45STakashi Iwai  * Maya44 routing switch settings have different meanings than the standard
38272cbfd45STakashi Iwai  * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
38372cbfd45STakashi Iwai  */
maya_pb_route_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)38472cbfd45STakashi Iwai static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
38572cbfd45STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
38672cbfd45STakashi Iwai {
387a2af050fSTakashi Iwai 	static const char * const texts[] = {
38872cbfd45STakashi Iwai 		"PCM Out", /* 0 */
38972cbfd45STakashi Iwai 		"Input 1", "Input 2", "Input 3", "Input 4"
39072cbfd45STakashi Iwai 	};
39172cbfd45STakashi Iwai 
392597da2e4STakashi Iwai 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
39372cbfd45STakashi Iwai }
39472cbfd45STakashi Iwai 
maya_pb_route_shift(int idx)39572cbfd45STakashi Iwai static int maya_pb_route_shift(int idx)
39672cbfd45STakashi Iwai {
39772cbfd45STakashi Iwai 	static const unsigned char shift[10] =
39872cbfd45STakashi Iwai 		{ 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
39972cbfd45STakashi Iwai 	return shift[idx % 10];
40072cbfd45STakashi Iwai }
40172cbfd45STakashi Iwai 
maya_pb_route_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)40272cbfd45STakashi Iwai static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
40372cbfd45STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
40472cbfd45STakashi Iwai {
40572cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
40672cbfd45STakashi Iwai 	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
40772cbfd45STakashi Iwai 	ucontrol->value.enumerated.item[0] =
40872cbfd45STakashi Iwai 		snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
40972cbfd45STakashi Iwai 	return 0;
41072cbfd45STakashi Iwai }
41172cbfd45STakashi Iwai 
maya_pb_route_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)41272cbfd45STakashi Iwai static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
41372cbfd45STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
41472cbfd45STakashi Iwai {
41572cbfd45STakashi Iwai 	struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
41672cbfd45STakashi Iwai 	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
41772cbfd45STakashi Iwai 	return snd_ice1724_put_route_val(chip->ice,
41872cbfd45STakashi Iwai 					 ucontrol->value.enumerated.item[0],
41972cbfd45STakashi Iwai 					 maya_pb_route_shift(idx));
42072cbfd45STakashi Iwai }
42172cbfd45STakashi Iwai 
42272cbfd45STakashi Iwai 
42372cbfd45STakashi Iwai /*
42472cbfd45STakashi Iwai  * controls to be added
42572cbfd45STakashi Iwai  */
42672cbfd45STakashi Iwai 
427b4e5e707STakashi Iwai static const struct snd_kcontrol_new maya_controls[] = {
42872cbfd45STakashi Iwai 	{
42972cbfd45STakashi Iwai 		.name = "Crossmix Playback Volume",
43072cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
43172cbfd45STakashi Iwai 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
43272cbfd45STakashi Iwai 			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
43372cbfd45STakashi Iwai 		.info = maya_vol_info,
43472cbfd45STakashi Iwai 		.get = maya_vol_get,
43572cbfd45STakashi Iwai 		.put = maya_vol_put,
43672cbfd45STakashi Iwai 		.tlv = { .p = db_scale_hp },
43772cbfd45STakashi Iwai 		.private_value = WM_VOL_HP,
43872cbfd45STakashi Iwai 		.count = 2,
43972cbfd45STakashi Iwai 	},
44072cbfd45STakashi Iwai 	{
44172cbfd45STakashi Iwai 		.name = "PCM Playback Volume",
44272cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
44372cbfd45STakashi Iwai 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
44472cbfd45STakashi Iwai 			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
44572cbfd45STakashi Iwai 		.info = maya_vol_info,
44672cbfd45STakashi Iwai 		.get = maya_vol_get,
44772cbfd45STakashi Iwai 		.put = maya_vol_put,
44872cbfd45STakashi Iwai 		.tlv = { .p = db_scale_dac },
44972cbfd45STakashi Iwai 		.private_value = WM_VOL_DAC,
45072cbfd45STakashi Iwai 		.count = 2,
45172cbfd45STakashi Iwai 	},
45272cbfd45STakashi Iwai 	{
45372cbfd45STakashi Iwai 		.name = "Line Capture Volume",
45472cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
45572cbfd45STakashi Iwai 		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
45672cbfd45STakashi Iwai 			SNDRV_CTL_ELEM_ACCESS_TLV_READ,
45772cbfd45STakashi Iwai 		.info = maya_vol_info,
45872cbfd45STakashi Iwai 		.get = maya_vol_get,
45972cbfd45STakashi Iwai 		.put = maya_vol_put,
46072cbfd45STakashi Iwai 		.tlv = { .p = db_scale_adc },
46172cbfd45STakashi Iwai 		.private_value = WM_VOL_ADC,
46272cbfd45STakashi Iwai 		.count = 2,
46372cbfd45STakashi Iwai 	},
46472cbfd45STakashi Iwai 	{
46572cbfd45STakashi Iwai 		.name = "PCM Playback Switch",
46672cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
46772cbfd45STakashi Iwai 		.info = maya_sw_info,
46872cbfd45STakashi Iwai 		.get = maya_sw_get,
46972cbfd45STakashi Iwai 		.put = maya_sw_put,
47072cbfd45STakashi Iwai 		.private_value = COMPOSE_SW_VAL(WM_SW_DAC,
47172cbfd45STakashi Iwai 						WM8776_REG_OUTPUT_MUX, 0x01),
47272cbfd45STakashi Iwai 		.count = 2,
47372cbfd45STakashi Iwai 	},
47472cbfd45STakashi Iwai 	{
47572cbfd45STakashi Iwai 		.name = "Bypass Playback Switch",
47672cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
47772cbfd45STakashi Iwai 		.info = maya_sw_info,
47872cbfd45STakashi Iwai 		.get = maya_sw_get,
47972cbfd45STakashi Iwai 		.put = maya_sw_put,
48072cbfd45STakashi Iwai 		.private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
48172cbfd45STakashi Iwai 						WM8776_REG_OUTPUT_MUX, 0x04),
48272cbfd45STakashi Iwai 		.count = 2,
48372cbfd45STakashi Iwai 	},
48472cbfd45STakashi Iwai 	{
48572cbfd45STakashi Iwai 		.name = "Capture Source",
48672cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
48772cbfd45STakashi Iwai 		.info = maya_rec_src_info,
48872cbfd45STakashi Iwai 		.get = maya_rec_src_get,
48972cbfd45STakashi Iwai 		.put = maya_rec_src_put,
49072cbfd45STakashi Iwai 	},
49172cbfd45STakashi Iwai 	{
49272cbfd45STakashi Iwai 		.name = "Mic Phantom Power Switch",
49372cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
49472cbfd45STakashi Iwai 		.info = maya_gpio_sw_info,
49572cbfd45STakashi Iwai 		.get = maya_gpio_sw_get,
49672cbfd45STakashi Iwai 		.put = maya_gpio_sw_put,
49772cbfd45STakashi Iwai 		.private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
49872cbfd45STakashi Iwai 	},
49972cbfd45STakashi Iwai 	{
50072cbfd45STakashi Iwai 		.name = "SPDIF Capture Switch",
50172cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
50272cbfd45STakashi Iwai 		.info = maya_gpio_sw_info,
50372cbfd45STakashi Iwai 		.get = maya_gpio_sw_get,
50472cbfd45STakashi Iwai 		.put = maya_gpio_sw_put,
50572cbfd45STakashi Iwai 		.private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
50672cbfd45STakashi Iwai 	},
50772cbfd45STakashi Iwai 	{
50872cbfd45STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
50972cbfd45STakashi Iwai 		.name = "H/W Playback Route",
51072cbfd45STakashi Iwai 		.info = maya_pb_route_info,
51172cbfd45STakashi Iwai 		.get = maya_pb_route_get,
51272cbfd45STakashi Iwai 		.put = maya_pb_route_put,
51372cbfd45STakashi Iwai 		.count = 4,  /* FIXME: do controls 5-9 have any meaning? */
51472cbfd45STakashi Iwai 	},
51572cbfd45STakashi Iwai };
51672cbfd45STakashi Iwai 
maya44_add_controls(struct snd_ice1712 * ice)517e23e7a14SBill Pemberton static int maya44_add_controls(struct snd_ice1712 *ice)
51872cbfd45STakashi Iwai {
51972cbfd45STakashi Iwai 	int err, i;
52072cbfd45STakashi Iwai 
52172cbfd45STakashi Iwai 	for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
52272cbfd45STakashi Iwai 		err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
52372cbfd45STakashi Iwai 							  ice->spec));
52472cbfd45STakashi Iwai 		if (err < 0)
52572cbfd45STakashi Iwai 			return err;
52672cbfd45STakashi Iwai 	}
52772cbfd45STakashi Iwai 	return 0;
52872cbfd45STakashi Iwai }
52972cbfd45STakashi Iwai 
53072cbfd45STakashi Iwai 
53172cbfd45STakashi Iwai /*
53272cbfd45STakashi Iwai  * initialize a wm8776 chip
53372cbfd45STakashi Iwai  */
wm8776_init(struct snd_ice1712 * ice,struct snd_wm8776 * wm,unsigned int addr)534e23e7a14SBill Pemberton static void wm8776_init(struct snd_ice1712 *ice,
53572cbfd45STakashi Iwai 			struct snd_wm8776 *wm, unsigned int addr)
53672cbfd45STakashi Iwai {
53772cbfd45STakashi Iwai 	static const unsigned short inits_wm8776[] = {
53872cbfd45STakashi Iwai 		0x02, 0x100, /* R2: headphone L+R muted + update */
53972cbfd45STakashi Iwai 		0x05, 0x100, /* R5: DAC output L+R muted + update */
54072cbfd45STakashi Iwai 		0x06, 0x000, /* R6: DAC output phase normal */
54172cbfd45STakashi Iwai 		0x07, 0x091, /* R7: DAC enable zero cross detection,
54272cbfd45STakashi Iwai 				normal output */
54372cbfd45STakashi Iwai 		0x08, 0x000, /* R8: DAC soft mute off */
54472cbfd45STakashi Iwai 		0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
54572cbfd45STakashi Iwai 		0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
54672cbfd45STakashi Iwai 		0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
54772cbfd45STakashi Iwai 				highpass filter enabled */
54872cbfd45STakashi Iwai 		0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
54972cbfd45STakashi Iwai 		0x0d, 0x000, /* R13: all power up */
55072cbfd45STakashi Iwai 		0x0e, 0x100, /* R14: ADC left muted,
55172cbfd45STakashi Iwai 				enable zero cross detection */
55272cbfd45STakashi Iwai 		0x0f, 0x100, /* R15: ADC right muted,
55372cbfd45STakashi Iwai 				enable zero cross detection */
55472cbfd45STakashi Iwai 			     /* R16: ALC...*/
55572cbfd45STakashi Iwai 		0x11, 0x000, /* R17: disable ALC */
55672cbfd45STakashi Iwai 			     /* R18: ALC...*/
55772cbfd45STakashi Iwai 			     /* R19: noise gate...*/
55872cbfd45STakashi Iwai 		0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
55972cbfd45STakashi Iwai 		0x16, 0x001, /* R22: output mux, select DAC */
56072cbfd45STakashi Iwai 		0xff, 0xff
56172cbfd45STakashi Iwai 	};
56272cbfd45STakashi Iwai 
56372cbfd45STakashi Iwai 	const unsigned short *ptr;
56472cbfd45STakashi Iwai 	unsigned char reg;
56572cbfd45STakashi Iwai 	unsigned short data;
56672cbfd45STakashi Iwai 
56772cbfd45STakashi Iwai 	wm->addr = addr;
56872cbfd45STakashi Iwai 	/* enable DAC output; mute bypass, aux & all inputs */
56972cbfd45STakashi Iwai 	wm->switch_bits = (1 << WM_SW_DAC);
57072cbfd45STakashi Iwai 
57172cbfd45STakashi Iwai 	ptr = inits_wm8776;
57272cbfd45STakashi Iwai 	while (*ptr != 0xff) {
57372cbfd45STakashi Iwai 		reg = *ptr++;
57472cbfd45STakashi Iwai 		data = *ptr++;
57572cbfd45STakashi Iwai 		wm8776_write(ice, wm, reg, data);
57672cbfd45STakashi Iwai 	}
57772cbfd45STakashi Iwai }
57872cbfd45STakashi Iwai 
57972cbfd45STakashi Iwai 
58072cbfd45STakashi Iwai /*
58172cbfd45STakashi Iwai  * change the rate on the WM8776 codecs.
58272cbfd45STakashi Iwai  * this assumes that the VT17xx's rate is changed by the calling function.
58372cbfd45STakashi Iwai  * NOTE: even though the WM8776's are running in slave mode and rate
58472cbfd45STakashi Iwai  * selection is automatic, we need to call snd_wm8776_set_rate() here
58572cbfd45STakashi Iwai  * to make sure some flags are set correctly.
58672cbfd45STakashi Iwai  */
set_rate(struct snd_ice1712 * ice,unsigned int rate)58772cbfd45STakashi Iwai static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
58872cbfd45STakashi Iwai {
58972cbfd45STakashi Iwai 	struct snd_maya44 *chip = ice->spec;
59072cbfd45STakashi Iwai 	unsigned int ratio, adc_ratio, val;
59172cbfd45STakashi Iwai 	int i;
59272cbfd45STakashi Iwai 
59372cbfd45STakashi Iwai 	switch (rate) {
59472cbfd45STakashi Iwai 	case 192000:
59572cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_128FS;
59672cbfd45STakashi Iwai 		break;
59772cbfd45STakashi Iwai 	case 176400:
59872cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_128FS;
59972cbfd45STakashi Iwai 		break;
60072cbfd45STakashi Iwai 	case 96000:
60172cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_256FS;
60272cbfd45STakashi Iwai 		break;
60372cbfd45STakashi Iwai 	case 88200:
60472cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_384FS;
60572cbfd45STakashi Iwai 		break;
60672cbfd45STakashi Iwai 	case 48000:
60772cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_512FS;
60872cbfd45STakashi Iwai 		break;
60972cbfd45STakashi Iwai 	case 44100:
61072cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_512FS;
61172cbfd45STakashi Iwai 		break;
61272cbfd45STakashi Iwai 	case 32000:
61372cbfd45STakashi Iwai 		ratio = WM8776_CLOCK_RATIO_768FS;
61472cbfd45STakashi Iwai 		break;
61572cbfd45STakashi Iwai 	case 0:
61672cbfd45STakashi Iwai 		/* no hint - S/PDIF input is master, simply return */
61772cbfd45STakashi Iwai 		return;
61872cbfd45STakashi Iwai 	default:
61972cbfd45STakashi Iwai 		snd_BUG();
62072cbfd45STakashi Iwai 		return;
62172cbfd45STakashi Iwai 	}
62272cbfd45STakashi Iwai 
62372cbfd45STakashi Iwai 	/*
62472cbfd45STakashi Iwai 	 * this currently sets the same rate for ADC and DAC, but limits
62572cbfd45STakashi Iwai 	 * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
62672cbfd45STakashi Iwai 	 * oversampling to 64x, as recommended by WM8776 datasheet.
62772cbfd45STakashi Iwai 	 * Setting the rate is not really necessary in slave mode.
62872cbfd45STakashi Iwai 	 */
62972cbfd45STakashi Iwai 	adc_ratio = ratio;
63072cbfd45STakashi Iwai 	if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
63172cbfd45STakashi Iwai 		adc_ratio = WM8776_CLOCK_RATIO_256FS;
63272cbfd45STakashi Iwai 
63372cbfd45STakashi Iwai 	val = adc_ratio;
63472cbfd45STakashi Iwai 	if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
63572cbfd45STakashi Iwai 		val |= 8;
63672cbfd45STakashi Iwai 	val |= ratio << 4;
63772cbfd45STakashi Iwai 
63872cbfd45STakashi Iwai 	mutex_lock(&chip->mutex);
63972cbfd45STakashi Iwai 	for (i = 0; i < 2; i++)
64072cbfd45STakashi Iwai 		wm8776_write_bits(ice, &chip->wm[i],
64172cbfd45STakashi Iwai 				  WM8776_REG_MASTER_MODE_CONTROL,
64272cbfd45STakashi Iwai 				  0x180, val);
64372cbfd45STakashi Iwai 	mutex_unlock(&chip->mutex);
64472cbfd45STakashi Iwai }
64572cbfd45STakashi Iwai 
64672cbfd45STakashi Iwai /*
64772cbfd45STakashi Iwai  * supported sample rates (to override the default one)
64872cbfd45STakashi Iwai  */
64972cbfd45STakashi Iwai 
650965f19beSTakashi Iwai static const unsigned int rates[] = {
65172cbfd45STakashi Iwai 	32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
65272cbfd45STakashi Iwai };
65372cbfd45STakashi Iwai 
65472cbfd45STakashi Iwai /* playback rates: 32..192 kHz */
655965f19beSTakashi Iwai static const struct snd_pcm_hw_constraint_list dac_rates = {
65672cbfd45STakashi Iwai 	.count = ARRAY_SIZE(rates),
65772cbfd45STakashi Iwai 	.list = rates,
65872cbfd45STakashi Iwai 	.mask = 0
65972cbfd45STakashi Iwai };
66072cbfd45STakashi Iwai 
66172cbfd45STakashi Iwai 
66272cbfd45STakashi Iwai /*
66372cbfd45STakashi Iwai  * chip addresses on I2C bus
66472cbfd45STakashi Iwai  */
665*f16a4e96STakashi Iwai static const unsigned char wm8776_addr[2] = {
66672cbfd45STakashi Iwai 	0x34, 0x36, /* codec 0 & 1 */
66772cbfd45STakashi Iwai };
66872cbfd45STakashi Iwai 
66972cbfd45STakashi Iwai /*
67072cbfd45STakashi Iwai  * initialize the chip
67172cbfd45STakashi Iwai  */
maya44_init(struct snd_ice1712 * ice)672e23e7a14SBill Pemberton static int maya44_init(struct snd_ice1712 *ice)
67372cbfd45STakashi Iwai {
67472cbfd45STakashi Iwai 	int i;
67572cbfd45STakashi Iwai 	struct snd_maya44 *chip;
67672cbfd45STakashi Iwai 
67772cbfd45STakashi Iwai 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
67872cbfd45STakashi Iwai 	if (!chip)
67972cbfd45STakashi Iwai 		return -ENOMEM;
68072cbfd45STakashi Iwai 	mutex_init(&chip->mutex);
68172cbfd45STakashi Iwai 	chip->ice = ice;
68272cbfd45STakashi Iwai 	ice->spec = chip;
68372cbfd45STakashi Iwai 
68472cbfd45STakashi Iwai 	/* initialise codecs */
68572cbfd45STakashi Iwai 	ice->num_total_dacs = 4;
68672cbfd45STakashi Iwai 	ice->num_total_adcs = 4;
68772cbfd45STakashi Iwai 	ice->akm_codecs = 0;
68872cbfd45STakashi Iwai 
68972cbfd45STakashi Iwai 	for (i = 0; i < 2; i++) {
69072cbfd45STakashi Iwai 		wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
69172cbfd45STakashi Iwai 		wm8776_select_input(chip, i, MAYA_LINE_IN);
69272cbfd45STakashi Iwai 	}
69372cbfd45STakashi Iwai 
69472cbfd45STakashi Iwai 	/* set card specific rates */
69572cbfd45STakashi Iwai 	ice->hw_rates = &dac_rates;
69672cbfd45STakashi Iwai 
69772cbfd45STakashi Iwai 	/* register change rate notifier */
69872cbfd45STakashi Iwai 	ice->gpio.set_pro_rate = set_rate;
69972cbfd45STakashi Iwai 
70072cbfd45STakashi Iwai 	/* RDMA1 (2nd input channel) is used for ADC by default */
70172cbfd45STakashi Iwai 	ice->force_rdma1 = 1;
70272cbfd45STakashi Iwai 
70372cbfd45STakashi Iwai 	/* have an own routing control */
70472cbfd45STakashi Iwai 	ice->own_routing = 1;
70572cbfd45STakashi Iwai 
70672cbfd45STakashi Iwai 	return 0;
70772cbfd45STakashi Iwai }
70872cbfd45STakashi Iwai 
70972cbfd45STakashi Iwai 
71072cbfd45STakashi Iwai /*
71172cbfd45STakashi Iwai  * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
71272cbfd45STakashi Iwai  * hence the driver needs to sets up it properly.
71372cbfd45STakashi Iwai  */
71472cbfd45STakashi Iwai 
715*f16a4e96STakashi Iwai static const unsigned char maya44_eeprom[] = {
71672cbfd45STakashi Iwai 	[ICE_EEP2_SYSCONF]     = 0x45,
71772cbfd45STakashi Iwai 		/* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
71872cbfd45STakashi Iwai 	[ICE_EEP2_ACLINK]      = 0x80,
71972cbfd45STakashi Iwai 		/* I2S */
72072cbfd45STakashi Iwai 	[ICE_EEP2_I2S]         = 0xf8,
72172cbfd45STakashi Iwai 		/* vol, 96k, 24bit, 192k */
72272cbfd45STakashi Iwai 	[ICE_EEP2_SPDIF]       = 0xc3,
72372cbfd45STakashi Iwai 		/* enable spdif out, spdif out supp, spdif-in, ext spdif out */
72472cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_DIR]    = 0xff,
72572cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_DIR1]   = 0xff,
72672cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_DIR2]   = 0xff,
72772cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,
72872cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,
72972cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,
73072cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PHANTOM_OFF) |
73172cbfd45STakashi Iwai 			(1 << GPIO_SPDIF_IN_INV),
73272cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_STATE1] = 0x00,
73372cbfd45STakashi Iwai 	[ICE_EEP2_GPIO_STATE2] = 0x00,
73472cbfd45STakashi Iwai };
73572cbfd45STakashi Iwai 
73672cbfd45STakashi Iwai /* entry point */
737e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
73872cbfd45STakashi Iwai 	{
73972cbfd45STakashi Iwai 		.subvendor = VT1724_SUBDEVICE_MAYA44,
74072cbfd45STakashi Iwai 		.name = "ESI Maya44",
74172cbfd45STakashi Iwai 		.model = "maya44",
74272cbfd45STakashi Iwai 		.chip_init = maya44_init,
74372cbfd45STakashi Iwai 		.build_controls = maya44_add_controls,
74472cbfd45STakashi Iwai 		.eeprom_size = sizeof(maya44_eeprom),
74572cbfd45STakashi Iwai 		.eeprom_data = maya44_eeprom,
74672cbfd45STakashi Iwai 	},
74772cbfd45STakashi Iwai 	{ } /* terminator */
74872cbfd45STakashi Iwai };
749