OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [sound/] [ppc/] [awacs.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * PMac AWACS lowlevel functions
3
 *
4
 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
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 <sound/driver.h>
24
#include <asm/io.h>
25
#include <asm/nvram.h>
26
#include <linux/init.h>
27
#include <linux/delay.h>
28
#include <linux/slab.h>
29
#include <sound/core.h>
30
#include "pmac.h"
31
 
32
 
33
#ifdef CONFIG_ADB_CUDA
34
#define PMAC_AMP_AVAIL
35
#endif
36
 
37
#ifdef PMAC_AMP_AVAIL
38
struct awacs_amp {
39
        unsigned char amp_master;
40
        unsigned char amp_vol[2][2];
41
        unsigned char amp_tone[2];
42
};
43
 
44
#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA)
45
 
46
#endif /* PMAC_AMP_AVAIL */
47
 
48
 
49
static void snd_pmac_screamer_wait(struct snd_pmac *chip)
50
{
51
        long timeout = 2000;
52
        while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) {
53
                mdelay(1);
54
                if (! --timeout) {
55
                        snd_printd("snd_pmac_screamer_wait timeout\n");
56
                        break;
57
                }
58
        }
59
}
60
 
61
/*
62
 * write AWACS register
63
 */
64
static void
65
snd_pmac_awacs_write(struct snd_pmac *chip, int val)
66
{
67
        long timeout = 5000000;
68
 
69
        if (chip->model == PMAC_SCREAMER)
70
                snd_pmac_screamer_wait(chip);
71
        out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22));
72
        while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) {
73
                if (! --timeout) {
74
                        snd_printd("snd_pmac_awacs_write timeout\n");
75
                        break;
76
                }
77
        }
78
}
79
 
80
static void
81
snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val)
82
{
83
        snd_pmac_awacs_write(chip, val | (reg << 12));
84
        chip->awacs_reg[reg] = val;
85
}
86
 
87
static void
88
snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val)
89
{
90
        snd_pmac_awacs_write(chip, val | (reg << 12));
91
}
92
 
93
#ifdef CONFIG_PM
94
/* Recalibrate chip */
95
static void screamer_recalibrate(struct snd_pmac *chip)
96
{
97
        if (chip->model != PMAC_SCREAMER)
98
                return;
99
 
100
        /* Sorry for the horrible delays... I hope to get that improved
101
         * by making the whole PM process asynchronous in a future version
102
         */
103
        snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
104
        if (chip->manufacturer == 0x1)
105
                /* delay for broken crystal part */
106
                msleep(750);
107
        snd_pmac_awacs_write_noreg(chip, 1,
108
                                   chip->awacs_reg[1] | MASK_RECALIBRATE |
109
                                   MASK_CMUTE | MASK_AMUTE);
110
        snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
111
        snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
112
}
113
 
114
#else
115
#define screamer_recalibrate(chip) /* NOP */
116
#endif
117
 
118
 
119
/*
120
 * additional callback to set the pcm format
121
 */
122
static void snd_pmac_awacs_set_format(struct snd_pmac *chip)
123
{
124
        chip->awacs_reg[1] &= ~MASK_SAMPLERATE;
125
        chip->awacs_reg[1] |= chip->rate_index << 3;
126
        snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1]);
127
}
128
 
129
 
130
/*
131
 * AWACS volume callbacks
132
 */
133
/*
134
 * volumes: 0-15 stereo
135
 */
136
static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
137
                                      struct snd_ctl_elem_info *uinfo)
138
{
139
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
140
        uinfo->count = 2;
141
        uinfo->value.integer.min = 0;
142
        uinfo->value.integer.max = 15;
143
        return 0;
144
}
145
 
146
static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
147
                                     struct snd_ctl_elem_value *ucontrol)
148
{
149
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
150
        int reg = kcontrol->private_value & 0xff;
151
        int lshift = (kcontrol->private_value >> 8) & 0xff;
152
        int inverted = (kcontrol->private_value >> 16) & 1;
153
        unsigned long flags;
154
        int vol[2];
155
 
156
        spin_lock_irqsave(&chip->reg_lock, flags);
157
        vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf;
158
        vol[1] = chip->awacs_reg[reg] & 0xf;
159
        spin_unlock_irqrestore(&chip->reg_lock, flags);
160
        if (inverted) {
161
                vol[0] = 0x0f - vol[0];
162
                vol[1] = 0x0f - vol[1];
163
        }
164
        ucontrol->value.integer.value[0] = vol[0];
165
        ucontrol->value.integer.value[1] = vol[1];
166
        return 0;
167
}
168
 
