aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712
diff options
context:
space:
mode:
authorSimone Zinanni <simone@develer.com>2005-04-11 08:08:40 -0400
committerJaroslav Kysela <perex@suse.cz>2005-05-29 03:58:58 -0400
commitaed058e8713f76be9258011238670064ea3e69a8 (patch)
tree77ba8c813b796d8ac0251858e97c96143a27f52a /sound/pci/ice1712
parentfd9a98ec0a7c8ce15928e3454d73533146d9d57c (diff)
[ALSA] Provides preliminary support for the Terratec Phase 28 card
ICE1712 driver Provides preliminary support for the Terratec Phase 28 card. Not extensively tested and probably buggy, but it seems to work. Signed-off-by: Simone Zinanni <simone@develer.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ice1712')
-rw-r--r--sound/pci/ice1712/ice1712.h5
-rw-r--r--sound/pci/ice1712/phase.c728
-rw-r--r--sound/pci/ice1712/phase.h19
3 files changed, 751 insertions, 1 deletions
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 8bb1c58c26a0..5ad4728daa7b 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,11 @@ struct _snd_ice1712 {
373 unsigned short master[2]; 373 unsigned short master[2];
374 unsigned short vol[8]; 374 unsigned short vol[8];
375 } aureon; 375 } aureon;
376 /* AC97 register cache for Phase28 */
377 struct phase28_spec {
378 unsigned short master[2];
379 unsigned short vol[8];
380 } phase28;
376 /* Hoontech-specific setting */ 381 /* Hoontech-specific setting */
377 struct hoontech_spec { 382 struct hoontech_spec {
378 unsigned char boxbits[4]; 383 unsigned char boxbits[4];
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index d1f90832443c..5bf734b04fa0 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -45,6 +45,47 @@
45#include "envy24ht.h" 45#include "envy24ht.h"
46#include "phase.h" 46#include "phase.h"
47 47
48/* WM8770 registers */
49#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
50#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
51#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
52#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
53#define WM_PHASE_SWAP 0x12 /* DAC phase */
54#define WM_DAC_CTRL1 0x13 /* DAC control bits */
55#define WM_MUTE 0x14 /* mute controls */
56#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
57#define WM_INT_CTRL 0x16 /* interface control */
58#define WM_MASTER 0x17 /* master clock and mode */
59#define WM_POWERDOWN 0x18 /* power-down controls */
60#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
61#define WM_ADC_MUX 0x1b /* input MUX */
62#define WM_OUT_MUX1 0x1c /* output MUX */
63#define WM_OUT_MUX2 0x1e /* output MUX */
64#define WM_RESET 0x1f /* software reset */
65
66
67/*
68 * Logarithmic volume values for WM8770
69 * Computed as 20 * Log10(255 / x)
70 */
71static unsigned char wm_vol[256] = {
72 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
73 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
74 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
75 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
76 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
77 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,
78 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,
79 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,
80 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,
81 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,
82 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,
83 0, 0
84};
85
86#define WM_VOL_MAX (sizeof(wm_vol) - 1)
87#define WM_VOL_MUTE 0x8000
88
48static akm4xxx_t akm_phase22 __devinitdata = { 89static akm4xxx_t akm_phase22 __devinitdata = {
49 .type = SND_AK4524, 90 .type = SND_AK4524,
50 .num_dacs = 2, 91 .num_dacs = 2,
@@ -124,6 +165,684 @@ static unsigned char phase22_eeprom[] __devinitdata = {
124 0x00, /* GPIO_STATE2 */ 165 0x00, /* GPIO_STATE2 */
125}; 166};
126 167
168static unsigned char phase28_eeprom[] __devinitdata = {
169 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
170 0x80, /* ACLINK: I2S */
171 0xfc, /* I2S: vol, 96k, 24bit, 192k */
172 0xc3, /* SPDIF: out-en, out-int, spdif-in */
173 0xff, /* GPIO_DIR */
174 0xff, /* GPIO_DIR1 */
175 0x5f, /* GPIO_DIR2 */
176 0x00, /* GPIO_MASK */
177 0x00, /* GPIO_MASK1 */
178 0x00, /* GPIO_MASK2 */
179 0x00, /* GPIO_STATE */
180 0x00, /* GPIO_STATE1 */
181 0x00, /* GPIO_STATE2 */
182};
183
184/*
185 * write data in the SPI mode
186 */
187static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
188{
189 unsigned int tmp;
190 int i;
191
192 tmp = snd_ice1712_gpio_read(ice);
193
194 snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
195 PHASE28_WM_CS));
196 tmp |= PHASE28_WM_RW;
197 tmp &= ~cs;
198 snd_ice1712_gpio_write(ice, tmp);
199 udelay(1);
200
201 for (i = bits - 1; i >= 0; i--) {
202 tmp &= ~PHASE28_SPI_CLK;
203 snd_ice1712_gpio_write(ice, tmp);
204 udelay(1);
205 if (data & (1 << i))
206 tmp |= PHASE28_SPI_MOSI;
207 else
208 tmp &= ~PHASE28_SPI_MOSI;
209 snd_ice1712_gpio_write(ice, tmp);
210 udelay(1);
211 tmp |= PHASE28_SPI_CLK;
212 snd_ice1712_gpio_write(ice, tmp);
213 udelay(1);
214 }
215
216 tmp &= ~PHASE28_SPI_CLK;
217 tmp |= cs;
218 snd_ice1712_gpio_write(ice, tmp);
219 udelay(1);
220 tmp |= PHASE28_SPI_CLK;
221 snd_ice1712_gpio_write(ice, tmp);
222 udelay(1);
223}
224
225/*
226 * get the current register value of WM codec
227 */
228static unsigned short wm_get(ice1712_t *ice, int reg)
229{
230 reg <<= 1;
231 return ((unsigned short)ice->akm[0].images[reg] << 8) |
232 ice->akm[0].images[reg + 1];
233}
234
235/*
236 * set the register value of WM codec
237 */
238static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
239{
240 phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
241}
242
243/*
244 * set the register value of WM codec and remember it
245 */
246static void wm_put(ice1712_t *ice, int reg, unsigned short val)
247{
248 wm_put_nocache(ice, reg, val);
249 reg <<= 1;
250 ice->akm[0].images[reg] = val >> 8;
251 ice->akm[0].images[reg + 1] = val;
252}
253
254static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
255{
256 unsigned char nvol;
257
258 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
259 nvol = 0;
260 else
261 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
262
263 wm_put(ice, index, nvol);
264 wm_put_nocache(ice, index, 0x180 | nvol);
265}
266
267/*
268 * DAC mute control
269 */
270#define wm_pcm_mute_info phase28_mono_bool_info
271
272static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
273{
274 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
275
276 down(&ice->gpio_mutex);
277 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
278 up(&ice->gpio_mutex);
279 return 0;
280}
281
282static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
283{
284 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
285 unsigned short nval, oval;
286 int change;
287
288 snd_ice1712_save_gpio_status(ice);
289 oval = wm_get(ice, WM_MUTE);
290 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
291 if ((change = (nval != oval)))
292 wm_put(ice, WM_MUTE, nval);
293 snd_ice1712_restore_gpio_status(ice);
294
295 return change;
296}
297
298/*
299 * Master volume attenuation mixer control
300 */
301static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
302{
303 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
304 uinfo->count = 2;
305 uinfo->value.integer.min = 0;
306 uinfo->value.integer.max = WM_VOL_MAX;
307 return 0;
308}
309
310static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
311{
312 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
313 int i;
314 for (i=0; i<2; i++)
315 ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
316 return 0;
317}
318
319static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
320{
321 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
322 int ch, change = 0;
323
324 snd_ice1712_save_gpio_status(ice);
325 for (ch = 0; ch < 2; ch++) {
326 if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
327 int dac;
328 ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
329 ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
330 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
331 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
332 ice->spec.phase28.vol[dac + ch],
333 ice->spec.phase28.master[ch]);
334 change = 1;
335 }
336 }
337 snd_ice1712_restore_gpio_status(ice);
338 return change;
339}
340
341static int __devinit phase28_init(ice1712_t *ice)
342{
343 static unsigned short wm_inits_phase28[] = {
344 /* These come first to reduce init pop noise */
345 0x1b, 0x044, /* ADC Mux (AC'97 source) */
346 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
347 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
348
349 0x18, 0x000, /* All power-up */
350
351 0x16, 0x122, /* I2S, normal polarity, 24bit */
352 0x17, 0x022, /* 256fs, slave mode */
353 0x00, 0, /* DAC1 analog mute */
354 0x01, 0, /* DAC2 analog mute */
355 0x02, 0, /* DAC3 analog mute */
356 0x03, 0, /* DAC4 analog mute */
357 0x04, 0, /* DAC5 analog mute */
358 0x05, 0, /* DAC6 analog mute */
359 0x06, 0, /* DAC7 analog mute */
360 0x07, 0, /* DAC8 analog mute */
361 0x08, 0x100, /* master analog mute */
362 0x09, 0xff, /* DAC1 digital full */
363 0x0a, 0xff, /* DAC2 digital full */
364 0x0b, 0xff, /* DAC3 digital full */
365 0x0c, 0xff, /* DAC4 digital full */
366 0x0d, 0xff, /* DAC5 digital full */
367 0x0e, 0xff, /* DAC6 digital full */
368 0x0f, 0xff, /* DAC7 digital full */
369 0x10, 0xff, /* DAC8 digital full */
370 0x11, 0x1ff, /* master digital full */
371 0x12, 0x000, /* phase normal */
372 0x13, 0x090, /* unmute DAC L/R */
373 0x14, 0x000, /* all unmute */
374 0x15, 0x000, /* no deemphasis, no ZFLG */
375 0x19, 0x000, /* -12dB ADC/L */
376 0x1a, 0x000, /* -12dB ADC/R */
377 (unsigned short)-1
378 };
379
380 unsigned int tmp;
381 akm4xxx_t *ak;
382 unsigned short *p;
383 int i;
384
385 ice->num_total_dacs = 8;
386 ice->num_total_adcs = 2;
387
388 // Initialize analog chips
389 ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
390 if (!ak)
391 return -ENOMEM;
392 ice->akm_codecs = 1;
393
394 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
395
396 /* reset the wm codec as the SPI mode */
397 snd_ice1712_save_gpio_status(ice);
398 snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
399
400 tmp = snd_ice1712_gpio_read(ice);
401 tmp &= ~PHASE28_WM_RESET;
402 snd_ice1712_gpio_write(ice, tmp);
403 udelay(1);
404 tmp |= PHASE28_WM_CS;
405 snd_ice1712_gpio_write(ice, tmp);
406 udelay(1);
407 tmp |= PHASE28_WM_RESET;
408 snd_ice1712_gpio_write(ice, tmp);
409 udelay(1);
410
411 p = wm_inits_phase28;
412 for (; *p != (unsigned short)-1; p += 2)
413 wm_put(ice, p[0], p[1]);
414
415 snd_ice1712_restore_gpio_status(ice);
416
417 ice->spec.phase28.master[0] = WM_VOL_MUTE;
418 ice->spec.phase28.master[1] = WM_VOL_MUTE;
419 for (i = 0; i < ice->num_total_dacs; i++) {
420 ice->spec.phase28.vol[i] = WM_VOL_MUTE;
421 wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]);
422 }
423
424 return 0;
425}
426
427/*
428 * DAC volume attenuation mixer control
429 */
430static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
431{
432 int voices = kcontrol->private_value >> 8;
433 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
434 uinfo->count = voices;
435 uinfo->value.integer.min = 0; /* mute (-101dB) */
436 uinfo->value.integer.max = 0x7F; /* 0dB */
437 return 0;
438}
439
440static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
441{
442 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
443 int i, ofs, voices;
444
445 voices = kcontrol->private_value >> 8;
446 ofs = kcontrol->private_value & 0xff;
447 for (i = 0; i < voices; i++)
448 ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE;
449 return 0;
450}
451
452static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
453{
454 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
455 int i, idx, ofs, voices;
456 int change = 0;
457
458 voices = kcontrol->private_value >> 8;
459 ofs = kcontrol->private_value & 0xff;
460 snd_ice1712_save_gpio_status(ice);
461 for (i = 0; i < voices; i++) {
462 idx = WM_DAC_ATTEN + ofs + i;
463 if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
464 ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
465 ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
466 wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
467 ice->spec.phase28.master[i]);
468 change = 1;
469 }
470 }
471 snd_ice1712_restore_gpio_status(ice);
472 return change;
473}
474
475/*
476 * WM8770 mute control
477 */
478static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
479 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
480 uinfo->count = kcontrol->private_value >> 8;
481 uinfo->value.integer.min = 0;
482 uinfo->value.integer.max = 1;
483 return 0;
484}
485
486static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
487{
488 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
489 int voices, ofs, i;
490
491 voices = kcontrol->private_value >> 8;
492 ofs = kcontrol->private_value & 0xFF;
493
494 for (i = 0; i < voices; i++)
495 ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
496 return 0;
497}
498
499static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
500{
501 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
502 int change = 0, voices, ofs, i;
503
504 voices = kcontrol->private_value >> 8;
505 ofs = kcontrol->private_value & 0xFF;
506
507 snd_ice1712_save_gpio_status(ice);
508 for (i = 0; i < voices; i++) {
509 int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
510 if (ucontrol->value.integer.value[i] != val) {
511 ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE;
512 ice->spec.phase28.vol[ofs + i] |=
513 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
514 wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i],
515 ice->spec.phase28.master[i]);
516 change = 1;
517 }
518 }
519 snd_ice1712_restore_gpio_status(ice);
520
521 return change;
522}
523
524/*
525 * WM8770 master mute control
526 */
527static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
528 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
529 uinfo->count = 2;
530 uinfo->value.integer.min = 0;
531 uinfo->value.integer.max = 1;
532 return 0;
533}
534
535static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
536{
537 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
538
539 ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
540 ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
541 return 0;
542}
543
544static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
545{
546 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
547 int change = 0, i;
548
549 snd_ice1712_save_gpio_status(ice);
550 for (i = 0; i < 2; i++) {
551 int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
552 if (ucontrol->value.integer.value[i] != val) {
553 int dac;
554 ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
555 ice->spec.phase28.master[i] |=
556 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
557 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
558 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
559 ice->spec.phase28.vol[dac + i],
560 ice->spec.phase28.master[i]);
561 change = 1;
562 }
563 }
564 snd_ice1712_restore_gpio_status(ice);
565
566 return change;
567}
568
569/* digital master volume */
570#define PCM_0dB 0xff
571#define PCM_RES 128 /* -64dB */
572#define PCM_MIN (PCM_0dB - PCM_RES)
573static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
574{
575 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
576 uinfo->count = 1;
577 uinfo->value.integer.min = 0; /* mute (-64dB) */
578 uinfo->value.integer.max = PCM_RES; /* 0dB */
579 return 0;
580}
581
582static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
583{
584 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
585 unsigned short val;
586
587 down(&ice->gpio_mutex);
588 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
589 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
590 ucontrol->value.integer.value[0] = val;
591 up(&ice->gpio_mutex);
592 return 0;
593}
594
595static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
596{
597 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
598 unsigned short ovol, nvol;
599 int change = 0;
600
601 snd_ice1712_save_gpio_status(ice);
602 nvol = ucontrol->value.integer.value[0];
603 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
604 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
605 if (ovol != nvol) {
606 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
607 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
608 change = 1;
609 }
610 snd_ice1712_restore_gpio_status(ice);
611 return change;
612}
613
614/*
615 */
616static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
617{
618 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
619 uinfo->count = 1;
620 uinfo->value.integer.min = 0;
621 uinfo->value.integer.max = 1;
622 return 0;
623}
624
625/*
626 * Deemphasis
627 */
628#define phase28_deemp_info phase28_mono_bool_info
629
630static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
631{
632 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
633 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
634 return 0;
635}
636
637static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
638{
639 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
640 int temp, temp2;
641 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
642 if (ucontrol->value.integer.value[0])
643 temp |= 0xf;
644 else
645 temp &= ~0xf;
646 if (temp != temp2) {
647 wm_put(ice, WM_DAC_CTRL2, temp);
648 return 1;
649 }
650 return 0;
651}
652
653/*
654 * ADC Oversampling
655 */
656static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
657{
658 static char *texts[2] = { "128x", "64x" };
659
660 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
661 uinfo->count = 1;
662 uinfo->value.enumerated.items = 2;
663
664 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
665 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
666 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
667
668 return 0;
669}
670
671static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
672{
673 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
674 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
675 return 0;
676}
677
678static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
679{
680 int temp, temp2;
681 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
682
683 temp2 = temp = wm_get(ice, WM_MASTER);
684
685 if (ucontrol->value.enumerated.item[0])
686 temp |= 0x8;
687 else
688 temp &= ~0x8;
689
690 if (temp != temp2) {
691 wm_put(ice, WM_MASTER, temp);
692 return 1;
693 }
694 return 0;
695}
696
697static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
698 {
699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
700 .name = "Master Playback Switch",
701 .info = wm_master_mute_info,
702 .get = wm_master_mute_get,
703 .put = wm_master_mute_put
704 },
705 {
706 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
707 .name = "Master Playback Volume",
708 .info = wm_master_vol_info,
709 .get = wm_master_vol_get,
710 .put = wm_master_vol_put
711 },
712 {
713 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
714 .name = "Front Playback Switch",
715 .info = wm_mute_info,
716 .get = wm_mute_get,
717 .put = wm_mute_put,
718 .private_value = (2 << 8) | 0
719 },
720 {
721 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
722 .name = "Front Playback Volume",
723 .info = wm_vol_info,
724 .get = wm_vol_get,
725 .put = wm_vol_put,
726 .private_value = (2 << 8) | 0
727 },
728 {
729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
730 .name = "Rear Playback Switch",
731 .info = wm_mute_info,
732 .get = wm_mute_get,
733 .put = wm_mute_put,
734 .private_value = (2 << 8) | 2
735 },
736 {
737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
738 .name = "Rear Playback Volume",
739 .info = wm_vol_info,
740 .get = wm_vol_get,
741 .put = wm_vol_put,
742 .private_value = (2 << 8) | 2
743 },
744 {
745 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
746 .name = "Center Playback Switch",
747 .info = wm_mute_info,
748 .get = wm_mute_get,
749 .put = wm_mute_put,
750 .private_value = (1 << 8) | 4
751 },
752 {
753 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
754 .name = "Center Playback Volume",
755 .info = wm_vol_info,
756 .get = wm_vol_get,
757 .put = wm_vol_put,
758 .private_value = (1 << 8) | 4
759 },
760 {
761 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
762 .name = "LFE Playback Switch",
763 .info = wm_mute_info,
764 .get = wm_mute_get,
765 .put = wm_mute_put,
766 .private_value = (1 << 8) | 5
767 },
768 {
769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
770 .name = "LFE Playback Volume",
771 .info = wm_vol_info,
772 .get = wm_vol_get,
773 .put = wm_vol_put,
774 .private_value = (1 << 8) | 5
775 },
776 {
777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
778 .name = "Side Playback Switch",
779 .info = wm_mute_info,
780 .get = wm_mute_get,
781 .put = wm_mute_put,
782 .private_value = (2 << 8) | 6
783 },
784 {
785 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
786 .name = "Side Playback Volume",
787 .info = wm_vol_info,
788 .get = wm_vol_get,
789 .put = wm_vol_put,
790 .private_value = (2 << 8) | 6
791 }
792};
793
794static snd_kcontrol_new_t wm_controls[] __devinitdata = {
795 {
796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
797 .name = "PCM Playback Switch",
798 .info = wm_pcm_mute_info,
799 .get = wm_pcm_mute_get,
800 .put = wm_pcm_mute_put
801 },
802 {
803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
804 .name = "PCM Playback Volume",
805 .info = wm_pcm_vol_info,
806 .get = wm_pcm_vol_get,
807 .put = wm_pcm_vol_put
808 },
809 {
810 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
811 .name = "DAC Deemphasis Switch",
812 .info = phase28_deemp_info,
813 .get = phase28_deemp_get,
814 .put = phase28_deemp_put
815 },
816 {
817 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
818 .name = "ADC Oversampling",
819 .info = phase28_oversampling_info,
820 .get = phase28_oversampling_get,
821 .put = phase28_oversampling_put
822 }
823};
824
825static int __devinit phase28_add_controls(ice1712_t *ice)
826{
827 unsigned int i, counts;
828 int err;
829
830 counts = ARRAY_SIZE(phase28_dac_controls);
831 for (i = 0; i < counts; i++) {
832 err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
833 if (err < 0)
834 return err;
835 }
836
837 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
838 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
839 if (err < 0)
840 return err;
841 }
842
843 return 0;
844}
845
127struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { 846struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
128 { 847 {
129 .subvendor = VT1724_SUBDEVICE_PHASE22, 848 .subvendor = VT1724_SUBDEVICE_PHASE22,
@@ -134,5 +853,14 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
134 .eeprom_size = sizeof(phase22_eeprom), 853 .eeprom_size = sizeof(phase22_eeprom),
135 .eeprom_data = phase22_eeprom, 854 .eeprom_data = phase22_eeprom,
136 }, 855 },
856 {
857 .subvendor = VT1724_SUBDEVICE_PHASE28,
858 .name = "Terratec PHASE 28",
859 .model = "phase28",
860 .chip_init = phase28_init,
861 .build_controls = phase28_add_controls,
862 .eeprom_size = sizeof(phase28_eeprom),
863 .eeprom_data = phase28_eeprom,
864 },
137 { } /* terminator */ 865 { } /* terminator */
138}; 866};
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index 6230cf16989f..13e841b55488 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -24,11 +24,28 @@
24 * 24 *
25 */ 25 */
26 26
27#define PHASE_DEVICE_DESC "{Terratec,Phase 22}," 27#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\
28 "{Terratec,Phase 28},"
28 29
29#define VT1724_SUBDEVICE_PHASE22 0x3b155011 30#define VT1724_SUBDEVICE_PHASE22 0x3b155011
31#define VT1724_SUBDEVICE_PHASE28 0x3b154911
30 32
31/* entry point */ 33/* entry point */
32extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; 34extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
33 35
36/* PHASE28 GPIO bits */
37#define PHASE28_SPI_MISO (1 << 21)
38#define PHASE28_WM_RESET (1 << 20)
39#define PHASE28_SPI_CLK (1 << 19)
40#define PHASE28_SPI_MOSI (1 << 18)
41#define PHASE28_WM_RW (1 << 17)
42#define PHASE28_AC97_RESET (1 << 16)
43#define PHASE28_DIGITAL_SEL1 (1 << 15)
44#define PHASE28_HP_SEL (1 << 14)
45#define PHASE28_WM_CS (1 << 12)
46#define PHASE28_AC97_COMMIT (1 << 11)
47#define PHASE28_AC97_ADDR (1 << 10)
48#define PHASE28_AC97_DATA_LOW (1 << 9)
49#define PHASE28_AC97_DATA_HIGH (1 << 8)
50#define PHASE28_AC97_DATA_MASK 0xFF
34#endif /* __SOUND_PHASE */ 51#endif /* __SOUND_PHASE */