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