169
static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol,
170
                                     struct snd_ctl_elem_value *ucontrol)
171
{
172
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
173
        int reg = kcontrol->private_value & 0xff;
174
        int lshift = (kcontrol->private_value >> 8) & 0xff;
175
        int inverted = (kcontrol->private_value >> 16) & 1;
176
        int val, oldval;
177
        unsigned long flags;
178
        int vol[2];
179
 
180
        vol[0] = ucontrol->value.integer.value[0];
181
        vol[1] = ucontrol->value.integer.value[1];
182
        if (inverted) {
183
                vol[0] = 0x0f - vol[0];
184
                vol[1] = 0x0f - vol[1];
185
        }
186
        vol[0] &= 0x0f;
187
        vol[1] &= 0x0f;
188
        spin_lock_irqsave(&chip->reg_lock, flags);
189
        oldval = chip->awacs_reg[reg];
190
        val = oldval & ~(0xf | (0xf << lshift));
191
        val |= vol[0] << lshift;
192
        val |= vol[1];
193
        if (oldval != val)
194
                snd_pmac_awacs_write_reg(chip, reg, val);
195
        spin_unlock_irqrestore(&chip->reg_lock, flags);
196
        return oldval != reg;
197
}
198
 
199
 
200
#define AWACS_VOLUME(xname, xreg, xshift, xinverted) \
201
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
202
  .info = snd_pmac_awacs_info_volume, \
203
  .get = snd_pmac_awacs_get_volume, \
204
  .put = snd_pmac_awacs_put_volume, \
205
  .private_value = (xreg) | ((xshift) << 8) | ((xinverted) << 16) }
206
 
207
/*
208
 * mute master/ogain for AWACS: mono
209
 */
210
static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol,
211
                                     struct snd_ctl_elem_value *ucontrol)
212
{
213
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
214
        int reg = kcontrol->private_value & 0xff;
215
        int shift = (kcontrol->private_value >> 8) & 0xff;
216
        int invert = (kcontrol->private_value >> 16) & 1;
217
        int val;
218
        unsigned long flags;
219
 
220
        spin_lock_irqsave(&chip->reg_lock, flags);
221
        val = (chip->awacs_reg[reg] >> shift) & 1;
222
        spin_unlock_irqrestore(&chip->reg_lock, flags);
223
        if (invert)
224
                val = 1 - val;
225
        ucontrol->value.integer.value[0] = val;
226
        return 0;
227
}
228
 
229
static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
230
                                     struct snd_ctl_elem_value *ucontrol)
231
{
232
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
233
        int reg = kcontrol->private_value & 0xff;
234
        int shift = (kcontrol->private_value >> 8) & 0xff;
235
        int invert = (kcontrol->private_value >> 16) & 1;
236
        int mask = 1 << shift;
237
        int val, changed;
238
        unsigned long flags;
239
 
240
        spin_lock_irqsave(&chip->reg_lock, flags);
241
        val = chip->awacs_reg[reg] & ~mask;
242
        if (ucontrol->value.integer.value[0] != invert)
243
                val |= mask;
244
        changed = chip->awacs_reg[reg] != val;
245
        if (changed)
246
                snd_pmac_awacs_write_reg(chip, reg, val);
247
        spin_unlock_irqrestore(&chip->reg_lock, flags);
248
        return changed;
249
}
250
 
251
#define AWACS_SWITCH(xname, xreg, xshift, xinvert) \
252
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
253
  .info = snd_pmac_boolean_mono_info, \
254
  .get = snd_pmac_awacs_get_switch, \
255
  .put = snd_pmac_awacs_put_switch, \
256
  .private_value = (xreg) | ((xshift) << 8) | ((xinvert) << 16) }
257
 
258
 
