1/*
2 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 *   Lowlevel functions for Audiotrak Prodigy 7.1 Hifi
5 *   based on pontis.c
6 *
7 *      Copyright (c) 2007 Julian Scheel <julian@jusst.de>
8 *      Copyright (c) 2007 allank
9 *      Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
10 *
11 *   This program is free software; you can redistribute it and/or modify
12 *   it under the terms of the GNU General Public License as published by
13 *   the Free Software Foundation; either version 2 of the License, or
14 *   (at your option) any later version.
15 *
16 *   This program is distributed in the hope that it will be useful,
17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *   GNU General Public License for more details.
20 *
21 *   You should have received a copy of the GNU General Public License
22 *   along with this program; if not, write to the Free Software
23 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24 *
25 */
26
27
28#include <linux/delay.h>
29#include <linux/interrupt.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/mutex.h>
33
34#include <sound/core.h>
35#include <sound/info.h>
36#include <sound/tlv.h>
37
38#include "ice1712.h"
39#include "envy24ht.h"
40#include "prodigy_hifi.h"
41
42struct prodigy_hifi_spec {
43	unsigned short master[2];
44	unsigned short vol[8];
45};
46
47/* I2C addresses */
48#define WM_DEV		0x34
49
50/* WM8776 registers */
51#define WM_HP_ATTEN_L		0x00	/* headphone left attenuation */
52#define WM_HP_ATTEN_R		0x01	/* headphone left attenuation */
53#define WM_HP_MASTER		0x02	/* headphone master (both channels),
54						override LLR */
55#define WM_DAC_ATTEN_L		0x03	/* digital left attenuation */
56#define WM_DAC_ATTEN_R		0x04
57#define WM_DAC_MASTER		0x05
58#define WM_PHASE_SWAP		0x06	/* DAC phase swap */
59#define WM_DAC_CTRL1		0x07
60#define WM_DAC_MUTE		0x08
61#define WM_DAC_CTRL2		0x09
62#define WM_DAC_INT		0x0a
63#define WM_ADC_INT		0x0b
64#define WM_MASTER_CTRL		0x0c
65#define WM_POWERDOWN		0x0d
66#define WM_ADC_ATTEN_L		0x0e
67#define WM_ADC_ATTEN_R		0x0f
68#define WM_ALC_CTRL1		0x10
69#define WM_ALC_CTRL2		0x11
70#define WM_ALC_CTRL3		0x12
71#define WM_NOISE_GATE		0x13
72#define WM_LIMITER		0x14
73#define WM_ADC_MUX		0x15
74#define WM_OUT_MUX		0x16
75#define WM_RESET		0x17
76
77/* Analog Recording Source :- Mic, LineIn, CD/Video, */
78
79/* implement capture source select control for WM8776 */
80
81#define WM_AIN1 "AIN1"
82#define WM_AIN2 "AIN2"
83#define WM_AIN3 "AIN3"
84#define WM_AIN4 "AIN4"
85#define WM_AIN5 "AIN5"
86
87/* GPIO pins of envy24ht connected to wm8766 */
88#define WM8766_SPI_CLK	 (1<<17) /* CLK, Pin97 on ICE1724 */
89#define WM8766_SPI_MD	  (1<<16) /* DATA VT1724 -> WM8766, Pin96 */
90#define WM8766_SPI_ML	  (1<<18) /* Latch, Pin98 */
91
92/* WM8766 registers */
93#define WM8766_DAC_CTRL	 0x02   /* DAC Control */
94#define WM8766_INT_CTRL	 0x03   /* Interface Control */
95#define WM8766_DAC_CTRL2	0x09
96#define WM8766_DAC_CTRL3	0x0a
97#define WM8766_RESET	    0x1f
98#define WM8766_LDA1	     0x00
99#define WM8766_LDA2	     0x04
100#define WM8766_LDA3	     0x06
101#define WM8766_RDA1	     0x01
102#define WM8766_RDA2	     0x05
103#define WM8766_RDA3	     0x07
104#define WM8766_MUTE1	    0x0C
105#define WM8766_MUTE2	    0x0F
106
107
108/*
109 * Prodigy HD2
110 */
111#define AK4396_ADDR    0x00
112#define AK4396_CSN    (1 << 8)    /* CSN->GPIO8, pin 75 */
113#define AK4396_CCLK   (1 << 9)    /* CCLK->GPIO9, pin 76 */
114#define AK4396_CDTI   (1 << 10)   /* CDTI->GPIO10, pin 77 */
115
116/* ak4396 registers */
117#define AK4396_CTRL1	    0x00
118#define AK4396_CTRL2	    0x01
119#define AK4396_CTRL3	    0x02
120#define AK4396_LCH_ATT	  0x03
121#define AK4396_RCH_ATT	  0x04
122
123
124/*
125 * get the current register value of WM codec
126 */
127static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
128{
129	reg <<= 1;
130	return ((unsigned short)ice->akm[0].images[reg] << 8) |
131		ice->akm[0].images[reg + 1];
132}
133
134/*
135 * set the register value of WM codec and remember it
136 */
137static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
138{
139	unsigned short cval;
140	cval = (reg << 9) | val;
141	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
142}
143
144static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
145{
146	wm_put_nocache(ice, reg, val);
147	reg <<= 1;
148	ice->akm[0].images[reg] = val >> 8;
149	ice->akm[0].images[reg + 1] = val;
150}
151
152/*
153 * write data in the SPI mode
154 */
155
156static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)
157{
158	unsigned int tmp = snd_ice1712_gpio_read(ice);
159	if (val)
160		tmp |= bit;
161	else
162		tmp &= ~bit;
163	snd_ice1712_gpio_write(ice, tmp);
164}
165
166/*
167 * SPI implementation for WM8766 codec - only writing supported, no readback
168 */
169
170static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data)
171{
172	int i;
173	for (i = 0; i < 16; i++) {
174		set_gpio_bit(ice, WM8766_SPI_CLK, 0);
175		udelay(1);
176		set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000);
177		udelay(1);
178		set_gpio_bit(ice, WM8766_SPI_CLK, 1);
179		udelay(1);
180		data <<= 1;
181	}
182}
183
184static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg,
185			     unsigned int data)
186{
187	unsigned int block;
188
189	snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD|
190					WM8766_SPI_CLK|WM8766_SPI_ML);
191	snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD|
192					WM8766_SPI_CLK|WM8766_SPI_ML));
193	/* latch must be low when writing */
194	set_gpio_bit(ice, WM8766_SPI_ML, 0);
195	block = (reg << 9) | (data & 0x1ff);
196	wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */
197	/* release latch */
198	set_gpio_bit(ice, WM8766_SPI_ML, 1);
199	udelay(1);
200	/* restore */
201	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
202	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
203}
204
205
206/*
207 * serial interface for ak4396 - only writing supported, no readback
208 */
209
210static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data)
211{
212	int i;
213	for (i = 0; i < 16; i++) {
214		set_gpio_bit(ice, AK4396_CCLK, 0);
215		udelay(1);
216		set_gpio_bit(ice, AK4396_CDTI, data & 0x8000);
217		udelay(1);
218		set_gpio_bit(ice, AK4396_CCLK, 1);
219		udelay(1);
220		data <<= 1;
221	}
222}
223
224static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg,
225			 unsigned int data)
226{
227	unsigned int block;
228
229	snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI);
230	snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI));
231	/* latch must be low when writing */
232	set_gpio_bit(ice, AK4396_CSN, 0);
233	block =  ((AK4396_ADDR & 0x03) << 14) | (1 << 13) |
234			((reg & 0x1f) << 8) | (data & 0xff);
235	ak4396_send_word(ice, block); /* REGISTER ADDRESS */
236	/* release latch */
237	set_gpio_bit(ice, AK4396_CSN, 1);
238	udelay(1);
239	/* restore */
240	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
241	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
242}
243
244
245/*
246 * ak4396 mixers
247 */
248
249
250
251/*
252 * DAC volume attenuation mixer control (-64dB to 0dB)
253 */
254
255static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol,
256			       struct snd_ctl_elem_info *uinfo)
257{
258	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
259	uinfo->count = 2;
260	uinfo->value.integer.min = 0;   /* mute */
261	uinfo->value.integer.max = 0xFF; /* linear */
262	return 0;
263}
264
265static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol,
266			      struct snd_ctl_elem_value *ucontrol)
267{
268	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
269	struct prodigy_hifi_spec *spec = ice->spec;
270	int i;
271
272	for (i = 0; i < 2; i++)
273		ucontrol->value.integer.value[i] = spec->vol[i];
274
275	return 0;
276}
277
278static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
279{
280	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
281	struct prodigy_hifi_spec *spec = ice->spec;
282	int i;
283	int change = 0;
284
285	mutex_lock(&ice->gpio_mutex);
286	for (i = 0; i < 2; i++) {
287		if (ucontrol->value.integer.value[i] != spec->vol[i]) {
288			spec->vol[i] = ucontrol->value.integer.value[i];
289			ak4396_write(ice, AK4396_LCH_ATT + i,
290				     spec->vol[i] & 0xff);
291			change = 1;
292		}
293	}
294	mutex_unlock(&ice->gpio_mutex);
295	return change;
296}
297
298static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
299static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
300
301static struct snd_kcontrol_new prodigy_hd2_controls[] = {
302    {
303	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
304	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
305		SNDRV_CTL_ELEM_ACCESS_TLV_READ),
306	.name = "Front Playback Volume",
307	.info = ak4396_dac_vol_info,
308	.get = ak4396_dac_vol_get,
309	.put = ak4396_dac_vol_put,
310	.tlv = { .p = ak4396_db_scale },
311    },
312};
313
314
315/* --------------- */
316
317/*
318 * Logarithmic volume values for WM87*6
319 * Computed as 20 * Log10(255 / x)
320 */
321static const unsigned char wm_vol[256] = {
322	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
323	23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
324	17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
325	13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
326	11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
327	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
328	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
329	5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
330	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
331	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
332	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333	0, 0
334};
335
336#define WM_VOL_MAX	(sizeof(wm_vol) - 1)
337#define WM_VOL_MUTE	0x8000
338
339
340#define DAC_0dB	0xff
341#define DAC_RES	128
342#define DAC_MIN	(DAC_0dB - DAC_RES)
343
344
345static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
346		       unsigned short vol, unsigned short master)
347{
348	unsigned char nvol;
349
350	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
351		nvol = 0;
352	else {
353		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
354				& WM_VOL_MAX;
355		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
356	}
357
358	wm_put(ice, index, nvol);
359	wm_put_nocache(ice, index, 0x100 | nvol);
360}
361
362static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index,
363			   unsigned short vol, unsigned short master)
364{
365	unsigned char nvol;
366
367	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
368		nvol = 0;
369	else {
370		nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
371				& WM_VOL_MAX;
372		nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
373	}
374
375	wm8766_spi_write(ice, index, (0x0100 | nvol));
376}
377
378
379/*
380 * DAC volume attenuation mixer control (-64dB to 0dB)
381 */
382
383static int wm_dac_vol_info(struct snd_kcontrol *kcontrol,
384			   struct snd_ctl_elem_info *uinfo)
385{
386	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
387	uinfo->count = 2;
388	uinfo->value.integer.min = 0;	/* mute */
389	uinfo->value.integer.max = DAC_RES;	/* 0dB, 0.5dB step */
390	return 0;
391}
392
393static int wm_dac_vol_get(struct snd_kcontrol *kcontrol,
394			  struct snd_ctl_elem_value *ucontrol)
395{
396	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
397	struct prodigy_hifi_spec *spec = ice->spec;
398	int i;
399
400	for (i = 0; i < 2; i++)
401		ucontrol->value.integer.value[i] =
402			spec->vol[2 + i] & ~WM_VOL_MUTE;
403	return 0;
404}
405
406static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
407{
408	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
409	struct prodigy_hifi_spec *spec = ice->spec;
410	int i, idx, change = 0;
411
412	mutex_lock(&ice->gpio_mutex);
413	for (i = 0; i < 2; i++) {
414		if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) {
415			idx = WM_DAC_ATTEN_L + i;
416			spec->vol[2 + i] &= WM_VOL_MUTE;
417			spec->vol[2 + i] |= ucontrol->value.integer.value[i];
418			wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]);
419			change = 1;
420		}
421	}
422	mutex_unlock(&ice->gpio_mutex);
423	return change;
424}
425
426
427/*
428 * WM8766 DAC volume attenuation mixer control
429 */
430static int wm8766_vol_info(struct snd_kcontrol *kcontrol,
431			   struct snd_ctl_elem_info *uinfo)
432{
433	int voices = kcontrol->private_value >> 8;
434	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
435	uinfo->count = voices;
436	uinfo->value.integer.min = 0;		/* mute */
437	uinfo->value.integer.max = DAC_RES;	/* 0dB */
438	return 0;
439}
440
441static int wm8766_vol_get(struct snd_kcontrol *kcontrol,
442			  struct snd_ctl_elem_value *ucontrol)
443{
444	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
445	struct prodigy_hifi_spec *spec = ice->spec;
446	int i, ofs, voices;
447
448	voices = kcontrol->private_value >> 8;
449	ofs = kcontrol->private_value & 0xff;
450	for (i = 0; i < voices; i++)
451		ucontrol->value.integer.value[i] = spec->vol[ofs + i];
452	return 0;
453}
454
455static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
456{
457	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
458	struct prodigy_hifi_spec *spec = ice->spec;
459	int i, idx, ofs, voices;
460	int change = 0;
461
462	voices = kcontrol->private_value >> 8;
463	ofs = kcontrol->private_value & 0xff;
464	mutex_lock(&ice->gpio_mutex);
465	for (i = 0; i < voices; i++) {
466		if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) {
467			idx = WM8766_LDA1 + ofs + i;
468			spec->vol[ofs + i] &= WM_VOL_MUTE;
469			spec->vol[ofs + i] |= ucontrol->value.integer.value[i];
470			wm8766_set_vol(ice, idx,
471				       spec->vol[ofs + i], spec->master[i]);
472			change = 1;
473		}
474	}
475	mutex_unlock(&ice->gpio_mutex);
476	return change;
477}
478
479/*
480 * Master volume attenuation mixer control / applied to WM8776+WM8766
481 */
482static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
483			      struct snd_ctl_elem_info *uinfo)
484{
485	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
486	uinfo->count = 2;
487	uinfo->value.integer.min = 0;
488	uinfo->value.integer.max = DAC_RES;
489	return 0;
490}
491
492static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
493			     struct snd_ctl_elem_value *ucontrol)
494{
495	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
496	struct prodigy_hifi_spec *spec = ice->spec;
497	int i;
498	for (i = 0; i < 2; i++)
499		ucontrol->value.integer.value[i] = spec->master[i];
500	return 0;
501}
502
503static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
504			     struct snd_ctl_elem_value *ucontrol)
505{
506	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
507	struct prodigy_hifi_spec *spec = ice->spec;
508	int ch, change = 0;
509
510	mutex_lock(&ice->gpio_mutex);
511	for (ch = 0; ch < 2; ch++) {
512		if (ucontrol->value.integer.value[ch] != spec->master[ch]) {
513			spec->master[ch] = ucontrol->value.integer.value[ch];
514
515			/* Apply to front DAC */
516			wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
517				   spec->vol[2 + ch], spec->master[ch]);
518
519			wm8766_set_vol(ice, WM8766_LDA1 + ch,
520				       spec->vol[0 + ch], spec->master[ch]);
521
522			wm8766_set_vol(ice, WM8766_LDA2 + ch,
523				       spec->vol[4 + ch], spec->master[ch]);
524
525			wm8766_set_vol(ice, WM8766_LDA3 + ch,
526				       spec->vol[6 + ch], spec->master[ch]);
527			change = 1;
528		}
529	}
530	mutex_unlock(&ice->gpio_mutex);
531	return change;
532}
533
534
535/* KONSTI */
536
537static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol,
538				struct snd_ctl_elem_info *uinfo)
539{
540	static const char * const texts[32] = {
541		"NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2,
542		WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3,
543		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3,
544		WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4,
545		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4,
546		WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4,
547		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
548		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
549		WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5,
550		WM_AIN1 "+" WM_AIN2 "+" WM_AIN5,
551		WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5,
552		WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
553		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
554		WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5,
555		WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
556		WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
557		WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
558		WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
559		WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
560		WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5
561	};
562
563	return snd_ctl_enum_info(uinfo, 1, 32, texts);
564}
565
566static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol,
567			       struct snd_ctl_elem_value *ucontrol)
568{
569	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
570
571	mutex_lock(&ice->gpio_mutex);
572	ucontrol->value.integer.value[0] = wm_get(ice, WM_ADC_MUX) & 0x1f;
573	mutex_unlock(&ice->gpio_mutex);
574	return 0;
575}
576
577static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol,
578			       struct snd_ctl_elem_value *ucontrol)
579{
580	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
581	unsigned short oval, nval;
582	int change = 0;
583
584	mutex_lock(&ice->gpio_mutex);
585	oval = wm_get(ice, WM_ADC_MUX);
586	nval = (oval & 0xe0) | ucontrol->value.integer.value[0];
587	if (nval != oval) {
588		wm_put(ice, WM_ADC_MUX, nval);
589		change = 1;
590	}
591	mutex_unlock(&ice->gpio_mutex);
592	return change;
593}
594
595/* KONSTI */
596
597/*
598 * ADC gain mixer control (-64dB to 0dB)
599 */
600
601#define ADC_0dB	0xcf
602#define ADC_RES	128
603#define ADC_MIN	(ADC_0dB - ADC_RES)
604
605static int wm_adc_vol_info(struct snd_kcontrol *kcontrol,
606			   struct snd_ctl_elem_info *uinfo)
607{
608	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
609	uinfo->count = 2;
610	uinfo->value.integer.min = 0;	/* mute (-64dB) */
611	uinfo->value.integer.max = ADC_RES;	/* 0dB, 0.5dB step */
612	return 0;
613}
614
615static int wm_adc_vol_get(struct snd_kcontrol *kcontrol,
616			  struct snd_ctl_elem_value *ucontrol)
617{
618	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
619	unsigned short val;
620	int i;
621
622	mutex_lock(&ice->gpio_mutex);
623	for (i = 0; i < 2; i++) {
624		val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
625		val = val > ADC_MIN ? (val - ADC_MIN) : 0;
626		ucontrol->value.integer.value[i] = val;
627	}
628	mutex_unlock(&ice->gpio_mutex);
629	return 0;
630}
631
632static int wm_adc_vol_put(struct snd_kcontrol *kcontrol,
633			  struct snd_ctl_elem_value *ucontrol)
634{
635	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
636	unsigned short ovol, nvol;
637	int i, idx, change = 0;
638
639	mutex_lock(&ice->gpio_mutex);
640	for (i = 0; i < 2; i++) {
641		nvol = ucontrol->value.integer.value[i];
642		nvol = nvol ? (nvol + ADC_MIN) : 0;
643		idx  = WM_ADC_ATTEN_L + i;
644		ovol = wm_get(ice, idx) & 0xff;
645		if (ovol != nvol) {
646			wm_put(ice, idx, nvol);
647			change = 1;
648		}
649	}
650	mutex_unlock(&ice->gpio_mutex);
651	return change;
652}
653
654/*
655 * ADC input mux mixer control
656 */
657#define wm_adc_mux_info		snd_ctl_boolean_mono_info
658
659static int wm_adc_mux_get(struct snd_kcontrol *kcontrol,
660			  struct snd_ctl_elem_value *ucontrol)
661{
662	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
663	int bit = kcontrol->private_value;
664
665	mutex_lock(&ice->gpio_mutex);
666	ucontrol->value.integer.value[0] =
667		(wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
668	mutex_unlock(&ice->gpio_mutex);
669	return 0;
670}
671
672static int wm_adc_mux_put(struct snd_kcontrol *kcontrol,
673			  struct snd_ctl_elem_value *ucontrol)
674{
675	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
676	int bit = kcontrol->private_value;
677	unsigned short oval, nval;
678	int change;
679
680	mutex_lock(&ice->gpio_mutex);
681	nval = oval = wm_get(ice, WM_ADC_MUX);
682	if (ucontrol->value.integer.value[0])
683		nval |= (1 << bit);
684	else
685		nval &= ~(1 << bit);
686	change = nval != oval;
687	if (change) {
688		wm_put(ice, WM_ADC_MUX, nval);
689	}
690	mutex_unlock(&ice->gpio_mutex);
691	return 0;
692}
693
694/*
695 * Analog bypass (In -> Out)
696 */
697#define wm_bypass_info		snd_ctl_boolean_mono_info
698
699static int wm_bypass_get(struct snd_kcontrol *kcontrol,
700			 struct snd_ctl_elem_value *ucontrol)
701{
702	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
703
704	mutex_lock(&ice->gpio_mutex);
705	ucontrol->value.integer.value[0] =
706		(wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
707	mutex_unlock(&ice->gpio_mutex);
708	return 0;
709}
710
711static int wm_bypass_put(struct snd_kcontrol *kcontrol,
712			 struct snd_ctl_elem_value *ucontrol)
713{
714	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
715	unsigned short val, oval;
716	int change = 0;
717
718	mutex_lock(&ice->gpio_mutex);
719	val = oval = wm_get(ice, WM_OUT_MUX);
720	if (ucontrol->value.integer.value[0])
721		val |= 0x04;
722	else
723		val &= ~0x04;
724	if (val != oval) {
725		wm_put(ice, WM_OUT_MUX, val);
726		change = 1;
727	}
728	mutex_unlock(&ice->gpio_mutex);
729	return change;
730}
731
732/*
733 * Left/Right swap
734 */
735#define wm_chswap_info		snd_ctl_boolean_mono_info
736
737static int wm_chswap_get(struct snd_kcontrol *kcontrol,
738			 struct snd_ctl_elem_value *ucontrol)
739{
740	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
741
742	mutex_lock(&ice->gpio_mutex);
743	ucontrol->value.integer.value[0] =
744			(wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
745	mutex_unlock(&ice->gpio_mutex);
746	return 0;
747}
748
749static int wm_chswap_put(struct snd_kcontrol *kcontrol,
750			 struct snd_ctl_elem_value *ucontrol)
751{
752	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
753	unsigned short val, oval;
754	int change = 0;
755
756	mutex_lock(&ice->gpio_mutex);
757	oval = wm_get(ice, WM_DAC_CTRL1);
758	val = oval & 0x0f;
759	if (ucontrol->value.integer.value[0])
760		val |= 0x60;
761	else
762		val |= 0x90;
763	if (val != oval) {
764		wm_put(ice, WM_DAC_CTRL1, val);
765		wm_put_nocache(ice, WM_DAC_CTRL1, val);
766		change = 1;
767	}
768	mutex_unlock(&ice->gpio_mutex);
769	return change;
770}
771
772
773/*
774 * mixers
775 */
776
777static struct snd_kcontrol_new prodigy_hifi_controls[] = {
778	{
779		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
780		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
781			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
782		.name = "Master Playback Volume",
783		.info = wm_master_vol_info,
784		.get = wm_master_vol_get,
785		.put = wm_master_vol_put,
786		.tlv = { .p = db_scale_wm_dac }
787	},
788	{
789		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
790		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
791			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
792		.name = "Front Playback Volume",
793		.info = wm_dac_vol_info,
794		.get = wm_dac_vol_get,
795		.put = wm_dac_vol_put,
796		.tlv = { .p = db_scale_wm_dac },
797	},
798	{
799		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
800		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
801			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
802		.name = "Rear Playback Volume",
803		.info = wm8766_vol_info,
804		.get = wm8766_vol_get,
805		.put = wm8766_vol_put,
806		.private_value = (2 << 8) | 0,
807		.tlv = { .p = db_scale_wm_dac },
808	},
809	{
810		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
811		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
812			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
813		.name = "Center Playback Volume",
814		.info = wm8766_vol_info,
815		.get = wm8766_vol_get,
816		.put = wm8766_vol_put,
817		.private_value = (1 << 8) | 4,
818		.tlv = { .p = db_scale_wm_dac }
819	},
820	{
821		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
822		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
823			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
824		.name = "LFE Playback Volume",
825		.info = wm8766_vol_info,
826		.get = wm8766_vol_get,
827		.put = wm8766_vol_put,
828		.private_value = (1 << 8) | 5,
829		.tlv = { .p = db_scale_wm_dac }
830	},
831	{
832		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
833		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
834			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
835		.name = "Side Playback Volume",
836		.info = wm8766_vol_info,
837		.get = wm8766_vol_get,
838		.put = wm8766_vol_put,
839		.private_value = (2 << 8) | 6,
840		.tlv = { .p = db_scale_wm_dac },
841	},
842	{
843		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
844		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
845			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
846		.name = "Capture Volume",
847		.info = wm_adc_vol_info,
848		.get = wm_adc_vol_get,
849		.put = wm_adc_vol_put,
850		.tlv = { .p = db_scale_wm_dac },
851	},
852	{
853		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
854		.name = "CD Capture Switch",
855		.info = wm_adc_mux_info,
856		.get = wm_adc_mux_get,
857		.put = wm_adc_mux_put,
858		.private_value = 0,
859	},
860	{
861		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
862		.name = "Line Capture Switch",
863		.info = wm_adc_mux_info,
864		.get = wm_adc_mux_get,
865		.put = wm_adc_mux_put,
866		.private_value = 1,
867	},
868	{
869		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
870		.name = "Analog Bypass Switch",
871		.info = wm_bypass_info,
872		.get = wm_bypass_get,
873		.put = wm_bypass_put,
874	},
875	{
876		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877		.name = "Swap Output Channels",
878		.info = wm_chswap_info,
879		.get = wm_chswap_get,
880		.put = wm_chswap_put,
881	},
882	{
883		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
884		.name = "Analog Capture Source",
885		.info = wm_adc_mux_enum_info,
886		.get = wm_adc_mux_enum_get,
887		.put = wm_adc_mux_enum_put,
888	},
889};
890
891/*
892 * WM codec registers
893 */
894static void wm_proc_regs_write(struct snd_info_entry *entry,
895			       struct snd_info_buffer *buffer)
896{
897	struct snd_ice1712 *ice = entry->private_data;
898	char line[64];
899	unsigned int reg, val;
900	mutex_lock(&ice->gpio_mutex);
901	while (!snd_info_get_line(buffer, line, sizeof(line))) {
902		if (sscanf(line, "%x %x", &reg, &val) != 2)
903			continue;
904		if (reg <= 0x17 && val <= 0xffff)
905			wm_put(ice, reg, val);
906	}
907	mutex_unlock(&ice->gpio_mutex);
908}
909
910static void wm_proc_regs_read(struct snd_info_entry *entry,
911			      struct snd_info_buffer *buffer)
912{
913	struct snd_ice1712 *ice = entry->private_data;
914	int reg, val;
915
916	mutex_lock(&ice->gpio_mutex);
917	for (reg = 0; reg <= 0x17; reg++) {
918		val = wm_get(ice, reg);
919		snd_iprintf(buffer, "%02x = %04x\n", reg, val);
920	}
921	mutex_unlock(&ice->gpio_mutex);
922}
923
924static void wm_proc_init(struct snd_ice1712 *ice)
925{
926	struct snd_info_entry *entry;
927	if (!snd_card_proc_new(ice->card, "wm_codec", &entry)) {
928		snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
929		entry->mode |= S_IWUSR;
930		entry->c.text.write = wm_proc_regs_write;
931	}
932}
933
934static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
935{
936	unsigned int i;
937	int err;
938
939	for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) {
940		err = snd_ctl_add(ice->card,
941				  snd_ctl_new1(&prodigy_hifi_controls[i], ice));
942		if (err < 0)
943			return err;
944	}
945
946	wm_proc_init(ice);
947
948	return 0;
949}
950
951static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
952{
953	unsigned int i;
954	int err;
955
956	for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) {
957		err = snd_ctl_add(ice->card,
958				  snd_ctl_new1(&prodigy_hd2_controls[i], ice));
959		if (err < 0)
960			return err;
961	}
962
963	wm_proc_init(ice);
964
965	return 0;
966}
967
968
969/*
970 * initialize the chip
971 */
972static int prodigy_hifi_init(struct snd_ice1712 *ice)
973{
974	static unsigned short wm_inits[] = {
975		/* These come first to reduce init pop noise */
976		WM_ADC_MUX,	0x0003,	/* ADC mute */
977		/* 0x00c0 replaced by 0x0003 */
978
979		WM_DAC_MUTE,	0x0001,	/* DAC softmute */
980		WM_DAC_CTRL1,	0x0000,	/* DAC mute */
981
982		WM_POWERDOWN,	0x0008,	/* All power-up except HP */
983		WM_RESET,	0x0000,	/* reset */
984	};
985	static unsigned short wm_inits2[] = {
986		WM_MASTER_CTRL,  0x0022, /* 256fs, slave mode */
987		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
988		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
989		WM_DAC_CTRL1,	0x0090,	/* DAC L/R */
990		WM_OUT_MUX,	0x0001,	/* OUT DAC */
991		WM_HP_ATTEN_L,	0x0179,	/* HP 0dB */
992		WM_HP_ATTEN_R,	0x0179,	/* HP 0dB */
993		WM_DAC_ATTEN_L,	0x0000,	/* DAC 0dB */
994		WM_DAC_ATTEN_L,	0x0100,	/* DAC 0dB */
995		WM_DAC_ATTEN_R,	0x0000,	/* DAC 0dB */
996		WM_DAC_ATTEN_R,	0x0100,	/* DAC 0dB */
997		WM_PHASE_SWAP,	0x0000,	/* phase normal */
998#if 0
999		WM_DAC_MASTER,	0x0100,	/* DAC master muted */
1000#endif
1001		WM_DAC_CTRL2,	0x0000,	/* no deemphasis, no ZFLG */
1002		WM_ADC_ATTEN_L,	0x0000,	/* ADC muted */
1003		WM_ADC_ATTEN_R,	0x0000,	/* ADC muted */
1004#if 1
1005		WM_ALC_CTRL1,	0x007b,	/* */
1006		WM_ALC_CTRL2,	0x0000,	/* */
1007		WM_ALC_CTRL3,	0x0000,	/* */
1008		WM_NOISE_GATE,	0x0000,	/* */
1009#endif
1010		WM_DAC_MUTE,	0x0000,	/* DAC unmute */
1011		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */
1012	};
1013	static unsigned short wm8766_inits[] = {
1014		WM8766_RESET,	   0x0000,
1015		WM8766_DAC_CTRL,	0x0120,
1016		WM8766_INT_CTRL,	0x0022, /* I2S Normal Mode, 24 bit */
1017		WM8766_DAC_CTRL2,       0x0001,
1018		WM8766_DAC_CTRL3,       0x0080,
1019		WM8766_LDA1,	    0x0100,
1020		WM8766_LDA2,	    0x0100,
1021		WM8766_LDA3,	    0x0100,
1022		WM8766_RDA1,	    0x0100,
1023		WM8766_RDA2,	    0x0100,
1024		WM8766_RDA3,	    0x0100,
1025		WM8766_MUTE1,	   0x0000,
1026		WM8766_MUTE2,	   0x0000,
1027	};
1028
1029	struct prodigy_hifi_spec *spec;
1030	unsigned int i;
1031
1032	ice->vt1720 = 0;
1033	ice->vt1724 = 1;
1034
1035	ice->num_total_dacs = 8;
1036	ice->num_total_adcs = 1;
1037
1038	/* HACK - use this as the SPDIF source.
1039	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
1040	*/
1041	ice->gpio.saved[0] = 0;
1042	/* to remember the register values */
1043
1044	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1045	if (! ice->akm)
1046		return -ENOMEM;
1047	ice->akm_codecs = 1;
1048
1049	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1050	if (!spec)
1051		return -ENOMEM;
1052	ice->spec = spec;
1053
1054	/* initialize WM8776 codec */
1055	for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
1056		wm_put(ice, wm_inits[i], wm_inits[i+1]);
1057	schedule_timeout_uninterruptible(1);
1058	for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)
1059		wm_put(ice, wm_inits2[i], wm_inits2[i+1]);
1060
1061	/* initialize WM8766 codec */
1062	for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)
1063		wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]);
1064
1065
1066	return 0;
1067}
1068
1069
1070/*
1071 * initialize the chip
1072 */
1073static void ak4396_init(struct snd_ice1712 *ice)
1074{
1075	static unsigned short ak4396_inits[] = {
1076		AK4396_CTRL1,	   0x87,   /* I2S Normal Mode, 24 bit */
1077		AK4396_CTRL2,	   0x02,
1078		AK4396_CTRL3,	   0x00,
1079		AK4396_LCH_ATT,	 0x00,
1080		AK4396_RCH_ATT,	 0x00,
1081	};
1082
1083	unsigned int i;
1084
1085	/* initialize ak4396 codec */
1086	/* reset codec */
1087	ak4396_write(ice, AK4396_CTRL1, 0x86);
1088	msleep(100);
1089	ak4396_write(ice, AK4396_CTRL1, 0x87);
1090
1091	for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)
1092		ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);
1093}
1094
1095#ifdef CONFIG_PM_SLEEP
1096static int prodigy_hd2_resume(struct snd_ice1712 *ice)
1097{
1098	/* initialize ak4396 codec and restore previous mixer volumes */
1099	struct prodigy_hifi_spec *spec = ice->spec;
1100	int i;
1101	mutex_lock(&ice->gpio_mutex);
1102	ak4396_init(ice);
1103	for (i = 0; i < 2; i++)
1104		ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);
1105	mutex_unlock(&ice->gpio_mutex);
1106	return 0;
1107}
1108#endif
1109
1110static int prodigy_hd2_init(struct snd_ice1712 *ice)
1111{
1112	struct prodigy_hifi_spec *spec;
1113
1114	ice->vt1720 = 0;
1115	ice->vt1724 = 1;
1116
1117	ice->num_total_dacs = 1;
1118	ice->num_total_adcs = 1;
1119
1120	/* HACK - use this as the SPDIF source.
1121	* don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
1122	*/
1123	ice->gpio.saved[0] = 0;
1124	/* to remember the register values */
1125
1126	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1127	if (! ice->akm)
1128		return -ENOMEM;
1129	ice->akm_codecs = 1;
1130
1131	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1132	if (!spec)
1133		return -ENOMEM;
1134	ice->spec = spec;
1135
1136#ifdef CONFIG_PM_SLEEP
1137	ice->pm_resume = &prodigy_hd2_resume;
1138	ice->pm_suspend_enabled = 1;
1139#endif
1140
1141	ak4396_init(ice);
1142
1143	return 0;
1144}
1145
1146
1147static unsigned char prodigy71hifi_eeprom[] = {
1148	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1149	0x80,   /* ACLINK: I2S */
1150	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1151	0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1152	0xff,   /* GPIO_DIR */
1153	0xff,   /* GPIO_DIR1 */
1154	0x5f,   /* GPIO_DIR2 */
1155	0x00,   /* GPIO_MASK */
1156	0x00,   /* GPIO_MASK1 */
1157	0x00,   /* GPIO_MASK2 */
1158	0x00,   /* GPIO_STATE */
1159	0x00,   /* GPIO_STATE1 */
1160	0x00,   /* GPIO_STATE2 */
1161};
1162
1163static unsigned char prodigyhd2_eeprom[] = {
1164	0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1165	0x80,   /* ACLINK: I2S */
1166	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1167	0xc3,   /* SPDIF: out-en, out-int, spdif-in */
1168	0xff,   /* GPIO_DIR */
1169	0xff,   /* GPIO_DIR1 */
1170	0x5f,   /* GPIO_DIR2 */
1171	0x00,   /* GPIO_MASK */
1172	0x00,   /* GPIO_MASK1 */
1173	0x00,   /* GPIO_MASK2 */
1174	0x00,   /* GPIO_STATE */
1175	0x00,   /* GPIO_STATE1 */
1176	0x00,   /* GPIO_STATE2 */
1177};
1178
1179static unsigned char fortissimo4_eeprom[] = {
1180	0x43,   /* SYSCONF: clock 512, ADC, 4DACs */
1181	0x80,   /* ACLINK: I2S */
1182	0xfc,   /* I2S: vol, 96k, 24bit, 192k */
1183	0xc1,   /* SPDIF: out-en, out-int */
1184	0xff,   /* GPIO_DIR */
1185	0xff,   /* GPIO_DIR1 */
1186	0x5f,   /* GPIO_DIR2 */
1187	0x00,   /* GPIO_MASK */
1188	0x00,   /* GPIO_MASK1 */
1189	0x00,   /* GPIO_MASK2 */
1190	0x00,   /* GPIO_STATE */
1191	0x00,   /* GPIO_STATE1 */
1192	0x00,   /* GPIO_STATE2 */
1193};
1194
1195/* entry point */
1196struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
1197	{
1198		.subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
1199		.name = "Audiotrak Prodigy 7.1 HiFi",
1200		.model = "prodigy71hifi",
1201		.chip_init = prodigy_hifi_init,
1202		.build_controls = prodigy_hifi_add_controls,
1203		.eeprom_size = sizeof(prodigy71hifi_eeprom),
1204		.eeprom_data = prodigy71hifi_eeprom,
1205		.driver = "Prodigy71HIFI",
1206	},
1207	{
1208	.subvendor = VT1724_SUBDEVICE_PRODIGY_HD2,
1209	.name = "Audiotrak Prodigy HD2",
1210	.model = "prodigyhd2",
1211	.chip_init = prodigy_hd2_init,
1212	.build_controls = prodigy_hd2_add_controls,
1213	.eeprom_size = sizeof(prodigyhd2_eeprom),
1214	.eeprom_data = prodigyhd2_eeprom,
1215	.driver = "Prodigy71HD2",
1216	},
1217	{
1218		.subvendor = VT1724_SUBDEVICE_FORTISSIMO4,
1219		.name = "Hercules Fortissimo IV",
1220		.model = "fortissimo4",
1221		.chip_init = prodigy_hifi_init,
1222		.build_controls = prodigy_hifi_add_controls,
1223		.eeprom_size = sizeof(fortissimo4_eeprom),
1224		.eeprom_data = fortissimo4_eeprom,
1225		.driver = "Fortissimo4",
1226	},
1227	{ } /* terminator */
1228};
1229
1230