Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/ppc/awacs.c
10814 views
1
/*
2
* PMac AWACS lowlevel functions
3
*
4
* Copyright (c) by Takashi Iwai <[email protected]>
5
* code based on dmasound.c.
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
22
23
#include <asm/io.h>
24
#include <asm/nvram.h>
25
#include <linux/init.h>
26
#include <linux/delay.h>
27
#include <linux/slab.h>
28
#include <sound/core.h>
29
#include "pmac.h"
30
31
32
#ifdef CONFIG_ADB_CUDA
33
#define PMAC_AMP_AVAIL
34
#endif
35
36
#ifdef PMAC_AMP_AVAIL
37
struct awacs_amp {
38
unsigned char amp_master;
39
unsigned char amp_vol[2][2];
40
unsigned char amp_tone[2];
41
};
42
43
#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA)
44
45
#endif /* PMAC_AMP_AVAIL */
46
47
48
static void snd_pmac_screamer_wait(struct snd_pmac *chip)
49
{
50
long timeout = 2000;
51
while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) {
52
mdelay(1);
53
if (! --timeout) {
54
snd_printd("snd_pmac_screamer_wait timeout\n");
55
break;
56
}
57
}
58
}
59
60
/*
61
* write AWACS register
62
*/
63
static void
64
snd_pmac_awacs_write(struct snd_pmac *chip, int val)
65
{
66
long timeout = 5000000;
67
68
if (chip->model == PMAC_SCREAMER)
69
snd_pmac_screamer_wait(chip);
70
out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22));
71
while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) {
72
if (! --timeout) {
73
snd_printd("snd_pmac_awacs_write timeout\n");
74
break;
75
}
76
}
77
}
78
79
static void
80
snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val)
81
{
82
snd_pmac_awacs_write(chip, val | (reg << 12));
83
chip->awacs_reg[reg] = val;
84
}
85
86
static void
87
snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val)
88
{
89
snd_pmac_awacs_write(chip, val | (reg << 12));
90
}
91
92
#ifdef CONFIG_PM
93
/* Recalibrate chip */
94
static void screamer_recalibrate(struct snd_pmac *chip)
95
{
96
if (chip->model != PMAC_SCREAMER)
97
return;
98
99
/* Sorry for the horrible delays... I hope to get that improved
100
* by making the whole PM process asynchronous in a future version
101
*/
102
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
103
if (chip->manufacturer == 0x1)
104
/* delay for broken crystal part */
105
msleep(750);
106
snd_pmac_awacs_write_noreg(chip, 1,
107
chip->awacs_reg[1] | MASK_RECALIBRATE |
108
MASK_CMUTE | MASK_AMUTE);
109
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
110
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
111
}
112
113
#else
114
#define screamer_recalibrate(chip) /* NOP */
115
#endif
116
117
118
/*
119
* additional callback to set the pcm format
120
*/
121
static void snd_pmac_awacs_set_format(struct snd_pmac *chip)
122
{
123
chip->awacs_reg[1] &= ~MASK_SAMPLERATE;
124
chip->awacs_reg[1] |= chip->rate_index << 3;
125
snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1]);
126
}
127
128
129
/*
130
* AWACS volume callbacks
131
*/
132
/*
133
* volumes: 0-15 stereo
134
*/
135
static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
136
struct snd_ctl_elem_info *uinfo)
137
{
138
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
139
uinfo->count = 2;
140
uinfo->value.integer.min = 0;
141
uinfo->value.integer.max = 15;
142
return 0;
143
}
144
145
static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
146
struct snd_ctl_elem_value *ucontrol)
147
{
148
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
149
int reg = kcontrol->private_value & 0xff;
150
int lshift = (kcontrol->private_value >> 8) & 0xff;
151
int inverted = (kcontrol->private_value >> 16) & 1;
152
unsigned long flags;
153
int vol[2];
154
155
spin_lock_irqsave(&chip->reg_lock, flags);
156
vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf;
157
vol[1] = chip->awacs_reg[reg] & 0xf;
158
spin_unlock_irqrestore(&chip->reg_lock, flags);
159
if (inverted) {
160
vol[0] = 0x0f - vol[0];
161
vol[1] = 0x0f - vol[1];
162
}
163
ucontrol->value.integer.value[0] = vol[0];
164
ucontrol->value.integer.value[1] = vol[1];
165
return 0;
166
}
167
168
static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol,
169
struct snd_ctl_elem_value *ucontrol)
170
{
171
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
172
int reg = kcontrol->private_value & 0xff;
173
int lshift = (kcontrol->private_value >> 8) & 0xff;
174
int inverted = (kcontrol->private_value >> 16) & 1;
175
int val, oldval;
176
unsigned long flags;
177
unsigned int vol[2];
178
179
vol[0] = ucontrol->value.integer.value[0];
180
vol[1] = ucontrol->value.integer.value[1];
181
if (vol[0] > 0x0f || vol[1] > 0x0f)
182
return -EINVAL;
183
if (inverted) {
184
vol[0] = 0x0f - vol[0];
185
vol[1] = 0x0f - vol[1];
186
}
187
vol[0] &= 0x0f;
188
vol[1] &= 0x0f;
189
spin_lock_irqsave(&chip->reg_lock, flags);
190
oldval = chip->awacs_reg[reg];
191
val = oldval & ~(0xf | (0xf << lshift));
192
val |= vol[0] << lshift;
193
val |= vol[1];
194
if (oldval != val)
195
snd_pmac_awacs_write_reg(chip, reg, val);
196
spin_unlock_irqrestore(&chip->reg_lock, flags);
197
return oldval != reg;
198
}
199
200
201
#define AWACS_VOLUME(xname, xreg, xshift, xinverted) \
202
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
203
.info = snd_pmac_awacs_info_volume, \
204
.get = snd_pmac_awacs_get_volume, \
205
.put = snd_pmac_awacs_put_volume, \
206
.private_value = (xreg) | ((xshift) << 8) | ((xinverted) << 16) }
207
208
/*
209
* mute master/ogain for AWACS: mono
210
*/
211
static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol,
212
struct snd_ctl_elem_value *ucontrol)
213
{
214
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
215
int reg = kcontrol->private_value & 0xff;
216
int shift = (kcontrol->private_value >> 8) & 0xff;
217
int invert = (kcontrol->private_value >> 16) & 1;
218
int val;
219
unsigned long flags;
220
221
spin_lock_irqsave(&chip->reg_lock, flags);
222
val = (chip->awacs_reg[reg] >> shift) & 1;
223
spin_unlock_irqrestore(&chip->reg_lock, flags);
224
if (invert)
225
val = 1 - val;
226
ucontrol->value.integer.value[0] = val;
227
return 0;
228
}
229
230
static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
231
struct snd_ctl_elem_value *ucontrol)
232
{
233
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
234
int reg = kcontrol->private_value & 0xff;
235
int shift = (kcontrol->private_value >> 8) & 0xff;
236
int invert = (kcontrol->private_value >> 16) & 1;
237
int mask = 1 << shift;
238
int val, changed;
239
unsigned long flags;
240
241
spin_lock_irqsave(&chip->reg_lock, flags);
242
val = chip->awacs_reg[reg] & ~mask;
243
if (ucontrol->value.integer.value[0] != invert)
244
val |= mask;
245
changed = chip->awacs_reg[reg] != val;
246
if (changed)
247
snd_pmac_awacs_write_reg(chip, reg, val);
248
spin_unlock_irqrestore(&chip->reg_lock, flags);
249
return changed;
250
}
251
252
#define AWACS_SWITCH(xname, xreg, xshift, xinvert) \
253
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
254
.info = snd_pmac_boolean_mono_info, \
255
.get = snd_pmac_awacs_get_switch, \
256
.put = snd_pmac_awacs_put_switch, \
257
.private_value = (xreg) | ((xshift) << 8) | ((xinvert) << 16) }
258
259
260
#ifdef PMAC_AMP_AVAIL
261
/*
262
* controls for perch/whisper extension cards, e.g. G3 desktop
263
*
264
* TDA7433 connected via i2c address 0x45 (= 0x8a),
265
* accessed through cuda
266
*/
267
static void awacs_set_cuda(int reg, int val)
268
{
269
struct adb_request req;
270
cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
271
reg, val);
272
while (! req.complete)
273
cuda_poll();
274
}
275
276
/*
277
* level = 0 - 14, 7 = 0 dB
278
*/
279
static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
280
{
281
amp->amp_tone[0] = bass;
282
amp->amp_tone[1] = treble;
283
if (bass > 7)
284
bass = (14 - bass) + 8;
285
if (treble > 7)
286
treble = (14 - treble) + 8;
287
awacs_set_cuda(2, (bass << 4) | treble);
288
}
289
290
/*
291
* vol = 0 - 31 (attenuation), 32 = mute bit, stereo
292
*/
293
static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
294
int lvol, int rvol, int do_check)
295
{
296
if (do_check && amp->amp_vol[index][0] == lvol &&
297
amp->amp_vol[index][1] == rvol)
298
return 0;
299
awacs_set_cuda(3 + index, lvol);
300
awacs_set_cuda(5 + index, rvol);
301
amp->amp_vol[index][0] = lvol;
302
amp->amp_vol[index][1] = rvol;
303
return 1;
304
}
305
306
/*
307
* 0 = -79 dB, 79 = 0 dB, 99 = +20 dB
308
*/
309
static void awacs_amp_set_master(struct awacs_amp *amp, int vol)
310
{
311
amp->amp_master = vol;
312
if (vol <= 79)
313
vol = 32 + (79 - vol);
314
else
315
vol = 32 - (vol - 79);
316
awacs_set_cuda(1, vol);
317
}
318
319
static void awacs_amp_free(struct snd_pmac *chip)
320
{
321
struct awacs_amp *amp = chip->mixer_data;
322
if (!amp)
323
return;
324
kfree(amp);
325
chip->mixer_data = NULL;
326
chip->mixer_free = NULL;
327
}
328
329
330
/*
331
* mixer controls
332
*/
333
static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
334
struct snd_ctl_elem_info *uinfo)
335
{
336
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
337
uinfo->count = 2;
338
uinfo->value.integer.min = 0;
339
uinfo->value.integer.max = 31;
340
return 0;
341
}
342
343
static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
344
struct snd_ctl_elem_value *ucontrol)
345
{
346
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
347
int index = kcontrol->private_value;
348
struct awacs_amp *amp = chip->mixer_data;
349
350
ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31);
351
ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31);
352
return 0;
353
}
354
355
static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
356
struct snd_ctl_elem_value *ucontrol)
357
{
358
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
359
int index = kcontrol->private_value;
360
int vol[2];
361
struct awacs_amp *amp = chip->mixer_data;
362
363
vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
364
| (amp->amp_vol[index][0] & 32);
365
vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
366
| (amp->amp_vol[index][1] & 32);
367
return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
368
}
369
370
static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
371
struct snd_ctl_elem_value *ucontrol)
372
{
373
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
374
int index = kcontrol->private_value;
375
struct awacs_amp *amp = chip->mixer_data;
376
377
ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
378
? 0 : 1;
379
ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
380
? 0 : 1;
381
return 0;
382
}
383
384
static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
385
struct snd_ctl_elem_value *ucontrol)
386
{
387
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
388
int index = kcontrol->private_value;
389
int vol[2];
390
struct awacs_amp *amp = chip->mixer_data;
391
392
vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
393
| (amp->amp_vol[index][0] & 31);
394
vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
395
| (amp->amp_vol[index][1] & 31);
396
return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
397
}
398
399
static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
400
struct snd_ctl_elem_info *uinfo)
401
{
402
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
403
uinfo->count = 1;
404
uinfo->value.integer.min = 0;
405
uinfo->value.integer.max = 14;
406
return 0;
407
}
408
409
static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
410
struct snd_ctl_elem_value *ucontrol)
411
{
412
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
413
int index = kcontrol->private_value;
414
struct awacs_amp *amp = chip->mixer_data;
415
416
ucontrol->value.integer.value[0] = amp->amp_tone[index];
417
return 0;
418
}
419
420
static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol,
421
struct snd_ctl_elem_value *ucontrol)
422
{
423
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
424
int index = kcontrol->private_value;
425
struct awacs_amp *amp = chip->mixer_data;
426
unsigned int val;
427
428
val = ucontrol->value.integer.value[0];
429
if (val > 14)
430
return -EINVAL;
431
if (val != amp->amp_tone[index]) {
432
amp->amp_tone[index] = val;
433
awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
434
return 1;
435
}
436
return 0;
437
}
438
439
static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
440
struct snd_ctl_elem_info *uinfo)
441
{
442
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
443
uinfo->count = 1;
444
uinfo->value.integer.min = 0;
445
uinfo->value.integer.max = 99;
446
return 0;
447
}
448
449
static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
450
struct snd_ctl_elem_value *ucontrol)
451
{
452
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
453
struct awacs_amp *amp = chip->mixer_data;
454
455
ucontrol->value.integer.value[0] = amp->amp_master;
456
return 0;
457
}
458
459
static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
460
struct snd_ctl_elem_value *ucontrol)
461
{
462
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
463
struct awacs_amp *amp = chip->mixer_data;
464
unsigned int val;
465
466
val = ucontrol->value.integer.value[0];
467
if (val > 99)
468
return -EINVAL;
469
if (val != amp->amp_master) {
470
amp->amp_master = val;
471
awacs_amp_set_master(amp, amp->amp_master);
472
return 1;
473
}
474
return 0;
475
}
476
477
#define AMP_CH_SPK 0
478
#define AMP_CH_HD 1
479
480
static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = {
481
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
482
.name = "Speaker Playback Volume",
483
.info = snd_pmac_awacs_info_volume_amp,
484
.get = snd_pmac_awacs_get_volume_amp,
485
.put = snd_pmac_awacs_put_volume_amp,
486
.private_value = AMP_CH_SPK,
487
},
488
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
489
.name = "Headphone Playback Volume",
490
.info = snd_pmac_awacs_info_volume_amp,
491
.get = snd_pmac_awacs_get_volume_amp,
492
.put = snd_pmac_awacs_put_volume_amp,
493
.private_value = AMP_CH_HD,
494
},
495
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
496
.name = "Tone Control - Bass",
497
.info = snd_pmac_awacs_info_tone_amp,
498
.get = snd_pmac_awacs_get_tone_amp,
499
.put = snd_pmac_awacs_put_tone_amp,
500
.private_value = 0,
501
},
502
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
503
.name = "Tone Control - Treble",
504
.info = snd_pmac_awacs_info_tone_amp,
505
.get = snd_pmac_awacs_get_tone_amp,
506
.put = snd_pmac_awacs_put_tone_amp,
507
.private_value = 1,
508
},
509
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
510
.name = "Amp Master Playback Volume",
511
.info = snd_pmac_awacs_info_master_amp,
512
.get = snd_pmac_awacs_get_master_amp,
513
.put = snd_pmac_awacs_put_master_amp,
514
},
515
};
516
517
static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = {
518
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
519
.name = "Headphone Playback Switch",
520
.info = snd_pmac_boolean_stereo_info,
521
.get = snd_pmac_awacs_get_switch_amp,
522
.put = snd_pmac_awacs_put_switch_amp,
523
.private_value = AMP_CH_HD,
524
};
525
526
static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = {
527
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
528
.name = "Speaker Playback Switch",
529
.info = snd_pmac_boolean_stereo_info,
530
.get = snd_pmac_awacs_get_switch_amp,
531
.put = snd_pmac_awacs_put_switch_amp,
532
.private_value = AMP_CH_SPK,
533
};
534
535
#endif /* PMAC_AMP_AVAIL */
536
537
538
/*
539
* mic boost for screamer
540
*/
541
static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
542
struct snd_ctl_elem_info *uinfo)
543
{
544
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
545
uinfo->count = 1;
546
uinfo->value.integer.min = 0;
547
uinfo->value.integer.max = 3;
548
return 0;
549
}
550
551
static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
552
struct snd_ctl_elem_value *ucontrol)
553
{
554
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
555
int val = 0;
556
unsigned long flags;
557
558
spin_lock_irqsave(&chip->reg_lock, flags);
559
if (chip->awacs_reg[6] & MASK_MIC_BOOST)
560
val |= 2;
561
if (chip->awacs_reg[0] & MASK_GAINLINE)
562
val |= 1;
563
spin_unlock_irqrestore(&chip->reg_lock, flags);
564
ucontrol->value.integer.value[0] = val;
565
return 0;
566
}
567
568
static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
569
struct snd_ctl_elem_value *ucontrol)
570
{
571
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
572
int changed = 0;
573
int val0, val6;
574
unsigned long flags;
575
576
spin_lock_irqsave(&chip->reg_lock, flags);
577
val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
578
val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
579
if (ucontrol->value.integer.value[0] & 1)
580
val0 |= MASK_GAINLINE;
581
if (ucontrol->value.integer.value[0] & 2)
582
val6 |= MASK_MIC_BOOST;
583
if (val0 != chip->awacs_reg[0]) {
584
snd_pmac_awacs_write_reg(chip, 0, val0);
585
changed = 1;
586
}
587
if (val6 != chip->awacs_reg[6]) {
588
snd_pmac_awacs_write_reg(chip, 6, val6);
589
changed = 1;
590
}
591
spin_unlock_irqrestore(&chip->reg_lock, flags);
592
return changed;
593
}
594
595
/*
596
* lists of mixer elements
597
*/
598
static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = {
599
AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
600
AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
601
/* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
602
};
603
604
static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = {
605
AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
606
AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
607
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
608
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
609
};
610
611
static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = {
612
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
613
};
614
615
static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = {
616
AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
617
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
618
};
619
620
static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = {
621
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
622
AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
623
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
624
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
625
};
626
627
static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = {
628
AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
629
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
630
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
631
};
632
633
static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = {
634
AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
635
};
636
637
static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = {
638
AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
639
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
640
};
641
642
/* FIXME: is this correct order?
643
* screamer (powerbook G3 pismo) seems to have different bits...
644
*/
645
static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = {
646
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
647
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
648
};
649
650
static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = {
651
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
652
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
653
};
654
655
static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = {
656
AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
657
};
658
659
static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata =
660
AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
661
662
static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata =
663
AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
664
665
static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata =
666
AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
667
668
static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = {
669
AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
670
};
671
672
static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = {
673
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
674
.name = "Mic Boost Capture Volume",
675
.info = snd_pmac_screamer_mic_boost_info,
676
.get = snd_pmac_screamer_mic_boost_get,
677
.put = snd_pmac_screamer_mic_boost_put,
678
},
679
};
680
681
static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata =
682
{
683
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
684
};
685
686
static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata =
687
{
688
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
689
AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
690
};
691
692
static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata =
693
{
694
AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
695
AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
696
};
697
698
static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = {
699
AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
700
};
701
702
static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata =
703
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
704
705
static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata =
706
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
707
708
static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata =
709
AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
710
711
712
/*
713
* add new mixer elements to the card
714
*/
715
static int build_mixers(struct snd_pmac *chip, int nums,
716
struct snd_kcontrol_new *mixers)
717
{
718
int i, err;
719
720
for (i = 0; i < nums; i++) {
721
err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));
722
if (err < 0)
723
return err;
724
}
725
return 0;
726
}
727
728
729
/*
730
* restore all registers
731
*/
732
static void awacs_restore_all_regs(struct snd_pmac *chip)
733
{
734
snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
735
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
736
snd_pmac_awacs_write_noreg(chip, 2, chip->awacs_reg[2]);
737
snd_pmac_awacs_write_noreg(chip, 4, chip->awacs_reg[4]);
738
if (chip->model == PMAC_SCREAMER) {
739
snd_pmac_awacs_write_noreg(chip, 5, chip->awacs_reg[5]);
740
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
741
snd_pmac_awacs_write_noreg(chip, 7, chip->awacs_reg[7]);
742
}
743
}
744
745
#ifdef CONFIG_PM
746
static void snd_pmac_awacs_suspend(struct snd_pmac *chip)
747
{
748
snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1]
749
| MASK_AMUTE | MASK_CMUTE));
750
}
751
752
static void snd_pmac_awacs_resume(struct snd_pmac *chip)
753
{
754
if (of_machine_is_compatible("PowerBook3,1")
755
|| of_machine_is_compatible("PowerBook3,2")) {
756
msleep(100);
757
snd_pmac_awacs_write_reg(chip, 1,
758
chip->awacs_reg[1] & ~MASK_PAROUT);
759
msleep(300);
760
}
761
762
awacs_restore_all_regs(chip);
763
if (chip->model == PMAC_SCREAMER) {
764
/* reset power bits in reg 6 */
765
mdelay(5);
766
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
767
}
768
screamer_recalibrate(chip);
769
#ifdef PMAC_AMP_AVAIL
770
if (chip->mixer_data) {
771
struct awacs_amp *amp = chip->mixer_data;
772
awacs_amp_set_vol(amp, 0,
773
amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
774
awacs_amp_set_vol(amp, 1,
775
amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
776
awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
777
awacs_amp_set_master(amp, amp->amp_master);
778
}
779
#endif
780
}
781
#endif /* CONFIG_PM */
782
783
#define IS_PM7500 (of_machine_is_compatible("AAPL,7500") \
784
|| of_machine_is_compatible("AAPL,8500") \
785
|| of_machine_is_compatible("AAPL,9500"))
786
#define IS_PM5500 (of_machine_is_compatible("AAPL,e411"))
787
#define IS_BEIGE (of_machine_is_compatible("AAPL,Gossamer"))
788
#define IS_IMAC1 (of_machine_is_compatible("PowerMac2,1"))
789
#define IS_IMAC2 (of_machine_is_compatible("PowerMac2,2") \
790
|| of_machine_is_compatible("PowerMac4,1"))
791
#define IS_G4AGP (of_machine_is_compatible("PowerMac3,1"))
792
#define IS_LOMBARD (of_machine_is_compatible("PowerBook1,1"))
793
794
static int imac1, imac2;
795
796
#ifdef PMAC_SUPPORT_AUTOMUTE
797
/*
798
* auto-mute stuffs
799
*/
800
static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip)
801
{
802
return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
803
}
804
805
#ifdef PMAC_AMP_AVAIL
806
static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute)
807
{
808
int vol[2];
809
vol[0] = amp->amp_vol[index][0] & 31;
810
vol[1] = amp->amp_vol[index][1] & 31;
811
if (mute) {
812
vol[0] |= 32;
813
vol[1] |= 32;
814
}
815
return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
816
}
817
#endif
818
819
static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
820
{
821
if (chip->auto_mute) {
822
#ifdef PMAC_AMP_AVAIL
823
if (chip->mixer_data) {
824
struct awacs_amp *amp = chip->mixer_data;
825
int changed;
826
if (snd_pmac_awacs_detect_headphone(chip)) {
827
changed = toggle_amp_mute(amp, AMP_CH_HD, 0);
828
changed |= toggle_amp_mute(amp, AMP_CH_SPK, 1);
829
} else {
830
changed = toggle_amp_mute(amp, AMP_CH_HD, 1);
831
changed |= toggle_amp_mute(amp, AMP_CH_SPK, 0);
832
}
833
if (do_notify && ! changed)
834
return;
835
} else
836
#endif
837
{
838
int reg = chip->awacs_reg[1]
839
| (MASK_HDMUTE | MASK_SPKMUTE);
840
if (imac1) {
841
reg &= ~MASK_SPKMUTE;
842
reg |= MASK_PAROUT1;
843
} else if (imac2) {
844
reg &= ~MASK_SPKMUTE;
845
reg &= ~MASK_PAROUT1;
846
}
847
if (snd_pmac_awacs_detect_headphone(chip))
848
reg &= ~MASK_HDMUTE;
849
else if (imac1)
850
reg &= ~MASK_PAROUT1;
851
else if (imac2)
852
reg |= MASK_PAROUT1;
853
else
854
reg &= ~MASK_SPKMUTE;
855
if (do_notify && reg == chip->awacs_reg[1])
856
return;
857
snd_pmac_awacs_write_reg(chip, 1, reg);
858
}
859
if (do_notify) {
860
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
861
&chip->master_sw_ctl->id);
862
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
863
&chip->speaker_sw_ctl->id);
864
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
865
&chip->hp_detect_ctl->id);
866
}
867
}
868
}
869
#endif /* PMAC_SUPPORT_AUTOMUTE */
870
871
872
/*
873
* initialize chip
874
*/
875
int __devinit
876
snd_pmac_awacs_init(struct snd_pmac *chip)
877
{
878
int pm7500 = IS_PM7500;
879
int pm5500 = IS_PM5500;
880
int beige = IS_BEIGE;
881
int g4agp = IS_G4AGP;
882
int lombard = IS_LOMBARD;
883
int imac;
884
int err, vol;
885
struct snd_kcontrol *vmaster_sw, *vmaster_vol;
886
struct snd_kcontrol *master_vol, *speaker_vol;
887
888
imac1 = IS_IMAC1;
889
imac2 = IS_IMAC2;
890
imac = imac1 || imac2;
891
/* looks like MASK_GAINLINE triggers something, so we set here
892
* as start-up
893
*/
894
chip->awacs_reg[0] = MASK_MUX_CD | 0xff | MASK_GAINLINE;
895
chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
896
/* FIXME: Only machines with external SRS module need MASK_PAROUT */
897
if (chip->has_iic || chip->device_id == 0x5 ||
898
/* chip->_device_id == 0x8 || */
899
chip->device_id == 0xb)
900
chip->awacs_reg[1] |= MASK_PAROUT;
901
/* get default volume from nvram */
902
// vol = (~nvram_read_byte(0x1308) & 7) << 1;
903
// vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );
904
vol = 0x0f; /* no, on alsa, muted as default */
905
vol = vol + (vol << 6);
906
chip->awacs_reg[2] = vol;
907
chip->awacs_reg[4] = vol;
908
if (chip->model == PMAC_SCREAMER) {
909
/* FIXME: screamer has loopthru vol control */
910
chip->awacs_reg[5] = vol;
911
/* FIXME: maybe should be vol << 3 for PCMCIA speaker */
912
chip->awacs_reg[6] = MASK_MIC_BOOST;
913
chip->awacs_reg[7] = 0;
914
}
915
916
awacs_restore_all_regs(chip);
917
chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf;
918
screamer_recalibrate(chip);
919
920
chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
921
#ifdef PMAC_AMP_AVAIL
922
if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {
923
struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL);
924
if (! amp)
925
return -ENOMEM;
926
chip->mixer_data = amp;
927
chip->mixer_free = awacs_amp_free;
928
/* mute and zero vol */
929
awacs_amp_set_vol(amp, 0, 63, 63, 0);
930
awacs_amp_set_vol(amp, 1, 63, 63, 0);
931
awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
932
awacs_amp_set_master(amp, 79); /* 0 dB */
933
}
934
#endif /* PMAC_AMP_AVAIL */
935
936
if (chip->hp_stat_mask == 0) {
937
/* set headphone-jack detection bit */
938
switch (chip->model) {
939
case PMAC_AWACS:
940
chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN
941
: MASK_LOCONN;
942
break;
943
case PMAC_SCREAMER:
944
switch (chip->device_id) {
945
case 0x08:
946
case 0x0B:
947
chip->hp_stat_mask = imac
948
? MASK_LOCONN_IMAC |
949
MASK_HDPLCONN_IMAC |
950
MASK_HDPRCONN_IMAC
951
: MASK_HDPCONN;
952
break;
953
case 0x00:
954
case 0x05:
955
chip->hp_stat_mask = MASK_LOCONN;
956
break;
957
default:
958
chip->hp_stat_mask = MASK_HDPCONN;
959
break;
960
}
961
break;
962
default:
963
snd_BUG();
964
break;
965
}
966
}
967
968
/*
969
* build mixers
970
*/
971
strcpy(chip->card->mixername, "PowerMac AWACS");
972
973
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
974
snd_pmac_awacs_mixers);
975
if (err < 0)
976
return err;
977
if (beige || g4agp)
978
;
979
else if (chip->model == PMAC_SCREAMER || pm5500)
980
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
981
snd_pmac_screamer_mixers2);
982
else if (!pm7500)
983
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
984
snd_pmac_awacs_mixers2);
985
if (err < 0)
986
return err;
987
if (pm5500) {
988
err = build_mixers(chip,
989
ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500),
990
snd_pmac_awacs_mixers2_pmac5500);
991
if (err < 0)
992
return err;
993
}
994
if (pm7500)
995
err = build_mixers(chip,
996
ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
997
snd_pmac_awacs_mixers_pmac7500);
998
else if (pm5500)
999
err = snd_ctl_add(chip->card,
1000
(master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500,
1001
chip)));
1002
else if (beige)
1003
err = build_mixers(chip,
1004
ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
1005
snd_pmac_screamer_mixers_beige);
1006
else if (imac || lombard) {
1007
err = snd_ctl_add(chip->card,
1008
(master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo,
1009
chip)));
1010
if (err < 0)
1011
return err;
1012
err = build_mixers(chip,
1013
ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
1014
snd_pmac_screamer_mixers_imac);
1015
} else if (g4agp)
1016
err = build_mixers(chip,
1017
ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp),
1018
snd_pmac_screamer_mixers_g4agp);
1019
else
1020
err = build_mixers(chip,
1021
ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
1022
snd_pmac_awacs_mixers_pmac);
1023
if (err < 0)
1024
return err;
1025
chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard)
1026
? &snd_pmac_awacs_master_sw_imac
1027
: pm5500
1028
? &snd_pmac_awacs_master_sw_pmac5500
1029
: &snd_pmac_awacs_master_sw, chip);
1030
err = snd_ctl_add(chip->card, chip->master_sw_ctl);
1031
if (err < 0)
1032
return err;
1033
#ifdef PMAC_AMP_AVAIL
1034
if (chip->mixer_data) {
1035
/* use amplifier. the signal is connected from route A
1036
* to the amp. the amp has its headphone and speaker
1037
* volumes and mute switches, so we use them instead of
1038
* screamer registers.
1039
* in this case, it seems the route C is not used.
1040
*/
1041
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
1042
snd_pmac_awacs_amp_vol);
1043
if (err < 0)
1044
return err;
1045
/* overwrite */
1046
chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
1047
chip);
1048
err = snd_ctl_add(chip->card, chip->master_sw_ctl);
1049
if (err < 0)
1050
return err;
1051
chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
1052
chip);
1053
err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
1054
if (err < 0)
1055
return err;
1056
} else
1057
#endif /* PMAC_AMP_AVAIL */
1058
{
1059
/* route A = headphone, route C = speaker */
1060
err = snd_ctl_add(chip->card,
1061
(speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol,
1062
chip)));
1063
if (err < 0)
1064
return err;
1065
chip->speaker_sw_ctl = snd_ctl_new1(imac1
1066
? &snd_pmac_awacs_speaker_sw_imac1
1067
: imac2
1068
? &snd_pmac_awacs_speaker_sw_imac2
1069
: &snd_pmac_awacs_speaker_sw, chip);
1070
err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
1071
if (err < 0)
1072
return err;
1073
}
1074
1075
if (pm5500 || imac || lombard) {
1076
vmaster_sw = snd_ctl_make_virtual_master(
1077
"Master Playback Switch", (unsigned int *) NULL);
1078
err = snd_ctl_add_slave_uncached(vmaster_sw,
1079
chip->master_sw_ctl);
1080
if (err < 0)
1081
return err;
1082
err = snd_ctl_add_slave_uncached(vmaster_sw,
1083
chip->speaker_sw_ctl);
1084
if (err < 0)
1085
return err;
1086
err = snd_ctl_add(chip->card, vmaster_sw);
1087
if (err < 0)
1088
return err;
1089
vmaster_vol = snd_ctl_make_virtual_master(
1090
"Master Playback Volume", (unsigned int *) NULL);
1091
err = snd_ctl_add_slave(vmaster_vol, master_vol);
1092
if (err < 0)
1093
return err;
1094
err = snd_ctl_add_slave(vmaster_vol, speaker_vol);
1095
if (err < 0)
1096
return err;
1097
err = snd_ctl_add(chip->card, vmaster_vol);
1098
if (err < 0)
1099
return err;
1100
}
1101
1102
if (beige || g4agp)
1103
err = build_mixers(chip,
1104
ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
1105
snd_pmac_screamer_mic_boost_beige);
1106
else if (imac)
1107
err = build_mixers(chip,
1108
ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
1109
snd_pmac_screamer_mic_boost_imac);
1110
else if (chip->model == PMAC_SCREAMER)
1111
err = build_mixers(chip,
1112
ARRAY_SIZE(snd_pmac_screamer_mic_boost),
1113
snd_pmac_screamer_mic_boost);
1114
else if (pm7500)
1115
err = build_mixers(chip,
1116
ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
1117
snd_pmac_awacs_mic_boost_pmac7500);
1118
else
1119
err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
1120
snd_pmac_awacs_mic_boost);
1121
if (err < 0)
1122
return err;
1123
1124
/*
1125
* set lowlevel callbacks
1126
*/
1127
chip->set_format = snd_pmac_awacs_set_format;
1128
#ifdef CONFIG_PM
1129
chip->suspend = snd_pmac_awacs_suspend;
1130
chip->resume = snd_pmac_awacs_resume;
1131
#endif
1132
#ifdef PMAC_SUPPORT_AUTOMUTE
1133
err = snd_pmac_add_automute(chip);
1134
if (err < 0)
1135
return err;
1136
chip->detect_headphone = snd_pmac_awacs_detect_headphone;
1137
chip->update_automute = snd_pmac_awacs_update_automute;
1138
snd_pmac_awacs_update_automute(chip, 0); /* update the status only */
1139
#endif
1140
if (chip->model == PMAC_SCREAMER) {
1141
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
1142
snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
1143
}
1144
1145
return 0;
1146
}
1147
1148