259
#ifdef PMAC_AMP_AVAIL
260
/*
261
 * controls for perch/whisper extension cards, e.g. G3 desktop
262
 *
263
 * TDA7433 connected via i2c address 0x45 (= 0x8a),
264
 * accessed through cuda
265
 */
266
static void awacs_set_cuda(int reg, int val)
267
{
268
        struct adb_request req;
269
        cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
270
        while (! req.complete)
271
                cuda_poll();
272
}
273
 
274
/*
275
 * level = 0 - 14, 7 = 0 dB
276
 */
277
static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
278
{
279
        amp->amp_tone[0] = bass;
280
        amp->amp_tone[1] = treble;
281
        if (bass > 7)
282
                bass = (14 - bass) + 8;
283
        if (treble > 7)
284
                treble = (14 - treble) + 8;
285
        awacs_set_cuda(2, (bass << 4) | treble);
286
}
287
 
288
/*
289
 * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
290
 */
291
static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
292
                             int do_check)
293
{
294
        if (do_check && amp->amp_vol[index][0] == lvol &&
295
            amp->amp_vol[index][1] == rvol)
296
                return 0;
297
        awacs_set_cuda(3 + index, lvol);
298
        awacs_set_cuda(5 + index, rvol);
299
        amp->amp_vol[index][0] = lvol;
300
        amp->amp_vol[index][1] = rvol;
301
        return 1;
302
}
303
 
304
/*
305
 * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB
306
 */
307
static void awacs_amp_set_master(struct awacs_amp *amp, int vol)
308
{
309
        amp->amp_master = vol;
310
        if (vol <= 79)
311
                vol = 32 + (79 - vol);
312
        else
313
                vol = 32 - (vol - 79);
314
        awacs_set_cuda(1, vol);
315
}
316
 
317
static void awacs_amp_free(struct snd_pmac *chip)
318
{
319
        struct awacs_amp *amp = chip->mixer_data;
320
        snd_assert(amp, return);
321
        kfree(amp);
322
        chip->mixer_data = NULL;
323
        chip->mixer_free = NULL;
324
}
325
 
326
 
327
/*
328
 * mixer controls
329
 */
330
static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
331
                                          struct snd_ctl_elem_info *uinfo)
332
{
333
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
334
        uinfo->count = 2;
335
        uinfo->value.integer.min = 0;
336
        uinfo->value.integer.max = 31;
337
        return 0;
338
}
339
 
340
static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
341
                                         struct snd_ctl_elem_value *ucontrol)
342
{
343
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
344
        int index = kcontrol->private_value;
345
        struct awacs_amp *amp = chip->mixer_data;
346
        snd_assert(amp, return -EINVAL);
347
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
348
        ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31);
349
        ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31);
350
        return 0;
351
}
352
 
353
static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
354
                                         struct snd_ctl_elem_value *ucontrol)
355
{
356
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
357
        int index = kcontrol->private_value;
358
        int vol[2];
359
        struct awacs_amp *amp = chip->mixer_data;
360
        snd_assert(amp, return -EINVAL);
361
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
362
 
363
        vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32);
364
        vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) | (amp->amp_vol[index][1] & 32);
365
        return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
366
}
367
 
368
static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
369
                                         struct snd_ctl_elem_value *ucontrol)
370
{
371
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
372
        int index = kcontrol->private_value;
373
        struct awacs_amp *amp = chip->mixer_data;
374
        snd_assert(amp, return -EINVAL);
375
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
376
        ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
377
        ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
378
        return 0;
379
}
380
 
381
static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
382
                                         struct snd_ctl_elem_value *ucontrol)
383
{
384
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
385
        int index = kcontrol->private_value;
386
        int vol[2];
387
        struct awacs_amp *amp = chip->mixer_data;
388
        snd_assert(amp, return -EINVAL);
389
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
390
 
391
        vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31);
392
        vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) | (amp->amp_vol[index][1] & 31);
393
        return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
394
}
395
 
396
static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
397
                                        struct snd_ctl_elem_info *uinfo)
398
{
399
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
400
        uinfo->count = 1;
401
        uinfo->value.integer.min = 0;
402
        uinfo->value.integer.max = 14;
403
        return 0;
404
}
405
 
406
static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
407
                                       struct snd_ctl_elem_value *ucontrol)
