Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/ice1712/prodigy192.c
10818 views
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
70
struct prodigy192_spec {
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
{
78
snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
79
}
80
81
static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
82
{
83
return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
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)
116
idx = STAC946X_MASTER_VOLUME;
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)
131
idx = STAC946X_MASTER_VOLUME;
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
{
150
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
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)
164
idx = STAC946X_MASTER_VOLUME;
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)
181
idx = STAC946X_MASTER_VOLUME;
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
{
242
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
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
288
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
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
{
374
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
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
{
383
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
384
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
385
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
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
{
394
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
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
{
402
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
403
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
404
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
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
{
413
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
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
{
422
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
423
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
424
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
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
{
433
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
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
567
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
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
{
612
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
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[] = {
625
AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
626
/* ice1724 expects I2S and provides clock,
627
* DEM0 disables the deemphasis filter
628
*/
629
AK4114_DIF_I24I2S | AK4114_DEM0 ,
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,
735
STAC946X_MASTER_CLOCKING, 0x11,
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,
796
[ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) ,
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
809
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),
819
.eeprom_data = prodigy71_eeprom,
820
},
821
{ } /* terminator */
822
};
823
824