diff options
Diffstat (limited to 'sound/pci/ice1712/phase.c')
-rw-r--r-- | sound/pci/ice1712/phase.c | 728 |
1 files changed, 728 insertions, 0 deletions
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 | */ | ||
71 | static 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 | |||
48 | static akm4xxx_t akm_phase22 __devinitdata = { | 89 | static 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 | ||
168 | static 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 | */ | ||
187 | static 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 | */ | ||
228 | static 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 | */ | ||
238 | static 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 | */ | ||
246 | static 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 | |||
254 | static 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 | |||
272 | static 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 | |||
282 | static 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 | */ | ||
301 | static 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 | |||
310 | static 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 | |||
319 | static 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 | |||
341 | static 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 | */ | ||
430 | static 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 | |||
440 | static 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 | |||
452 | static 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 | */ | ||
478 | static 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 | |||
486 | static 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 | |||
499 | static 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 | */ | ||
527 | static 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 | |||
535 | static 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 | |||
544 | static 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) | ||
573 | static 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 | |||
582 | static 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 | |||
595 | static 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 | */ | ||
616 | static 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 | |||
630 | static 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 | |||
637 | static 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 | */ | ||
656 | static 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 | |||
671 | static 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 | |||
678 | static 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 | |||
697 | static 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 | |||
794 | static 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 | |||
825 | static 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 | |||
127 | struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { | 846 | struct 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 | }; |