408
{
409
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
410
        int index = kcontrol->private_value;
411
        struct awacs_amp *amp = chip->mixer_data;
412
        snd_assert(amp, return -EINVAL);
413
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
414
        ucontrol->value.integer.value[0] = amp->amp_tone[index];
415
        return 0;
416
}
417
 
418
static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol,
419
                                       struct snd_ctl_elem_value *ucontrol)
420
{
421
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
422
        int index = kcontrol->private_value;
423
        struct awacs_amp *amp = chip->mixer_data;
424
        snd_assert(amp, return -EINVAL);
425
        snd_assert(index >= 0 && index <= 1, return -EINVAL);
426
        if (ucontrol->value.integer.value[0] != amp->amp_tone[index]) {
427
                amp->amp_tone[index] = ucontrol->value.integer.value[0];
428
                awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
429
                return 1;
430
        }
431
        return 0;
432
}
433
 
434
static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
435
                                          struct snd_ctl_elem_info *uinfo)
436
{
437
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
438
        uinfo->count = 1;
439
        uinfo->value.integer.min = 0;
440
        uinfo->value.integer.max = 99;
441
        return 0;
442
}
443
 
444
static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
445
                                         struct snd_ctl_elem_value *ucontrol)
446
{
447
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
448
        struct awacs_amp *amp = chip->mixer_data;
449
        snd_assert(amp, return -EINVAL);
450
        ucontrol->value.integer.value[0] = amp->amp_master;
451
        return 0;
452
}
453
 
454
static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
455
                                         struct snd_ctl_elem_value *ucontrol)
456
{
457
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
458
        struct awacs_amp *amp = chip->mixer_data;
459
        snd_assert(amp, return -EINVAL);
460
        if (ucontrol->value.integer.value[0] != amp->amp_master) {
461
                amp->amp_master = ucontrol->value.integer.value[0];
462
                awacs_amp_set_master(amp, amp->amp_master);
463
                return 1;
464
        }
465
        return 0;
466
}
467
 
468
#define AMP_CH_SPK      0
469
#define AMP_CH_HD       1
470
 
471
static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __initdata = {
472
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
473
          .name = "PC Speaker Playback Volume",
474
          .info = snd_pmac_awacs_info_volume_amp,
475
          .get = snd_pmac_awacs_get_volume_amp,
476
          .put = snd_pmac_awacs_put_volume_amp,
477
          .private_value = AMP_CH_SPK,
478
        },
479
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
480
          .name = "Headphone Playback Volume",
481
          .info = snd_pmac_awacs_info_volume_amp,
482
          .get = snd_pmac_awacs_get_volume_amp,
483
          .put = snd_pmac_awacs_put_volume_amp,
484
          .private_value = AMP_CH_HD,
485
        },
486
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
487
          .name = "Tone Control - Bass",
488
          .info = snd_pmac_awacs_info_tone_amp,
489
          .get = snd_pmac_awacs_get_tone_amp,
490
          .put = snd_pmac_awacs_put_tone_amp,
491
          .private_value = 0,
492
        },
493
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494
          .name = "Tone Control - Treble",
495
          .info = snd_pmac_awacs_info_tone_amp,
496
          .get = snd_pmac_awacs_get_tone_amp,
497
          .put = snd_pmac_awacs_put_tone_amp,
498
          .private_value = 1,
499
        },
500
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
501
          .name = "Amp Master Playback Volume",
502
          .info = snd_pmac_awacs_info_master_amp,
503
          .get = snd_pmac_awacs_get_master_amp,
504
          .put = snd_pmac_awacs_put_master_amp,
505
        },
506
};
507
 
508
static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __initdata = {
509
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
510
        .name = "Headphone Playback Switch",
511
        .info = snd_pmac_boolean_stereo_info,
512
        .get = snd_pmac_awacs_get_switch_amp,
513
        .put = snd_pmac_awacs_put_switch_amp,
514
        .private_value = AMP_CH_HD,
515
};
516
 
517
static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __initdata = {
518
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
519
        .name = "PC Speaker 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_SPK,
524
};
525
 
526
#endif /* PMAC_AMP_AVAIL */
527
 
528
 
529
/*
530
 * mic boost for screamer
531
 */
