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