cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

awacs.c (32048B)


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