532
static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
533
                                            struct snd_ctl_elem_info *uinfo)
534
{
535
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
536
        uinfo->count = 1;
537
        uinfo->value.integer.min = 0;
538
        uinfo->value.integer.max = 2;
539
        return 0;
540
}
541
 
542
static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
543
                                           struct snd_ctl_elem_value *ucontrol)
544
{
545
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
546
        int val;
547
        unsigned long flags;
548
 
549
        spin_lock_irqsave(&chip->reg_lock, flags);
550
        if (chip->awacs_reg[6] & MASK_MIC_BOOST)
551
                val = 2;
552
        else if (chip->awacs_reg[0] & MASK_GAINLINE)
553
                val = 1;
554
        else
555
                val = 0;
556
        spin_unlock_irqrestore(&chip->reg_lock, flags);
557
        ucontrol->value.integer.value[0] = val;
558
        return 0;
559
}
560
 
561
static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
562
                                           struct snd_ctl_elem_value *ucontrol)
563
{
564
        struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
565
        int changed = 0;
566
        int val0, val6;
567
        unsigned long flags;
568
 
569
        spin_lock_irqsave(&chip->reg_lock, flags);
570
        val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
571
        val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
572
        if (ucontrol->value.integer.value[0] > 0) {
573
                val0 |= MASK_GAINLINE;
574
                if (ucontrol->value.integer.value[0] > 1)
575
                        val6 |= MASK_MIC_BOOST;
576
        }
577
        if (val0 != chip->awacs_reg[0]) {
578
                snd_pmac_awacs_write_reg(chip, 0, val0);
579
                changed = 1;
580
        }
581
        if (val6 != chip->awacs_reg[6]) {
582
                snd_pmac_awacs_write_reg(chip, 6, val6);
583
                changed = 1;
584
        }
585
        spin_unlock_irqrestore(&chip->reg_lock, flags);
586
        return changed;
587
}
588
 
589
/*
590
 * lists of mixer elements
591
 */
592
static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
593
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
594
        AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
595
        AWACS_VOLUME("Capture Volume", 0, 4, 0),
596
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
597
};
598
 
599
/* FIXME: is this correct order?
600
 * screamer (powerbook G3 pismo) seems to have different bits...
601
 */
602
static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __initdata = {
603
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
604
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
605
};
606
 
607
static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
608
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
609
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
610
};
611
 
612
static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
613
AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
614
 
615
static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
616
        AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
617
};
618
 
619
static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
620
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
621
          .name = "Mic Boost",
622
          .info = snd_pmac_screamer_mic_boost_info,
623
          .get = snd_pmac_screamer_mic_boost_get,
624
          .put = snd_pmac_screamer_mic_boost_put,
625
        },
626
};
627
 
628
static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
629
        AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
630
};
631
static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
632
AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
633
 
634
 
635
/*
636
 * add new mixer elements to the card
637
 */
638
static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
639
{
640
        int i, err;
641
 
642
        for (i = 0; i < nums; i++) {
643
                if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
644
                        return err;
645
        }
646
        return 0;
647
}
648
 
649
 
650
/*
651
 * restore all registers
652
 */
653
static void awacs_restore_all_regs(struct snd_pmac *chip)
654
{
655
        snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
656
        snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
657
        snd_pmac_awacs_write_noreg(chip, 2, chip->awacs_reg[2]);
658
        snd_pmac_awacs_write_noreg(chip, 4, chip->awacs_reg[4]);
659
        if (chip->model == PMAC_SCREAMER) {
660
                snd_pmac_awacs_write_noreg(chip, 5, chip->awacs_reg[5]);
661
                snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
662
                snd_pmac_awacs_write_noreg(chip, 7, chip->awacs_reg[7]);
663
        }
664
}
665
 
666
#ifdef CONFIG_PM
667
static void snd_pmac_awacs_suspend(struct snd_pmac *chip)
668
{
669
        snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1]
670
                                             | MASK_AMUTE | MASK_CMUTE));
671
}
672
 
