~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/ice1712/phase.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  *   ALSA driver for ICEnsemble ICE1724 (Envy24)
  4  *
  5  *   Lowlevel functions for Terratec PHASE 22
  6  *
  7  *      Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
  8  */
  9 
 10 /* PHASE 22 overview:
 11  *   Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out)
 12  *   Analog chip: AK4524 (partially via Philip's 74HCT125)
 13  *   Digital receiver: CS8414-CS (supported in this release)
 14  *              PHASE 22 revision 2.0 and Terrasoniq/Musonik TS22PCI have CS8416
 15  *              (support status unknown, please test and report)
 16  *
 17  *   Envy connects to AK4524
 18  *      - CS directly from GPIO 10
 19  *      - CCLK via 74HCT125's gate #4 from GPIO 4
 20  *      - CDTI via 74HCT125's gate #2 from GPIO 5
 21  *              CDTI may be completely blocked by 74HCT125's gate #1
 22  *              controlled by GPIO 3
 23  */
 24 
 25 /* PHASE 28 overview:
 26  *   Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
 27  *   Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
 28  *   Digital receiver: CS8414-CS (supported in this release)
 29  */
 30 
 31 #include <linux/delay.h>
 32 #include <linux/interrupt.h>
 33 #include <linux/init.h>
 34 #include <linux/slab.h>
 35 #include <linux/mutex.h>
 36 
 37 #include <sound/core.h>
 38 
 39 #include "ice1712.h"
 40 #include "envy24ht.h"
 41 #include "phase.h"
 42 #include <sound/tlv.h>
 43 
 44 /* AC97 register cache for Phase28 */
 45 struct phase28_spec {
 46         unsigned short master[2];
 47         unsigned short vol[8];
 48 };
 49 
 50 /* WM8770 registers */
 51 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
 52 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
 53 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
 54 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
 55 #define WM_PHASE_SWAP           0x12    /* DAC phase */
 56 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
 57 #define WM_MUTE                 0x14    /* mute controls */
 58 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
 59 #define WM_INT_CTRL             0x16    /* interface control */
 60 #define WM_MASTER               0x17    /* master clock and mode */
 61 #define WM_POWERDOWN            0x18    /* power-down controls */
 62 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
 63 #define WM_ADC_MUX              0x1b    /* input MUX */
 64 #define WM_OUT_MUX1             0x1c    /* output MUX */
 65 #define WM_OUT_MUX2             0x1e    /* output MUX */
 66 #define WM_RESET                0x1f    /* software reset */
 67 
 68 
 69 /*
 70  * Logarithmic volume values for WM8770
 71  * Computed as 20 * Log10(255 / x)
 72  */
 73 static const unsigned char wm_vol[256] = {
 74         127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24,
 75         24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18,
 76         17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14,
 77         14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
 78         11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9,
 79         9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
 80         7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
 81         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 82         4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 83         3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 84         2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 85         1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 86 };
 87 
 88 #define WM_VOL_MAX      (sizeof(wm_vol) - 1)
 89 #define WM_VOL_MUTE     0x8000
 90 
 91 static const struct snd_akm4xxx akm_phase22 = {
 92         .type = SND_AK4524,
 93         .num_dacs = 2,
 94         .num_adcs = 2,
 95 };
 96 
 97 static const struct snd_ak4xxx_private akm_phase22_priv = {
 98         .caddr =        2,
 99         .cif =          1,
100         .data_mask =    1 << 4,
101         .clk_mask =     1 << 5,
102         .cs_mask =      1 << 10,
103         .cs_addr =      1 << 10,
104         .cs_none =      0,
105         .add_flags =    1 << 3,
106         .mask_flags =   0,
107 };
108 
109 static int phase22_init(struct snd_ice1712 *ice)
110 {
111         struct snd_akm4xxx *ak;
112         int err;
113 
114         /* Configure DAC/ADC description for generic part of ice1724 */
115         switch (ice->eeprom.subvendor) {
116         case VT1724_SUBDEVICE_PHASE22:
117         case VT1724_SUBDEVICE_TS22:
118                 ice->num_total_dacs = 2;
119                 ice->num_total_adcs = 2;
120                 ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
121                 break;
122         default:
123                 snd_BUG();
124                 return -EINVAL;
125         }
126 
127         /* Initialize analog chips */
128         ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
129         ak = ice->akm;
130         if (!ak)
131                 return -ENOMEM;
132         ice->akm_codecs = 1;
133         switch (ice->eeprom.subvendor) {
134         case VT1724_SUBDEVICE_PHASE22:
135         case VT1724_SUBDEVICE_TS22:
136                 err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
137                                                 &akm_phase22_priv, ice);
138                 if (err < 0)
139                         return err;
140                 break;
141         }
142 
143         return 0;
144 }
145 
146 static int phase22_add_controls(struct snd_ice1712 *ice)
147 {
148         int err = 0;
149 
150         switch (ice->eeprom.subvendor) {
151         case VT1724_SUBDEVICE_PHASE22:
152         case VT1724_SUBDEVICE_TS22:
153                 err = snd_ice1712_akm4xxx_build_controls(ice);
154                 if (err < 0)
155                         return err;
156         }
157         return 0;
158 }
159 
160 static const unsigned char phase22_eeprom[] = {
161         [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
162                                         spdif-in/1xADC, 1xDACs */
163         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
164         [ICE_EEP2_I2S]         = 0xf0,  /* vol, 96k, 24bit */
165         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
166         [ICE_EEP2_GPIO_DIR]    = 0xff,
167         [ICE_EEP2_GPIO_DIR1]   = 0xff,
168         [ICE_EEP2_GPIO_DIR2]   = 0xff,
169         [ICE_EEP2_GPIO_MASK]   = 0x00,
170         [ICE_EEP2_GPIO_MASK1]  = 0x00,
171         [ICE_EEP2_GPIO_MASK2]  = 0x00,
172         [ICE_EEP2_GPIO_STATE]  = 0x00,
173         [ICE_EEP2_GPIO_STATE1] = 0x00,
174         [ICE_EEP2_GPIO_STATE2] = 0x00,
175 };
176 
177 static const unsigned char phase28_eeprom[] = {
178         [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
179                                         spdif-in/1xADC, 4xDACs */
180         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
181         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
182         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
183         [ICE_EEP2_GPIO_DIR]    = 0xff,
184         [ICE_EEP2_GPIO_DIR1]   = 0xff,
185         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
186         [ICE_EEP2_GPIO_MASK]   = 0x00,
187         [ICE_EEP2_GPIO_MASK1]  = 0x00,
188         [ICE_EEP2_GPIO_MASK2]  = 0x00,
189         [ICE_EEP2_GPIO_STATE]  = 0x00,
190         [ICE_EEP2_GPIO_STATE1] = 0x00,
191         [ICE_EEP2_GPIO_STATE2] = 0x00,
192 };
193 
194 /*
195  * write data in the SPI mode
196  */
197 static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
198                                 unsigned int data, int bits)
199 {
200         unsigned int tmp;
201         int i;
202 
203         tmp = snd_ice1712_gpio_read(ice);
204 
205         snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
206                                         PHASE28_SPI_CLK|PHASE28_WM_CS));
207         tmp |= PHASE28_WM_RW;
208         tmp &= ~cs;
209         snd_ice1712_gpio_write(ice, tmp);
210         udelay(1);
211 
212         for (i = bits - 1; i >= 0; i--) {
213                 tmp &= ~PHASE28_SPI_CLK;
214                 snd_ice1712_gpio_write(ice, tmp);
215                 udelay(1);
216                 if (data & (1 << i))
217                         tmp |= PHASE28_SPI_MOSI;
218                 else
219                         tmp &= ~PHASE28_SPI_MOSI;
220                 snd_ice1712_gpio_write(ice, tmp);
221                 udelay(1);
222                 tmp |= PHASE28_SPI_CLK;
223                 snd_ice1712_gpio_write(ice, tmp);
224                 udelay(1);
225         }
226 
227         tmp &= ~PHASE28_SPI_CLK;
228         tmp |= cs;
229         snd_ice1712_gpio_write(ice, tmp);
230         udelay(1);
231         tmp |= PHASE28_SPI_CLK;
232         snd_ice1712_gpio_write(ice, tmp);
233         udelay(1);
234 }
235 
236 /*
237  * get the current register value of WM codec
238  */
239 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
240 {
241         reg <<= 1;
242         return ((unsigned short)ice->akm[0].images[reg] << 8) |
243                 ice->akm[0].images[reg + 1];
244 }
245 
246 /*
247  * set the register value of WM codec
248  */
249 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
250 {
251         phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
252 }
253 
254 /*
255  * set the register value of WM codec and remember it
256  */
257 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
258 {
259         wm_put_nocache(ice, reg, val);
260         reg <<= 1;
261         ice->akm[0].images[reg] = val >> 8;
262         ice->akm[0].images[reg + 1] = val;
263 }
264 
265 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
266                         unsigned short vol, unsigned short master)
267 {
268         unsigned char nvol;
269 
270         if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
271                 nvol = 0;
272         else
273                 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
274                         (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
275 
276         wm_put(ice, index, nvol);
277         wm_put_nocache(ice, index, 0x180 | nvol);
278 }
279 
280 /*
281  * DAC mute control
282  */
283 #define wm_pcm_mute_info        snd_ctl_boolean_mono_info
284 
285 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
286                                 struct snd_ctl_elem_value *ucontrol)
287 {
288         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
289 
290         mutex_lock(&ice->gpio_mutex);
291         ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
292                                                 0 : 1;
293         mutex_unlock(&ice->gpio_mutex);
294         return 0;
295 }
296 
297 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
298                                 struct snd_ctl_elem_value *ucontrol)
299 {
300         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
301         unsigned short nval, oval;
302         int change;
303 
304         snd_ice1712_save_gpio_status(ice);
305         oval = wm_get(ice, WM_MUTE);
306         nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
307         change = (nval != oval);
308         if (change)
309                 wm_put(ice, WM_MUTE, nval);
310         snd_ice1712_restore_gpio_status(ice);
311 
312         return change;
313 }
314 
315 /*
316  * Master volume attenuation mixer control
317  */
318 static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
319                                 struct snd_ctl_elem_info *uinfo)
320 {
321         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
322         uinfo->count = 2;
323         uinfo->value.integer.min = 0;
324         uinfo->value.integer.max = WM_VOL_MAX;
325         return 0;
326 }
327 
328 static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
329                                 struct snd_ctl_elem_value *ucontrol)
330 {
331         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
332         struct phase28_spec *spec = ice->spec;
333         int i;
334         for (i = 0; i < 2; i++)
335                 ucontrol->value.integer.value[i] = spec->master[i] &
336                                                         ~WM_VOL_MUTE;
337         return 0;
338 }
339 
340 static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
341                                 struct snd_ctl_elem_value *ucontrol)
342 {
343         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
344         struct phase28_spec *spec = ice->spec;
345         int ch, change = 0;
346 
347         snd_ice1712_save_gpio_status(ice);
348         for (ch = 0; ch < 2; ch++) {
349                 unsigned int vol = ucontrol->value.integer.value[ch];
350                 if (vol > WM_VOL_MAX)
351                         continue;
352                 vol |= spec->master[ch] & WM_VOL_MUTE;
353                 if (vol != spec->master[ch]) {
354                         int dac;
355                         spec->master[ch] = vol;
356                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
357                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
358                                            spec->vol[dac + ch],
359                                            spec->master[ch]);
360                         change = 1;
361                 }
362         }
363         snd_ice1712_restore_gpio_status(ice);
364         return change;
365 }
366 
367 static int phase28_init(struct snd_ice1712 *ice)
368 {
369         static const unsigned short wm_inits_phase28[] = {
370                 /* These come first to reduce init pop noise */
371                 0x1b, 0x044,    /* ADC Mux (AC'97 source) */
372                 0x1c, 0x00B,    /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
373                 0x1d, 0x009,    /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
374 
375                 0x18, 0x000,    /* All power-up */
376 
377                 0x16, 0x122,    /* I2S, normal polarity, 24bit */
378                 0x17, 0x022,    /* 256fs, slave mode */
379                 0x00, 0,        /* DAC1 analog mute */
380                 0x01, 0,        /* DAC2 analog mute */
381                 0x02, 0,        /* DAC3 analog mute */
382                 0x03, 0,        /* DAC4 analog mute */
383                 0x04, 0,        /* DAC5 analog mute */
384                 0x05, 0,        /* DAC6 analog mute */
385                 0x06, 0,        /* DAC7 analog mute */
386                 0x07, 0,        /* DAC8 analog mute */
387                 0x08, 0x100,    /* master analog mute */
388                 0x09, 0xff,     /* DAC1 digital full */
389                 0x0a, 0xff,     /* DAC2 digital full */
390                 0x0b, 0xff,     /* DAC3 digital full */
391                 0x0c, 0xff,     /* DAC4 digital full */
392                 0x0d, 0xff,     /* DAC5 digital full */
393                 0x0e, 0xff,     /* DAC6 digital full */
394                 0x0f, 0xff,     /* DAC7 digital full */
395                 0x10, 0xff,     /* DAC8 digital full */
396                 0x11, 0x1ff,    /* master digital full */
397                 0x12, 0x000,    /* phase normal */
398                 0x13, 0x090,    /* unmute DAC L/R */
399                 0x14, 0x000,    /* all unmute */
400                 0x15, 0x000,    /* no deemphasis, no ZFLG */
401                 0x19, 0x000,    /* -12dB ADC/L */
402                 0x1a, 0x000,    /* -12dB ADC/R */
403                 (unsigned short)-1
404         };
405 
406         unsigned int tmp;
407         struct snd_akm4xxx *ak;
408         struct phase28_spec *spec;
409         const unsigned short *p;
410         int i;
411 
412         ice->num_total_dacs = 8;
413         ice->num_total_adcs = 2;
414 
415         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
416         if (!spec)
417                 return -ENOMEM;
418         ice->spec = spec;
419 
420         /* Initialize analog chips */
421         ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
422         ak = ice->akm;
423         if (!ak)
424                 return -ENOMEM;
425         ice->akm_codecs = 1;
426 
427         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
428 
429         /* reset the wm codec as the SPI mode */
430         snd_ice1712_save_gpio_status(ice);
431         snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
432                                         PHASE28_HP_SEL));
433 
434         tmp = snd_ice1712_gpio_read(ice);
435         tmp &= ~PHASE28_WM_RESET;
436         snd_ice1712_gpio_write(ice, tmp);
437         udelay(1);
438         tmp |= PHASE28_WM_CS;
439         snd_ice1712_gpio_write(ice, tmp);
440         udelay(1);
441         tmp |= PHASE28_WM_RESET;
442         snd_ice1712_gpio_write(ice, tmp);
443         udelay(1);
444 
445         p = wm_inits_phase28;
446         for (; *p != (unsigned short)-1; p += 2)
447                 wm_put(ice, p[0], p[1]);
448 
449         snd_ice1712_restore_gpio_status(ice);
450 
451         spec->master[0] = WM_VOL_MUTE;
452         spec->master[1] = WM_VOL_MUTE;
453         for (i = 0; i < ice->num_total_dacs; i++) {
454                 spec->vol[i] = WM_VOL_MUTE;
455                 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
456         }
457 
458         return 0;
459 }
460 
461 /*
462  * DAC volume attenuation mixer control
463  */
464 static int wm_vol_info(struct snd_kcontrol *kcontrol,
465                         struct snd_ctl_elem_info *uinfo)
466 {
467         int voices = kcontrol->private_value >> 8;
468         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
469         uinfo->count = voices;
470         uinfo->value.integer.min = 0;           /* mute (-101dB) */
471         uinfo->value.integer.max = 0x7F;        /* 0dB */
472         return 0;
473 }
474 
475 static int wm_vol_get(struct snd_kcontrol *kcontrol,
476                         struct snd_ctl_elem_value *ucontrol)
477 {
478         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
479         struct phase28_spec *spec = ice->spec;
480         int i, ofs, voices;
481 
482         voices = kcontrol->private_value >> 8;
483         ofs = kcontrol->private_value & 0xff;
484         for (i = 0; i < voices; i++)
485                 ucontrol->value.integer.value[i] =
486                         spec->vol[ofs+i] & ~WM_VOL_MUTE;
487         return 0;
488 }
489 
490 static int wm_vol_put(struct snd_kcontrol *kcontrol,
491                         struct snd_ctl_elem_value *ucontrol)
492 {
493         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
494         struct phase28_spec *spec = ice->spec;
495         int i, idx, ofs, voices;
496         int change = 0;
497 
498         voices = kcontrol->private_value >> 8;
499         ofs = kcontrol->private_value & 0xff;
500         snd_ice1712_save_gpio_status(ice);
501         for (i = 0; i < voices; i++) {
502                 unsigned int vol;
503                 vol = ucontrol->value.integer.value[i];
504                 if (vol > 0x7f)
505                         continue;
506                 vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
507                 if (vol != spec->vol[ofs+i]) {
508                         spec->vol[ofs+i] = vol;
509                         idx  = WM_DAC_ATTEN + ofs + i;
510                         wm_set_vol(ice, idx, spec->vol[ofs+i],
511                                    spec->master[i]);
512                         change = 1;
513                 }
514         }
515         snd_ice1712_restore_gpio_status(ice);
516         return change;
517 }
518 
519 /*
520  * WM8770 mute control
521  */
522 static int wm_mute_info(struct snd_kcontrol *kcontrol,
523                         struct snd_ctl_elem_info *uinfo) {
524         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
525         uinfo->count = kcontrol->private_value >> 8;
526         uinfo->value.integer.min = 0;
527         uinfo->value.integer.max = 1;
528         return 0;
529 }
530 
531 static int wm_mute_get(struct snd_kcontrol *kcontrol,
532                         struct snd_ctl_elem_value *ucontrol)
533 {
534         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
535         struct phase28_spec *spec = ice->spec;
536         int voices, ofs, i;
537 
538         voices = kcontrol->private_value >> 8;
539         ofs = kcontrol->private_value & 0xFF;
540 
541         for (i = 0; i < voices; i++)
542                 ucontrol->value.integer.value[i] =
543                         (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
544         return 0;
545 }
546 
547 static int wm_mute_put(struct snd_kcontrol *kcontrol,
548                         struct snd_ctl_elem_value *ucontrol)
549 {
550         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
551         struct phase28_spec *spec = ice->spec;
552         int change = 0, voices, ofs, i;
553 
554         voices = kcontrol->private_value >> 8;
555         ofs = kcontrol->private_value & 0xFF;
556 
557         snd_ice1712_save_gpio_status(ice);
558         for (i = 0; i < voices; i++) {
559                 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
560                 if (ucontrol->value.integer.value[i] != val) {
561                         spec->vol[ofs + i] &= ~WM_VOL_MUTE;
562                         spec->vol[ofs + i] |=
563                                 ucontrol->value.integer.value[i] ? 0 :
564                                 WM_VOL_MUTE;
565                         wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
566                                         spec->master[i]);
567                         change = 1;
568                 }
569         }
570         snd_ice1712_restore_gpio_status(ice);
571 
572         return change;
573 }
574 
575 /*
576  * WM8770 master mute control
577  */
578 #define wm_master_mute_info             snd_ctl_boolean_stereo_info
579 
580 static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
581                                 struct snd_ctl_elem_value *ucontrol)
582 {
583         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
584         struct phase28_spec *spec = ice->spec;
585 
586         ucontrol->value.integer.value[0] =
587                 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
588         ucontrol->value.integer.value[1] =
589                 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
590         return 0;
591 }
592 
593 static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
594                                 struct snd_ctl_elem_value *ucontrol)
595 {
596         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
597         struct phase28_spec *spec = ice->spec;
598         int change = 0, i;
599 
600         snd_ice1712_save_gpio_status(ice);
601         for (i = 0; i < 2; i++) {
602                 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
603                 if (ucontrol->value.integer.value[i] != val) {
604                         int dac;
605                         spec->master[i] &= ~WM_VOL_MUTE;
606                         spec->master[i] |=
607                                 ucontrol->value.integer.value[i] ? 0 :
608                                 WM_VOL_MUTE;
609                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
610                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
611                                                 spec->vol[dac + i],
612                                                 spec->master[i]);
613                         change = 1;
614                 }
615         }
616         snd_ice1712_restore_gpio_status(ice);
617 
618         return change;
619 }
620 
621 /* digital master volume */
622 #define PCM_0dB 0xff
623 #define PCM_RES 128     /* -64dB */
624 #define PCM_MIN (PCM_0dB - PCM_RES)
625 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
626                                 struct snd_ctl_elem_info *uinfo)
627 {
628         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
629         uinfo->count = 1;
630         uinfo->value.integer.min = 0;           /* mute (-64dB) */
631         uinfo->value.integer.max = PCM_RES;     /* 0dB */
632         return 0;
633 }
634 
635 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
636                                 struct snd_ctl_elem_value *ucontrol)
637 {
638         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
639         unsigned short val;
640 
641         mutex_lock(&ice->gpio_mutex);
642         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
643         val = val > PCM_MIN ? (val - PCM_MIN) : 0;
644         ucontrol->value.integer.value[0] = val;
645         mutex_unlock(&ice->gpio_mutex);
646         return 0;
647 }
648 
649 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
650                                 struct snd_ctl_elem_value *ucontrol)
651 {
652         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
653         unsigned short ovol, nvol;
654         int change = 0;
655 
656         nvol = ucontrol->value.integer.value[0];
657         if (nvol > PCM_RES)
658                 return -EINVAL;
659         snd_ice1712_save_gpio_status(ice);
660         nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
661         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
662         if (ovol != nvol) {
663                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
664                 /* update */
665                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
666                 change = 1;
667         }
668         snd_ice1712_restore_gpio_status(ice);
669         return change;
670 }
671 
672 /*
673  * Deemphasis
674  */
675 #define phase28_deemp_info      snd_ctl_boolean_mono_info
676 
677 static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
678                                 struct snd_ctl_elem_value *ucontrol)
679 {
680         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
681         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
682                                                 0xf;
683         return 0;
684 }
685 
686 static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
687                                 struct snd_ctl_elem_value *ucontrol)
688 {
689         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
690         int temp, temp2;
691         temp = wm_get(ice, WM_DAC_CTRL2);
692         temp2 = temp;
693         if (ucontrol->value.integer.value[0])
694                 temp |= 0xf;
695         else
696                 temp &= ~0xf;
697         if (temp != temp2) {
698                 wm_put(ice, WM_DAC_CTRL2, temp);
699                 return 1;
700         }
701         return 0;
702 }
703 
704 /*
705  * ADC Oversampling
706  */
707 static int phase28_oversampling_info(struct snd_kcontrol *k,
708                                         struct snd_ctl_elem_info *uinfo)
709 {
710         static const char * const texts[2] = { "128x", "64x"    };
711 
712         return snd_ctl_enum_info(uinfo, 1, 2, texts);
713 }
714 
715 static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
716                                         struct snd_ctl_elem_value *ucontrol)
717 {
718         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
719         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
720                                                 0x8;
721         return 0;
722 }
723 
724 static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
725                                         struct snd_ctl_elem_value *ucontrol)
726 {
727         int temp, temp2;
728         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
729 
730         temp = wm_get(ice, WM_MASTER);
731         temp2 = temp;
732 
733         if (ucontrol->value.enumerated.item[0])
734                 temp |= 0x8;
735         else
736                 temp &= ~0x8;
737 
738         if (temp != temp2) {
739                 wm_put(ice, WM_MASTER, temp);
740                 return 1;
741         }
742         return 0;
743 }
744 
745 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
746 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
747 
748 static const struct snd_kcontrol_new phase28_dac_controls[] = {
749         {
750                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
751                 .name = "Master Playback Switch",
752                 .info = wm_master_mute_info,
753                 .get = wm_master_mute_get,
754                 .put = wm_master_mute_put
755         },
756         {
757                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
758                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
759                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
760                 .name = "Master Playback Volume",
761                 .info = wm_master_vol_info,
762                 .get = wm_master_vol_get,
763                 .put = wm_master_vol_put,
764                 .tlv = { .p = db_scale_wm_dac }
765         },
766         {
767                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
768                 .name = "Front Playback Switch",
769                 .info = wm_mute_info,
770                 .get = wm_mute_get,
771                 .put = wm_mute_put,
772                 .private_value = (2 << 8) | 0
773         },
774         {
775                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
776                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
777                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
778                 .name = "Front Playback Volume",
779                 .info = wm_vol_info,
780                 .get = wm_vol_get,
781                 .put = wm_vol_put,
782                 .private_value = (2 << 8) | 0,
783                 .tlv = { .p = db_scale_wm_dac }
784         },
785         {
786                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
787                 .name = "Rear Playback Switch",
788                 .info = wm_mute_info,
789                 .get = wm_mute_get,
790                 .put = wm_mute_put,
791                 .private_value = (2 << 8) | 2
792         },
793         {
794                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
795                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
796                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
797                 .name = "Rear Playback Volume",
798                 .info = wm_vol_info,
799                 .get = wm_vol_get,
800                 .put = wm_vol_put,
801                 .private_value = (2 << 8) | 2,
802                 .tlv = { .p = db_scale_wm_dac }
803         },
804         {
805                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
806                 .name = "Center Playback Switch",
807                 .info = wm_mute_info,
808                 .get = wm_mute_get,
809                 .put = wm_mute_put,
810                 .private_value = (1 << 8) | 4
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 = wm_vol_info,
818                 .get = wm_vol_get,
819                 .put = wm_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                 .name = "LFE Playback Switch",
826                 .info = wm_mute_info,
827                 .get = wm_mute_get,
828                 .put = wm_mute_put,
829                 .private_value = (1 << 8) | 5
830         },
831         {
832                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
833                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
834                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
835                 .name = "LFE Playback Volume",
836                 .info = wm_vol_info,
837                 .get = wm_vol_get,
838                 .put = wm_vol_put,
839                 .private_value = (1 << 8) | 5,
840                 .tlv = { .p = db_scale_wm_dac }
841         },
842         {
843                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
844                 .name = "Side Playback Switch",
845                 .info = wm_mute_info,
846                 .get = wm_mute_get,
847                 .put = wm_mute_put,
848                 .private_value = (2 << 8) | 6
849         },
850         {
851                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
852                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
853                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
854                 .name = "Side Playback Volume",
855                 .info = wm_vol_info,
856                 .get = wm_vol_get,
857                 .put = wm_vol_put,
858                 .private_value = (2 << 8) | 6,
859                 .tlv = { .p = db_scale_wm_dac }
860         }
861 };
862 
863 static const struct snd_kcontrol_new wm_controls[] = {
864         {
865                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
866                 .name = "PCM Playback Switch",
867                 .info = wm_pcm_mute_info,
868                 .get = wm_pcm_mute_get,
869                 .put = wm_pcm_mute_put
870         },
871         {
872                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
873                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
874                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
875                 .name = "PCM Playback Volume",
876                 .info = wm_pcm_vol_info,
877                 .get = wm_pcm_vol_get,
878                 .put = wm_pcm_vol_put,
879                 .tlv = { .p = db_scale_wm_pcm }
880         },
881         {
882                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
883                 .name = "DAC Deemphasis Switch",
884                 .info = phase28_deemp_info,
885                 .get = phase28_deemp_get,
886                 .put = phase28_deemp_put
887         },
888         {
889                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
890                 .name = "ADC Oversampling",
891                 .info = phase28_oversampling_info,
892                 .get = phase28_oversampling_get,
893                 .put = phase28_oversampling_put
894         }
895 };
896 
897 static int phase28_add_controls(struct snd_ice1712 *ice)
898 {
899         unsigned int i, counts;
900         int err;
901 
902         counts = ARRAY_SIZE(phase28_dac_controls);
903         for (i = 0; i < counts; i++) {
904                 err = snd_ctl_add(ice->card,
905                                         snd_ctl_new1(&phase28_dac_controls[i],
906                                                         ice));
907                 if (err < 0)
908                         return err;
909         }
910 
911         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
912                 err = snd_ctl_add(ice->card,
913                                         snd_ctl_new1(&wm_controls[i], ice));
914                 if (err < 0)
915                         return err;
916         }
917 
918         return 0;
919 }
920 
921 struct snd_ice1712_card_info snd_vt1724_phase_cards[] = {
922         {
923                 .subvendor = VT1724_SUBDEVICE_PHASE22,
924                 .name = "Terratec PHASE 22",
925                 .model = "phase22",
926                 .chip_init = phase22_init,
927                 .build_controls = phase22_add_controls,
928                 .eeprom_size = sizeof(phase22_eeprom),
929                 .eeprom_data = phase22_eeprom,
930         },
931         {
932                 .subvendor = VT1724_SUBDEVICE_PHASE28,
933                 .name = "Terratec PHASE 28",
934                 .model = "phase28",
935                 .chip_init = phase28_init,
936                 .build_controls = phase28_add_controls,
937                 .eeprom_size = sizeof(phase28_eeprom),
938                 .eeprom_data = phase28_eeprom,
939         },
940         {
941                 .subvendor = VT1724_SUBDEVICE_TS22,
942                 .name = "Terrasoniq TS22 PCI",
943                 .model = "TS22",
944                 .chip_init = phase22_init,
945                 .build_controls = phase22_add_controls,
946                 .eeprom_size = sizeof(phase22_eeprom),
947                 .eeprom_data = phase22_eeprom,
948         },
949         { } /* terminator */
950 };
951 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php