Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
prodigy192.c
Go to the documentation of this file.
1 /*
2  * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  * Lowlevel functions for AudioTrak Prodigy 192 cards
5  * Supported IEC958 input from optional MI/ODI/O add-on card.
6  *
7  * Specifics (SW, HW):
8  * -------------------
9  * * 49.5MHz crystal
10  * * SPDIF-OUT on the card:
11  * - coax (through isolation transformer)/toslink supplied by
12  * 74HC04 gates - 3 in parallel
13  * - output switched between on-board CD drive dig-out connector
14  * and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled
15  * by GPIO20 (0 = CD dig-out, 1 = SPDTX)
16  * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax
17  *
18  * * MI/ODI/O card: AK4114 based, used for iec958 input only
19  * - toslink input -> RX0
20  * - coax input -> RX1
21  * - 4wire protocol:
22  * AK4114 ICE1724
23  * ------------------------------
24  * CDTO (pin 32) -- GPIO11 pin 86
25  * CDTI (pin 33) -- GPIO10 pin 77
26  * CCLK (pin 34) -- GPIO9 pin 76
27  * CSN (pin 35) -- GPIO8 pin 75
28  * - output data Mode 7 (24bit, I2S, slave)
29  * - both MCKO1 and MCKO2 of ak4114 are fed to FPGA, which
30  * outputs master clock to SPMCLKIN of ice1724.
31  * Experimentally I found out that only a combination of
32  * OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 -
33  * VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct
34  * sampling rate. That means the the FPGA doubles the
35  * MCK01 rate.
36  *
37  * Copyright (c) 2003 Takashi Iwai <[email protected]>
38  * Copyright (c) 2003 Dimitromanolakis Apostolos <[email protected]>
39  * Copyright (c) 2004 Kouichi ONO <[email protected]>
40  *
41  * This program is free software; you can redistribute it and/or modify
42  * it under the terms of the GNU General Public License as published by
43  * the Free Software Foundation; either version 2 of the License, or
44  * (at your option) any later version.
45  *
46  * This program is distributed in the hope that it will be useful,
47  * but WITHOUT ANY WARRANTY; without even the implied warranty of
48  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49  * GNU General Public License for more details.
50  *
51  * You should have received a copy of the GNU General Public License
52  * along with this program; if not, write to the Free Software
53  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54  *
55  */
56 
57 #include <asm/io.h>
58 #include <linux/delay.h>
59 #include <linux/interrupt.h>
60 #include <linux/init.h>
61 #include <linux/slab.h>
62 #include <sound/core.h>
63 
64 #include "ice1712.h"
65 #include "envy24ht.h"
66 #include "prodigy192.h"
67 #include "stac946x.h"
68 #include <sound/tlv.h>
69 
71  struct ak4114 *ak4114;
72  /* rate change needs atomic mute/unmute of all dacs*/
73  struct mutex mute_mutex;
74 };
75 
76 static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val)
77 {
79 }
80 
81 static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
82 {
84 }
85 
86 /*
87  * DAC mute control
88  */
89 
90 /*
91  * idx = STAC9460 volume register number, mute: 0 = mute, 1 = unmute
92  */
93 static int stac9460_dac_mute(struct snd_ice1712 *ice, int idx,
94  unsigned char mute)
95 {
96  unsigned char new, old;
97  int change;
98  old = stac9460_get(ice, idx);
99  new = (~mute << 7 & 0x80) | (old & ~0x80);
100  change = (new != old);
101  if (change)
102  /*printk ("Volume register 0x%02x: 0x%02x\n", idx, new);*/
103  stac9460_put(ice, idx, new);
104  return change;
105 }
106 
107 #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
108 
109 static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
110 {
111  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
112  unsigned char val;
113  int idx;
114 
115  if (kcontrol->private_value)
117  else
118  idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
119  val = stac9460_get(ice, idx);
120  ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
121  return 0;
122 }
123 
124 static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
125 {
126  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
127  struct prodigy192_spec *spec = ice->spec;
128  int idx, change;
129 
130  if (kcontrol->private_value)
132  else
133  idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
134  /* due to possible conflicts with stac9460_set_rate_val, mutexing */
135  mutex_lock(&spec->mute_mutex);
136  /*
137  printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx,
138  ucontrol->value.integer.value[0]);
139  */
140  change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]);
141  mutex_unlock(&spec->mute_mutex);
142  return change;
143 }
144 
145 /*
146  * DAC volume attenuation mixer control
147  */
148 static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
149 {
151  uinfo->count = 1;
152  uinfo->value.integer.min = 0; /* mute */
153  uinfo->value.integer.max = 0x7f; /* 0dB */
154  return 0;
155 }
156 
157 static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
158 {
159  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
160  int idx;
161  unsigned char vol;
162 
163  if (kcontrol->private_value)
165  else
166  idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
167  vol = stac9460_get(ice, idx) & 0x7f;
168  ucontrol->value.integer.value[0] = 0x7f - vol;
169 
170  return 0;
171 }
172 
173 static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
174 {
175  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
176  int idx;
177  unsigned char tmp, ovol, nvol;
178  int change;
179 
180  if (kcontrol->private_value)
182  else
183  idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
184  nvol = ucontrol->value.integer.value[0];
185  tmp = stac9460_get(ice, idx);
186  ovol = 0x7f - (tmp & 0x7f);
187  change = (ovol != nvol);
188  if (change) {
189  ovol = (0x7f - nvol) | (tmp & 0x80);
190  /*
191  printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n",
192  idx, ovol);
193  */
194  stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
195  }
196  return change;
197 }
198 
199 /*
200  * ADC mute control
201  */
202 #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
203 
204 static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
205 {
206  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
207  unsigned char val;
208  int i;
209 
210  for (i = 0; i < 2; ++i) {
211  val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
212  ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
213  }
214 
215  return 0;
216 }
217 
218 static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
219 {
220  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
221  unsigned char new, old;
222  int i, reg;
223  int change;
224 
225  for (i = 0; i < 2; ++i) {
226  reg = STAC946X_MIC_L_VOLUME + i;
227  old = stac9460_get(ice, reg);
228  new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80);
229  change = (new != old);
230  if (change)
231  stac9460_put(ice, reg, new);
232  }
233 
234  return change;
235 }
236 
237 /*
238  * ADC gain mixer control
239  */
240 static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
241 {
243  uinfo->count = 2;
244  uinfo->value.integer.min = 0; /* 0dB */
245  uinfo->value.integer.max = 0x0f; /* 22.5dB */
246  return 0;
247 }
248 
249 static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
250 {
251  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
252  int i, reg;
253  unsigned char vol;
254 
255  for (i = 0; i < 2; ++i) {
256  reg = STAC946X_MIC_L_VOLUME + i;
257  vol = stac9460_get(ice, reg) & 0x0f;
258  ucontrol->value.integer.value[i] = 0x0f - vol;
259  }
260 
261  return 0;
262 }
263 
264 static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
265 {
266  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
267  int i, reg;
268  unsigned char ovol, nvol;
269  int change;
270 
271  for (i = 0; i < 2; ++i) {
272  reg = STAC946X_MIC_L_VOLUME + i;
273  nvol = ucontrol->value.integer.value[i] & 0x0f;
274  ovol = 0x0f - stac9460_get(ice, reg);
275  change = ((ovol & 0x0f) != nvol);
276  if (change)
277  stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f));
278  }
279 
280  return change;
281 }
282 
283 static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
284  struct snd_ctl_elem_info *uinfo)
285 {
286  static char *texts[2] = { "Line In", "Mic" };
287 
289  uinfo->count = 1;
290  uinfo->value.enumerated.items = 2;
291 
292  if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
293  uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
294  strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
295 
296  return 0;
297 }
298 
299 
300 static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
301  struct snd_ctl_elem_value *ucontrol)
302 {
303  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
304  unsigned char val;
305 
306  val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
307  ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
308  return 0;
309 }
310 
311 static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
312  struct snd_ctl_elem_value *ucontrol)
313 {
314  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
315  unsigned char new, old;
316  int change;
317  old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
318  new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
319  change = (new != old);
320  if (change)
321  stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
322  return change;
323 }
324 /*
325  * Handler for setting correct codec rate - called when rate change is detected
326  */
327 static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
328 {
329  unsigned char old, new;
330  int idx;
331  unsigned char changed[7];
332  struct prodigy192_spec *spec = ice->spec;
333 
334  if (rate == 0) /* no hint - S/PDIF input is master, simply return */
335  return;
336  else if (rate <= 48000)
337  new = 0x08; /* 256x, base rate mode */
338  else if (rate <= 96000)
339  new = 0x11; /* 256x, mid rate mode */
340  else
341  new = 0x12; /* 128x, high rate mode */
342  old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);
343  if (old == new)
344  return;
345  /* change detected, setting master clock, muting first */
346  /* due to possible conflicts with mute controls - mutexing */
347  mutex_lock(&spec->mute_mutex);
348  /* we have to remember current mute status for each DAC */
349  for (idx = 0; idx < 7 ; ++idx)
350  changed[idx] = stac9460_dac_mute(ice,
351  STAC946X_MASTER_VOLUME + idx, 0);
352  /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
353  stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
354  udelay(10);
355  /* unmuting - only originally unmuted dacs -
356  * i.e. those changed when muting */
357  for (idx = 0; idx < 7 ; ++idx) {
358  if (changed[idx])
359  stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1);
360  }
361  mutex_unlock(&spec->mute_mutex);
362 }
363 
364 
365 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
366 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
367 
368 /*
369  * mixers
370  */
371 
372 static struct snd_kcontrol_new stac_controls[] __devinitdata = {
373  {
375  .name = "Master Playback Switch",
376  .info = stac9460_dac_mute_info,
377  .get = stac9460_dac_mute_get,
378  .put = stac9460_dac_mute_put,
379  .private_value = 1,
380  .tlv = { .p = db_scale_dac }
381  },
382  {
386  .name = "Master Playback Volume",
387  .info = stac9460_dac_vol_info,
388  .get = stac9460_dac_vol_get,
389  .put = stac9460_dac_vol_put,
390  .private_value = 1,
391  .tlv = { .p = db_scale_dac }
392  },
393  {
395  .name = "DAC Switch",
396  .count = 6,
397  .info = stac9460_dac_mute_info,
398  .get = stac9460_dac_mute_get,
399  .put = stac9460_dac_mute_put,
400  },
401  {
405  .name = "DAC Volume",
406  .count = 6,
407  .info = stac9460_dac_vol_info,
408  .get = stac9460_dac_vol_get,
409  .put = stac9460_dac_vol_put,
410  .tlv = { .p = db_scale_dac }
411  },
412  {
414  .name = "ADC Capture Switch",
415  .count = 1,
416  .info = stac9460_adc_mute_info,
417  .get = stac9460_adc_mute_get,
418  .put = stac9460_adc_mute_put,
419 
420  },
421  {
425  .name = "ADC Capture Volume",
426  .count = 1,
427  .info = stac9460_adc_vol_info,
428  .get = stac9460_adc_vol_get,
429  .put = stac9460_adc_vol_put,
430  .tlv = { .p = db_scale_adc }
431  },
432  {
434  .name = "Analog Capture Input",
435  .info = stac9460_mic_sw_info,
436  .get = stac9460_mic_sw_get,
437  .put = stac9460_mic_sw_put,
438 
439  },
440 };
441 
442 /* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */
443 /* CDTO (pin 32) -- GPIO11 pin 86
444  * CDTI (pin 33) -- GPIO10 pin 77
445  * CCLK (pin 34) -- GPIO9 pin 76
446  * CSN (pin 35) -- GPIO8 pin 75
447  */
448 #define AK4114_ADDR 0x00 /* C1-C0: Chip Address
449  * (According to datasheet fixed to “00”)
450  */
451 
452 /*
453  * 4wire ak4114 protocol - writing data
454  */
455 static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
456  unsigned int data, int idx)
457 {
458  for (; idx >= 0; idx--) {
459  /* drop clock */
460  gpio &= ~VT1724_PRODIGY192_CCLK;
461  snd_ice1712_gpio_write(ice, gpio);
462  udelay(1);
463  /* set data */
464  if (data & (1 << idx))
465  gpio |= VT1724_PRODIGY192_CDOUT;
466  else
467  gpio &= ~VT1724_PRODIGY192_CDOUT;
468  snd_ice1712_gpio_write(ice, gpio);
469  udelay(1);
470  /* raise clock */
471  gpio |= VT1724_PRODIGY192_CCLK;
472  snd_ice1712_gpio_write(ice, gpio);
473  udelay(1);
474  }
475 }
476 
477 /*
478  * 4wire ak4114 protocol - reading data
479  */
480 static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
481  int idx)
482 {
483  unsigned char data = 0;
484 
485  for (; idx >= 0; idx--) {
486  /* drop clock */
487  gpio &= ~VT1724_PRODIGY192_CCLK;
488  snd_ice1712_gpio_write(ice, gpio);
489  udelay(1);
490  /* read data */
491  if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN)
492  data |= (1 << idx);
493  udelay(1);
494  /* raise clock */
495  gpio |= VT1724_PRODIGY192_CCLK;
496  snd_ice1712_gpio_write(ice, gpio);
497  udelay(1);
498  }
499  return data;
500 }
501 /*
502  * 4wire ak4114 protocol - starting sequence
503  */
504 static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice)
505 {
506  unsigned int tmp;
507 
508  snd_ice1712_save_gpio_status(ice);
509  tmp = snd_ice1712_gpio_read(ice);
510 
511  tmp |= VT1724_PRODIGY192_CCLK; /* high at init */
512  tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */
513  snd_ice1712_gpio_write(ice, tmp);
514  udelay(1);
515  return tmp;
516 }
517 
518 /*
519  * 4wire ak4114 protocol - final sequence
520  */
521 static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
522 {
523  tmp |= VT1724_PRODIGY192_CS; /* raise chip select */
524  snd_ice1712_gpio_write(ice, tmp);
525  udelay(1);
526  snd_ice1712_restore_gpio_status(ice);
527 }
528 
529 /*
530  * Write data to addr register of ak4114
531  */
532 static void prodigy192_ak4114_write(void *private_data, unsigned char addr,
533  unsigned char data)
534 {
535  struct snd_ice1712 *ice = private_data;
536  unsigned int tmp, addrdata;
537  tmp = prodigy192_4wire_start(ice);
538  addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
539  addrdata = (addrdata << 8) | data;
540  write_data(ice, tmp, addrdata, 15);
541  prodigy192_4wire_finish(ice, tmp);
542 }
543 
544 /*
545  * Read data from addr register of ak4114
546  */
547 static unsigned char prodigy192_ak4114_read(void *private_data,
548  unsigned char addr)
549 {
550  struct snd_ice1712 *ice = private_data;
551  unsigned int tmp;
552  unsigned char data;
553 
554  tmp = prodigy192_4wire_start(ice);
555  write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
556  data = read_data(ice, tmp, 7);
557  prodigy192_4wire_finish(ice, tmp);
558  return data;
559 }
560 
561 
562 static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
563  struct snd_ctl_elem_info *uinfo)
564 {
565  static char *texts[2] = { "Toslink", "Coax" };
566 
568  uinfo->count = 1;
569  uinfo->value.enumerated.items = 2;
570  if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
571  uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
572  strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
573  return 0;
574 }
575 
576 
577 static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol,
578  struct snd_ctl_elem_value *ucontrol)
579 {
580  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
581  unsigned char val;
582 
583  val = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
584  /* AK4114_IPS0 bit = 0 -> RX0 = Toslink
585  * AK4114_IPS0 bit = 1 -> RX1 = Coax
586  */
587  ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0;
588  return 0;
589 }
590 
591 static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
592  struct snd_ctl_elem_value *ucontrol)
593 {
594  struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
595  unsigned char new, old, itemvalue;
596  int change;
597 
598  old = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
599  /* AK4114_IPS0 could be any bit */
600  itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00;
601 
602  new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0);
603  change = (new != old);
604  if (change)
605  prodigy192_ak4114_write(ice, AK4114_REG_IO1, new);
606  return change;
607 }
608 
609 
610 static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
611  {
613  .name = "MIODIO IEC958 Capture Input",
614  .info = ak4114_input_sw_info,
615  .get = ak4114_input_sw_get,
616  .put = ak4114_input_sw_put,
617 
618  }
619 };
620 
621 
622 static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
623 {
624  static const unsigned char ak4114_init_vals[] = {
626  /* ice1724 expects I2S and provides clock,
627  * DEM0 disables the deemphasis filter
628  */
630  AK4114_TX1E,
631  AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */
632  0,
633  0
634  };
635  static const unsigned char ak4114_init_txcsb[] = {
636  0x41, 0x02, 0x2c, 0x00, 0x00
637  };
638  struct prodigy192_spec *spec = ice->spec;
639  int err;
640 
641  err = snd_ak4114_create(ice->card,
642  prodigy192_ak4114_read,
643  prodigy192_ak4114_write,
644  ak4114_init_vals, ak4114_init_txcsb,
645  ice, &spec->ak4114);
646  if (err < 0)
647  return err;
648  /* AK4114 in Prodigy192 cannot detect external rate correctly.
649  * No reason to stop capture stream due to incorrect checks */
650  spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
651  return 0;
652 }
653 
654 static void stac9460_proc_regs_read(struct snd_info_entry *entry,
655  struct snd_info_buffer *buffer)
656 {
657  struct snd_ice1712 *ice = entry->private_data;
658  int reg, val;
659  /* registers 0x0 - 0x14 */
660  for (reg = 0; reg <= 0x15; reg++) {
661  val = stac9460_get(ice, reg);
662  snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
663  }
664 }
665 
666 
667 static void stac9460_proc_init(struct snd_ice1712 *ice)
668 {
669  struct snd_info_entry *entry;
670  if (!snd_card_proc_new(ice->card, "stac9460_codec", &entry))
671  snd_info_set_text_ops(entry, ice, stac9460_proc_regs_read);
672 }
673 
674 
675 static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
676 {
677  struct prodigy192_spec *spec = ice->spec;
678  unsigned int i;
679  int err;
680 
681  for (i = 0; i < ARRAY_SIZE(stac_controls); i++) {
682  err = snd_ctl_add(ice->card,
683  snd_ctl_new1(&stac_controls[i], ice));
684  if (err < 0)
685  return err;
686  }
687  if (spec->ak4114) {
688  /* ak4114 is connected */
689  for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) {
690  err = snd_ctl_add(ice->card,
691  snd_ctl_new1(&ak4114_controls[i],
692  ice));
693  if (err < 0)
694  return err;
695  }
696  err = snd_ak4114_build(spec->ak4114,
697  NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */
698  ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
699  if (err < 0)
700  return err;
701  }
702  stac9460_proc_init(ice);
703  return 0;
704 }
705 
706 /*
707  * check for presence of MI/ODI/O add-on card with digital inputs
708  */
709 static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
710 {
711 
712  unsigned char orig_value;
713  const unsigned char test_data = 0xd1; /* random value */
714  unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */
715  int exists = 0;
716 
717  orig_value = prodigy192_ak4114_read(ice, addr);
718  prodigy192_ak4114_write(ice, addr, test_data);
719  if (prodigy192_ak4114_read(ice, addr) == test_data) {
720  /* ak4114 seems to communicate, apparently exists */
721  /* writing back original value */
722  prodigy192_ak4114_write(ice, addr, orig_value);
723  exists = 1;
724  }
725  return exists;
726 }
727 
728 /*
729  * initialize the chip
730  */
731 static int __devinit prodigy192_init(struct snd_ice1712 *ice)
732 {
733  static const unsigned short stac_inits_prodigy[] = {
734  STAC946X_RESET, 0,
736 /* STAC946X_MASTER_VOLUME, 0,
737  STAC946X_LF_VOLUME, 0,
738  STAC946X_RF_VOLUME, 0,
739  STAC946X_LR_VOLUME, 0,
740  STAC946X_RR_VOLUME, 0,
741  STAC946X_CENTER_VOLUME, 0,
742  STAC946X_LFE_VOLUME, 0,*/
743  (unsigned short)-1
744  };
745  const unsigned short *p;
746  int err = 0;
747  struct prodigy192_spec *spec;
748 
749  /* prodigy 192 */
750  ice->num_total_dacs = 6;
751  ice->num_total_adcs = 2;
752  ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */
753 
754  spec = kzalloc(sizeof(*spec), GFP_KERNEL);
755  if (!spec)
756  return -ENOMEM;
757  ice->spec = spec;
758  mutex_init(&spec->mute_mutex);
759 
760  /* initialize codec */
761  p = stac_inits_prodigy;
762  for (; *p != (unsigned short)-1; p += 2)
763  stac9460_put(ice, p[0], p[1]);
764  ice->gpio.set_pro_rate = stac9460_set_rate_val;
765 
766  /* MI/ODI/O add on card with AK4114 */
767  if (prodigy192_miodio_exists(ice)) {
768  err = prodigy192_ak4114_init(ice);
769  /* from this moment if err = 0 then
770  * spec->ak4114 should not be null
771  */
772  snd_printdd("AK4114 initialized with status %d\n", err);
773  } else
774  snd_printdd("AK4114 not found\n");
775  if (err < 0)
776  return err;
777 
778  return 0;
779 }
780 
781 
782 /*
783  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
784  * hence the driver needs to sets up it properly.
785  */
786 
787 static unsigned char prodigy71_eeprom[] __devinitdata = {
788  [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401,
789  * spdif-in+ 1 stereo ADC,
790  * 3 stereo DACs
791  */
792  [ICE_EEP2_ACLINK] = 0x80, /* I2S */
793  [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
794  [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
795  [ICE_EEP2_GPIO_DIR] = 0xff,
797  [ICE_EEP2_GPIO_DIR2] = 0xbf,
798  [ICE_EEP2_GPIO_MASK] = 0x00,
799  [ICE_EEP2_GPIO_MASK1] = 0x00,
800  [ICE_EEP2_GPIO_MASK2] = 0x00,
801  [ICE_EEP2_GPIO_STATE] = 0x00,
802  [ICE_EEP2_GPIO_STATE1] = 0x00,
803  [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. input
804  * passthrough,
805  * 1 = SPDIF-OUT from ice1724
806  */
807 };
808 
810 /* entry point */
811 struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
812  {
813  .subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
814  .name = "Audiotrak Prodigy 192",
815  .model = "prodigy192",
816  .chip_init = prodigy192_init,
817  .build_controls = prodigy192_add_controls,
818  .eeprom_size = sizeof(prodigy71_eeprom),
820  },
821  { } /* terminator */
822 };