673
static void snd_pmac_awacs_resume(struct snd_pmac *chip)
674
{
675
        if (machine_is_compatible("PowerBook3,1")
676
            || machine_is_compatible("PowerBook3,2")) {
677
                msleep(100);
678
                snd_pmac_awacs_write_reg(chip, 1,
679
                        chip->awacs_reg[1] & ~MASK_PAROUT);
680
                msleep(300);
681
        }
682
 
683
        awacs_restore_all_regs(chip);
684
        if (chip->model == PMAC_SCREAMER) {
685
                /* reset power bits in reg 6 */
686
                mdelay(5);
687
                snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
688
        }
689
        screamer_recalibrate(chip);
690
#ifdef PMAC_AMP_AVAIL
691
        if (chip->mixer_data) {
692
                struct awacs_amp *amp = chip->mixer_data;
693
                awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
694
                awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
695
                awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
696
                awacs_amp_set_master(amp, amp->amp_master);
697
        }
698
#endif
699
}
700
#endif /* CONFIG_PM */
701
 
702
#ifdef PMAC_SUPPORT_AUTOMUTE
703
/*
704
 * auto-mute stuffs
705
 */
706
static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip)
707
{
708
        return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
709
}
710
 
711
#ifdef PMAC_AMP_AVAIL
712
static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute)
713
{
714
        int vol[2];
715
        vol[0] = amp->amp_vol[index][0] & 31;
716
        vol[1] = amp->amp_vol[index][1] & 31;
717
        if (mute) {
718
                vol[0] |= 32;
719
                vol[1] |= 32;
720
        }
721
        return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
722
}
723
#endif
724
 
725
static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
726
{
727
        if (chip->auto_mute) {
728
#ifdef PMAC_AMP_AVAIL
729
                if (chip->mixer_data) {
730
                        struct awacs_amp *amp = chip->mixer_data;
731
                        int changed;
732
                        if (snd_pmac_awacs_detect_headphone(chip)) {
733
                                changed = toggle_amp_mute(amp, AMP_CH_HD, 0);
734
                                changed |= toggle_amp_mute(amp, AMP_CH_SPK, 1);
735
                        } else {
736
                                changed = toggle_amp_mute(amp, AMP_CH_HD, 1);
737
                                changed |= toggle_amp_mute(amp, AMP_CH_SPK, 0);
738
                        }
739
                        if (do_notify && ! changed)
740
                                return;
741
                } else
742
#endif
743
                {
744
                        int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
745
                        if (snd_pmac_awacs_detect_headphone(chip))
746
                                reg &= ~MASK_HDMUTE;
747
                        else
748
                                reg &= ~MASK_SPKMUTE;
749
                        if (do_notify && reg == chip->awacs_reg[1])
750
                                return;
751
                        snd_pmac_awacs_write_reg(chip, 1, reg);
752
                }
753
                if (do_notify) {
754
                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
755
                                       &chip->master_sw_ctl->id);
756
                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
757
                                       &chip->speaker_sw_ctl->id);
758
                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
759
                                       &chip->hp_detect_ctl->id);
760
                }
761
        }
762
}
763
#endif /* PMAC_SUPPORT_AUTOMUTE */
764
 
765
 
766
/*
767
 * initialize chip
768
 */
769
int __init
770
snd_pmac_awacs_init(struct snd_pmac *chip)
771
{
772
        int err, vol;
773
 
774
        /* looks like MASK_GAINLINE triggers something, so we set here
775
         * as start-up
776
         */
777
        chip->awacs_reg[0] = MASK_MUX_CD | 0xff | MASK_GAINLINE;
778
        chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
779
        /* FIXME: Only machines with external SRS module need MASK_PAROUT */
780
        if (chip->has_iic || chip->device_id == 0x5 ||
781
            /*chip->_device_id == 0x8 || */
782
            chip->device_id == 0xb)
783
                chip->awacs_reg[1] |= MASK_PAROUT;
784
        /* get default volume from nvram */
785
        // vol = (~nvram_read_byte(0x1308) & 7) << 1;
786
        // vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );
787
        vol = 0x0f; /* no, on alsa, muted as default */
788
        vol = vol + (vol << 6);
789
        chip->awacs_reg[2] = vol;
790
        chip->awacs_reg[4] = vol;
791
        if (chip->model == PMAC_SCREAMER) {
792
                chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
793
                chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
794
                chip->awacs_reg[7] = 0;
795
        }
796
 
797
        awacs_restore_all_regs(chip);
798
        chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf;
799
        screamer_recalibrate(chip);
800
 
801
        chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
802
#ifdef PMAC_AMP_AVAIL
803
        if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {
804
                struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL);
805
                if (! amp)
806
                        return -ENOMEM;
807
                chip->mixer_data = amp;
808
                chip->mixer_free = awacs_amp_free;
809
                awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
810
                awacs_amp_set_vol(amp, 1, 63, 63, 0);
811
                awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
812
                awacs_amp_set_master(amp, 79); /* 0 dB */
813
        }
