1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Lowlevel functions for ESI Maya44 cards
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
8*4882a593Smuzhiyun * Based on the patches by Rainer Zimmermann <mail@lightshed.de>
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <sound/core.h>
14*4882a593Smuzhiyun #include <sound/control.h>
15*4882a593Smuzhiyun #include <sound/pcm.h>
16*4882a593Smuzhiyun #include <sound/tlv.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "ice1712.h"
19*4882a593Smuzhiyun #include "envy24ht.h"
20*4882a593Smuzhiyun #include "maya44.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* WM8776 register indexes */
23*4882a593Smuzhiyun #define WM8776_REG_HEADPHONE_L 0x00
24*4882a593Smuzhiyun #define WM8776_REG_HEADPHONE_R 0x01
25*4882a593Smuzhiyun #define WM8776_REG_HEADPHONE_MASTER 0x02
26*4882a593Smuzhiyun #define WM8776_REG_DAC_ATTEN_L 0x03
27*4882a593Smuzhiyun #define WM8776_REG_DAC_ATTEN_R 0x04
28*4882a593Smuzhiyun #define WM8776_REG_DAC_ATTEN_MASTER 0x05
29*4882a593Smuzhiyun #define WM8776_REG_DAC_PHASE 0x06
30*4882a593Smuzhiyun #define WM8776_REG_DAC_CONTROL 0x07
31*4882a593Smuzhiyun #define WM8776_REG_DAC_MUTE 0x08
32*4882a593Smuzhiyun #define WM8776_REG_DAC_DEEMPH 0x09
33*4882a593Smuzhiyun #define WM8776_REG_DAC_IF_CONTROL 0x0a
34*4882a593Smuzhiyun #define WM8776_REG_ADC_IF_CONTROL 0x0b
35*4882a593Smuzhiyun #define WM8776_REG_MASTER_MODE_CONTROL 0x0c
36*4882a593Smuzhiyun #define WM8776_REG_POWERDOWN 0x0d
37*4882a593Smuzhiyun #define WM8776_REG_ADC_ATTEN_L 0x0e
38*4882a593Smuzhiyun #define WM8776_REG_ADC_ATTEN_R 0x0f
39*4882a593Smuzhiyun #define WM8776_REG_ADC_ALC1 0x10
40*4882a593Smuzhiyun #define WM8776_REG_ADC_ALC2 0x11
41*4882a593Smuzhiyun #define WM8776_REG_ADC_ALC3 0x12
42*4882a593Smuzhiyun #define WM8776_REG_ADC_NOISE_GATE 0x13
43*4882a593Smuzhiyun #define WM8776_REG_ADC_LIMITER 0x14
44*4882a593Smuzhiyun #define WM8776_REG_ADC_MUX 0x15
45*4882a593Smuzhiyun #define WM8776_REG_OUTPUT_MUX 0x16
46*4882a593Smuzhiyun #define WM8776_REG_RESET 0x17
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define WM8776_NUM_REGS 0x18
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* clock ratio identifiers for snd_wm8776_set_rate() */
51*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_128FS 0
52*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_192FS 1
53*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_256FS 2
54*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_384FS 3
55*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_512FS 4
56*4882a593Smuzhiyun #define WM8776_CLOCK_RATIO_768FS 5
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
59*4882a593Smuzhiyun enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun struct snd_wm8776 {
62*4882a593Smuzhiyun unsigned char addr;
63*4882a593Smuzhiyun unsigned short regs[WM8776_NUM_REGS];
64*4882a593Smuzhiyun unsigned char volumes[WM_NUM_VOLS][2];
65*4882a593Smuzhiyun unsigned int switch_bits;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun struct snd_maya44 {
69*4882a593Smuzhiyun struct snd_ice1712 *ice;
70*4882a593Smuzhiyun struct snd_wm8776 wm[2];
71*4882a593Smuzhiyun struct mutex mutex;
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /* 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)76*4882a593Smuzhiyun static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
77*4882a593Smuzhiyun unsigned char reg, unsigned short val)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun /*
80*4882a593Smuzhiyun * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
81*4882a593Smuzhiyun * of the address field
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun snd_vt1724_write_i2c(ice, wm->addr,
84*4882a593Smuzhiyun (reg << 1) | ((val >> 8) & 1),
85*4882a593Smuzhiyun val & 0xff);
86*4882a593Smuzhiyun wm->regs[reg] = val;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /*
90*4882a593Smuzhiyun * update the given register with and/or mask and save the data to the cache
91*4882a593Smuzhiyun */
wm8776_write_bits(struct snd_ice1712 * ice,struct snd_wm8776 * wm,unsigned char reg,unsigned short mask,unsigned short val)92*4882a593Smuzhiyun static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
93*4882a593Smuzhiyun unsigned char reg,
94*4882a593Smuzhiyun unsigned short mask, unsigned short val)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun val |= wm->regs[reg] & ~mask;
97*4882a593Smuzhiyun if (val != wm->regs[reg]) {
98*4882a593Smuzhiyun wm8776_write(ice, wm, reg, val);
99*4882a593Smuzhiyun return 1;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun return 0;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /*
106*4882a593Smuzhiyun * WM8776 volume controls
107*4882a593Smuzhiyun */
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun struct maya_vol_info {
110*4882a593Smuzhiyun unsigned int maxval; /* volume range: 0..maxval */
111*4882a593Smuzhiyun unsigned char regs[2]; /* left and right registers */
112*4882a593Smuzhiyun unsigned short mask; /* value mask */
113*4882a593Smuzhiyun unsigned short offset; /* zero-value offset */
114*4882a593Smuzhiyun unsigned short mute; /* mute bit */
115*4882a593Smuzhiyun unsigned short update; /* update bits */
116*4882a593Smuzhiyun unsigned char mux_bits[2]; /* extra bits for ADC mute */
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
120*4882a593Smuzhiyun [WM_VOL_HP] = {
121*4882a593Smuzhiyun .maxval = 80,
122*4882a593Smuzhiyun .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
123*4882a593Smuzhiyun .mask = 0x7f,
124*4882a593Smuzhiyun .offset = 0x30,
125*4882a593Smuzhiyun .mute = 0x00,
126*4882a593Smuzhiyun .update = 0x180, /* update and zero-cross enable */
127*4882a593Smuzhiyun },
128*4882a593Smuzhiyun [WM_VOL_DAC] = {
129*4882a593Smuzhiyun .maxval = 255,
130*4882a593Smuzhiyun .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
131*4882a593Smuzhiyun .mask = 0xff,
132*4882a593Smuzhiyun .offset = 0x01,
133*4882a593Smuzhiyun .mute = 0x00,
134*4882a593Smuzhiyun .update = 0x100, /* zero-cross enable */
135*4882a593Smuzhiyun },
136*4882a593Smuzhiyun [WM_VOL_ADC] = {
137*4882a593Smuzhiyun .maxval = 91,
138*4882a593Smuzhiyun .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
139*4882a593Smuzhiyun .mask = 0xff,
140*4882a593Smuzhiyun .offset = 0xa5,
141*4882a593Smuzhiyun .mute = 0xa5,
142*4882a593Smuzhiyun .update = 0x100, /* update */
143*4882a593Smuzhiyun .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
144*4882a593Smuzhiyun },
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /*
148*4882a593Smuzhiyun * dB tables
149*4882a593Smuzhiyun */
150*4882a593Smuzhiyun /* headphone output: mute, -73..+6db (1db step) */
151*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
152*4882a593Smuzhiyun /* DAC output: mute, -127..0db (0.5db step) */
153*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
154*4882a593Smuzhiyun /* ADC gain: mute, -21..+24db (0.5db step) */
155*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
156*4882a593Smuzhiyun
maya_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)157*4882a593Smuzhiyun static int maya_vol_info(struct snd_kcontrol *kcontrol,
158*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun unsigned int idx = kcontrol->private_value;
161*4882a593Smuzhiyun const struct maya_vol_info *vol = &vol_info[idx];
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
164*4882a593Smuzhiyun uinfo->count = 2;
165*4882a593Smuzhiyun uinfo->value.integer.min = 0;
166*4882a593Smuzhiyun uinfo->value.integer.max = vol->maxval;
167*4882a593Smuzhiyun return 0;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
maya_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)170*4882a593Smuzhiyun static int maya_vol_get(struct snd_kcontrol *kcontrol,
171*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
174*4882a593Smuzhiyun struct snd_wm8776 *wm =
175*4882a593Smuzhiyun &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
176*4882a593Smuzhiyun unsigned int idx = kcontrol->private_value;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun mutex_lock(&chip->mutex);
179*4882a593Smuzhiyun ucontrol->value.integer.value[0] = wm->volumes[idx][0];
180*4882a593Smuzhiyun ucontrol->value.integer.value[1] = wm->volumes[idx][1];
181*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
182*4882a593Smuzhiyun return 0;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
maya_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)185*4882a593Smuzhiyun static int maya_vol_put(struct snd_kcontrol *kcontrol,
186*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
189*4882a593Smuzhiyun struct snd_wm8776 *wm =
190*4882a593Smuzhiyun &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
191*4882a593Smuzhiyun unsigned int idx = kcontrol->private_value;
192*4882a593Smuzhiyun const struct maya_vol_info *vol = &vol_info[idx];
193*4882a593Smuzhiyun unsigned int val, data;
194*4882a593Smuzhiyun int ch, changed = 0;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun mutex_lock(&chip->mutex);
197*4882a593Smuzhiyun for (ch = 0; ch < 2; ch++) {
198*4882a593Smuzhiyun val = ucontrol->value.integer.value[ch];
199*4882a593Smuzhiyun if (val > vol->maxval)
200*4882a593Smuzhiyun val = vol->maxval;
201*4882a593Smuzhiyun if (val == wm->volumes[idx][ch])
202*4882a593Smuzhiyun continue;
203*4882a593Smuzhiyun if (!val)
204*4882a593Smuzhiyun data = vol->mute;
205*4882a593Smuzhiyun else
206*4882a593Smuzhiyun data = (val - 1) + vol->offset;
207*4882a593Smuzhiyun data |= vol->update;
208*4882a593Smuzhiyun changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
209*4882a593Smuzhiyun vol->mask | vol->update, data);
210*4882a593Smuzhiyun if (vol->mux_bits[ch])
211*4882a593Smuzhiyun wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
212*4882a593Smuzhiyun vol->mux_bits[ch],
213*4882a593Smuzhiyun val ? 0 : vol->mux_bits[ch]);
214*4882a593Smuzhiyun wm->volumes[idx][ch] = val;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
217*4882a593Smuzhiyun return changed;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun * WM8776 switch controls
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun #define COMPOSE_SW_VAL(idx, reg, mask) ((idx) | ((reg) << 8) | ((mask) << 16))
225*4882a593Smuzhiyun #define GET_SW_VAL_IDX(val) ((val) & 0xff)
226*4882a593Smuzhiyun #define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff)
227*4882a593Smuzhiyun #define GET_SW_VAL_MASK(val) (((val) >> 16) & 0xff)
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun #define maya_sw_info snd_ctl_boolean_mono_info
230*4882a593Smuzhiyun
maya_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)231*4882a593Smuzhiyun static int maya_sw_get(struct snd_kcontrol *kcontrol,
232*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
235*4882a593Smuzhiyun struct snd_wm8776 *wm =
236*4882a593Smuzhiyun &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
237*4882a593Smuzhiyun unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
240*4882a593Smuzhiyun return 0;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
maya_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)243*4882a593Smuzhiyun static int maya_sw_put(struct snd_kcontrol *kcontrol,
244*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
247*4882a593Smuzhiyun struct snd_wm8776 *wm =
248*4882a593Smuzhiyun &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
249*4882a593Smuzhiyun unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
250*4882a593Smuzhiyun unsigned int mask, val;
251*4882a593Smuzhiyun int changed;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun mutex_lock(&chip->mutex);
254*4882a593Smuzhiyun mask = 1 << idx;
255*4882a593Smuzhiyun wm->switch_bits &= ~mask;
256*4882a593Smuzhiyun val = ucontrol->value.integer.value[0];
257*4882a593Smuzhiyun if (val)
258*4882a593Smuzhiyun wm->switch_bits |= mask;
259*4882a593Smuzhiyun mask = GET_SW_VAL_MASK(kcontrol->private_value);
260*4882a593Smuzhiyun changed = wm8776_write_bits(chip->ice, wm,
261*4882a593Smuzhiyun GET_SW_VAL_REG(kcontrol->private_value),
262*4882a593Smuzhiyun mask, val ? mask : 0);
263*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
264*4882a593Smuzhiyun return changed;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun * GPIO pins (known ones for maya44)
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun #define GPIO_PHANTOM_OFF 2
271*4882a593Smuzhiyun #define GPIO_MIC_RELAY 4
272*4882a593Smuzhiyun #define GPIO_SPDIF_IN_INV 5
273*4882a593Smuzhiyun #define GPIO_MUST_BE_0 7
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /*
276*4882a593Smuzhiyun * GPIO switch controls
277*4882a593Smuzhiyun */
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun #define COMPOSE_GPIO_VAL(shift, inv) ((shift) | ((inv) << 8))
280*4882a593Smuzhiyun #define GET_GPIO_VAL_SHIFT(val) ((val) & 0xff)
281*4882a593Smuzhiyun #define GET_GPIO_VAL_INV(val) (((val) >> 8) & 1)
282*4882a593Smuzhiyun
maya_set_gpio_bits(struct snd_ice1712 * ice,unsigned int mask,unsigned int bits)283*4882a593Smuzhiyun static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
284*4882a593Smuzhiyun unsigned int bits)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun unsigned int data;
287*4882a593Smuzhiyun data = snd_ice1712_gpio_read(ice);
288*4882a593Smuzhiyun if ((data & mask) == bits)
289*4882a593Smuzhiyun return 0;
290*4882a593Smuzhiyun snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
291*4882a593Smuzhiyun return 1;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun #define maya_gpio_sw_info snd_ctl_boolean_mono_info
295*4882a593Smuzhiyun
maya_gpio_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)296*4882a593Smuzhiyun static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
297*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
300*4882a593Smuzhiyun unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
301*4882a593Smuzhiyun unsigned int val;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
304*4882a593Smuzhiyun if (GET_GPIO_VAL_INV(kcontrol->private_value))
305*4882a593Smuzhiyun val = !val;
306*4882a593Smuzhiyun ucontrol->value.integer.value[0] = val;
307*4882a593Smuzhiyun return 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
maya_gpio_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)310*4882a593Smuzhiyun static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
311*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
314*4882a593Smuzhiyun unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
315*4882a593Smuzhiyun unsigned int val, mask;
316*4882a593Smuzhiyun int changed;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun mutex_lock(&chip->mutex);
319*4882a593Smuzhiyun mask = 1 << shift;
320*4882a593Smuzhiyun val = ucontrol->value.integer.value[0];
321*4882a593Smuzhiyun if (GET_GPIO_VAL_INV(kcontrol->private_value))
322*4882a593Smuzhiyun val = !val;
323*4882a593Smuzhiyun val = val ? mask : 0;
324*4882a593Smuzhiyun changed = maya_set_gpio_bits(chip->ice, mask, val);
325*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
326*4882a593Smuzhiyun return changed;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /*
330*4882a593Smuzhiyun * capture source selection
331*4882a593Smuzhiyun */
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* known working input slots (0-4) */
334*4882a593Smuzhiyun #define MAYA_LINE_IN 1 /* in-2 */
335*4882a593Smuzhiyun #define MAYA_MIC_IN 3 /* in-4 */
336*4882a593Smuzhiyun
wm8776_select_input(struct snd_maya44 * chip,int idx,int line)337*4882a593Smuzhiyun static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
340*4882a593Smuzhiyun 0x1f, 1 << line);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
maya_rec_src_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)343*4882a593Smuzhiyun static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
344*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun static const char * const texts[] = { "Line", "Mic" };
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
maya_rec_src_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)351*4882a593Smuzhiyun static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
352*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
355*4882a593Smuzhiyun int sel;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
358*4882a593Smuzhiyun sel = 1;
359*4882a593Smuzhiyun else
360*4882a593Smuzhiyun sel = 0;
361*4882a593Smuzhiyun ucontrol->value.enumerated.item[0] = sel;
362*4882a593Smuzhiyun return 0;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
maya_rec_src_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)365*4882a593Smuzhiyun static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
366*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
369*4882a593Smuzhiyun int sel = ucontrol->value.enumerated.item[0];
370*4882a593Smuzhiyun int changed;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun mutex_lock(&chip->mutex);
373*4882a593Smuzhiyun changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
374*4882a593Smuzhiyun sel ? (1 << GPIO_MIC_RELAY) : 0);
375*4882a593Smuzhiyun wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
376*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
377*4882a593Smuzhiyun return changed;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun /*
381*4882a593Smuzhiyun * Maya44 routing switch settings have different meanings than the standard
382*4882a593Smuzhiyun * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
383*4882a593Smuzhiyun */
maya_pb_route_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)384*4882a593Smuzhiyun static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
385*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun static const char * const texts[] = {
388*4882a593Smuzhiyun "PCM Out", /* 0 */
389*4882a593Smuzhiyun "Input 1", "Input 2", "Input 3", "Input 4"
390*4882a593Smuzhiyun };
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
maya_pb_route_shift(int idx)395*4882a593Smuzhiyun static int maya_pb_route_shift(int idx)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun static const unsigned char shift[10] =
398*4882a593Smuzhiyun { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
399*4882a593Smuzhiyun return shift[idx % 10];
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
maya_pb_route_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)402*4882a593Smuzhiyun static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
403*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
406*4882a593Smuzhiyun int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
407*4882a593Smuzhiyun ucontrol->value.enumerated.item[0] =
408*4882a593Smuzhiyun snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
maya_pb_route_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)412*4882a593Smuzhiyun static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
413*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
416*4882a593Smuzhiyun int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
417*4882a593Smuzhiyun return snd_ice1724_put_route_val(chip->ice,
418*4882a593Smuzhiyun ucontrol->value.enumerated.item[0],
419*4882a593Smuzhiyun maya_pb_route_shift(idx));
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /*
424*4882a593Smuzhiyun * controls to be added
425*4882a593Smuzhiyun */
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun static const struct snd_kcontrol_new maya_controls[] = {
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun .name = "Crossmix Playback Volume",
430*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431*4882a593Smuzhiyun .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
432*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ,
433*4882a593Smuzhiyun .info = maya_vol_info,
434*4882a593Smuzhiyun .get = maya_vol_get,
435*4882a593Smuzhiyun .put = maya_vol_put,
436*4882a593Smuzhiyun .tlv = { .p = db_scale_hp },
437*4882a593Smuzhiyun .private_value = WM_VOL_HP,
438*4882a593Smuzhiyun .count = 2,
439*4882a593Smuzhiyun },
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun .name = "PCM Playback Volume",
442*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
443*4882a593Smuzhiyun .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
444*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ,
445*4882a593Smuzhiyun .info = maya_vol_info,
446*4882a593Smuzhiyun .get = maya_vol_get,
447*4882a593Smuzhiyun .put = maya_vol_put,
448*4882a593Smuzhiyun .tlv = { .p = db_scale_dac },
449*4882a593Smuzhiyun .private_value = WM_VOL_DAC,
450*4882a593Smuzhiyun .count = 2,
451*4882a593Smuzhiyun },
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun .name = "Line Capture Volume",
454*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
455*4882a593Smuzhiyun .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
456*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ,
457*4882a593Smuzhiyun .info = maya_vol_info,
458*4882a593Smuzhiyun .get = maya_vol_get,
459*4882a593Smuzhiyun .put = maya_vol_put,
460*4882a593Smuzhiyun .tlv = { .p = db_scale_adc },
461*4882a593Smuzhiyun .private_value = WM_VOL_ADC,
462*4882a593Smuzhiyun .count = 2,
463*4882a593Smuzhiyun },
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun .name = "PCM Playback Switch",
466*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
467*4882a593Smuzhiyun .info = maya_sw_info,
468*4882a593Smuzhiyun .get = maya_sw_get,
469*4882a593Smuzhiyun .put = maya_sw_put,
470*4882a593Smuzhiyun .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
471*4882a593Smuzhiyun WM8776_REG_OUTPUT_MUX, 0x01),
472*4882a593Smuzhiyun .count = 2,
473*4882a593Smuzhiyun },
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun .name = "Bypass Playback Switch",
476*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
477*4882a593Smuzhiyun .info = maya_sw_info,
478*4882a593Smuzhiyun .get = maya_sw_get,
479*4882a593Smuzhiyun .put = maya_sw_put,
480*4882a593Smuzhiyun .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
481*4882a593Smuzhiyun WM8776_REG_OUTPUT_MUX, 0x04),
482*4882a593Smuzhiyun .count = 2,
483*4882a593Smuzhiyun },
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun .name = "Capture Source",
486*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
487*4882a593Smuzhiyun .info = maya_rec_src_info,
488*4882a593Smuzhiyun .get = maya_rec_src_get,
489*4882a593Smuzhiyun .put = maya_rec_src_put,
490*4882a593Smuzhiyun },
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun .name = "Mic Phantom Power Switch",
493*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494*4882a593Smuzhiyun .info = maya_gpio_sw_info,
495*4882a593Smuzhiyun .get = maya_gpio_sw_get,
496*4882a593Smuzhiyun .put = maya_gpio_sw_put,
497*4882a593Smuzhiyun .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
498*4882a593Smuzhiyun },
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun .name = "SPDIF Capture Switch",
501*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
502*4882a593Smuzhiyun .info = maya_gpio_sw_info,
503*4882a593Smuzhiyun .get = maya_gpio_sw_get,
504*4882a593Smuzhiyun .put = maya_gpio_sw_put,
505*4882a593Smuzhiyun .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
506*4882a593Smuzhiyun },
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
509*4882a593Smuzhiyun .name = "H/W Playback Route",
510*4882a593Smuzhiyun .info = maya_pb_route_info,
511*4882a593Smuzhiyun .get = maya_pb_route_get,
512*4882a593Smuzhiyun .put = maya_pb_route_put,
513*4882a593Smuzhiyun .count = 4, /* FIXME: do controls 5-9 have any meaning? */
514*4882a593Smuzhiyun },
515*4882a593Smuzhiyun };
516*4882a593Smuzhiyun
maya44_add_controls(struct snd_ice1712 * ice)517*4882a593Smuzhiyun static int maya44_add_controls(struct snd_ice1712 *ice)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int err, i;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
522*4882a593Smuzhiyun err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
523*4882a593Smuzhiyun ice->spec));
524*4882a593Smuzhiyun if (err < 0)
525*4882a593Smuzhiyun return err;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun return 0;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /*
532*4882a593Smuzhiyun * initialize a wm8776 chip
533*4882a593Smuzhiyun */
wm8776_init(struct snd_ice1712 * ice,struct snd_wm8776 * wm,unsigned int addr)534*4882a593Smuzhiyun static void wm8776_init(struct snd_ice1712 *ice,
535*4882a593Smuzhiyun struct snd_wm8776 *wm, unsigned int addr)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun static const unsigned short inits_wm8776[] = {
538*4882a593Smuzhiyun 0x02, 0x100, /* R2: headphone L+R muted + update */
539*4882a593Smuzhiyun 0x05, 0x100, /* R5: DAC output L+R muted + update */
540*4882a593Smuzhiyun 0x06, 0x000, /* R6: DAC output phase normal */
541*4882a593Smuzhiyun 0x07, 0x091, /* R7: DAC enable zero cross detection,
542*4882a593Smuzhiyun normal output */
543*4882a593Smuzhiyun 0x08, 0x000, /* R8: DAC soft mute off */
544*4882a593Smuzhiyun 0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
545*4882a593Smuzhiyun 0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
546*4882a593Smuzhiyun 0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
547*4882a593Smuzhiyun highpass filter enabled */
548*4882a593Smuzhiyun 0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
549*4882a593Smuzhiyun 0x0d, 0x000, /* R13: all power up */
550*4882a593Smuzhiyun 0x0e, 0x100, /* R14: ADC left muted,
551*4882a593Smuzhiyun enable zero cross detection */
552*4882a593Smuzhiyun 0x0f, 0x100, /* R15: ADC right muted,
553*4882a593Smuzhiyun enable zero cross detection */
554*4882a593Smuzhiyun /* R16: ALC...*/
555*4882a593Smuzhiyun 0x11, 0x000, /* R17: disable ALC */
556*4882a593Smuzhiyun /* R18: ALC...*/
557*4882a593Smuzhiyun /* R19: noise gate...*/
558*4882a593Smuzhiyun 0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
559*4882a593Smuzhiyun 0x16, 0x001, /* R22: output mux, select DAC */
560*4882a593Smuzhiyun 0xff, 0xff
561*4882a593Smuzhiyun };
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun const unsigned short *ptr;
564*4882a593Smuzhiyun unsigned char reg;
565*4882a593Smuzhiyun unsigned short data;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun wm->addr = addr;
568*4882a593Smuzhiyun /* enable DAC output; mute bypass, aux & all inputs */
569*4882a593Smuzhiyun wm->switch_bits = (1 << WM_SW_DAC);
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun ptr = inits_wm8776;
572*4882a593Smuzhiyun while (*ptr != 0xff) {
573*4882a593Smuzhiyun reg = *ptr++;
574*4882a593Smuzhiyun data = *ptr++;
575*4882a593Smuzhiyun wm8776_write(ice, wm, reg, data);
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /*
581*4882a593Smuzhiyun * change the rate on the WM8776 codecs.
582*4882a593Smuzhiyun * this assumes that the VT17xx's rate is changed by the calling function.
583*4882a593Smuzhiyun * NOTE: even though the WM8776's are running in slave mode and rate
584*4882a593Smuzhiyun * selection is automatic, we need to call snd_wm8776_set_rate() here
585*4882a593Smuzhiyun * to make sure some flags are set correctly.
586*4882a593Smuzhiyun */
set_rate(struct snd_ice1712 * ice,unsigned int rate)587*4882a593Smuzhiyun static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun struct snd_maya44 *chip = ice->spec;
590*4882a593Smuzhiyun unsigned int ratio, adc_ratio, val;
591*4882a593Smuzhiyun int i;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun switch (rate) {
594*4882a593Smuzhiyun case 192000:
595*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_128FS;
596*4882a593Smuzhiyun break;
597*4882a593Smuzhiyun case 176400:
598*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_128FS;
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun case 96000:
601*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_256FS;
602*4882a593Smuzhiyun break;
603*4882a593Smuzhiyun case 88200:
604*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_384FS;
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun case 48000:
607*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_512FS;
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun case 44100:
610*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_512FS;
611*4882a593Smuzhiyun break;
612*4882a593Smuzhiyun case 32000:
613*4882a593Smuzhiyun ratio = WM8776_CLOCK_RATIO_768FS;
614*4882a593Smuzhiyun break;
615*4882a593Smuzhiyun case 0:
616*4882a593Smuzhiyun /* no hint - S/PDIF input is master, simply return */
617*4882a593Smuzhiyun return;
618*4882a593Smuzhiyun default:
619*4882a593Smuzhiyun snd_BUG();
620*4882a593Smuzhiyun return;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /*
624*4882a593Smuzhiyun * this currently sets the same rate for ADC and DAC, but limits
625*4882a593Smuzhiyun * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
626*4882a593Smuzhiyun * oversampling to 64x, as recommended by WM8776 datasheet.
627*4882a593Smuzhiyun * Setting the rate is not really necessary in slave mode.
628*4882a593Smuzhiyun */
629*4882a593Smuzhiyun adc_ratio = ratio;
630*4882a593Smuzhiyun if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
631*4882a593Smuzhiyun adc_ratio = WM8776_CLOCK_RATIO_256FS;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun val = adc_ratio;
634*4882a593Smuzhiyun if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
635*4882a593Smuzhiyun val |= 8;
636*4882a593Smuzhiyun val |= ratio << 4;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun mutex_lock(&chip->mutex);
639*4882a593Smuzhiyun for (i = 0; i < 2; i++)
640*4882a593Smuzhiyun wm8776_write_bits(ice, &chip->wm[i],
641*4882a593Smuzhiyun WM8776_REG_MASTER_MODE_CONTROL,
642*4882a593Smuzhiyun 0x180, val);
643*4882a593Smuzhiyun mutex_unlock(&chip->mutex);
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun /*
647*4882a593Smuzhiyun * supported sample rates (to override the default one)
648*4882a593Smuzhiyun */
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun static const unsigned int rates[] = {
651*4882a593Smuzhiyun 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
652*4882a593Smuzhiyun };
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* playback rates: 32..192 kHz */
655*4882a593Smuzhiyun static const struct snd_pcm_hw_constraint_list dac_rates = {
656*4882a593Smuzhiyun .count = ARRAY_SIZE(rates),
657*4882a593Smuzhiyun .list = rates,
658*4882a593Smuzhiyun .mask = 0
659*4882a593Smuzhiyun };
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun /*
663*4882a593Smuzhiyun * chip addresses on I2C bus
664*4882a593Smuzhiyun */
665*4882a593Smuzhiyun static const unsigned char wm8776_addr[2] = {
666*4882a593Smuzhiyun 0x34, 0x36, /* codec 0 & 1 */
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /*
670*4882a593Smuzhiyun * initialize the chip
671*4882a593Smuzhiyun */
maya44_init(struct snd_ice1712 * ice)672*4882a593Smuzhiyun static int maya44_init(struct snd_ice1712 *ice)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun int i;
675*4882a593Smuzhiyun struct snd_maya44 *chip;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun chip = kzalloc(sizeof(*chip), GFP_KERNEL);
678*4882a593Smuzhiyun if (!chip)
679*4882a593Smuzhiyun return -ENOMEM;
680*4882a593Smuzhiyun mutex_init(&chip->mutex);
681*4882a593Smuzhiyun chip->ice = ice;
682*4882a593Smuzhiyun ice->spec = chip;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /* initialise codecs */
685*4882a593Smuzhiyun ice->num_total_dacs = 4;
686*4882a593Smuzhiyun ice->num_total_adcs = 4;
687*4882a593Smuzhiyun ice->akm_codecs = 0;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun for (i = 0; i < 2; i++) {
690*4882a593Smuzhiyun wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
691*4882a593Smuzhiyun wm8776_select_input(chip, i, MAYA_LINE_IN);
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun /* set card specific rates */
695*4882a593Smuzhiyun ice->hw_rates = &dac_rates;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun /* register change rate notifier */
698*4882a593Smuzhiyun ice->gpio.set_pro_rate = set_rate;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun /* RDMA1 (2nd input channel) is used for ADC by default */
701*4882a593Smuzhiyun ice->force_rdma1 = 1;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun /* have an own routing control */
704*4882a593Smuzhiyun ice->own_routing = 1;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun return 0;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /*
711*4882a593Smuzhiyun * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
712*4882a593Smuzhiyun * hence the driver needs to sets up it properly.
713*4882a593Smuzhiyun */
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun static const unsigned char maya44_eeprom[] = {
716*4882a593Smuzhiyun [ICE_EEP2_SYSCONF] = 0x45,
717*4882a593Smuzhiyun /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
718*4882a593Smuzhiyun [ICE_EEP2_ACLINK] = 0x80,
719*4882a593Smuzhiyun /* I2S */
720*4882a593Smuzhiyun [ICE_EEP2_I2S] = 0xf8,
721*4882a593Smuzhiyun /* vol, 96k, 24bit, 192k */
722*4882a593Smuzhiyun [ICE_EEP2_SPDIF] = 0xc3,
723*4882a593Smuzhiyun /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
724*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR] = 0xff,
725*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR1] = 0xff,
726*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR2] = 0xff,
727*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK] = 0/*0x9f*/,
728*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK1] = 0/*0xff*/,
729*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK2] = 0/*0x7f*/,
730*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE] = (1 << GPIO_PHANTOM_OFF) |
731*4882a593Smuzhiyun (1 << GPIO_SPDIF_IN_INV),
732*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE1] = 0x00,
733*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE2] = 0x00,
734*4882a593Smuzhiyun };
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /* entry point */
737*4882a593Smuzhiyun struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun .subvendor = VT1724_SUBDEVICE_MAYA44,
740*4882a593Smuzhiyun .name = "ESI Maya44",
741*4882a593Smuzhiyun .model = "maya44",
742*4882a593Smuzhiyun .chip_init = maya44_init,
743*4882a593Smuzhiyun .build_controls = maya44_add_controls,
744*4882a593Smuzhiyun .eeprom_size = sizeof(maya44_eeprom),
745*4882a593Smuzhiyun .eeprom_data = maya44_eeprom,
746*4882a593Smuzhiyun },
747*4882a593Smuzhiyun { } /* terminator */
748*4882a593Smuzhiyun };
749