814
#endif /* PMAC_AMP_AVAIL */
815
 
816
        if (chip->hp_stat_mask == 0) {
817
                /* set headphone-jack detection bit */
818
                switch (chip->model) {
819
                case PMAC_AWACS:
820
                        chip->hp_stat_mask = 0x04;
821
                        break;
822
                case PMAC_SCREAMER:
823
                        switch (chip->device_id) {
824
                        case 0x08:
825
                                /* 1 = side jack, 2 = front jack */
826
                                chip->hp_stat_mask = 0x03;
827
                                break;
828
                        case 0x00:
829
                        case 0x05:
830
                                chip->hp_stat_mask = 0x04;
831
                                break;
832
                        default:
833
                                chip->hp_stat_mask = 0x08;
834
                                break;
835
                        }
836
                        break;
837
                default:
838
                        snd_BUG();
839
                        break;
840
                }
841
        }
842
 
843
        /*
844
         * build mixers
845
         */
846
        strcpy(chip->card->mixername, "PowerMac AWACS");
847
 
848
        if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
849
                                snd_pmac_awacs_mixers)) < 0)
850
                return err;
851
        if (chip->model == PMAC_SCREAMER)
852
                err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
853
                                   snd_pmac_screamer_mixers2);
854
        else
855
                err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
856
                                   snd_pmac_awacs_mixers2);
857
        if (err < 0)
858
                return err;
859
        chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
860
        if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
861
                return err;
862
#ifdef PMAC_AMP_AVAIL
863
        if (chip->mixer_data) {
864
                /* use amplifier.  the signal is connected from route A
865
                 * to the amp.  the amp has its headphone and speaker
866
                 * volumes and mute switches, so we use them instead of
867
                 * screamer registers.
868
                 * in this case, it seems the route C is not used.
869
                 */
870
                if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
871
                                        snd_pmac_awacs_amp_vol)) < 0)
872
                        return err;
873
                /* overwrite */
874
                chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
875
                if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
876
                        return err;
877
                chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
878
                if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
879
                        return err;
880
        } else
881
#endif /* PMAC_AMP_AVAIL */
882
        {
883
                /* route A = headphone, route C = speaker */
884
                if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
885
                                        snd_pmac_awacs_speaker_vol)) < 0)
886
                        return err;
887
                chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
888
                if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
889
                        return err;
890
        }
891
 
892
        if (chip->model == PMAC_SCREAMER) {
893
                if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
894
                                        snd_pmac_screamer_mic_boost)) < 0)
895
                        return err;
896
        } else {
897
                if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
898
                                        snd_pmac_awacs_mic_boost)) < 0)
899
                        return err;
900
        }
901
 
902
        /*
903
         * set lowlevel callbacks
904
         */
905
        chip->set_format = snd_pmac_awacs_set_format;
906
#ifdef CONFIG_PM
907
        chip->suspend = snd_pmac_awacs_suspend;
908
        chip->resume = snd_pmac_awacs_resume;
909
#endif
910
#ifdef PMAC_SUPPORT_AUTOMUTE
911
        if ((err = snd_pmac_add_automute(chip)) < 0)
912
                return err;
913
        chip->detect_headphone = snd_pmac_awacs_detect_headphone;
914
        chip->update_automute = snd_pmac_awacs_update_automute;
915
        snd_pmac_awacs_update_automute(chip, 0); /* update the status only */
916
#endif
917
        if (chip->model == PMAC_SCREAMER) {
918
                snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
919
                snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
920
        }
921
 
922
        return 0;
923
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.