diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/ppc')
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/Kconfig | 52 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/Makefile | 10 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/awacs.c | 1146 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/awacs.h | 205 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/beep.c | 285 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/burgundy.c | 732 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/burgundy.h | 114 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/daca.c | 282 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/keywest.c | 147 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/pmac.c | 1410 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/pmac.h | 210 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/powermac.c | 195 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/snd_ps3.c | 1160 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/snd_ps3.h | 136 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h | 891 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/tumbler.c | 1495 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/ppc/tumbler_volume.h | 250 |
17 files changed, 0 insertions, 8720 deletions
diff --git a/ANDROID_3.4.5/sound/ppc/Kconfig b/ANDROID_3.4.5/sound/ppc/Kconfig deleted file mode 100644 index 0519c60f..00000000 --- a/ANDROID_3.4.5/sound/ppc/Kconfig +++ /dev/null @@ -1,52 +0,0 @@ -# ALSA PowerMac drivers - -menuconfig SND_PPC - bool "PowerPC sound devices" - depends on PPC - default y - help - Support for sound devices specific to PowerPC architectures. - -if SND_PPC - -config SND_POWERMAC - tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)" - depends on I2C && INPUT && PPC_PMAC - select SND_PCM - select SND_VMASTER - help - Say Y here to include support for the integrated sound device. - - To compile this driver as a module, choose M here: the module - will be called snd-powermac. - -config SND_POWERMAC_AUTO_DRC - bool "Toggle DRC automatically at headphone/line plug-in" - depends on SND_POWERMAC - default y - help - Say Y here to enable the automatic toggle of DRC (dynamic - range compression) on Tumbler/Snapper. - If this feature is enabled, DRC is turned off when the - headphone/line jack is plugged, and turned on when unplugged. - - Note that you can turn on/off DRC manually even without this - option. - -config SND_PS3 - tristate "PS3 Audio support" - depends on PS3_PS3AV - select SND_PCM - default m - help - Say Y here to include support for audio on the PS3 - - To compile this driver as a module, choose M here: the module - will be called snd_ps3. - -config SND_PS3_DEFAULT_START_DELAY - int "Startup delay time in ms" - depends on SND_PS3 - default "2000" - -endif # SND_PPC diff --git a/ANDROID_3.4.5/sound/ppc/Makefile b/ANDROID_3.4.5/sound/ppc/Makefile deleted file mode 100644 index 679c45a8..00000000 --- a/ANDROID_3.4.5/sound/ppc/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o -obj-$(CONFIG_SND_PS3) += snd_ps3.o diff --git a/ANDROID_3.4.5/sound/ppc/awacs.c b/ANDROID_3.4.5/sound/ppc/awacs.c deleted file mode 100644 index b3667938..00000000 --- a/ANDROID_3.4.5/sound/ppc/awacs.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * PMac AWACS lowlevel functions - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * code based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <asm/io.h> -#include <asm/nvram.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <sound/core.h> -#include "pmac.h" - - -#ifdef CONFIG_ADB_CUDA -#define PMAC_AMP_AVAIL -#endif - -#ifdef PMAC_AMP_AVAIL -struct awacs_amp { - unsigned char amp_master; - unsigned char amp_vol[2][2]; - unsigned char amp_tone[2]; -}; - -#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA) - -#endif /* PMAC_AMP_AVAIL */ - - -static void snd_pmac_screamer_wait(struct snd_pmac *chip) -{ - long timeout = 2000; - while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) { - mdelay(1); - if (! --timeout) { - snd_printd("snd_pmac_screamer_wait timeout\n"); - break; - } - } -} - -/* - * write AWACS register - */ -static void -snd_pmac_awacs_write(struct snd_pmac *chip, int val) -{ - long timeout = 5000000; - - if (chip->model == PMAC_SCREAMER) - snd_pmac_screamer_wait(chip); - out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22)); - while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) { - if (! --timeout) { - snd_printd("snd_pmac_awacs_write timeout\n"); - break; - } - } -} - -static void -snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val) -{ - snd_pmac_awacs_write(chip, val | (reg << 12)); - chip->awacs_reg[reg] = val; -} - -static void -snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val) -{ - snd_pmac_awacs_write(chip, val | (reg << 12)); -} - -#ifdef CONFIG_PM -/* Recalibrate chip */ -static void screamer_recalibrate(struct snd_pmac *chip) -{ - if (chip->model != PMAC_SCREAMER) - return; - - /* Sorry for the horrible delays... I hope to get that improved - * by making the whole PM process asynchronous in a future version - */ - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - if (chip->manufacturer == 0x1) - /* delay for broken crystal part */ - msleep(750); - snd_pmac_awacs_write_noreg(chip, 1, - chip->awacs_reg[1] | MASK_RECALIBRATE | - MASK_CMUTE | MASK_AMUTE); - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); -} - -#else -#define screamer_recalibrate(chip) /* NOP */ -#endif - - -/* - * additional callback to set the pcm format - */ -static void snd_pmac_awacs_set_format(struct snd_pmac *chip) -{ - chip->awacs_reg[1] &= ~MASK_SAMPLERATE; - chip->awacs_reg[1] |= chip->rate_index << 3; - snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1]); -} - - -/* - * AWACS volume callbacks - */ -/* - * volumes: 0-15 stereo - */ -static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 15; - return 0; -} - -static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int lshift = (kcontrol->private_value >> 8) & 0xff; - int inverted = (kcontrol->private_value >> 16) & 1; - unsigned long flags; - int vol[2]; - - spin_lock_irqsave(&chip->reg_lock, flags); - vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf; - vol[1] = chip->awacs_reg[reg] & 0xf; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (inverted) { - vol[0] = 0x0f - vol[0]; - vol[1] = 0x0f - vol[1]; - } - ucontrol->value.integer.value[0] = vol[0]; - ucontrol->value.integer.value[1] = vol[1]; - return 0; -} - -static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int lshift = (kcontrol->private_value >> 8) & 0xff; - int inverted = (kcontrol->private_value >> 16) & 1; - int val, oldval; - unsigned long flags; - unsigned int vol[2]; - - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] > 0x0f || vol[1] > 0x0f) - return -EINVAL; - if (inverted) { - vol[0] = 0x0f - vol[0]; - vol[1] = 0x0f - vol[1]; - } - vol[0] &= 0x0f; - vol[1] &= 0x0f; - spin_lock_irqsave(&chip->reg_lock, flags); - oldval = chip->awacs_reg[reg]; - val = oldval & ~(0xf | (0xf << lshift)); - val |= vol[0] << lshift; - val |= vol[1]; - if (oldval != val) - snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return oldval != reg; -} - - -#define AWACS_VOLUME(xname, xreg, xshift, xinverted) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_pmac_awacs_info_volume, \ - .get = snd_pmac_awacs_get_volume, \ - .put = snd_pmac_awacs_put_volume, \ - .private_value = (xreg) | ((xshift) << 8) | ((xinverted) << 16) } - -/* - * mute master/ogain for AWACS: mono - */ -static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 16) & 1; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->awacs_reg[reg] >> shift) & 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - val = 1 - val; - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 16) & 1; - int mask = 1 << shift; - int val, changed; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val = chip->awacs_reg[reg] & ~mask; - if (ucontrol->value.integer.value[0] != invert) - val |= mask; - changed = chip->awacs_reg[reg] != val; - if (changed) - snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return changed; -} - -#define AWACS_SWITCH(xname, xreg, xshift, xinvert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_pmac_boolean_mono_info, \ - .get = snd_pmac_awacs_get_switch, \ - .put = snd_pmac_awacs_put_switch, \ - .private_value = (xreg) | ((xshift) << 8) | ((xinvert) << 16) } - - -#ifdef PMAC_AMP_AVAIL -/* - * controls for perch/whisper extension cards, e.g. G3 desktop - * - * TDA7433 connected via i2c address 0x45 (= 0x8a), - * accessed through cuda - */ -static void awacs_set_cuda(int reg, int val) -{ - struct adb_request req; - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, - reg, val); - while (! req.complete) - cuda_poll(); -} - -/* - * level = 0 - 14, 7 = 0 dB - */ -static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble) -{ - amp->amp_tone[0] = bass; - amp->amp_tone[1] = treble; - if (bass > 7) - bass = (14 - bass) + 8; - if (treble > 7) - treble = (14 - treble) + 8; - awacs_set_cuda(2, (bass << 4) | treble); -} - -/* - * vol = 0 - 31 (attenuation), 32 = mute bit, stereo - */ -static int awacs_amp_set_vol(struct awacs_amp *amp, int index, - int lvol, int rvol, int do_check) -{ - if (do_check && amp->amp_vol[index][0] == lvol && - amp->amp_vol[index][1] == rvol) - return 0; - awacs_set_cuda(3 + index, lvol); - awacs_set_cuda(5 + index, rvol); - amp->amp_vol[index][0] = lvol; - amp->amp_vol[index][1] = rvol; - return 1; -} - -/* - * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB - */ -static void awacs_amp_set_master(struct awacs_amp *amp, int vol) -{ - amp->amp_master = vol; - if (vol <= 79) - vol = 32 + (79 - vol); - else - vol = 32 - (vol - 79); - awacs_set_cuda(1, vol); -} - -static void awacs_amp_free(struct snd_pmac *chip) -{ - struct awacs_amp *amp = chip->mixer_data; - if (!amp) - return; - kfree(amp); - chip->mixer_data = NULL; - chip->mixer_free = NULL; -} - - -/* - * mixer controls - */ -static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 31; - return 0; -} - -static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31); - ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31); - return 0; -} - -static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int vol[2]; - struct awacs_amp *amp = chip->mixer_data; - - vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) - | (amp->amp_vol[index][0] & 32); - vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) - | (amp->amp_vol[index][1] & 32); - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} - -static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) - ? 0 : 1; - ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) - ? 0 : 1; - return 0; -} - -static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int vol[2]; - struct awacs_amp *amp = chip->mixer_data; - - vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) - | (amp->amp_vol[index][0] & 31); - vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) - | (amp->amp_vol[index][1] & 31); - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} - -static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 14; - return 0; -} - -static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = amp->amp_tone[index]; - return 0; -} - -static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - unsigned int val; - - val = ucontrol->value.integer.value[0]; - if (val > 14) - return -EINVAL; - if (val != amp->amp_tone[index]) { - amp->amp_tone[index] = val; - awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]); - return 1; - } - return 0; -} - -static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 99; - return 0; -} - -static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = amp->amp_master; - return 0; -} - -static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct awacs_amp *amp = chip->mixer_data; - unsigned int val; - - val = ucontrol->value.integer.value[0]; - if (val > 99) - return -EINVAL; - if (val != amp->amp_master) { - amp->amp_master = val; - awacs_amp_set_master(amp, amp->amp_master); - return 1; - } - return 0; -} - -#define AMP_CH_SPK 0 -#define AMP_CH_HD 1 - -static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Volume", - .info = snd_pmac_awacs_info_volume_amp, - .get = snd_pmac_awacs_get_volume_amp, - .put = snd_pmac_awacs_put_volume_amp, - .private_value = AMP_CH_SPK, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = snd_pmac_awacs_info_volume_amp, - .get = snd_pmac_awacs_get_volume_amp, - .put = snd_pmac_awacs_put_volume_amp, - .private_value = AMP_CH_HD, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Tone Control - Bass", - .info = snd_pmac_awacs_info_tone_amp, - .get = snd_pmac_awacs_get_tone_amp, - .put = snd_pmac_awacs_put_tone_amp, - .private_value = 0, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Tone Control - Treble", - .info = snd_pmac_awacs_info_tone_amp, - .get = snd_pmac_awacs_get_tone_amp, - .put = snd_pmac_awacs_put_tone_amp, - .private_value = 1, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Amp Master Playback Volume", - .info = snd_pmac_awacs_info_master_amp, - .get = snd_pmac_awacs_get_master_amp, - .put = snd_pmac_awacs_put_master_amp, - }, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = snd_pmac_awacs_get_switch_amp, - .put = snd_pmac_awacs_put_switch_amp, - .private_value = AMP_CH_HD, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = snd_pmac_awacs_get_switch_amp, - .put = snd_pmac_awacs_put_switch_amp, - .private_value = AMP_CH_SPK, -}; - -#endif /* PMAC_AMP_AVAIL */ - - -/* - * mic boost for screamer - */ -static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 3; - return 0; -} - -static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->awacs_reg[6] & MASK_MIC_BOOST) - val |= 2; - if (chip->awacs_reg[0] & MASK_GAINLINE) - val |= 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int val0, val6; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val0 = chip->awacs_reg[0] & ~MASK_GAINLINE; - val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST; - if (ucontrol->value.integer.value[0] & 1) - val0 |= MASK_GAINLINE; - if (ucontrol->value.integer.value[0] & 2) - val6 |= MASK_MIC_BOOST; - if (val0 != chip->awacs_reg[0]) { - snd_pmac_awacs_write_reg(chip, 0, val0); - changed = 1; - } - if (val6 != chip->awacs_reg[6]) { - snd_pmac_awacs_write_reg(chip, 6, val6); - changed = 1; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return changed; -} - -/* - * lists of mixer elements - */ -static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = { - AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0), - AWACS_VOLUME("Master Capture Volume", 0, 4, 0), -/* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */ -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = { - AWACS_VOLUME("Master Playback Volume", 2, 6, 1), - AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = { - AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), - AWACS_VOLUME("Master Playback Volume", 5, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = { - AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = { - AWACS_VOLUME("Master Playback Volume", 2, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -/* FIXME: is this correct order? - * screamer (powerbook G3 pismo) seems to have different bits... - */ -static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = { - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0), - AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = { - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), - AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = { - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata = -AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata = -AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata = -AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = { - AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost Capture Volume", - .info = snd_pmac_screamer_mic_boost_info, - .get = snd_pmac_screamer_mic_boost_get, - .put = snd_pmac_screamer_mic_boost_put, - }, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), - AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), - AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = { - AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0); - - -/* - * add new mixer elements to the card - */ -static int build_mixers(struct snd_pmac *chip, int nums, - struct snd_kcontrol_new *mixers) -{ - int i, err; - - for (i = 0; i < nums; i++) { - err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip)); - if (err < 0) - return err; - } - return 0; -} - - -/* - * restore all registers - */ -static void awacs_restore_all_regs(struct snd_pmac *chip) -{ - snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]); - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - snd_pmac_awacs_write_noreg(chip, 2, chip->awacs_reg[2]); - snd_pmac_awacs_write_noreg(chip, 4, chip->awacs_reg[4]); - if (chip->model == PMAC_SCREAMER) { - snd_pmac_awacs_write_noreg(chip, 5, chip->awacs_reg[5]); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - snd_pmac_awacs_write_noreg(chip, 7, chip->awacs_reg[7]); - } -} - -#ifdef CONFIG_PM -static void snd_pmac_awacs_suspend(struct snd_pmac *chip) -{ - snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] - | MASK_AMUTE | MASK_CMUTE)); -} - -static void snd_pmac_awacs_resume(struct snd_pmac *chip) -{ - if (of_machine_is_compatible("PowerBook3,1") - || of_machine_is_compatible("PowerBook3,2")) { - msleep(100); - snd_pmac_awacs_write_reg(chip, 1, - chip->awacs_reg[1] & ~MASK_PAROUT); - msleep(300); - } - - awacs_restore_all_regs(chip); - if (chip->model == PMAC_SCREAMER) { - /* reset power bits in reg 6 */ - mdelay(5); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - } - screamer_recalibrate(chip); -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - struct awacs_amp *amp = chip->mixer_data; - awacs_amp_set_vol(amp, 0, - amp->amp_vol[0][0], amp->amp_vol[0][1], 0); - awacs_amp_set_vol(amp, 1, - amp->amp_vol[1][0], amp->amp_vol[1][1], 0); - awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]); - awacs_amp_set_master(amp, amp->amp_master); - } -#endif -} -#endif /* CONFIG_PM */ - -#define IS_PM7500 (of_machine_is_compatible("AAPL,7500") \ - || of_machine_is_compatible("AAPL,8500") \ - || of_machine_is_compatible("AAPL,9500")) -#define IS_PM5500 (of_machine_is_compatible("AAPL,e411")) -#define IS_BEIGE (of_machine_is_compatible("AAPL,Gossamer")) -#define IS_IMAC1 (of_machine_is_compatible("PowerMac2,1")) -#define IS_IMAC2 (of_machine_is_compatible("PowerMac2,2") \ - || of_machine_is_compatible("PowerMac4,1")) -#define IS_G4AGP (of_machine_is_compatible("PowerMac3,1")) -#define IS_LOMBARD (of_machine_is_compatible("PowerBook1,1")) - -static int imac1, imac2; - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip) -{ - return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0; -} - -#ifdef PMAC_AMP_AVAIL -static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute) -{ - int vol[2]; - vol[0] = amp->amp_vol[index][0] & 31; - vol[1] = amp->amp_vol[index][1] & 31; - if (mute) { - vol[0] |= 32; - vol[1] |= 32; - } - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} -#endif - -static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - struct awacs_amp *amp = chip->mixer_data; - int changed; - if (snd_pmac_awacs_detect_headphone(chip)) { - changed = toggle_amp_mute(amp, AMP_CH_HD, 0); - changed |= toggle_amp_mute(amp, AMP_CH_SPK, 1); - } else { - changed = toggle_amp_mute(amp, AMP_CH_HD, 1); - changed |= toggle_amp_mute(amp, AMP_CH_SPK, 0); - } - if (do_notify && ! changed) - return; - } else -#endif - { - int reg = chip->awacs_reg[1] - | (MASK_HDMUTE | MASK_SPKMUTE); - if (imac1) { - reg &= ~MASK_SPKMUTE; - reg |= MASK_PAROUT1; - } else if (imac2) { - reg &= ~MASK_SPKMUTE; - reg &= ~MASK_PAROUT1; - } - if (snd_pmac_awacs_detect_headphone(chip)) - reg &= ~MASK_HDMUTE; - else if (imac1) - reg &= ~MASK_PAROUT1; - else if (imac2) - reg |= MASK_PAROUT1; - else - reg &= ~MASK_SPKMUTE; - if (do_notify && reg == chip->awacs_reg[1]) - return; - snd_pmac_awacs_write_reg(chip, 1, reg); - } - if (do_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->speaker_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - } - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* - * initialize chip - */ -int __devinit -snd_pmac_awacs_init(struct snd_pmac *chip) -{ - int pm7500 = IS_PM7500; - int pm5500 = IS_PM5500; - int beige = IS_BEIGE; - int g4agp = IS_G4AGP; - int lombard = IS_LOMBARD; - int imac; - int err, vol; - struct snd_kcontrol *vmaster_sw, *vmaster_vol; - struct snd_kcontrol *master_vol, *speaker_vol; - - imac1 = IS_IMAC1; - imac2 = IS_IMAC2; - imac = imac1 || imac2; - /* looks like MASK_GAINLINE triggers something, so we set here - * as start-up - */ - chip->awacs_reg[0] = MASK_MUX_CD | 0xff | MASK_GAINLINE; - chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE; - /* FIXME: Only machines with external SRS module need MASK_PAROUT */ - if (chip->has_iic || chip->device_id == 0x5 || - /* chip->_device_id == 0x8 || */ - chip->device_id == 0xb) - chip->awacs_reg[1] |= MASK_PAROUT; - /* get default volume from nvram */ - // vol = (~nvram_read_byte(0x1308) & 7) << 1; - // vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 ); - vol = 0x0f; /* no, on alsa, muted as default */ - vol = vol + (vol << 6); - chip->awacs_reg[2] = vol; - chip->awacs_reg[4] = vol; - if (chip->model == PMAC_SCREAMER) { - /* FIXME: screamer has loopthru vol control */ - chip->awacs_reg[5] = vol; - /* FIXME: maybe should be vol << 3 for PCMCIA speaker */ - chip->awacs_reg[6] = MASK_MIC_BOOST; - chip->awacs_reg[7] = 0; - } - - awacs_restore_all_regs(chip); - chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf; - screamer_recalibrate(chip); - - chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf; -#ifdef PMAC_AMP_AVAIL - if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) { - struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL); - if (! amp) - return -ENOMEM; - chip->mixer_data = amp; - chip->mixer_free = awacs_amp_free; - /* mute and zero vol */ - awacs_amp_set_vol(amp, 0, 63, 63, 0); - awacs_amp_set_vol(amp, 1, 63, 63, 0); - awacs_amp_set_tone(amp, 7, 7); /* 0 dB */ - awacs_amp_set_master(amp, 79); /* 0 dB */ - } -#endif /* PMAC_AMP_AVAIL */ - - if (chip->hp_stat_mask == 0) { - /* set headphone-jack detection bit */ - switch (chip->model) { - case PMAC_AWACS: - chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN - : MASK_LOCONN; - break; - case PMAC_SCREAMER: - switch (chip->device_id) { - case 0x08: - case 0x0B: - chip->hp_stat_mask = imac - ? MASK_LOCONN_IMAC | - MASK_HDPLCONN_IMAC | - MASK_HDPRCONN_IMAC - : MASK_HDPCONN; - break; - case 0x00: - case 0x05: - chip->hp_stat_mask = MASK_LOCONN; - break; - default: - chip->hp_stat_mask = MASK_HDPCONN; - break; - } - break; - default: - snd_BUG(); - break; - } - } - - /* - * build mixers - */ - strcpy(chip->card->mixername, "PowerMac AWACS"); - - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers), - snd_pmac_awacs_mixers); - if (err < 0) - return err; - if (beige || g4agp) - ; - else if (chip->model == PMAC_SCREAMER || pm5500) - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), - snd_pmac_screamer_mixers2); - else if (!pm7500) - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2), - snd_pmac_awacs_mixers2); - if (err < 0) - return err; - if (pm5500) { - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500), - snd_pmac_awacs_mixers2_pmac5500); - if (err < 0) - return err; - } - if (pm7500) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500), - snd_pmac_awacs_mixers_pmac7500); - else if (pm5500) - err = snd_ctl_add(chip->card, - (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500, - chip))); - else if (beige) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_beige), - snd_pmac_screamer_mixers_beige); - else if (imac || lombard) { - err = snd_ctl_add(chip->card, - (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo, - chip))); - if (err < 0) - return err; - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_imac), - snd_pmac_screamer_mixers_imac); - } else if (g4agp) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp), - snd_pmac_screamer_mixers_g4agp); - else - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers_pmac), - snd_pmac_awacs_mixers_pmac); - if (err < 0) - return err; - chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard) - ? &snd_pmac_awacs_master_sw_imac - : pm5500 - ? &snd_pmac_awacs_master_sw_pmac5500 - : &snd_pmac_awacs_master_sw, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - /* use amplifier. the signal is connected from route A - * to the amp. the amp has its headphone and speaker - * volumes and mute switches, so we use them instead of - * screamer registers. - * in this case, it seems the route C is not used. - */ - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol), - snd_pmac_awacs_amp_vol); - if (err < 0) - return err; - /* overwrite */ - chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, - chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, - chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; - } else -#endif /* PMAC_AMP_AVAIL */ - { - /* route A = headphone, route C = speaker */ - err = snd_ctl_add(chip->card, - (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol, - chip))); - if (err < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(imac1 - ? &snd_pmac_awacs_speaker_sw_imac1 - : imac2 - ? &snd_pmac_awacs_speaker_sw_imac2 - : &snd_pmac_awacs_speaker_sw, chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; - } - - if (pm5500 || imac || lombard) { - vmaster_sw = snd_ctl_make_virtual_master( - "Master Playback Switch", (unsigned int *) NULL); - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->master_sw_ctl); - if (err < 0) - return err; - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->speaker_sw_ctl); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, vmaster_sw); - if (err < 0) - return err; - vmaster_vol = snd_ctl_make_virtual_master( - "Master Playback Volume", (unsigned int *) NULL); - err = snd_ctl_add_slave(vmaster_vol, master_vol); - if (err < 0) - return err; - err = snd_ctl_add_slave(vmaster_vol, speaker_vol); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, vmaster_vol); - if (err < 0) - return err; - } - - if (beige || g4agp) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige), - snd_pmac_screamer_mic_boost_beige); - else if (imac) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac), - snd_pmac_screamer_mic_boost_imac); - else if (chip->model == PMAC_SCREAMER) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost), - snd_pmac_screamer_mic_boost); - else if (pm7500) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500), - snd_pmac_awacs_mic_boost_pmac7500); - else - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost), - snd_pmac_awacs_mic_boost); - if (err < 0) - return err; - - /* - * set lowlevel callbacks - */ - chip->set_format = snd_pmac_awacs_set_format; -#ifdef CONFIG_PM - chip->suspend = snd_pmac_awacs_suspend; - chip->resume = snd_pmac_awacs_resume; -#endif -#ifdef PMAC_SUPPORT_AUTOMUTE - err = snd_pmac_add_automute(chip); - if (err < 0) - return err; - chip->detect_headphone = snd_pmac_awacs_detect_headphone; - chip->update_automute = snd_pmac_awacs_update_automute; - snd_pmac_awacs_update_automute(chip, 0); /* update the status only */ -#endif - if (chip->model == PMAC_SCREAMER) { - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]); - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/awacs.h b/ANDROID_3.4.5/sound/ppc/awacs.h deleted file mode 100644 index c33e6a53..00000000 --- a/ANDROID_3.4.5/sound/ppc/awacs.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Driver for PowerMac AWACS onboard soundchips - * Copyright (c) 2001 by Takashi Iwai <tiwai@suse.de> - * based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef __AWACS_H -#define __AWACS_H - -/*******************************/ -/* AWACs Audio Register Layout */ -/*******************************/ - -struct awacs_regs { - unsigned control; /* Audio control register */ - unsigned pad0[3]; - unsigned codec_ctrl; /* Codec control register */ - unsigned pad1[3]; - unsigned codec_stat; /* Codec status register */ - unsigned pad2[3]; - unsigned clip_count; /* Clipping count register */ - unsigned pad3[3]; - unsigned byteswap; /* Data is little-endian if 1 */ -}; - -/*******************/ -/* Audio Bit Masks */ -/*******************/ - -/* Audio Control Reg Bit Masks */ -/* ----- ------- --- --- ----- */ -#define MASK_ISFSEL (0xf) /* Input SubFrame Select */ -#define MASK_OSFSEL (0xf << 4) /* Output SubFrame Select */ -#define MASK_RATE (0x7 << 8) /* Sound Rate */ -#define MASK_CNTLERR (0x1 << 11) /* Error */ -#define MASK_PORTCHG (0x1 << 12) /* Port Change */ -#define MASK_IEE (0x1 << 13) /* Enable Interrupt on Error */ -#define MASK_IEPC (0x1 << 14) /* Enable Interrupt on Port Change */ -#define MASK_SSFSEL (0x3 << 15) /* Status SubFrame Select */ - -/* Audio Codec Control Reg Bit Masks */ -/* ----- ----- ------- --- --- ----- */ -#define MASK_NEWECMD (0x1 << 24) /* Lock: don't write to reg when 1 */ -#define MASK_EMODESEL (0x3 << 22) /* Send info out on which frame? */ -#define MASK_EXMODEADDR (0x3ff << 12) /* Extended Mode Address -- 10 bits */ -#define MASK_EXMODEDATA (0xfff) /* Extended Mode Data -- 12 bits */ - -/* Audio Codec Control Address Values / Masks */ -/* ----- ----- ------- ------- ------ - ----- */ -#define MASK_ADDR0 (0x0 << 12) /* Expanded Data Mode Address 0 */ -#define MASK_ADDR_MUX MASK_ADDR0 /* Mux Control */ -#define MASK_ADDR_GAIN MASK_ADDR0 - -#define MASK_ADDR1 (0x1 << 12) /* Expanded Data Mode Address 1 */ -#define MASK_ADDR_MUTE MASK_ADDR1 -#define MASK_ADDR_RATE MASK_ADDR1 - -#define MASK_ADDR2 (0x2 << 12) /* Expanded Data Mode Address 2 */ -#define MASK_ADDR_VOLA MASK_ADDR2 /* Volume Control A -- Headphones */ -#define MASK_ADDR_VOLHD MASK_ADDR2 - -#define MASK_ADDR4 (0x4 << 12) /* Expanded Data Mode Address 4 */ -#define MASK_ADDR_VOLC MASK_ADDR4 /* Volume Control C -- Speaker */ -#define MASK_ADDR_VOLSPK MASK_ADDR4 - -/* additional registers of screamer */ -#define MASK_ADDR5 (0x5 << 12) /* Expanded Data Mode Address 5 */ -#define MASK_ADDR6 (0x6 << 12) /* Expanded Data Mode Address 6 */ -#define MASK_ADDR7 (0x7 << 12) /* Expanded Data Mode Address 7 */ - -/* Address 0 Bit Masks & Macros */ -/* ------- - --- ----- - ------ */ -#define MASK_GAINRIGHT (0xf) /* Gain Right Mask */ -#define MASK_GAINLEFT (0xf << 4) /* Gain Left Mask */ -#define MASK_GAINLINE (0x1 << 8) /* Disable Mic preamp */ -#define MASK_GAINMIC (0x0 << 8) /* Enable Mic preamp */ -#define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */ -#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */ -#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */ -#define MASK_MUX_LINE MASK_MUX_AUDIN -#define SHIFT_GAINLINE 8 -#define SHIFT_MUX_CD 9 -#define SHIFT_MUX_MIC 10 -#define SHIFT_MUX_LINE 11 - -#define GAINRIGHT(x) ((x) & MASK_GAINRIGHT) -#define GAINLEFT(x) (((x) << 4) & MASK_GAINLEFT) - -/* Address 1 Bit Masks */ -/* ------- - --- ----- */ -#define MASK_ADDR1RES1 (0x3) /* Reserved */ -#define MASK_RECALIBRATE (0x1 << 2) /* Recalibrate */ -#define MASK_SAMPLERATE (0x7 << 3) /* Sample Rate: */ -#define MASK_LOOPTHRU (0x1 << 6) /* Loopthrough Enable */ -#define SHIFT_LOOPTHRU 6 -#define MASK_CMUTE (0x1 << 7) /* Output C (Speaker) Mute when 1 */ -#define MASK_SPKMUTE MASK_CMUTE -#define SHIFT_SPKMUTE 7 -#define MASK_ADDR1RES2 (0x1 << 8) /* Reserved */ -#define MASK_AMUTE (0x1 << 9) /* Output A (Headphone) Mute when 1 */ -#define MASK_HDMUTE MASK_AMUTE -#define SHIFT_HDMUTE 9 -#define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */ -#define MASK_PAROUT0 (0x1 << 10) /* Parallel Out (???) */ -#define MASK_PAROUT1 (0x1 << 11) /* Parallel Out (enable speaker) */ -#define SHIFT_PAROUT 10 -#define SHIFT_PAROUT0 10 -#define SHIFT_PAROUT1 11 - -#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */ -#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */ -#define SAMPLERATE_24000 (0x2 << 3) /* 24 or 22.05 kHz */ -#define SAMPLERATE_19200 (0x3 << 3) /* 19.2 or 17.64 kHz */ -#define SAMPLERATE_16000 (0x4 << 3) /* 16 or 14.7 kHz */ -#define SAMPLERATE_12000 (0x5 << 3) /* 12 or 11.025 kHz */ -#define SAMPLERATE_9600 (0x6 << 3) /* 9.6 or 8.82 kHz */ -#define SAMPLERATE_8000 (0x7 << 3) /* 8 or 7.35 kHz */ - -/* Address 2 & 4 Bit Masks & Macros */ -/* ------- - - - --- ----- - ------ */ -#define MASK_OUTVOLRIGHT (0xf) /* Output Right Volume */ -#define MASK_ADDR2RES1 (0x2 << 4) /* Reserved */ -#define MASK_ADDR4RES1 MASK_ADDR2RES1 -#define MASK_OUTVOLLEFT (0xf << 6) /* Output Left Volume */ -#define MASK_ADDR2RES2 (0x2 << 10) /* Reserved */ -#define MASK_ADDR4RES2 MASK_ADDR2RES2 - -#define VOLRIGHT(x) (((~(x)) & MASK_OUTVOLRIGHT)) -#define VOLLEFT(x) (((~(x)) << 6) & MASK_OUTVOLLEFT) - -/* address 6 */ -#define MASK_MIC_BOOST (0x4) /* screamer mic boost */ -#define SHIFT_MIC_BOOST 2 - -/* Audio Codec Status Reg Bit Masks */ -/* ----- ----- ------ --- --- ----- */ -#define MASK_EXTEND (0x1 << 23) /* Extend */ -#define MASK_VALID (0x1 << 22) /* Valid Data? */ -#define MASK_OFLEFT (0x1 << 21) /* Overflow Left */ -#define MASK_OFRIGHT (0x1 << 20) /* Overflow Right */ -#define MASK_ERRCODE (0xf << 16) /* Error Code */ -#define MASK_REVISION (0xf << 12) /* Revision Number */ -#define MASK_MFGID (0xf << 8) /* Mfg. ID */ -#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */ -#define MASK_INSENSE (0xf) /* port sense bits: */ -#define MASK_HDPCONN 8 /* headphone plugged in */ -#define MASK_LOCONN 4 /* line-out plugged in */ -#define MASK_LICONN 2 /* line-in plugged in */ -#define MASK_MICCONN 1 /* microphone plugged in */ -#define MASK_LICONN_IMAC 8 /* line-in plugged in */ -#define MASK_HDPRCONN_IMAC 4 /* headphone right plugged in */ -#define MASK_HDPLCONN_IMAC 2 /* headphone left plugged in */ -#define MASK_LOCONN_IMAC 1 /* line-out plugged in */ - -/* Clipping Count Reg Bit Masks */ -/* -------- ----- --- --- ----- */ -#define MASK_CLIPLEFT (0xff << 7) /* Clipping Count, Left Channel */ -#define MASK_CLIPRIGHT (0xff) /* Clipping Count, Right Channel */ - -/* DBDMA ChannelStatus Bit Masks */ -/* ----- ------------- --- ----- */ -#define MASK_CSERR (0x1 << 7) /* Error */ -#define MASK_EOI (0x1 << 6) /* End of Input -- - only for Input Channel */ -#define MASK_CSUNUSED (0x1f << 1) /* bits 1-5 not used */ -#define MASK_WAIT (0x1) /* Wait */ - -/* Various Rates */ -/* ------- ----- */ -#define RATE_48000 (0x0 << 8) /* 48 kHz */ -#define RATE_44100 (0x0 << 8) /* 44.1 kHz */ -#define RATE_32000 (0x1 << 8) /* 32 kHz */ -#define RATE_29400 (0x1 << 8) /* 29.4 kHz */ -#define RATE_24000 (0x2 << 8) /* 24 kHz */ -#define RATE_22050 (0x2 << 8) /* 22.05 kHz */ -#define RATE_19200 (0x3 << 8) /* 19.2 kHz */ -#define RATE_17640 (0x3 << 8) /* 17.64 kHz */ -#define RATE_16000 (0x4 << 8) /* 16 kHz */ -#define RATE_14700 (0x4 << 8) /* 14.7 kHz */ -#define RATE_12000 (0x5 << 8) /* 12 kHz */ -#define RATE_11025 (0x5 << 8) /* 11.025 kHz */ -#define RATE_9600 (0x6 << 8) /* 9.6 kHz */ -#define RATE_8820 (0x6 << 8) /* 8.82 kHz */ -#define RATE_8000 (0x7 << 8) /* 8 kHz */ -#define RATE_7350 (0x7 << 8) /* 7.35 kHz */ - -#define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */ - - -#endif /* __AWACS_H */ diff --git a/ANDROID_3.4.5/sound/ppc/beep.c b/ANDROID_3.4.5/sound/ppc/beep.c deleted file mode 100644 index a9d35078..00000000 --- a/ANDROID_3.4.5/sound/ppc/beep.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Beep using pcm - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <asm/io.h> -#include <asm/irq.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <sound/core.h> -#include <sound/control.h> -#include "pmac.h" - -struct pmac_beep { - int running; /* boolean */ - int volume; /* mixer volume: 0-100 */ - int volume_play; /* currently playing volume */ - int hz; - int nsamples; - short *buf; /* allocated wave buffer */ - dma_addr_t addr; /* physical address of buffer */ - struct input_dev *dev; -}; - -/* - * stop beep if running - */ -void snd_pmac_beep_stop(struct snd_pmac *chip) -{ - struct pmac_beep *beep = chip->beep; - if (beep && beep->running) { - beep->running = 0; - snd_pmac_beep_dma_stop(chip); - } -} - -/* - * Stuff for outputting a beep. The values range from -327 to +327 - * so we can multiply by an amplitude in the range 0..100 to get a - * signed short value to put in the output buffer. - */ -static short beep_wform[256] = { - 0, 40, 79, 117, 153, 187, 218, 245, - 269, 288, 304, 316, 323, 327, 327, 324, - 318, 310, 299, 288, 275, 262, 249, 236, - 224, 213, 204, 196, 190, 186, 183, 182, - 182, 183, 186, 189, 192, 196, 200, 203, - 206, 208, 209, 209, 209, 207, 204, 201, - 197, 193, 188, 183, 179, 174, 170, 166, - 163, 161, 160, 159, 159, 160, 161, 162, - 164, 166, 168, 169, 171, 171, 171, 170, - 169, 167, 163, 159, 155, 150, 144, 139, - 133, 128, 122, 117, 113, 110, 107, 105, - 103, 103, 103, 103, 104, 104, 105, 105, - 105, 103, 101, 97, 92, 86, 78, 68, - 58, 45, 32, 18, 3, -11, -26, -41, - -55, -68, -79, -88, -95, -100, -102, -102, - -99, -93, -85, -75, -62, -48, -33, -16, - 0, 16, 33, 48, 62, 75, 85, 93, - 99, 102, 102, 100, 95, 88, 79, 68, - 55, 41, 26, 11, -3, -18, -32, -45, - -58, -68, -78, -86, -92, -97, -101, -103, - -105, -105, -105, -104, -104, -103, -103, -103, - -103, -105, -107, -110, -113, -117, -122, -128, - -133, -139, -144, -150, -155, -159, -163, -167, - -169, -170, -171, -171, -171, -169, -168, -166, - -164, -162, -161, -160, -159, -159, -160, -161, - -163, -166, -170, -174, -179, -183, -188, -193, - -197, -201, -204, -207, -209, -209, -209, -208, - -206, -203, -200, -196, -192, -189, -186, -183, - -182, -182, -183, -186, -190, -196, -204, -213, - -224, -236, -249, -262, -275, -288, -299, -310, - -318, -324, -327, -327, -323, -316, -304, -288, - -269, -245, -218, -187, -153, -117, -79, -40, -}; - -#define BEEP_SRATE 22050 /* 22050 Hz sample rate */ -#define BEEP_BUFLEN 512 -#define BEEP_VOLUME 15 /* 0 - 100 */ - -static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, - unsigned int code, int hz) -{ - struct snd_pmac *chip; - struct pmac_beep *beep; - unsigned long flags; - int beep_speed = 0; - int srate; - int period, ncycles, nsamples; - int i, j, f; - short *p; - - if (type != EV_SND) - return -1; - - switch (code) { - case SND_BELL: if (hz) hz = 1000; - case SND_TONE: break; - default: return -1; - } - - chip = input_get_drvdata(dev); - if (! chip || (beep = chip->beep) == NULL) - return -1; - - if (! hz) { - spin_lock_irqsave(&chip->reg_lock, flags); - if (beep->running) - snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; - } - - beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE); - srate = chip->freq_table[beep_speed]; - - if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) - hz = 1000; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->playback.running || chip->capture.running || beep->running) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; - } - beep->running = 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - if (hz == beep->hz && beep->volume == beep->volume_play) { - nsamples = beep->nsamples; - } else { - period = srate * 256 / hz; /* fixed point */ - ncycles = BEEP_BUFLEN * 256 / period; - nsamples = (period * ncycles) >> 8; - f = ncycles * 65536 / nsamples; - j = 0; - p = beep->buf; - for (i = 0; i < nsamples; ++i, p += 2) { - p[0] = p[1] = beep_wform[j >> 8] * beep->volume; - j = (j + f) & 0xffff; - } - beep->hz = hz; - beep->volume_play = beep->volume; - beep->nsamples = nsamples; - } - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -/* - * beep volume mixer - */ - -static int snd_pmac_info_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_get_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (snd_BUG_ON(!chip->beep)) - return -ENXIO; - ucontrol->value.integer.value[0] = chip->beep->volume; - return 0; -} - -static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int oval, nval; - if (snd_BUG_ON(!chip->beep)) - return -ENXIO; - oval = chip->beep->volume; - nval = ucontrol->value.integer.value[0]; - if (nval > 100) - return -EINVAL; - chip->beep->volume = nval; - return oval != chip->beep->volume; -} - -static struct snd_kcontrol_new snd_pmac_beep_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Beep Playback Volume", - .info = snd_pmac_info_beep, - .get = snd_pmac_get_beep, - .put = snd_pmac_put_beep, -}; - -/* Initialize beep stuff */ -int __devinit snd_pmac_attach_beep(struct snd_pmac *chip) -{ - struct pmac_beep *beep; - struct input_dev *input_dev; - struct snd_kcontrol *beep_ctl; - void *dmabuf; - int err = -ENOMEM; - - beep = kzalloc(sizeof(*beep), GFP_KERNEL); - if (! beep) - return -ENOMEM; - dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - &beep->addr, GFP_KERNEL); - input_dev = input_allocate_device(); - if (! dmabuf || ! input_dev) - goto fail1; - - /* FIXME: set more better values */ - input_dev->name = "PowerMac Beep"; - input_dev->phys = "powermac/beep"; - input_dev->id.bustype = BUS_ADB; - input_dev->id.vendor = 0x001f; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT_MASK(EV_SND); - input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); - input_dev->event = snd_pmac_beep_event; - input_dev->dev.parent = &chip->pdev->dev; - input_set_drvdata(input_dev, chip); - - beep->dev = input_dev; - beep->buf = dmabuf; - beep->volume = BEEP_VOLUME; - beep->running = 0; - - beep_ctl = snd_ctl_new1(&snd_pmac_beep_mixer, chip); - err = snd_ctl_add(chip->card, beep_ctl); - if (err < 0) - goto fail1; - - chip->beep = beep; - - err = input_register_device(beep->dev); - if (err) - goto fail2; - - return 0; - - fail2: snd_ctl_remove(chip->card, beep_ctl); - fail1: input_free_device(input_dev); - if (dmabuf) - dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - dmabuf, beep->addr); - kfree(beep); - return err; -} - -void snd_pmac_detach_beep(struct snd_pmac *chip) -{ - if (chip->beep) { - input_unregister_device(chip->beep->dev); - dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - chip->beep->buf, chip->beep->addr); - kfree(chip->beep); - chip->beep = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/ppc/burgundy.c b/ANDROID_3.4.5/sound/ppc/burgundy.c deleted file mode 100644 index 00e2d516..00000000 --- a/ANDROID_3.4.5/sound/ppc/burgundy.c +++ /dev/null @@ -1,732 +0,0 @@ -/* - * PMac Burgundy lowlevel functions - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * code based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <asm/io.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <sound/core.h> -#include "pmac.h" -#include "burgundy.h" - - -/* Waits for busy flag to clear */ -static inline void -snd_pmac_burgundy_busy_wait(struct snd_pmac *chip) -{ - int timeout = 50; - while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); -} - -static inline void -snd_pmac_burgundy_extend_wait(struct snd_pmac *chip) -{ - int timeout; - timeout = 50; - while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n"); - timeout = 50; - while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n"); -} - -static void -snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val) -{ - out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); -} - -static unsigned -snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr) -{ - unsigned val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100100); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<8; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100200); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<16; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100300); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24; - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return val; -} - -static void -snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, - unsigned int val) -{ - out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); - snd_pmac_burgundy_busy_wait(chip); -} - -static unsigned -snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr) -{ - unsigned val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return val; -} - -#define BASE2ADDR(base) ((base) << 12) -#define ADDR2BASE(addr) ((addr) >> 12) - -/* - * Burgundy volume: 0 - 100, stereo, word reg - */ -static void -snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address, - long *volume, int shift) -{ - int hardvolume, lvolume, rvolume; - - if (volume[0] < 0 || volume[0] > 100 || - volume[1] < 0 || volume[1] > 100) - return; /* -EINVAL */ - lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; - rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; - - hardvolume = lvolume + (rvolume << shift); - if (shift == 8) - hardvolume |= hardvolume << 16; - - snd_pmac_burgundy_wcw(chip, address, hardvolume); -} - -static void -snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address, - long *volume, int shift) -{ - int wvolume; - - wvolume = snd_pmac_burgundy_rcw(chip, address); - - volume[0] = wvolume & 0xff; - if (volume[0] >= BURGUNDY_VOLUME_OFFSET) - volume[0] -= BURGUNDY_VOLUME_OFFSET; - else - volume[0] = 0; - volume[1] = (wvolume >> shift) & 0xff; - if (volume[1] >= BURGUNDY_VOLUME_OFFSET) - volume[1] -= BURGUNDY_VOLUME_OFFSET; - else - volume[1] = 0; -} - -static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int shift = (kcontrol->private_value >> 8) & 0xff; - snd_pmac_burgundy_read_volume(chip, addr, - ucontrol->value.integer.value, shift); - return 0; -} - -static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int shift = (kcontrol->private_value >> 8) & 0xff; - long nvoices[2]; - - snd_pmac_burgundy_write_volume(chip, addr, - ucontrol->value.integer.value, shift); - snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift); - return (nvoices[0] != ucontrol->value.integer.value[0] || - nvoices[1] != ucontrol->value.integer.value[1]); -} - -#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_volume,\ - .get = snd_pmac_burgundy_get_volume,\ - .put = snd_pmac_burgundy_put_volume,\ - .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) } - -/* - * Burgundy volume: 0 - 100, stereo, 2-byte reg - */ -static void -snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address, - long *volume, int off) -{ - int lvolume, rvolume; - - off |= off << 2; - lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; - rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; - - snd_pmac_burgundy_wcb(chip, address + off, lvolume); - snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume); -} - -static void -snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address, - long *volume, int off) -{ - volume[0] = snd_pmac_burgundy_rcb(chip, address + off); - if (volume[0] >= BURGUNDY_VOLUME_OFFSET) - volume[0] -= BURGUNDY_VOLUME_OFFSET; - else - volume[0] = 0; - volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100); - if (volume[1] >= BURGUNDY_VOLUME_OFFSET) - volume[1] -= BURGUNDY_VOLUME_OFFSET; - else - volume[1] = 0; -} - -static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int off = kcontrol->private_value & 0x300; - snd_pmac_burgundy_read_volume_2b(chip, addr, - ucontrol->value.integer.value, off); - return 0; -} - -static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int off = kcontrol->private_value & 0x300; - long nvoices[2]; - - snd_pmac_burgundy_write_volume_2b(chip, addr, - ucontrol->value.integer.value, off); - snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off); - return (nvoices[0] != ucontrol->value.integer.value[0] || - nvoices[1] != ucontrol->value.integer.value[1]); -} - -#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_volume_2b,\ - .get = snd_pmac_burgundy_get_volume_2b,\ - .put = snd_pmac_burgundy_put_volume_2b,\ - .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) } - -/* - * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg - */ -static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 15; - return 0; -} - -static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int atten = (kcontrol->private_value >> 25) & 1; - int oval; - - oval = snd_pmac_burgundy_rcb(chip, addr); - if (atten) - oval = ~oval & 0xff; - ucontrol->value.integer.value[0] = oval & 0xf; - if (stereo) - ucontrol->value.integer.value[1] = (oval >> 4) & 0xf; - return 0; -} - -static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int atten = (kcontrol->private_value >> 25) & 1; - int oval, val; - - oval = snd_pmac_burgundy_rcb(chip, addr); - if (atten) - oval = ~oval & 0xff; - val = ucontrol->value.integer.value[0]; - if (stereo) - val |= ucontrol->value.integer.value[1] << 4; - else - val |= ucontrol->value.integer.value[0] << 4; - if (atten) - val = ~val & 0xff; - snd_pmac_burgundy_wcb(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_gain,\ - .get = snd_pmac_burgundy_get_gain,\ - .put = snd_pmac_burgundy_put_gain,\ - .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) } - -/* - * Burgundy switch: 0/1, mono/stereo, word reg - */ -static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = 1 << (kcontrol->private_value & 0xff); - int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int val = snd_pmac_burgundy_rcw(chip, addr); - ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; - if (stereo) - ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; - return 0; -} - -static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = 1 << (kcontrol->private_value & 0xff); - int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int val, oval; - oval = snd_pmac_burgundy_rcw(chip, addr); - val = oval & ~(lmask | (stereo ? rmask : 0)); - if (ucontrol->value.integer.value[0]) - val |= lmask; - if (stereo && ucontrol->value.integer.value[1]) - val |= rmask; - snd_pmac_burgundy_wcw(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_switch_w,\ - .get = snd_pmac_burgundy_get_switch_w,\ - .put = snd_pmac_burgundy_put_switch_w,\ - .private_value = ((lbit) | ((rbit) << 8)\ - | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } - -/* - * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask - */ -static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = kcontrol->private_value & 0xff; - int rmask = (kcontrol->private_value >> 8) & 0xff; - int stereo = (kcontrol->private_value >> 24) & 1; - int val = snd_pmac_burgundy_rcb(chip, addr); - ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; - if (stereo) - ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; - return 0; -} - -static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = kcontrol->private_value & 0xff; - int rmask = (kcontrol->private_value >> 8) & 0xff; - int stereo = (kcontrol->private_value >> 24) & 1; - int val, oval; - oval = snd_pmac_burgundy_rcb(chip, addr); - val = oval & ~(lmask | rmask); - if (ucontrol->value.integer.value[0]) - val |= lmask; - if (stereo && ucontrol->value.integer.value[1]) - val |= rmask; - snd_pmac_burgundy_wcb(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_switch_b,\ - .get = snd_pmac_burgundy_get_switch_b,\ - .put = snd_pmac_burgundy_put_switch_b,\ - .private_value = ((lmask) | ((rmask) << 8)\ - | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } - -/* - * Burgundy mixers - */ -static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = { - BURGUNDY_VOLUME_W("Master Playback Volume", 0, - MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8), - BURGUNDY_VOLUME_W("CD Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLCD, 16), - BURGUNDY_VOLUME_2B("Input Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIX01, 2), - BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIX23, 0), - BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINCD, 1, 0), - BURGUNDY_SWITCH_W("Master Capture Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0), - BURGUNDY_SWITCH_W("CD Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1), - BURGUNDY_SWITCH_W("CD Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1), -/* BURGUNDY_SWITCH_W("Loop Capture Switch", 0, - * MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1), - * BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0), - * BURGUNDY_SWITCH_B("Mixer Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0), - * BURGUNDY_SWITCH_B("PCM out Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0), - */ BURGUNDY_SWITCH_B("PCM Capture Switch", 0, - MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0) -}; -static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = { - BURGUNDY_VOLUME_W("Line in Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLLINE, 16), - BURGUNDY_VOLUME_W("Mic Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIC, 16), - BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINLINE, 1, 0), - BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), - BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), - BURGUNDY_VOLUME_B("Line out Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1), - BURGUNDY_VOLUME_B("Headphone Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENHP, 1, 1), - BURGUNDY_SWITCH_W("Line in Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1), - BURGUNDY_SWITCH_W("Mic Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), - BURGUNDY_SWITCH_W("Line in Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1), - BURGUNDY_SWITCH_W("Mic Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), - BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0, - MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) -}; -static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = { - BURGUNDY_VOLUME_W("Line in Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIC, 16), - BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), - BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1), - BURGUNDY_VOLUME_B("Line out Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), - BURGUNDY_SWITCH_W("Line in Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), - BURGUNDY_SWITCH_W("Line in Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), -/* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0, - * MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */ -}; -static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Master Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT, - BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Master Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_INTERN - | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_INTERN, 0, 0); -static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Line out Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Line out Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Headphone Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1); - - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip) -{ - return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0; -} - -static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { - int imac = of_machine_is_compatible("iMac"); - int reg, oreg; - reg = oreg = snd_pmac_burgundy_rcb(chip, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); - reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT - | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) - : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT - | BURGUNDY_OUTPUT_INTERN); - if (snd_pmac_burgundy_detect_headphone(chip)) - reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) - : (BURGUNDY_OUTPUT_LEFT - | BURGUNDY_OUTPUT_RIGHT); - else - reg |= imac ? (BURGUNDY_OUTPUT_LEFT - | BURGUNDY_OUTPUT_RIGHT) - : (BURGUNDY_OUTPUT_INTERN); - if (do_notify && reg == oreg) - return; - snd_pmac_burgundy_wcb(chip, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg); - if (do_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->speaker_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - } - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* - * initialize burgundy - */ -int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip) -{ - int imac = of_machine_is_compatible("iMac"); - int i, err; - - /* Checks to see the chip is alive and kicking */ - if ((in_le32(&chip->awacs->codec_ctrl) & MASK_ERRCODE) == 0xf0000) { - printk(KERN_WARNING "pmac burgundy: disabled by MacOS :-(\n"); - return 1; - } - - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES, - DEF_BURGUNDY_OUTPUTENABLES); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - DEF_BURGUNDY_MORE_OUTPUTENABLES); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTSELECTS, - DEF_BURGUNDY_OUTPUTSELECTS); - - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21, - DEF_BURGUNDY_INPSEL21); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3, - imac ? DEF_BURGUNDY_INPSEL3_IMAC - : DEF_BURGUNDY_INPSEL3_PMAC); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD, - DEF_BURGUNDY_GAINCD); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE, - DEF_BURGUNDY_GAINLINE); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMIC, - DEF_BURGUNDY_GAINMIC); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMODEM, - DEF_BURGUNDY_GAINMODEM); - - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENSPEAKER, - DEF_BURGUNDY_ATTENSPEAKER); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENLINEOUT, - DEF_BURGUNDY_ATTENLINEOUT); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENHP, - DEF_BURGUNDY_ATTENHP); - - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_MASTER_VOLUME, - DEF_BURGUNDY_MASTER_VOLUME); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLCD, - DEF_BURGUNDY_VOLCD); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLLINE, - DEF_BURGUNDY_VOLLINE); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC, - DEF_BURGUNDY_VOLMIC); - - if (chip->hp_stat_mask == 0) { - /* set headphone-jack detection bit */ - if (imac) - chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER - | BURGUNDY_HPDETECT_IMAC_LOWER - | BURGUNDY_HPDETECT_IMAC_SIDE; - else - chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK; - } - /* - * build burgundy mixers - */ - strcpy(chip->card->mixername, "PowerMac Burgundy"); - - for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip)); - if (err < 0) - return err; - } - for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac) - : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i] - : &snd_pmac_burgundy_mixers_pmac[i], chip)); - if (err < 0) - return err; - } - chip->master_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_master_sw_imac - : &snd_pmac_burgundy_master_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - chip->master_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_line_sw_imac - : &snd_pmac_burgundy_line_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - if (imac) { - chip->master_sw_ctl = snd_ctl_new1( - &snd_pmac_burgundy_hp_sw_imac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - } - chip->speaker_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_speaker_sw_imac - : &snd_pmac_burgundy_speaker_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; -#ifdef PMAC_SUPPORT_AUTOMUTE - err = snd_pmac_add_automute(chip); - if (err < 0) - return err; - - chip->detect_headphone = snd_pmac_burgundy_detect_headphone; - chip->update_automute = snd_pmac_burgundy_update_automute; - snd_pmac_burgundy_update_automute(chip, 0); /* update the status only */ -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/burgundy.h b/ANDROID_3.4.5/sound/ppc/burgundy.h deleted file mode 100644 index 7a7f9cf3..00000000 --- a/ANDROID_3.4.5/sound/ppc/burgundy.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Driver for PowerMac Burgundy onboard soundchips - * Copyright (c) 2001 by Takashi Iwai <tiwai@suse.de> - * based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef __BURGUNDY_H -#define __BURGUNDY_H - -#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12) -#define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) -#define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) - -#define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12) - -#define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12) - -#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12) -#define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12) -#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12) -#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12) -#define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12) - -#define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12) - -#define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12) - -#define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12) -#define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12) -#define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12) -#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12) - -#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12) -#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12) - -#define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1) -#define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2) -#define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3) -#define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4) - -#define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1) -#define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2) -#define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3) -#define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4) - - -/* These are all default values for the burgundy */ -#define DEF_BURGUNDY_INPSEL21 (0xAA) -#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A) -#define DEF_BURGUNDY_INPSEL3_PMAC (0x05) - -#define DEF_BURGUNDY_GAINCD (0x33) -#define DEF_BURGUNDY_GAINLINE (0x44) -#define DEF_BURGUNDY_GAINMIC (0x44) -#define DEF_BURGUNDY_GAINMODEM (0x06) - -/* Remember: lowest volume here is 0x9B (155) */ -#define DEF_BURGUNDY_VOLCD (0xCCCCCCCC) -#define DEF_BURGUNDY_VOLLINE (0x00000000) -#define DEF_BURGUNDY_VOLMIC (0x00000000) -#define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC) - -#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F) -#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A) - -/* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */ -#define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD) - -#define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E) - -#define DEF_BURGUNDY_ATTENSPEAKER (0x44) -#define DEF_BURGUNDY_ATTENLINEOUT (0xCC) -#define DEF_BURGUNDY_ATTENHP (0xCC) - -/* MORE_OUTPUTENABLES bits */ -#define BURGUNDY_OUTPUT_LEFT 0x02 -#define BURGUNDY_OUTPUT_RIGHT 0x04 -#define BURGUNDY_LINEOUT_LEFT 0x08 -#define BURGUNDY_LINEOUT_RIGHT 0x10 -#define BURGUNDY_HP_LEFT 0x20 -#define BURGUNDY_HP_RIGHT 0x40 -#define BURGUNDY_OUTPUT_INTERN 0x80 - -/* Headphone detection bits */ -#define BURGUNDY_HPDETECT_PMAC_BACK 0x04 -#define BURGUNDY_HPDETECT_IMAC_SIDE 0x04 -#define BURGUNDY_HPDETECT_IMAC_UPPER 0x08 -#define BURGUNDY_HPDETECT_IMAC_LOWER 0x01 - -/* Volume offset */ -#define BURGUNDY_VOLUME_OFFSET 155 - -#endif /* __BURGUNDY_H */ diff --git a/ANDROID_3.4.5/sound/ppc/daca.c b/ANDROID_3.4.5/sound/ppc/daca.c deleted file mode 100644 index 24200b7b..00000000 --- a/ANDROID_3.4.5/sound/ppc/daca.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * PMac DACA lowlevel functions - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/kmod.h> -#include <linux/slab.h> -#include <sound/core.h> -#include "pmac.h" - -/* i2c address */ -#define DACA_I2C_ADDR 0x4d - -/* registers */ -#define DACA_REG_SR 0x01 -#define DACA_REG_AVOL 0x02 -#define DACA_REG_GCFG 0x03 - -/* maximum volume value */ -#define DACA_VOL_MAX 0x38 - - -struct pmac_daca { - struct pmac_keywest i2c; - int left_vol, right_vol; - unsigned int deemphasis : 1; - unsigned int amp_on : 1; -}; - - -/* - * initialize / detect DACA - */ -static int daca_init_client(struct pmac_keywest *i2c) -{ - unsigned short wdata = 0x00; - /* SR: no swap, 1bit delay, 32-48kHz */ - /* GCFG: power amp inverted, DAC on */ - if (i2c_smbus_write_byte_data(i2c->client, DACA_REG_SR, 0x08) < 0 || - i2c_smbus_write_byte_data(i2c->client, DACA_REG_GCFG, 0x05) < 0) - return -EINVAL; - return i2c_smbus_write_block_data(i2c->client, DACA_REG_AVOL, - 2, (unsigned char*)&wdata); -} - -/* - * update volume - */ -static int daca_set_volume(struct pmac_daca *mix) -{ - unsigned char data[2]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->left_vol > DACA_VOL_MAX) - data[0] = DACA_VOL_MAX; - else - data[0] = mix->left_vol; - if (mix->right_vol > DACA_VOL_MAX) - data[1] = DACA_VOL_MAX; - else - data[1] = mix->right_vol; - data[1] |= mix->deemphasis ? 0x40 : 0; - if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, - 2, data) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); - return -EINVAL; - } - return 0; -} - - -/* deemphasis switch */ -#define daca_info_deemphasis snd_ctl_boolean_mono_info - -static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0; - return 0; -} - -static int daca_put_deemphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->deemphasis != ucontrol->value.integer.value[0]; - if (change) { - mix->deemphasis = !!ucontrol->value.integer.value[0]; - daca_set_volume(mix); - } - return change; -} - -/* output volume */ -static int daca_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = DACA_VOL_MAX; - return 0; -} - -static int daca_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->left_vol; - ucontrol->value.integer.value[1] = mix->right_vol; - return 0; -} - -static int daca_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - unsigned int vol[2]; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] > DACA_VOL_MAX || vol[1] > DACA_VOL_MAX) - return -EINVAL; - change = mix->left_vol != vol[0] || - mix->right_vol != vol[1]; - if (change) { - mix->left_vol = vol[0]; - mix->right_vol = vol[1]; - daca_set_volume(mix); - } - return change; -} - -/* amplifier switch */ -#define daca_info_amp daca_info_deemphasis - -static int daca_get_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0; - return 0; -} - -static int daca_put_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->amp_on != ucontrol->value.integer.value[0]; - if (change) { - mix->amp_on = !!ucontrol->value.integer.value[0]; - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); - } - return change; -} - -static struct snd_kcontrol_new daca_mixers[] = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Deemphasis Switch", - .info = daca_info_deemphasis, - .get = daca_get_deemphasis, - .put = daca_put_deemphasis - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = daca_info_volume, - .get = daca_get_volume, - .put = daca_put_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Power Amplifier Switch", - .info = daca_info_amp, - .get = daca_get_amp, - .put = daca_put_amp - }, -}; - - -#ifdef CONFIG_PM -static void daca_resume(struct snd_pmac *chip) -{ - struct pmac_daca *mix = chip->mixer_data; - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08); - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); - daca_set_volume(mix); -} -#endif /* CONFIG_PM */ - - -static void daca_cleanup(struct snd_pmac *chip) -{ - struct pmac_daca *mix = chip->mixer_data; - if (! mix) - return; - snd_pmac_keywest_cleanup(&mix->i2c); - kfree(mix); - chip->mixer_data = NULL; -} - -/* exported */ -int __devinit snd_pmac_daca_init(struct snd_pmac *chip) -{ - int i, err; - struct pmac_daca *mix; - - request_module("i2c-powermac"); - - mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (! mix) - return -ENOMEM; - chip->mixer_data = mix; - chip->mixer_free = daca_cleanup; - mix->amp_on = 1; /* default on */ - - mix->i2c.addr = DACA_I2C_ADDR; - mix->i2c.init_client = daca_init_client; - mix->i2c.name = "DACA"; - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) - return err; - - /* - * build mixers - */ - strcpy(chip->card->mixername, "PowerMac DACA"); - - for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0) - return err; - } - -#ifdef CONFIG_PM - chip->resume = daca_resume; -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/keywest.c b/ANDROID_3.4.5/sound/ppc/keywest.c deleted file mode 100644 index 4080becf..00000000 --- a/ANDROID_3.4.5/sound/ppc/keywest.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * common keywest i2c layer - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <sound/core.h> -#include "pmac.h" - -/* - * we have to keep a static variable here since i2c attach_adapter - * callback cannot pass a private data. - */ -static struct pmac_keywest *keywest_ctx; - - -static int keywest_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - i2c_set_clientdata(client, keywest_ctx); - return 0; -} - -/* - * This is kind of a hack, best would be to turn powermac to fixed i2c - * bus numbers and declare the sound device as part of platform - * initialization - */ -static int keywest_attach_adapter(struct i2c_adapter *adapter) -{ - struct i2c_board_info info; - - if (! keywest_ctx) - return -EINVAL; - - if (strncmp(adapter->name, "mac-io", 6)) - return 0; /* ignored */ - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "keywest", I2C_NAME_SIZE); - info.addr = keywest_ctx->addr; - keywest_ctx->client = i2c_new_device(adapter, &info); - if (!keywest_ctx->client) - return -ENODEV; - /* - * We know the driver is already loaded, so the device should be - * already bound. If not it means binding failed, and then there - * is no point in keeping the device instantiated. - */ - if (!keywest_ctx->client->driver) { - i2c_unregister_device(keywest_ctx->client); - keywest_ctx->client = NULL; - return -ENODEV; - } - - /* - * Let i2c-core delete that device on driver removal. - * This is safe because i2c-core holds the core_lock mutex for us. - */ - list_add_tail(&keywest_ctx->client->detected, - &keywest_ctx->client->driver->clients); - return 0; -} - -static int keywest_remove(struct i2c_client *client) -{ - if (! keywest_ctx) - return 0; - if (client == keywest_ctx->client) - keywest_ctx->client = NULL; - - return 0; -} - - -static const struct i2c_device_id keywest_i2c_id[] = { - { "keywest", 0 }, - { } -}; - -static struct i2c_driver keywest_driver = { - .driver = { - .name = "PMac Keywest Audio", - }, - .attach_adapter = keywest_attach_adapter, - .probe = keywest_probe, - .remove = keywest_remove, - .id_table = keywest_i2c_id, -}; - -/* exported */ -void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c) -{ - if (keywest_ctx && keywest_ctx == i2c) { - i2c_del_driver(&keywest_driver); - keywest_ctx = NULL; - } -} - -int __devinit snd_pmac_tumbler_post_init(void) -{ - int err; - - if (!keywest_ctx || !keywest_ctx->client) - return -ENXIO; - - if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) { - snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); - return err; - } - return 0; -} - -/* exported */ -int __devinit snd_pmac_keywest_init(struct pmac_keywest *i2c) -{ - int err; - - if (keywest_ctx) - return -EBUSY; - - keywest_ctx = i2c; - - if ((err = i2c_add_driver(&keywest_driver))) { - snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/pmac.c b/ANDROID_3.4.5/sound/ppc/pmac.c deleted file mode 100644 index ab96cde7..00000000 --- a/ANDROID_3.4.5/sound/ppc/pmac.c +++ /dev/null @@ -1,1410 +0,0 @@ -/* - * PMac DBDMA lowlevel functions - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * code based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include <asm/io.h> -#include <asm/irq.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <sound/core.h> -#include "pmac.h" -#include <sound/pcm_params.h> -#include <asm/pmac_feature.h> -#include <asm/pci-bridge.h> - - -/* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */ -static int awacs_freqs[8] = { - 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 -}; -/* fixed frequency table for tumbler */ -static int tumbler_freqs[1] = { - 44100 -}; - - -/* - * we will allocate a single 'emergency' dbdma cmd block to use if the - * tx status comes up "DEAD". This happens on some PowerComputing Pmac - * clones, either owing to a bug in dbdma or some interaction between - * IDE and sound. However, this measure would deal with DEAD status if - * it appeared elsewhere. - */ -static struct pmac_dbdma emergency_dbdma; -static int emergency_in_use; - - -/* - * allocate DBDMA command arrays - */ -static int snd_pmac_dbdma_alloc(struct snd_pmac *chip, struct pmac_dbdma *rec, int size) -{ - unsigned int rsize = sizeof(struct dbdma_cmd) * (size + 1); - - rec->space = dma_alloc_coherent(&chip->pdev->dev, rsize, - &rec->dma_base, GFP_KERNEL); - if (rec->space == NULL) - return -ENOMEM; - rec->size = size; - memset(rec->space, 0, rsize); - rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space); - rec->addr = rec->dma_base + (unsigned long)((char *)rec->cmds - (char *)rec->space); - - return 0; -} - -static void snd_pmac_dbdma_free(struct snd_pmac *chip, struct pmac_dbdma *rec) -{ - if (rec->space) { - unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); - - dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); - } -} - - -/* - * pcm stuff - */ - -/* - * look up frequency table - */ - -unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate) -{ - int i, ok, found; - - ok = rec->cur_freqs; - if (rate > chip->freq_table[0]) - return 0; - found = 0; - for (i = 0; i < chip->num_freqs; i++, ok >>= 1) { - if (! (ok & 1)) continue; - found = i; - if (rate >= chip->freq_table[i]) - break; - } - return found; -} - -/* - * check whether another stream is active - */ -static inline int another_stream(int stream) -{ - return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; -} - -/* - * allocate buffers - */ -static int snd_pmac_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params)); -} - -/* - * release buffers - */ -static int snd_pmac_pcm_hw_free(struct snd_pcm_substream *subs) -{ - snd_pcm_lib_free_pages(subs); - return 0; -} - -/* - * get a stream of the opposite direction - */ -static struct pmac_stream *snd_pmac_get_stream(struct snd_pmac *chip, int stream) -{ - switch (stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - return &chip->playback; - case SNDRV_PCM_STREAM_CAPTURE: - return &chip->capture; - default: - snd_BUG(); - return NULL; - } -} - -/* - * wait while run status is on - */ -static inline void -snd_pmac_wait_ack(struct pmac_stream *rec) -{ - int timeout = 50000; - while ((in_le32(&rec->dma->status) & RUN) && timeout-- > 0) - udelay(1); -} - -/* - * set the format and rate to the chip. - * call the lowlevel function if defined (e.g. for AWACS). - */ -static void snd_pmac_pcm_set_format(struct snd_pmac *chip) -{ - /* set up frequency and format */ - out_le32(&chip->awacs->control, chip->control_mask | (chip->rate_index << 8)); - out_le32(&chip->awacs->byteswap, chip->format == SNDRV_PCM_FORMAT_S16_LE ? 1 : 0); - if (chip->set_format) - chip->set_format(chip); -} - -/* - * stop the DMA transfer - */ -static inline void snd_pmac_dma_stop(struct pmac_stream *rec) -{ - out_le32(&rec->dma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - snd_pmac_wait_ack(rec); -} - -/* - * set the command pointer address - */ -static inline void snd_pmac_dma_set_command(struct pmac_stream *rec, struct pmac_dbdma *cmd) -{ - out_le32(&rec->dma->cmdptr, cmd->addr); -} - -/* - * start the DMA - */ -static inline void snd_pmac_dma_run(struct pmac_stream *rec, int status) -{ - out_le32(&rec->dma->control, status | (status << 16)); -} - - -/* - * prepare playback/capture stream - */ -static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs) -{ - int i; - volatile struct dbdma_cmd __iomem *cp; - struct snd_pcm_runtime *runtime = subs->runtime; - int rate_index; - long offset; - struct pmac_stream *astr; - - rec->dma_size = snd_pcm_lib_buffer_bytes(subs); - rec->period_size = snd_pcm_lib_period_bytes(subs); - rec->nperiods = rec->dma_size / rec->period_size; - rec->cur_period = 0; - rate_index = snd_pmac_rate_index(chip, rec, runtime->rate); - - /* set up constraints */ - astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - if (! astr) - return -EINVAL; - astr->cur_freqs = 1 << rate_index; - astr->cur_formats = 1 << runtime->format; - chip->rate_index = rate_index; - chip->format = runtime->format; - - /* We really want to execute a DMA stop command, after the AWACS - * is initialized. - * For reasons I don't understand, it stops the hissing noise - * common to many PowerBook G3 systems and random noise otherwise - * captured on iBook2's about every third time. -ReneR - */ - spin_lock_irq(&chip->reg_lock); - snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); - spin_unlock_irq(&chip->reg_lock); - mdelay(5); - spin_lock_irq(&chip->reg_lock); - /* continuous DMA memory type doesn't provide the physical address, - * so we need to resolve the address here... - */ - offset = runtime->dma_addr; - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { - st_le32(&cp->phy_addr, offset); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ - st_le16(&cp->xfer_status, 0); - offset += rec->period_size; - } - /* make loop */ - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, rec->cmd.addr); - - snd_pmac_dma_stop(rec); - snd_pmac_dma_set_command(rec, &rec->cmd); - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - - -/* - * PCM trigger/stop - */ -static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs, int cmd) -{ - volatile struct dbdma_cmd __iomem *cp; - int i, command; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (rec->running) - return -EBUSY; - command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ? - OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS; - spin_lock(&chip->reg_lock); - snd_pmac_beep_stop(chip); - snd_pmac_pcm_set_format(chip); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, command); - snd_pmac_dma_set_command(rec, &rec->cmd); - (void)in_le32(&rec->dma->status); - snd_pmac_dma_run(rec, RUN|WAKE); - rec->running = 1; - spin_unlock(&chip->reg_lock); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&chip->reg_lock); - rec->running = 0; - /*printk(KERN_DEBUG "stopped!!\n");*/ - snd_pmac_dma_stop(rec); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, DBDMA_STOP); - spin_unlock(&chip->reg_lock); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * return the current pointer - */ -inline -static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, - struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - int count = 0; - -#if 1 /* hmm.. how can we get the current dma pointer?? */ - int stat; - volatile struct dbdma_cmd __iomem *cp = &rec->cmd.cmds[rec->cur_period]; - stat = ld_le16(&cp->xfer_status); - if (stat & (ACTIVE|DEAD)) { - count = in_le16(&cp->res_count); - if (count) - count = rec->period_size - count; - } -#endif - count += rec->cur_period * rec->period_size; - /*printk(KERN_DEBUG "pointer=%d\n", count);*/ - return bytes_to_frames(subs->runtime, count); -} - -/* - * playback - */ - -static int snd_pmac_playback_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_prepare(chip, &chip->playback, subs); -} - -static int snd_pmac_playback_trigger(struct snd_pcm_substream *subs, - int cmd) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_trigger(chip, &chip->playback, subs, cmd); -} - -static snd_pcm_uframes_t snd_pmac_playback_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_pointer(chip, &chip->playback, subs); -} - - -/* - * capture - */ - -static int snd_pmac_capture_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_prepare(chip, &chip->capture, subs); -} - -static int snd_pmac_capture_trigger(struct snd_pcm_substream *subs, - int cmd) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_trigger(chip, &chip->capture, subs, cmd); -} - -static snd_pcm_uframes_t snd_pmac_capture_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_pointer(chip, &chip->capture, subs); -} - - -/* - * Handle DEAD DMA transfers: - * if the TX status comes up "DEAD" - reported on some Power Computing machines - * we need to re-start the dbdma - but from a different physical start address - * and with a different transfer length. It would get very messy to do this - * with the normal dbdma_cmd blocks - we would have to re-write the buffer start - * addresses each time. So, we will keep a single dbdma_cmd block which can be - * fiddled with. - * When DEAD status is first reported the content of the faulted dbdma block is - * copied into the emergency buffer and we note that the buffer is in use. - * we then bump the start physical address by the amount that was successfully - * output before it died. - * On any subsequent DEAD result we just do the bump-ups (we know that we are - * already using the emergency dbdma_cmd). - * CHECK: this just tries to "do it". It is possible that we should abandon - * xfers when the number of residual bytes gets below a certain value - I can - * see that this might cause a loop-forever if a too small transfer causes - * DEAD status. However this is a TODO for now - we'll see what gets reported. - * When we get a successful transfer result with the emergency buffer we just - * pretend that it completed using the original dmdma_cmd and carry on. The - * 'next_cmd' field will already point back to the original loop of blocks. - */ -static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec, - volatile struct dbdma_cmd __iomem *cp) -{ - unsigned short req, res ; - unsigned int phy ; - - /* printk(KERN_WARNING "snd-powermac: DMA died - patching it up!\n"); */ - - /* to clear DEAD status we must first clear RUN - set it to quiescent to be on the safe side */ - (void)in_le32(&rec->dma->status); - out_le32(&rec->dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - - if (!emergency_in_use) { /* new problem */ - memcpy((void *)emergency_dbdma.cmds, (void *)cp, - sizeof(struct dbdma_cmd)); - emergency_in_use = 1; - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); - cp = emergency_dbdma.cmds; - } - - /* now bump the values to reflect the amount - we haven't yet shifted */ - req = ld_le16(&cp->req_count); - res = ld_le16(&cp->res_count); - phy = ld_le32(&cp->phy_addr); - phy += (req - res); - st_le16(&cp->req_count, res); - st_le16(&cp->res_count, 0); - st_le16(&cp->xfer_status, 0); - st_le32(&cp->phy_addr, phy); - - st_le32(&cp->cmd_dep, rec->cmd.addr - + sizeof(struct dbdma_cmd)*((rec->cur_period+1)%rec->nperiods)); - - st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS); - - /* point at our patched up command block */ - out_le32(&rec->dma->cmdptr, emergency_dbdma.addr); - - /* we must re-start the controller */ - (void)in_le32(&rec->dma->status); - /* should complete clearing the DEAD status */ - out_le32(&rec->dma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); -} - -/* - * update playback/capture pointer from interrupts - */ -static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) -{ - volatile struct dbdma_cmd __iomem *cp; - int c; - int stat; - - spin_lock(&chip->reg_lock); - if (rec->running) { - for (c = 0; c < rec->nperiods; c++) { /* at most all fragments */ - - if (emergency_in_use) /* already using DEAD xfer? */ - cp = emergency_dbdma.cmds; - else - cp = &rec->cmd.cmds[rec->cur_period]; - - stat = ld_le16(&cp->xfer_status); - - if (stat & DEAD) { - snd_pmac_pcm_dead_xfer(rec, cp); - break; /* this block is still going */ - } - - if (emergency_in_use) - emergency_in_use = 0 ; /* done that */ - - if (! (stat & ACTIVE)) - break; - - /*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/ - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ - rec->cur_period++; - if (rec->cur_period >= rec->nperiods) { - rec->cur_period = 0; - } - - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(rec->substream); - spin_lock(&chip->reg_lock); - } - } - spin_unlock(&chip->reg_lock); -} - - -/* - * hw info - */ - -static struct snd_pcm_hardware snd_pmac_playback = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_44100, - .rate_min = 7350, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 131072, - .period_bytes_min = 256, - .period_bytes_max = 16384, - .periods_min = 3, - .periods_max = PMAC_MAX_FRAGS, -}; - -static struct snd_pcm_hardware snd_pmac_capture = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_44100, - .rate_min = 7350, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 131072, - .period_bytes_min = 256, - .period_bytes_max = 16384, - .periods_min = 3, - .periods_max = PMAC_MAX_FRAGS, -}; - - -#if 0 // NYI -static int snd_pmac_hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pmac *chip = rule->private; - struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]); - int i, freq_table[8], num_freqs; - - if (! rec) - return -EINVAL; - num_freqs = 0; - for (i = chip->num_freqs - 1; i >= 0; i--) { - if (rec->cur_freqs & (1 << i)) - freq_table[num_freqs++] = chip->freq_table[i]; - } - - return snd_interval_list(hw_param_interval(params, rule->var), - num_freqs, freq_table, 0); -} - -static int snd_pmac_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pmac *chip = rule->private; - struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]); - - if (! rec) - return -EINVAL; - return snd_mask_refine_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - rec->cur_formats); -} -#endif // NYI - -static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - int i; - - /* look up frequency table and fill bit mask */ - runtime->hw.rates = 0; - for (i = 0; i < chip->num_freqs; i++) - if (chip->freqs_ok & (1 << i)) - runtime->hw.rates |= - snd_pcm_rate_to_rate_bit(chip->freq_table[i]); - - /* check for minimum and maximum rates */ - for (i = 0; i < chip->num_freqs; i++) { - if (chip->freqs_ok & (1 << i)) { - runtime->hw.rate_max = chip->freq_table[i]; - break; - } - } - for (i = chip->num_freqs - 1; i >= 0; i--) { - if (chip->freqs_ok & (1 << i)) { - runtime->hw.rate_min = chip->freq_table[i]; - break; - } - } - runtime->hw.formats = chip->formats_ok; - if (chip->can_capture) { - if (! chip->can_duplex) - runtime->hw.info |= SNDRV_PCM_INFO_HALF_DUPLEX; - runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; - } - runtime->private_data = rec; - rec->substream = subs; - -#if 0 /* FIXME: still under development.. */ - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_pmac_hw_rule_rate, chip, rec->stream, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, - snd_pmac_hw_rule_format, chip, rec->stream, -1); -#endif - - runtime->hw.periods_max = rec->cmd.size - 1; - - /* constraints to fix choppy sound */ - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - return 0; -} - -static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - struct pmac_stream *astr; - - snd_pmac_dma_stop(rec); - - astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - if (! astr) - return -EINVAL; - - /* reset constraints */ - astr->cur_freqs = chip->freqs_ok; - astr->cur_formats = chip->formats_ok; - - return 0; -} - -static int snd_pmac_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - subs->runtime->hw = snd_pmac_playback; - return snd_pmac_pcm_open(chip, &chip->playback, subs); -} - -static int snd_pmac_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - subs->runtime->hw = snd_pmac_capture; - return snd_pmac_pcm_open(chip, &chip->capture, subs); -} - -static int snd_pmac_playback_close(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - return snd_pmac_pcm_close(chip, &chip->playback, subs); -} - -static int snd_pmac_capture_close(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - return snd_pmac_pcm_close(chip, &chip->capture, subs); -} - -/* - */ - -static struct snd_pcm_ops snd_pmac_playback_ops = { - .open = snd_pmac_playback_open, - .close = snd_pmac_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pmac_pcm_hw_params, - .hw_free = snd_pmac_pcm_hw_free, - .prepare = snd_pmac_playback_prepare, - .trigger = snd_pmac_playback_trigger, - .pointer = snd_pmac_playback_pointer, -}; - -static struct snd_pcm_ops snd_pmac_capture_ops = { - .open = snd_pmac_capture_open, - .close = snd_pmac_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pmac_pcm_hw_params, - .hw_free = snd_pmac_pcm_hw_free, - .prepare = snd_pmac_capture_prepare, - .trigger = snd_pmac_capture_trigger, - .pointer = snd_pmac_capture_pointer, -}; - -int __devinit snd_pmac_pcm_new(struct snd_pmac *chip) -{ - struct snd_pcm *pcm; - int err; - int num_captures = 1; - - if (! chip->can_capture) - num_captures = 0; - err = snd_pcm_new(chip->card, chip->card->driver, 0, 1, num_captures, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_pmac_playback_ops); - if (chip->can_capture) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_pmac_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - strcpy(pcm->name, chip->card->shortname); - chip->pcm = pcm; - - chip->formats_ok = SNDRV_PCM_FMTBIT_S16_BE; - if (chip->can_byte_swap) - chip->formats_ok |= SNDRV_PCM_FMTBIT_S16_LE; - - chip->playback.cur_formats = chip->formats_ok; - chip->capture.cur_formats = chip->formats_ok; - chip->playback.cur_freqs = chip->freqs_ok; - chip->capture.cur_freqs = chip->freqs_ok; - - /* preallocate 64k buffer */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &chip->pdev->dev, - 64 * 1024, 64 * 1024); - - return 0; -} - - -static void snd_pmac_dbdma_reset(struct snd_pmac *chip) -{ - out_le32(&chip->playback.dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - snd_pmac_wait_ack(&chip->playback); - out_le32(&chip->capture.dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - snd_pmac_wait_ack(&chip->capture); -} - - -/* - * handling beep - */ -void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed) -{ - struct pmac_stream *rec = &chip->playback; - - snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->req_count, bytes); - st_le16(&chip->extra_dma.cmds->xfer_status, 0); - st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr); - st_le32(&chip->extra_dma.cmds->phy_addr, addr); - st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS); - out_le32(&chip->awacs->control, - (in_le32(&chip->awacs->control) & ~0x1f00) - | (speed << 8)); - out_le32(&chip->awacs->byteswap, 0); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); -} - -void snd_pmac_beep_dma_stop(struct snd_pmac *chip) -{ - snd_pmac_dma_stop(&chip->playback); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); - snd_pmac_pcm_set_format(chip); /* reset format */ -} - - -/* - * interrupt handlers - */ -static irqreturn_t -snd_pmac_tx_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - snd_pmac_pcm_update(chip, &chip->playback); - return IRQ_HANDLED; -} - - -static irqreturn_t -snd_pmac_rx_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - snd_pmac_pcm_update(chip, &chip->capture); - return IRQ_HANDLED; -} - - -static irqreturn_t -snd_pmac_ctrl_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - int ctrl = in_le32(&chip->awacs->control); - - /*printk(KERN_DEBUG "pmac: control interrupt.. 0x%x\n", ctrl);*/ - if (ctrl & MASK_PORTCHG) { - /* do something when headphone is plugged/unplugged? */ - if (chip->update_automute) - chip->update_automute(chip, 1); - } - if (ctrl & MASK_CNTLERR) { - int err = (in_le32(&chip->awacs->codec_stat) & MASK_ERRCODE) >> 16; - if (err && chip->model <= PMAC_SCREAMER) - snd_printk(KERN_DEBUG "error %x\n", err); - } - /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ - out_le32(&chip->awacs->control, ctrl); - return IRQ_HANDLED; -} - - -/* - * a wrapper to feature call for compatibility - */ -static void snd_pmac_sound_feature(struct snd_pmac *chip, int enable) -{ - if (ppc_md.feature_call) - ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); -} - -/* - * release resources - */ - -static int snd_pmac_free(struct snd_pmac *chip) -{ - /* stop sounds */ - if (chip->initialized) { - snd_pmac_dbdma_reset(chip); - /* disable interrupts from awacs interface */ - out_le32(&chip->awacs->control, in_le32(&chip->awacs->control) & 0xfff); - } - - if (chip->node) - snd_pmac_sound_feature(chip, 0); - - /* clean up mixer if any */ - if (chip->mixer_free) - chip->mixer_free(chip); - - snd_pmac_detach_beep(chip); - - /* release resources */ - if (chip->irq >= 0) - free_irq(chip->irq, (void*)chip); - if (chip->tx_irq >= 0) - free_irq(chip->tx_irq, (void*)chip); - if (chip->rx_irq >= 0) - free_irq(chip->rx_irq, (void*)chip); - snd_pmac_dbdma_free(chip, &chip->playback.cmd); - snd_pmac_dbdma_free(chip, &chip->capture.cmd); - snd_pmac_dbdma_free(chip, &chip->extra_dma); - snd_pmac_dbdma_free(chip, &emergency_dbdma); - if (chip->macio_base) - iounmap(chip->macio_base); - if (chip->latch_base) - iounmap(chip->latch_base); - if (chip->awacs) - iounmap(chip->awacs); - if (chip->playback.dma) - iounmap(chip->playback.dma); - if (chip->capture.dma) - iounmap(chip->capture.dma); - - if (chip->node) { - int i; - for (i = 0; i < 3; i++) { - if (chip->requested & (1 << i)) - release_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i])); - } - } - - if (chip->pdev) - pci_dev_put(chip->pdev); - of_node_put(chip->node); - kfree(chip); - return 0; -} - - -/* - * free the device - */ -static int snd_pmac_dev_free(struct snd_device *device) -{ - struct snd_pmac *chip = device->device_data; - return snd_pmac_free(chip); -} - - -/* - * check the machine support byteswap (little-endian) - */ - -static void __devinit detect_byte_swap(struct snd_pmac *chip) -{ - struct device_node *mio; - - /* if seems that Keylargo can't byte-swap */ - for (mio = chip->node->parent; mio; mio = mio->parent) { - if (strcmp(mio->name, "mac-io") == 0) { - if (of_device_is_compatible(mio, "Keylargo")) - chip->can_byte_swap = 0; - break; - } - } - - /* it seems the Pismo & iBook can't byte-swap in hardware. */ - if (of_machine_is_compatible("PowerBook3,1") || - of_machine_is_compatible("PowerBook2,1")) - chip->can_byte_swap = 0 ; - - if (of_machine_is_compatible("PowerBook2,1")) - chip->can_duplex = 0; -} - - -/* - * detect a sound chip - */ -static int __devinit snd_pmac_detect(struct snd_pmac *chip) -{ - struct device_node *sound; - struct device_node *dn; - const unsigned int *prop; - unsigned int l; - struct macio_chip* macio; - - if (!machine_is(powermac)) - return -ENODEV; - - chip->subframe = 0; - chip->revision = 0; - chip->freqs_ok = 0xff; /* all ok */ - chip->model = PMAC_AWACS; - chip->can_byte_swap = 1; - chip->can_duplex = 1; - chip->can_capture = 1; - chip->num_freqs = ARRAY_SIZE(awacs_freqs); - chip->freq_table = awacs_freqs; - chip->pdev = NULL; - - chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */ - - /* check machine type */ - if (of_machine_is_compatible("AAPL,3400/2400") - || of_machine_is_compatible("AAPL,3500")) - chip->is_pbook_3400 = 1; - else if (of_machine_is_compatible("PowerBook1,1") - || of_machine_is_compatible("AAPL,PowerBook1998")) - chip->is_pbook_G3 = 1; - chip->node = of_find_node_by_name(NULL, "awacs"); - sound = of_node_get(chip->node); - - /* - * powermac G3 models have a node called "davbus" - * with a child called "sound". - */ - if (!chip->node) - chip->node = of_find_node_by_name(NULL, "davbus"); - /* - * if we didn't find a davbus device, try 'i2s-a' since - * this seems to be what iBooks have - */ - if (! chip->node) { - chip->node = of_find_node_by_name(NULL, "i2s-a"); - if (chip->node && chip->node->parent && - chip->node->parent->parent) { - if (of_device_is_compatible(chip->node->parent->parent, - "K2-Keylargo")) - chip->is_k2 = 1; - } - } - if (! chip->node) - return -ENODEV; - - if (!sound) { - sound = of_find_node_by_name(NULL, "sound"); - while (sound && sound->parent != chip->node) - sound = of_find_node_by_name(sound, "sound"); - } - if (! sound) { - of_node_put(chip->node); - chip->node = NULL; - return -ENODEV; - } - prop = of_get_property(sound, "sub-frame", NULL); - if (prop && *prop < 16) - chip->subframe = *prop; - prop = of_get_property(sound, "layout-id", NULL); - if (prop) { - /* partly deprecate snd-powermac, for those machines - * that have a layout-id property for now */ - printk(KERN_INFO "snd-powermac no longer handles any " - "machines with a layout-id property " - "in the device-tree, use snd-aoa.\n"); - of_node_put(sound); - of_node_put(chip->node); - chip->node = NULL; - return -ENODEV; - } - /* This should be verified on older screamers */ - if (of_device_is_compatible(sound, "screamer")) { - chip->model = PMAC_SCREAMER; - // chip->can_byte_swap = 0; /* FIXME: check this */ - } - if (of_device_is_compatible(sound, "burgundy")) { - chip->model = PMAC_BURGUNDY; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "daca")) { - chip->model = PMAC_DACA; - chip->can_capture = 0; /* no capture */ - chip->can_duplex = 0; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "tumbler")) { - chip->model = PMAC_TUMBLER; - chip->can_capture = of_machine_is_compatible("PowerMac4,2") - || of_machine_is_compatible("PowerBook3,2") - || of_machine_is_compatible("PowerBook3,3") - || of_machine_is_compatible("PowerBook4,1") - || of_machine_is_compatible("PowerBook4,2") - || of_machine_is_compatible("PowerBook4,3"); - chip->can_duplex = 0; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->freq_table = tumbler_freqs; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "snapper")) { - chip->model = PMAC_SNAPPER; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->freq_table = tumbler_freqs; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - prop = of_get_property(sound, "device-id", NULL); - if (prop) - chip->device_id = *prop; - dn = of_find_node_by_name(NULL, "perch"); - chip->has_iic = (dn != NULL); - of_node_put(dn); - - /* We need the PCI device for DMA allocations, let's use a crude method - * for now ... - */ - macio = macio_find(chip->node, macio_unknown); - if (macio == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio !\n"); - else { - struct pci_dev *pdev = NULL; - - for_each_pci_dev(pdev) { - struct device_node *np = pci_device_to_OF_node(pdev); - if (np && np == macio->of_node) { - chip->pdev = pdev; - break; - } - } - } - if (chip->pdev == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio PCI" - " device !\n"); - - detect_byte_swap(chip); - - /* look for a property saying what sample rates - are available */ - prop = of_get_property(sound, "sample-rates", &l); - if (! prop) - prop = of_get_property(sound, "output-frame-rates", &l); - if (prop) { - int i; - chip->freqs_ok = 0; - for (l /= sizeof(int); l > 0; --l) { - unsigned int r = *prop++; - /* Apple 'Fixed' format */ - if (r >= 0x10000) - r >>= 16; - for (i = 0; i < chip->num_freqs; ++i) { - if (r == chip->freq_table[i]) { - chip->freqs_ok |= (1 << i); - break; - } - } - } - } else { - /* assume only 44.1khz */ - chip->freqs_ok = 1; - } - - of_node_put(sound); - return 0; -} - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute - */ -static int pmac_auto_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->auto_mute; - return 0; -} - -static int pmac_auto_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (ucontrol->value.integer.value[0] != chip->auto_mute) { - chip->auto_mute = !!ucontrol->value.integer.value[0]; - if (chip->update_automute) - chip->update_automute(chip, 1); - return 1; - } - return 0; -} - -static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (chip->detect_headphone) - ucontrol->value.integer.value[0] = chip->detect_headphone(chip); - else - ucontrol->value.integer.value[0] = 0; - return 0; -} - -static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Auto Mute Switch", - .info = snd_pmac_boolean_mono_info, - .get = pmac_auto_mute_get, - .put = pmac_auto_mute_put, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detection", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_pmac_boolean_mono_info, - .get = pmac_hp_detect_get, - }, -}; - -int __devinit snd_pmac_add_automute(struct snd_pmac *chip) -{ - int err; - chip->auto_mute = 1; - err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); - if (err < 0) { - printk(KERN_ERR "snd-powermac: Failed to add automute control\n"); - return err; - } - chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); - return snd_ctl_add(chip->card, chip->hp_detect_ctl); -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - -/* - * create and detect a pmac chip record - */ -int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) -{ - struct snd_pmac *chip; - struct device_node *np; - int i, err; - unsigned int irq; - unsigned long ctrl_addr, txdma_addr, rxdma_addr; - static struct snd_device_ops ops = { - .dev_free = snd_pmac_dev_free, - }; - - *chip_return = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->card = card; - - spin_lock_init(&chip->reg_lock); - chip->irq = chip->tx_irq = chip->rx_irq = -1; - - chip->playback.stream = SNDRV_PCM_STREAM_PLAYBACK; - chip->capture.stream = SNDRV_PCM_STREAM_CAPTURE; - - if ((err = snd_pmac_detect(chip)) < 0) - goto __error; - - if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(chip, &chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0 || - snd_pmac_dbdma_alloc(chip, &emergency_dbdma, 2) < 0) { - err = -ENOMEM; - goto __error; - } - - np = chip->node; - chip->requested = 0; - if (chip->is_k2) { - static char *rnames[] = { - "Sound Control", "Sound DMA" }; - for (i = 0; i < 2; i ++) { - if (of_address_to_resource(np->parent, i, - &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); - err = -ENODEV; - goto __error; - } - if (request_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i]), - rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); - err = -ENODEV; - goto __error; - } - chip->requested |= (1 << i); - } - ctrl_addr = chip->rsrc[0].start; - txdma_addr = chip->rsrc[1].start; - rxdma_addr = txdma_addr + 0x100; - } else { - static char *rnames[] = { - "Sound Control", "Sound Tx DMA", "Sound Rx DMA" }; - for (i = 0; i < 3; i ++) { - if (of_address_to_resource(np, i, - &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); - err = -ENODEV; - goto __error; - } - if (request_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i]), - rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); - err = -ENODEV; - goto __error; - } - chip->requested |= (1 << i); - } - ctrl_addr = chip->rsrc[0].start; - txdma_addr = chip->rsrc[1].start; - rxdma_addr = chip->rsrc[2].start; - } - - chip->awacs = ioremap(ctrl_addr, 0x1000); - chip->playback.dma = ioremap(txdma_addr, 0x100); - chip->capture.dma = ioremap(rxdma_addr, 0x100); - if (chip->model <= PMAC_BURGUNDY) { - irq = irq_of_parse_and_map(np, 0); - if (request_irq(irq, snd_pmac_ctrl_intr, 0, - "PMac", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", - irq); - err = -EBUSY; - goto __error; - } - chip->irq = irq; - } - irq = irq_of_parse_and_map(np, 1); - if (request_irq(irq, snd_pmac_tx_intr, 0, "PMac Output", (void*)chip)){ - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); - err = -EBUSY; - goto __error; - } - chip->tx_irq = irq; - irq = irq_of_parse_and_map(np, 2); - if (request_irq(irq, snd_pmac_rx_intr, 0, "PMac Input", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); - err = -EBUSY; - goto __error; - } - chip->rx_irq = irq; - - snd_pmac_sound_feature(chip, 1); - - /* reset & enable interrupts */ - if (chip->model <= PMAC_BURGUNDY) - out_le32(&chip->awacs->control, chip->control_mask); - - /* Powerbooks have odd ways of enabling inputs such as - an expansion-bay CD or sound from an internal modem - or a PC-card modem. */ - if (chip->is_pbook_3400) { - /* Enable CD and PC-card sound inputs. */ - /* This is done by reading from address - * f301a000, + 0x10 to enable the expansion-bay - * CD sound input, + 0x80 to enable the PC-card - * sound input. The 0x100 enables the SCSI bus - * terminator power. - */ - chip->latch_base = ioremap (0xf301a000, 0x1000); - in_8(chip->latch_base + 0x190); - } else if (chip->is_pbook_G3) { - struct device_node* mio; - for (mio = chip->node->parent; mio; mio = mio->parent) { - if (strcmp(mio->name, "mac-io") == 0) { - struct resource r; - if (of_address_to_resource(mio, 0, &r) == 0) - chip->macio_base = - ioremap(r.start, 0x40); - break; - } - } - /* Enable CD sound input. */ - /* The relevant bits for writing to this byte are 0x8f. - * I haven't found out what the 0x80 bit does. - * For the 0xf bits, writing 3 or 7 enables the CD - * input, any other value disables it. Values - * 1, 3, 5, 7 enable the microphone. Values 0, 2, - * 4, 6, 8 - f enable the input from the modem. - */ - if (chip->macio_base) - out_8(chip->macio_base + 0x37, 3); - } - - /* Reset dbdma channels */ - snd_pmac_dbdma_reset(chip); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) - goto __error; - - *chip_return = chip; - return 0; - - __error: - snd_pmac_free(chip); - return err; -} - - -/* - * sleep notify for powerbook - */ - -#ifdef CONFIG_PM - -/* - * Save state when going to sleep, restore it afterwards. - */ - -void snd_pmac_suspend(struct snd_pmac *chip) -{ - unsigned long flags; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (chip->suspend) - chip->suspend(chip); - snd_pcm_suspend_all(chip->pcm); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->irq >= 0) - disable_irq(chip->irq); - if (chip->tx_irq >= 0) - disable_irq(chip->tx_irq); - if (chip->rx_irq >= 0) - disable_irq(chip->rx_irq); - snd_pmac_sound_feature(chip, 0); -} - -void snd_pmac_resume(struct snd_pmac *chip) -{ - snd_pmac_sound_feature(chip, 1); - if (chip->resume) - chip->resume(chip); - /* enable CD sound input */ - if (chip->macio_base && chip->is_pbook_G3) - out_8(chip->macio_base + 0x37, 3); - else if (chip->is_pbook_3400) - in_8(chip->latch_base + 0x190); - - snd_pmac_pcm_set_format(chip); - - if (chip->irq >= 0) - enable_irq(chip->irq); - if (chip->tx_irq >= 0) - enable_irq(chip->tx_irq); - if (chip->rx_irq >= 0) - enable_irq(chip->rx_irq); - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); -} - -#endif /* CONFIG_PM */ - diff --git a/ANDROID_3.4.5/sound/ppc/pmac.h b/ANDROID_3.4.5/sound/ppc/pmac.h deleted file mode 100644 index 25c512c2..00000000 --- a/ANDROID_3.4.5/sound/ppc/pmac.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Driver for PowerMac onboard soundchips - * Copyright (c) 2001 by Takashi Iwai <tiwai@suse.de> - * based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef __PMAC_H -#define __PMAC_H - -#include <sound/control.h> -#include <sound/pcm.h> -#include "awacs.h" - -#include <linux/adb.h> -#ifdef CONFIG_ADB_CUDA -#include <linux/cuda.h> -#endif -#ifdef CONFIG_ADB_PMU -#include <linux/pmu.h> -#endif -#include <linux/nvram.h> -#include <linux/tty.h> -#include <linux/vt_kern.h> -#include <asm/dbdma.h> -#include <asm/prom.h> -#include <asm/machdep.h> - -/* maximum number of fragments */ -#define PMAC_MAX_FRAGS 32 - - -#define PMAC_SUPPORT_AUTOMUTE - -/* - * DBDMA space - */ -struct pmac_dbdma { - dma_addr_t dma_base; - dma_addr_t addr; - struct dbdma_cmd __iomem *cmds; - void *space; - int size; -}; - -/* - * playback/capture stream - */ -struct pmac_stream { - int running; /* boolean */ - - int stream; /* PLAYBACK/CAPTURE */ - - int dma_size; /* in bytes */ - int period_size; /* in bytes */ - int buffer_size; /* in kbytes */ - int nperiods, cur_period; - - struct pmac_dbdma cmd; - volatile struct dbdma_regs __iomem *dma; - - struct snd_pcm_substream *substream; - - unsigned int cur_freqs; /* currently available frequencies */ - unsigned int cur_formats; /* currently available formats */ -}; - - -/* - */ - -enum snd_pmac_model { - PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, - PMAC_SNAPPER -}; - -struct snd_pmac { - struct snd_card *card; - - /* h/w info */ - struct device_node *node; - struct pci_dev *pdev; - unsigned int revision; - unsigned int manufacturer; - unsigned int subframe; - unsigned int device_id; - enum snd_pmac_model model; - - unsigned int has_iic : 1; - unsigned int is_pbook_3400 : 1; - unsigned int is_pbook_G3 : 1; - unsigned int is_k2 : 1; - - unsigned int can_byte_swap : 1; - unsigned int can_duplex : 1; - unsigned int can_capture : 1; - - unsigned int auto_mute : 1; - unsigned int initialized : 1; - unsigned int feature_is_set : 1; - - unsigned int requested; - struct resource rsrc[3]; - - int num_freqs; - int *freq_table; - unsigned int freqs_ok; /* bit flags */ - unsigned int formats_ok; /* pcm hwinfo */ - int active; - int rate_index; - int format; /* current format */ - - spinlock_t reg_lock; - volatile struct awacs_regs __iomem *awacs; - int awacs_reg[8]; /* register cache */ - unsigned int hp_stat_mask; - - unsigned char __iomem *latch_base; - unsigned char __iomem *macio_base; - - struct pmac_stream playback; - struct pmac_stream capture; - - struct pmac_dbdma extra_dma; - - int irq, tx_irq, rx_irq; - - struct snd_pcm *pcm; - - struct pmac_beep *beep; - - unsigned int control_mask; /* control mask */ - - /* mixer stuffs */ - void *mixer_data; - void (*mixer_free)(struct snd_pmac *); - struct snd_kcontrol *master_sw_ctl; - struct snd_kcontrol *speaker_sw_ctl; - struct snd_kcontrol *drc_sw_ctl; /* only used for tumbler -ReneR */ - struct snd_kcontrol *hp_detect_ctl; - struct snd_kcontrol *lineout_sw_ctl; - - /* lowlevel callbacks */ - void (*set_format)(struct snd_pmac *chip); - void (*update_automute)(struct snd_pmac *chip, int do_notify); - int (*detect_headphone)(struct snd_pmac *chip); -#ifdef CONFIG_PM - void (*suspend)(struct snd_pmac *chip); - void (*resume)(struct snd_pmac *chip); -#endif - -}; - - -/* exported functions */ -int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return); -int snd_pmac_pcm_new(struct snd_pmac *chip); -int snd_pmac_attach_beep(struct snd_pmac *chip); -void snd_pmac_detach_beep(struct snd_pmac *chip); -void snd_pmac_beep_stop(struct snd_pmac *chip); -unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate); - -void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed); -void snd_pmac_beep_dma_stop(struct snd_pmac *chip); - -#ifdef CONFIG_PM -void snd_pmac_suspend(struct snd_pmac *chip); -void snd_pmac_resume(struct snd_pmac *chip); -#endif - -/* initialize mixer */ -int snd_pmac_awacs_init(struct snd_pmac *chip); -int snd_pmac_burgundy_init(struct snd_pmac *chip); -int snd_pmac_daca_init(struct snd_pmac *chip); -int snd_pmac_tumbler_init(struct snd_pmac *chip); -int snd_pmac_tumbler_post_init(void); - -/* i2c functions */ -struct pmac_keywest { - int addr; - struct i2c_client *client; - int id; - int (*init_client)(struct pmac_keywest *i2c); - char *name; -}; - -int snd_pmac_keywest_init(struct pmac_keywest *i2c); -void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c); - -/* misc */ -#define snd_pmac_boolean_stereo_info snd_ctl_boolean_stereo_info -#define snd_pmac_boolean_mono_info snd_ctl_boolean_mono_info - -int snd_pmac_add_automute(struct snd_pmac *chip); - -#endif /* __PMAC_H */ diff --git a/ANDROID_3.4.5/sound/ppc/powermac.c b/ANDROID_3.4.5/sound/ppc/powermac.c deleted file mode 100644 index 5a4e263b..00000000 --- a/ANDROID_3.4.5/sound/ppc/powermac.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Driver for PowerMac AWACS - * Copyright (c) 2001 by Takashi Iwai <tiwai@suse.de> - * based on dmasound.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include "pmac.h" -#include "awacs.h" -#include "burgundy.h" - -#define CHIP_NAME "PMac" - -MODULE_DESCRIPTION("PowerMac"); -MODULE_SUPPORTED_DEVICE("{{Apple,PowerMac}}"); -MODULE_LICENSE("GPL"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static bool enable_beep = 1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip."); -module_param(enable_beep, bool, 0444); -MODULE_PARM_DESC(enable_beep, "Enable beep using PCM."); - -static struct platform_device *device; - - -/* - */ - -static int __devinit snd_pmac_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_pmac *chip; - char *name_ext; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_pmac_new(card, &chip)) < 0) - goto __error; - card->private_data = chip; - - switch (chip->model) { - case PMAC_BURGUNDY: - strcpy(card->driver, "PMac Burgundy"); - strcpy(card->shortname, "PowerMac Burgundy"); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_burgundy_init(chip)) < 0) - goto __error; - break; - case PMAC_DACA: - strcpy(card->driver, "PMac DACA"); - strcpy(card->shortname, "PowerMac DACA"); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_daca_init(chip)) < 0) - goto __error; - break; - case PMAC_TUMBLER: - case PMAC_SNAPPER: - name_ext = chip->model == PMAC_TUMBLER ? "Tumbler" : "Snapper"; - sprintf(card->driver, "PMac %s", name_ext); - sprintf(card->shortname, "PowerMac %s", name_ext); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) - goto __error; - break; - case PMAC_AWACS: - case PMAC_SCREAMER: - name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; - sprintf(card->driver, "PMac %s", name_ext); - sprintf(card->shortname, "PowerMac %s", name_ext); - if (chip->is_pbook_3400) - name_ext = " [PB3400]"; - else if (chip->is_pbook_G3) - name_ext = " [PBG3]"; - else - name_ext = ""; - sprintf(card->longname, "%s%s Rev %d", - card->shortname, name_ext, chip->revision); - if ((err = snd_pmac_awacs_init(chip)) < 0) - goto __error; - break; - default: - snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model); - err = -EINVAL; - goto __error; - } - - if ((err = snd_pmac_pcm_new(chip)) < 0) - goto __error; - - chip->initialized = 1; - if (enable_beep) - snd_pmac_attach_beep(chip); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) < 0) - goto __error; - - platform_set_drvdata(devptr, card); - return 0; - -__error: - snd_card_free(card); - return err; -} - - -static int __devexit snd_pmac_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_pmac_driver_suspend(struct platform_device *devptr, pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(devptr); - snd_pmac_suspend(card->private_data); - return 0; -} - -static int snd_pmac_driver_resume(struct platform_device *devptr) -{ - struct snd_card *card = platform_get_drvdata(devptr); - snd_pmac_resume(card->private_data); - return 0; -} -#endif - -#define SND_PMAC_DRIVER "snd_powermac" - -static struct platform_driver snd_pmac_driver = { - .probe = snd_pmac_probe, - .remove = __devexit_p(snd_pmac_remove), -#ifdef CONFIG_PM - .suspend = snd_pmac_driver_suspend, - .resume = snd_pmac_driver_resume, -#endif - .driver = { - .name = SND_PMAC_DRIVER - }, -}; - -static int __init alsa_card_pmac_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_pmac_driver)) < 0) - return err; - device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); - return 0; - -} - -static void __exit alsa_card_pmac_exit(void) -{ - if (!IS_ERR(device)) - platform_device_unregister(device); - platform_driver_unregister(&snd_pmac_driver); -} - -module_init(alsa_card_pmac_init) -module_exit(alsa_card_pmac_exit) diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3.c b/ANDROID_3.4.5/sound/ppc/snd_ps3.c deleted file mode 100644 index 1aa52eff..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * All rights reserved. - * Copyright 2006, 2007 Sony Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the Licence. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/dma-mapping.h> -#include <linux/dmapool.h> -#include <linux/gfp.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/module.h> - -#include <sound/asound.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/memalloc.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> - -#include <asm/dma.h> -#include <asm/firmware.h> -#include <asm/lv1call.h> -#include <asm/ps3.h> -#include <asm/ps3av.h> - -#include "snd_ps3.h" -#include "snd_ps3_reg.h" - - -/* - * global - */ -static struct snd_ps3_card_info the_card; - -static int snd_ps3_start_delay = CONFIG_SND_PS3_DEFAULT_START_DELAY; - -module_param_named(start_delay, snd_ps3_start_delay, uint, 0644); -MODULE_PARM_DESC(start_delay, "time to insert silent data in ms"); - -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for PS3 soundchip."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for PS3 soundchip."); - - -/* - * PS3 audio register access - */ -static inline u32 read_reg(unsigned int reg) -{ - return in_be32(the_card.mapped_mmio_vaddr + reg); -} -static inline void write_reg(unsigned int reg, u32 val) -{ - out_be32(the_card.mapped_mmio_vaddr + reg, val); -} -static inline void update_reg(unsigned int reg, u32 or_val) -{ - u32 newval = read_reg(reg) | or_val; - write_reg(reg, newval); -} -static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val) -{ - u32 newval = (read_reg(reg) & mask) | or_val; - write_reg(reg, newval); -} - -/* - * ALSA defs - */ -static const struct snd_pcm_hardware snd_ps3_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE), - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 96000, - - .channels_min = 2, /* stereo only */ - .channels_max = 2, - - .buffer_bytes_max = PS3_AUDIO_FIFO_SIZE * 64, - - /* interrupt by four stages */ - .period_bytes_min = PS3_AUDIO_FIFO_STAGE_SIZE * 4, - .period_bytes_max = PS3_AUDIO_FIFO_STAGE_SIZE * 4, - - .periods_min = 16, - .periods_max = 32, /* buffer_size_max/ period_bytes_max */ - - .fifo_size = PS3_AUDIO_FIFO_SIZE -}; - -static int snd_ps3_verify_dma_stop(struct snd_ps3_card_info *card, - int count, int force_stop) -{ - int dma_ch, done, retries, stop_forced = 0; - uint32_t status; - - for (dma_ch = 0; dma_ch < 8; dma_ch++) { - retries = count; - do { - status = read_reg(PS3_AUDIO_KICK(dma_ch)) & - PS3_AUDIO_KICK_STATUS_MASK; - switch (status) { - case PS3_AUDIO_KICK_STATUS_DONE: - case PS3_AUDIO_KICK_STATUS_NOTIFY: - case PS3_AUDIO_KICK_STATUS_CLEAR: - case PS3_AUDIO_KICK_STATUS_ERROR: - done = 1; - break; - default: - done = 0; - udelay(10); - } - } while (!done && --retries); - if (!retries && force_stop) { - pr_info("%s: DMA ch %d is not stopped.", - __func__, dma_ch); - /* last resort. force to stop dma. - * NOTE: this cause DMA done interrupts - */ - update_reg(PS3_AUDIO_CONFIG, PS3_AUDIO_CONFIG_CLEAR); - stop_forced = 1; - } - } - return stop_forced; -} - -/* - * wait for all dma is done. - * NOTE: caller should reset card->running before call. - * If not, the interrupt handler will re-start DMA, - * then DMA is never stopped. - */ -static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card) -{ - int stop_forced; - /* - * wait for the last dma is done - */ - - /* - * expected maximum DMA done time is 5.7ms + something (DMA itself). - * 5.7ms is from 16bit/sample 2ch 44.1Khz; the time next - * DMA kick event would occur. - */ - stop_forced = snd_ps3_verify_dma_stop(card, 700, 1); - - /* - * clear outstanding interrupts. - */ - update_reg(PS3_AUDIO_INTR_0, 0); - update_reg(PS3_AUDIO_AX_IS, 0); - - /* - *revert CLEAR bit since it will not reset automatically after DMA stop - */ - if (stop_forced) - update_mask_reg(PS3_AUDIO_CONFIG, ~PS3_AUDIO_CONFIG_CLEAR, 0); - /* ensure the hardware sees changes */ - wmb(); -} - -static void snd_ps3_kick_dma(struct snd_ps3_card_info *card) -{ - - update_reg(PS3_AUDIO_KICK(0), PS3_AUDIO_KICK_REQUEST); - /* ensure the hardware sees the change */ - wmb(); -} - -/* - * convert virtual addr to ioif bus addr. - */ -static dma_addr_t v_to_bus(struct snd_ps3_card_info *card, void *paddr, int ch) -{ - return card->dma_start_bus_addr[ch] + - (paddr - card->dma_start_vaddr[ch]); -}; - - -/* - * increment ring buffer pointer. - * NOTE: caller must hold write spinlock - */ -static void snd_ps3_bump_buffer(struct snd_ps3_card_info *card, - enum snd_ps3_ch ch, size_t byte_count, - int stage) -{ - if (!stage) - card->dma_last_transfer_vaddr[ch] = - card->dma_next_transfer_vaddr[ch]; - card->dma_next_transfer_vaddr[ch] += byte_count; - if ((card->dma_start_vaddr[ch] + (card->dma_buffer_size / 2)) <= - card->dma_next_transfer_vaddr[ch]) { - card->dma_next_transfer_vaddr[ch] = card->dma_start_vaddr[ch]; - } -} -/* - * setup dmac to send data to audio and attenuate samples on the ring buffer - */ -static int snd_ps3_program_dma(struct snd_ps3_card_info *card, - enum snd_ps3_dma_filltype filltype) -{ - /* this dmac does not support over 4G */ - uint32_t dma_addr; - int fill_stages, dma_ch, stage; - enum snd_ps3_ch ch; - uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ - void *start_vaddr; - unsigned long irqsave; - int silent = 0; - - switch (filltype) { - case SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL: - silent = 1; - /* intentionally fall thru */ - case SND_PS3_DMA_FILLTYPE_FIRSTFILL: - ch0_kick_event = PS3_AUDIO_KICK_EVENT_ALWAYS; - break; - - case SND_PS3_DMA_FILLTYPE_SILENT_RUNNING: - silent = 1; - /* intentionally fall thru */ - case SND_PS3_DMA_FILLTYPE_RUNNING: - ch0_kick_event = PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY; - break; - } - - snd_ps3_verify_dma_stop(card, 700, 0); - fill_stages = 4; - spin_lock_irqsave(&card->dma_lock, irqsave); - for (ch = 0; ch < 2; ch++) { - start_vaddr = card->dma_next_transfer_vaddr[0]; - for (stage = 0; stage < fill_stages; stage++) { - dma_ch = stage * 2 + ch; - if (silent) - dma_addr = card->null_buffer_start_dma_addr; - else - dma_addr = - v_to_bus(card, - card->dma_next_transfer_vaddr[ch], - ch); - - write_reg(PS3_AUDIO_SOURCE(dma_ch), - (PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY | - dma_addr)); - - /* dst: fixed to 3wire#0 */ - if (ch == 0) - write_reg(PS3_AUDIO_DEST(dma_ch), - (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | - PS3_AUDIO_AO_3W_LDATA(0))); - else - write_reg(PS3_AUDIO_DEST(dma_ch), - (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | - PS3_AUDIO_AO_3W_RDATA(0))); - - /* count always 1 DMA block (1/2 stage = 128 bytes) */ - write_reg(PS3_AUDIO_DMASIZE(dma_ch), 0); - /* bump pointer if needed */ - if (!silent) - snd_ps3_bump_buffer(card, ch, - PS3_AUDIO_DMAC_BLOCK_SIZE, - stage); - - /* kick event */ - if (dma_ch == 0) - write_reg(PS3_AUDIO_KICK(dma_ch), - ch0_kick_event); - else - write_reg(PS3_AUDIO_KICK(dma_ch), - PS3_AUDIO_KICK_EVENT_AUDIO_DMA(dma_ch - - 1) | - PS3_AUDIO_KICK_REQUEST); - } - } - /* ensure the hardware sees the change */ - wmb(); - spin_unlock_irqrestore(&card->dma_lock, irqsave); - - return 0; -} - -/* - * Interrupt handler - */ -static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id) -{ - - uint32_t port_intr; - int underflow_occured = 0; - struct snd_ps3_card_info *card = dev_id; - - if (!card->running) { - update_reg(PS3_AUDIO_AX_IS, 0); - update_reg(PS3_AUDIO_INTR_0, 0); - return IRQ_HANDLED; - } - - port_intr = read_reg(PS3_AUDIO_AX_IS); - /* - *serial buffer empty detected (every 4 times), - *program next dma and kick it - */ - if (port_intr & PS3_AUDIO_AX_IE_ASOBEIE(0)) { - write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBEIE(0)); - if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { - write_reg(PS3_AUDIO_AX_IS, port_intr); - underflow_occured = 1; - } - if (card->silent) { - /* we are still in silent time */ - snd_ps3_program_dma(card, - (underflow_occured) ? - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL : - SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); - snd_ps3_kick_dma(card); - card->silent--; - } else { - snd_ps3_program_dma(card, - (underflow_occured) ? - SND_PS3_DMA_FILLTYPE_FIRSTFILL : - SND_PS3_DMA_FILLTYPE_RUNNING); - snd_ps3_kick_dma(card); - snd_pcm_period_elapsed(card->substream); - } - } else if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { - write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBUIE(0)); - /* - * serial out underflow, but buffer empty not detected. - * in this case, fill fifo with 0 to recover. After - * filling dummy data, serial automatically start to - * consume them and then will generate normal buffer - * empty interrupts. - * If both buffer underflow and buffer empty are occurred, - * it is better to do nomal data transfer than empty one - */ - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - } - /* clear interrupt cause */ - return IRQ_HANDLED; -}; - -/* - * audio mute on/off - * mute_on : 0 output enabled - * 1 mute - */ -static int snd_ps3_mute(int mute_on) -{ - return ps3av_audio_mute(mute_on); -} - -/* - * av setting - * NOTE: calling this function may generate audio interrupt. - */ -static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card) -{ - int ret, retries, i; - pr_debug("%s: start\n", __func__); - - ret = ps3av_set_audio_mode(card->avs.avs_audio_ch, - card->avs.avs_audio_rate, - card->avs.avs_audio_width, - card->avs.avs_audio_format, - card->avs.avs_audio_source); - /* - * Reset the following unwanted settings: - */ - - /* disable all 3wire buffers */ - update_mask_reg(PS3_AUDIO_AO_3WMCTRL, - ~(PS3_AUDIO_AO_3WMCTRL_ASOEN(0) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(1) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(2) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(3)), - 0); - wmb(); /* ensure the hardware sees the change */ - /* wait for actually stopped */ - retries = 1000; - while ((read_reg(PS3_AUDIO_AO_3WMCTRL) & - (PS3_AUDIO_AO_3WMCTRL_ASORUN(0) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(1) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(2) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(3))) && - --retries) { - udelay(1); - } - - /* reset buffer pointer */ - for (i = 0; i < 4; i++) { - update_reg(PS3_AUDIO_AO_3WCTRL(i), - PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET); - udelay(10); - } - wmb(); /* ensure the hardware actually start resetting */ - - /* enable 3wire#0 buffer */ - update_reg(PS3_AUDIO_AO_3WMCTRL, PS3_AUDIO_AO_3WMCTRL_ASOEN(0)); - - - /* In 24bit mode,ALSA inserts a zero byte at first byte of per sample */ - update_mask_reg(PS3_AUDIO_AO_3WCTRL(0), - ~PS3_AUDIO_AO_3WCTRL_ASODF, - PS3_AUDIO_AO_3WCTRL_ASODF_LSB); - update_mask_reg(PS3_AUDIO_AO_SPDCTRL(0), - ~PS3_AUDIO_AO_SPDCTRL_SPODF, - PS3_AUDIO_AO_SPDCTRL_SPODF_LSB); - /* ensure all the setting above is written back to register */ - wmb(); - /* avsetting driver altered AX_IE, caller must reset it if you want */ - pr_debug("%s: end\n", __func__); - return ret; -} - -/* - * set sampling rate according to the substream - */ -static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - struct snd_ps3_avsetting_info avs; - int ret; - - avs = card->avs; - - pr_debug("%s: called freq=%d width=%d\n", __func__, - substream->runtime->rate, - snd_pcm_format_width(substream->runtime->format)); - - pr_debug("%s: before freq=%d width=%d\n", __func__, - card->avs.avs_audio_rate, card->avs.avs_audio_width); - - /* sample rate */ - switch (substream->runtime->rate) { - case 44100: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_44K; - break; - case 48000: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; - break; - case 88200: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_88K; - break; - case 96000: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_96K; - break; - default: - pr_info("%s: invalid rate %d\n", __func__, - substream->runtime->rate); - return 1; - } - - /* width */ - switch (snd_pcm_format_width(substream->runtime->format)) { - case 16: - avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; - break; - case 24: - avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_24; - break; - default: - pr_info("%s: invalid width %d\n", __func__, - snd_pcm_format_width(substream->runtime->format)); - return 1; - } - - memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8); - - if (memcmp(&card->avs, &avs, sizeof(avs))) { - pr_debug("%s: after freq=%d width=%d\n", __func__, - card->avs.avs_audio_rate, card->avs.avs_audio_width); - - card->avs = avs; - snd_ps3_change_avsetting(card); - ret = 0; - } else - ret = 1; - - /* check CS non-audio bit and mute accordingly */ - if (avs.avs_cs_info[0] & 0x02) - ps3av_audio_mute_analog(1); /* mute if non-audio */ - else - ps3av_audio_mute_analog(0); - - return ret; -} - -/* - * PCM operators - */ -static int snd_ps3_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - int pcm_index; - - pcm_index = substream->pcm->device; - /* to retrieve substream/runtime in interrupt handler */ - card->substream = substream; - - runtime->hw = snd_ps3_pcm_hw; - - card->start_delay = snd_ps3_start_delay; - - /* mute off */ - snd_ps3_mute(0); /* this function sleep */ - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - PS3_AUDIO_FIFO_STAGE_SIZE * 4 * 2); - return 0; -}; - -static int snd_ps3_pcm_close(struct snd_pcm_substream *substream) -{ - /* mute on */ - snd_ps3_mute(1); - return 0; -}; - -static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - size_t size; - - /* alloc transport buffer */ - size = params_buffer_bytes(hw_params); - snd_pcm_lib_malloc_pages(substream, size); - return 0; -}; - -static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream) -{ - int ret; - ret = snd_pcm_lib_free_pages(substream); - return ret; -}; - -static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, - unsigned int delay_ms) -{ - int ret; - int rate ; - - rate = substream->runtime->rate; - ret = snd_pcm_format_size(substream->runtime->format, - rate * delay_ms / 1000) - * substream->runtime->channels; - - pr_debug("%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n", - __func__, - delay_ms, - rate, - snd_pcm_format_size(substream->runtime->format, rate), - rate * delay_ms / 1000, - ret); - - return ret; -}; - -static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - unsigned long irqsave; - - if (!snd_ps3_set_avsetting(substream)) { - /* some parameter changed */ - write_reg(PS3_AUDIO_AX_IE, - PS3_AUDIO_AX_IE_ASOBEIE(0) | - PS3_AUDIO_AX_IE_ASOBUIE(0)); - /* - * let SPDIF device re-lock with SPDIF signal, - * start with some silence - */ - card->silent = snd_ps3_delay_to_bytes(substream, - card->start_delay) / - (PS3_AUDIO_FIFO_STAGE_SIZE * 4); /* every 4 times */ - } - - /* restart ring buffer pointer */ - spin_lock_irqsave(&card->dma_lock, irqsave); - { - card->dma_buffer_size = runtime->dma_bytes; - - card->dma_last_transfer_vaddr[SND_PS3_CH_L] = - card->dma_next_transfer_vaddr[SND_PS3_CH_L] = - card->dma_start_vaddr[SND_PS3_CH_L] = - runtime->dma_area; - card->dma_start_bus_addr[SND_PS3_CH_L] = runtime->dma_addr; - - card->dma_last_transfer_vaddr[SND_PS3_CH_R] = - card->dma_next_transfer_vaddr[SND_PS3_CH_R] = - card->dma_start_vaddr[SND_PS3_CH_R] = - runtime->dma_area + (runtime->dma_bytes / 2); - card->dma_start_bus_addr[SND_PS3_CH_R] = - runtime->dma_addr + (runtime->dma_bytes / 2); - - pr_debug("%s: vaddr=%p bus=%#llx\n", __func__, - card->dma_start_vaddr[SND_PS3_CH_L], - card->dma_start_bus_addr[SND_PS3_CH_L]); - - } - spin_unlock_irqrestore(&card->dma_lock, irqsave); - - /* ensure the hardware sees the change */ - mb(); - - return 0; -}; - -static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* clear outstanding interrupts */ - update_reg(PS3_AUDIO_AX_IS, 0); - - spin_lock(&card->dma_lock); - { - card->running = 1; - } - spin_unlock(&card->dma_lock); - - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - while (read_reg(PS3_AUDIO_KICK(7)) & - PS3_AUDIO_KICK_STATUS_MASK) { - udelay(1); - } - snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); - snd_ps3_kick_dma(card); - break; - - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&card->dma_lock); - { - card->running = 0; - } - spin_unlock(&card->dma_lock); - snd_ps3_wait_for_dma_stop(card); - break; - default: - break; - - } - - return ret; -}; - -/* - * report current pointer - */ -static snd_pcm_uframes_t snd_ps3_pcm_pointer( - struct snd_pcm_substream *substream) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - size_t bytes; - snd_pcm_uframes_t ret; - - spin_lock(&card->dma_lock); - { - bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] - - card->dma_start_vaddr[SND_PS3_CH_L]); - } - spin_unlock(&card->dma_lock); - - ret = bytes_to_frames(substream->runtime, bytes * 2); - - return ret; -}; - -/* - * SPDIF status bits controls - */ -static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */ -static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, 8); - return 0; -} - -static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return 0; -} - -static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8); - return 0; -} - -static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) { - memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new spdif_ctls[] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_cmask_get, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_pmask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_default_get, - .put = snd_ps3_spdif_default_put, - }, -}; - -static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = { - .open = snd_ps3_pcm_open, - .close = snd_ps3_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ps3_pcm_hw_params, - .hw_free = snd_ps3_pcm_hw_free, - .prepare = snd_ps3_pcm_prepare, - .trigger = snd_ps3_pcm_trigger, - .pointer = snd_ps3_pcm_pointer, -}; - - -static int __devinit snd_ps3_map_mmio(void) -{ - the_card.mapped_mmio_vaddr = - ioremap(the_card.ps3_dev->m_region->bus_addr, - the_card.ps3_dev->m_region->len); - - if (!the_card.mapped_mmio_vaddr) { - pr_info("%s: ioremap 0 failed p=%#lx l=%#lx \n", - __func__, the_card.ps3_dev->m_region->lpar_addr, - the_card.ps3_dev->m_region->len); - return -ENXIO; - } - - return 0; -}; - -static void snd_ps3_unmap_mmio(void) -{ - iounmap(the_card.mapped_mmio_vaddr); - the_card.mapped_mmio_vaddr = NULL; -} - -static int __devinit snd_ps3_allocate_irq(void) -{ - int ret; - u64 lpar_addr, lpar_size; - u64 __iomem *mapped; - - /* FIXME: move this to device_init (H/W probe) */ - - /* get irq outlet */ - ret = lv1_gpu_device_map(1, &lpar_addr, &lpar_size); - if (ret) { - pr_info("%s: device map 1 failed %d\n", __func__, - ret); - return -ENXIO; - } - - mapped = ioremap(lpar_addr, lpar_size); - if (!mapped) { - pr_info("%s: ioremap 1 failed \n", __func__); - return -ENXIO; - } - - the_card.audio_irq_outlet = in_be64(mapped); - - iounmap(mapped); - ret = lv1_gpu_device_unmap(1); - if (ret) - pr_info("%s: unmap 1 failed\n", __func__); - - /* irq */ - ret = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, - the_card.audio_irq_outlet, - &the_card.irq_no); - if (ret) { - pr_info("%s:ps3_alloc_irq failed (%d)\n", __func__, ret); - return ret; - } - - ret = request_irq(the_card.irq_no, snd_ps3_interrupt, 0, - SND_PS3_DRIVER_NAME, &the_card); - if (ret) { - pr_info("%s: request_irq failed (%d)\n", __func__, ret); - goto cleanup_irq; - } - - return 0; - - cleanup_irq: - ps3_irq_plug_destroy(the_card.irq_no); - return ret; -}; - -static void snd_ps3_free_irq(void) -{ - free_irq(the_card.irq_no, &the_card); - ps3_irq_plug_destroy(the_card.irq_no); -} - -static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) -{ - uint64_t val; - int ret; - - val = (ioaddr_start & (0x0fUL << 32)) >> (32 - 20) | - (0x03UL << 24) | - (0x0fUL << 12) | - (PS3_AUDIO_IOID); - - ret = lv1_gpu_attribute(0x100, 0x007, val); - if (ret) - pr_info("%s: gpu_attribute failed %d\n", __func__, - ret); -} - -static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card) -{ - /* - * avsetting driver seems to never change the followings - * so, init them here once - */ - - /* no dma interrupt needed */ - write_reg(PS3_AUDIO_INTR_EN_0, 0); - - /* use every 4 buffer empty interrupt */ - update_mask_reg(PS3_AUDIO_AX_IC, - PS3_AUDIO_AX_IC_AASOIMD_MASK, - PS3_AUDIO_AX_IC_AASOIMD_EVERY4); - - /* enable 3wire clocks */ - update_mask_reg(PS3_AUDIO_AO_3WMCTRL, - ~(PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED | - PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED), - 0); - update_reg(PS3_AUDIO_AO_3WMCTRL, - PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT); -} - -static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card) -{ - int ret; - pr_debug("%s: start\n", __func__); - card->avs.avs_audio_ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2; - card->avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; - card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; - card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM; - card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; - memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8); - - ret = snd_ps3_change_avsetting(card); - - snd_ps3_audio_fixup(card); - - /* to start to generate SPDIF signal, fill data */ - snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - pr_debug("%s: end\n", __func__); - return ret; -} - -static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) -{ - int i, ret; - u64 lpar_addr, lpar_size; - - BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); - BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); - - the_card.ps3_dev = dev; - - ret = ps3_open_hv_device(dev); - - if (ret) - return -ENXIO; - - /* setup MMIO */ - ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); - if (ret) { - pr_info("%s: device map 2 failed %d\n", __func__, ret); - goto clean_open; - } - ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, - PAGE_SHIFT); - - ret = snd_ps3_map_mmio(); - if (ret) - goto clean_dev_map; - - /* setup DMA area */ - ps3_dma_region_init(dev, dev->d_region, - PAGE_SHIFT, /* use system page size */ - 0, /* dma type; not used */ - NULL, - _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); - dev->d_region->ioid = PS3_AUDIO_IOID; - - ret = ps3_dma_region_create(dev->d_region); - if (ret) { - pr_info("%s: region_create\n", __func__); - goto clean_mmio; - } - - snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); - - /* CONFIG_SND_PS3_DEFAULT_START_DELAY */ - the_card.start_delay = snd_ps3_start_delay; - - /* irq */ - if (snd_ps3_allocate_irq()) { - ret = -ENXIO; - goto clean_dma_region; - } - - /* create card instance */ - ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); - if (ret < 0) - goto clean_irq; - - strcpy(the_card.card->driver, "PS3"); - strcpy(the_card.card->shortname, "PS3"); - strcpy(the_card.card->longname, "PS3 sound"); - - /* create control elements */ - for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { - ret = snd_ctl_add(the_card.card, - snd_ctl_new1(&spdif_ctls[i], &the_card)); - if (ret < 0) - goto clean_card; - } - - /* create PCM devices instance */ - /* NOTE:this driver works assuming pcm:substream = 1:1 */ - ret = snd_pcm_new(the_card.card, - "SPDIF", - 0, /* instance index, will be stored pcm.device*/ - 1, /* output substream */ - 0, /* input substream */ - &(the_card.pcm)); - if (ret) - goto clean_card; - - the_card.pcm->private_data = &the_card; - strcpy(the_card.pcm->name, "SPDIF"); - - /* set pcm ops */ - snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_ps3_pcm_spdif_ops); - - the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; - /* pre-alloc PCM DMA buffer*/ - ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, - SNDRV_DMA_TYPE_DEV, - &dev->core, - SND_PS3_PCM_PREALLOC_SIZE, - SND_PS3_PCM_PREALLOC_SIZE); - if (ret < 0) { - pr_info("%s: prealloc failed\n", __func__); - goto clean_card; - } - - /* - * allocate null buffer - * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2 - * PAGE_SIZE is enogh - */ - the_card.null_buffer_start_vaddr = - dma_alloc_coherent(&the_card.ps3_dev->core, - PAGE_SIZE, - &the_card.null_buffer_start_dma_addr, - GFP_KERNEL); - if (!the_card.null_buffer_start_vaddr) { - pr_info("%s: nullbuffer alloc failed\n", __func__); - goto clean_preallocate; - } - pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); - /* set default sample rate/word width */ - snd_ps3_init_avsetting(&the_card); - - /* register the card */ - snd_card_set_dev(the_card.card, &dev->core); - ret = snd_card_register(the_card.card); - if (ret < 0) - goto clean_dma_map; - - pr_info("%s started. start_delay=%dms\n", - the_card.card->longname, the_card.start_delay); - return 0; - -clean_dma_map: - dma_free_coherent(&the_card.ps3_dev->core, - PAGE_SIZE, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); -clean_preallocate: - snd_pcm_lib_preallocate_free_for_all(the_card.pcm); -clean_card: - snd_card_free(the_card.card); -clean_irq: - snd_ps3_free_irq(); -clean_dma_region: - ps3_dma_region_free(dev->d_region); -clean_mmio: - snd_ps3_unmap_mmio(); -clean_dev_map: - lv1_gpu_device_unmap(2); -clean_open: - ps3_close_hv_device(dev); - /* - * there is no destructor function to pcm. - * midlayer automatically releases if the card removed - */ - return ret; -}; /* snd_ps3_probe */ - -/* called when module removal */ -static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev) -{ - int ret; - pr_info("%s:start id=%d\n", __func__, dev->match_id); - if (dev->match_id != PS3_MATCH_ID_SOUND) - return -ENXIO; - - /* - * ctl and preallocate buffer will be freed in - * snd_card_free - */ - ret = snd_card_free(the_card.card); - if (ret) - pr_info("%s: ctl freecard=%d\n", __func__, ret); - - dma_free_coherent(&dev->core, - PAGE_SIZE, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); - - ps3_dma_region_free(dev->d_region); - - snd_ps3_free_irq(); - snd_ps3_unmap_mmio(); - - lv1_gpu_device_unmap(2); - ps3_close_hv_device(dev); - pr_info("%s:end id=%d\n", __func__, dev->match_id); - return 0; -} /* snd_ps3_remove */ - -static struct ps3_system_bus_driver snd_ps3_bus_driver_info = { - .match_id = PS3_MATCH_ID_SOUND, - .probe = snd_ps3_driver_probe, - .remove = snd_ps3_driver_remove, - .shutdown = snd_ps3_driver_remove, - .core = { - .name = SND_PS3_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - - -/* - * module/subsystem initialize/terminate - */ -static int __init snd_ps3_init(void) -{ - int ret; - - if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) - return -ENXIO; - - memset(&the_card, 0, sizeof(the_card)); - spin_lock_init(&the_card.dma_lock); - - /* register systembus DRIVER, this calls our probe() func */ - ret = ps3_system_bus_driver_register(&snd_ps3_bus_driver_info); - - return ret; -} -module_init(snd_ps3_init); - -static void __exit snd_ps3_exit(void) -{ - ps3_system_bus_driver_unregister(&snd_ps3_bus_driver_info); -} -module_exit(snd_ps3_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PS3 sound driver"); -MODULE_AUTHOR("Sony Computer Entertainment Inc."); -MODULE_ALIAS(PS3_MODULE_ALIAS_SOUND); diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3.h b/ANDROID_3.4.5/sound/ppc/snd_ps3.h deleted file mode 100644 index 326fb29e..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * All rights reserved. - * Copyright 2006, 2007 Sony Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the Licence. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if !defined(_SND_PS3_H_) -#define _SND_PS3_H_ - -#include <linux/irqreturn.h> - -#define SND_PS3_DRIVER_NAME "snd_ps3" - -enum snd_ps3_out_channel { - SND_PS3_OUT_SPDIF_0, - SND_PS3_OUT_SPDIF_1, - SND_PS3_OUT_SERIAL_0, - SND_PS3_OUT_DEVS -}; - -enum snd_ps3_dma_filltype { - SND_PS3_DMA_FILLTYPE_FIRSTFILL, - SND_PS3_DMA_FILLTYPE_RUNNING, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL, - SND_PS3_DMA_FILLTYPE_SILENT_RUNNING -}; - -enum snd_ps3_ch { - SND_PS3_CH_L = 0, - SND_PS3_CH_R = 1, - SND_PS3_CH_MAX = 2 -}; - -struct snd_ps3_avsetting_info { - uint32_t avs_audio_ch; /* fixed */ - uint32_t avs_audio_rate; - uint32_t avs_audio_width; - uint32_t avs_audio_format; /* fixed */ - uint32_t avs_audio_source; /* fixed */ - unsigned char avs_cs_info[8]; -}; -/* - * PS3 audio 'card' instance - * there should be only ONE hardware. - */ -struct snd_ps3_card_info { - struct ps3_system_bus_device *ps3_dev; - struct snd_card *card; - - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - - /* hvc info */ - u64 audio_lpar_addr; - u64 audio_lpar_size; - - /* registers */ - void __iomem *mapped_mmio_vaddr; - - /* irq */ - u64 audio_irq_outlet; - unsigned int irq_no; - - /* remember avsetting */ - struct snd_ps3_avsetting_info avs; - - /* dma buffer management */ - spinlock_t dma_lock; - /* dma_lock start */ - void * dma_start_vaddr[2]; /* 0 for L, 1 for R */ - dma_addr_t dma_start_bus_addr[2]; - size_t dma_buffer_size; - void * dma_last_transfer_vaddr[2]; - void * dma_next_transfer_vaddr[2]; - int silent; - /* dma_lock end */ - - int running; - - /* null buffer */ - void *null_buffer_start_vaddr; - dma_addr_t null_buffer_start_dma_addr; - - /* start delay */ - unsigned int start_delay; - -}; - - -/* PS3 audio DMAC block size in bytes */ -#define PS3_AUDIO_DMAC_BLOCK_SIZE (128) -/* one stage (stereo) of audio FIFO in bytes */ -#define PS3_AUDIO_FIFO_STAGE_SIZE (256) -/* how many stages the fifo have */ -#define PS3_AUDIO_FIFO_STAGE_COUNT (8) -/* fifo size 128 bytes * 8 stages * stereo (2ch) */ -#define PS3_AUDIO_FIFO_SIZE \ - (PS3_AUDIO_FIFO_STAGE_SIZE * PS3_AUDIO_FIFO_STAGE_COUNT) - -/* PS3 audio DMAC max block count in one dma shot = 128 (0x80) blocks*/ -#define PS3_AUDIO_DMAC_MAX_BLOCKS (PS3_AUDIO_DMASIZE_BLOCKS_MASK + 1) - -#define PS3_AUDIO_NORMAL_DMA_START_CH (0) -#define PS3_AUDIO_NORMAL_DMA_COUNT (8) -#define PS3_AUDIO_NULL_DMA_START_CH \ - (PS3_AUDIO_NORMAL_DMA_START_CH + PS3_AUDIO_NORMAL_DMA_COUNT) -#define PS3_AUDIO_NULL_DMA_COUNT (2) - -#define SND_PS3_MAX_VOL (0x0F) -#define SND_PS3_MIN_VOL (0x00) -#define SND_PS3_MIN_ATT SND_PS3_MIN_VOL -#define SND_PS3_MAX_ATT SND_PS3_MAX_VOL - -#define SND_PS3_PCM_PREALLOC_SIZE \ - (PS3_AUDIO_DMAC_BLOCK_SIZE * PS3_AUDIO_DMAC_MAX_BLOCKS * 4) - -#define SND_PS3_DMA_REGION_SIZE \ - (SND_PS3_PCM_PREALLOC_SIZE + PAGE_SIZE) - -#define PS3_AUDIO_IOID (1UL) - -#endif /* _SND_PS3_H_ */ diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h b/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h deleted file mode 100644 index 2e630207..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2006, 2007 Sony Corporation - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * interrupt / configure registers - */ - -#define PS3_AUDIO_INTR_0 (0x00000100) -#define PS3_AUDIO_INTR_EN_0 (0x00000140) -#define PS3_AUDIO_CONFIG (0x00000200) - -/* - * DMAC registers - * n:0..9 - */ -#define PS3_AUDIO_DMAC_REGBASE(x) (0x0000210 + 0x20 * (x)) - -#define PS3_AUDIO_KICK(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x00) -#define PS3_AUDIO_SOURCE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x04) -#define PS3_AUDIO_DEST(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x08) -#define PS3_AUDIO_DMASIZE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x0C) - -/* - * mute control - */ -#define PS3_AUDIO_AX_MCTRL (0x00004000) -#define PS3_AUDIO_AX_ISBP (0x00004004) -#define PS3_AUDIO_AX_AOBP (0x00004008) -#define PS3_AUDIO_AX_IC (0x00004010) -#define PS3_AUDIO_AX_IE (0x00004014) -#define PS3_AUDIO_AX_IS (0x00004018) - -/* - * three wire serial - * n:0..3 - */ -#define PS3_AUDIO_AO_MCTRL (0x00006000) -#define PS3_AUDIO_AO_3WMCTRL (0x00006004) - -#define PS3_AUDIO_AO_3WCTRL(n) (0x00006200 + 0x200 * (n)) - -/* - * S/PDIF - * n:0..1 - * x:0..11 - * y:0..5 - */ -#define PS3_AUDIO_AO_SPD_REGBASE(n) (0x00007200 + 0x200 * (n)) - -#define PS3_AUDIO_AO_SPDCTRL(n) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x00) -#define PS3_AUDIO_AO_SPDUB(n, x) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x04 + 0x04 * (x)) -#define PS3_AUDIO_AO_SPDCS(n, y) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x34 + 0x04 * (y)) - - -/* - PS3_AUDIO_INTR_0 register tells an interrupt handler which audio - DMA channel triggered the interrupt. The interrupt status for a channel - can be cleared by writing a '1' to the corresponding bit. A new interrupt - cannot be generated until the previous interrupt has been cleared. - - Note that the status reported by PS3_AUDIO_INTR_0 is independent of the - value of PS3_AUDIO_INTR_EN_0. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -#define PS3_AUDIO_INTR_0_CHAN(n) (1 << ((n) * 2)) -#define PS3_AUDIO_INTR_0_CHAN9 PS3_AUDIO_INTR_0_CHAN(9) -#define PS3_AUDIO_INTR_0_CHAN8 PS3_AUDIO_INTR_0_CHAN(8) -#define PS3_AUDIO_INTR_0_CHAN7 PS3_AUDIO_INTR_0_CHAN(7) -#define PS3_AUDIO_INTR_0_CHAN6 PS3_AUDIO_INTR_0_CHAN(6) -#define PS3_AUDIO_INTR_0_CHAN5 PS3_AUDIO_INTR_0_CHAN(5) -#define PS3_AUDIO_INTR_0_CHAN4 PS3_AUDIO_INTR_0_CHAN(4) -#define PS3_AUDIO_INTR_0_CHAN3 PS3_AUDIO_INTR_0_CHAN(3) -#define PS3_AUDIO_INTR_0_CHAN2 PS3_AUDIO_INTR_0_CHAN(2) -#define PS3_AUDIO_INTR_0_CHAN1 PS3_AUDIO_INTR_0_CHAN(1) -#define PS3_AUDIO_INTR_0_CHAN0 PS3_AUDIO_INTR_0_CHAN(0) - -/* - The PS3_AUDIO_INTR_EN_0 register specifies which DMA channels can generate - an interrupt to the PU. Each bit of PS3_AUDIO_INTR_EN_0 is ANDed with the - corresponding bit in PS3_AUDIO_INTR_0. The resulting bits are OR'd together - to generate the Audio interrupt. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_EN_0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - - Bit assignments are same as PS3_AUDIO_INTR_0 -*/ - -/* - PS3_AUDIO_CONFIG - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 C|0 0 0 0 0 0 0 0| CONFIG - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ - -/* The CLEAR field cancels all pending transfers, and stops any running DMA - transfers. Any interrupts associated with the canceled transfers - will occur as if the transfer had finished. - Since this bit is designed to recover from DMA related issues - which are caused by unpredictable situations, it is preferred to wait - for normal DMA transfer end without using this bit. -*/ -#define PS3_AUDIO_CONFIG_CLEAR (1 << 8) /* RWIVF */ - -/* - PS3_AUDIO_AX_MCTRL: Audio Port Mute Control Register - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|A|A|0 0 0 0 0 0 0|S|S|A|A|A|A| AX_MCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* 3 Wire Audio Serial Output Channel Mutes (0..3) */ -#define PS3_AUDIO_AX_MCTRL_ASOMT(n) (1 << (3 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO3MT (1 << 0) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO2MT (1 << 1) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO1MT (1 << 2) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO0MT (1 << 3) /* RWIVF */ - -/* S/PDIF mutes (0,1)*/ -#define PS3_AUDIO_AX_MCTRL_SPOMT(n) (1 << (5 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_SPO1MT (1 << 4) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_SPO0MT (1 << 5) /* RWIVF */ - -/* All 3 Wire Serial Outputs Mute */ -#define PS3_AUDIO_AX_MCTRL_AASOMT (1 << 13) /* RWIVF */ - -/* All S/PDIF Mute */ -#define PS3_AUDIO_AX_MCTRL_ASPOMT (1 << 14) /* RWIVF */ - -/* All Audio Outputs Mute */ -#define PS3_AUDIO_AX_MCTRL_AAOMT (1 << 15) /* RWIVF */ - -/* - S/PDIF Outputs Buffer Read/Write Pointer Register - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B|0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B| AX_ISBP - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ -/* - S/PDIF Output Channel Read Buffer Numbers - Buffer number is value of field. - Indicates current read access buffer ID from Audio Data - Transfer controller of S/PDIF Output -*/ - -#define PS3_AUDIO_AX_ISBP_SPOBRN_MASK(n) (0x7 << 4 * (1 - (n))) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO1BRN_MASK (0x7 << 0) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO0BRN_MASK (0x7 << 4) /* R-IUF */ - -/* -S/PDIF Output Channel Buffer Write Numbers -Indicates current write access buffer ID from bus master. -*/ -#define PS3_AUDIO_AX_ISBP_SPOBWN_MASK(n) (0x7 << 4 * (5 - (n))) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO1BWN_MASK (0x7 << 16) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO0BWN_MASK (0x7 << 20) /* R-IUF */ - -/* - 3 Wire Audio Serial Outputs Buffer Read/Write - Pointer Register - Buffer number is value of field - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B|0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B| AX_AOBP - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -3 Wire Audio Serial Output Channel Buffer Read Numbers -Indicates current read access buffer Id from Audio Data Transfer -Controller of 3 Wire Audio Serial Output Channels -*/ -#define PS3_AUDIO_AX_AOBP_ASOBRN_MASK(n) (0x7 << 4 * (3 - (n))) /* R-IUF */ - -#define PS3_AUDIO_AX_AOBP_ASO3BRN_MASK (0x7 << 0) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO2BRN_MASK (0x7 << 4) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO1BRN_MASK (0x7 << 8) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO0BRN_MASK (0x7 << 12) /* R-IUF */ - -/* -3 Wire Audio Serial Output Channel Buffer Write Numbers -Indicates current write access buffer ID from bus master. -*/ -#define PS3_AUDIO_AX_AOBP_ASOBWN_MASK(n) (0x7 << 4 * (7 - (n))) /* R-IUF */ - -#define PS3_AUDIO_AX_AOBP_ASO3BWN_MASK (0x7 << 16) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO2BWN_MASK (0x7 << 20) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO1BWN_MASK (0x7 << 24) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO0BWN_MASK (0x7 << 28) /* R-IUF */ - - - -/* -Audio Port Interrupt Condition Register -For the fields in this register, the following values apply: -0 = Interrupt is generated every interrupt event. -1 = Interrupt is generated every 2 interrupt events. -2 = Interrupt is generated every 4 interrupt events. -3 = Reserved - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0 0|SPO|0 0|SPO|0 0|AAS|0 0 0 0 0 0 0 0 0 0 0 0| AX_IC - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -All 3-Wire Audio Serial Outputs Interrupt Mode -Configures the Interrupt and Signal Notification -condition of all 3-wire Audio Serial Outputs. -*/ -#define PS3_AUDIO_AX_IC_AASOIMD_MASK (0x3 << 12) /* RWIVF */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY1 (0x0 << 12) /* RWI-V */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY2 (0x1 << 12) /* RW--V */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY4 (0x2 << 12) /* RW--V */ - -/* -S/PDIF Output Channel Interrupt Modes -Configures the Interrupt and signal Notification -conditions of S/PDIF output channels. -*/ -#define PS3_AUDIO_AX_IC_SPO1IMD_MASK (0x3 << 16) /* RWIVF */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY1 (0x0 << 16) /* RWI-V */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY2 (0x1 << 16) /* RW--V */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY4 (0x2 << 16) /* RW--V */ - -#define PS3_AUDIO_AX_IC_SPO0IMD_MASK (0x3 << 20) /* RWIVF */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY1 (0x0 << 20) /* RWI-V */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY2 (0x1 << 20) /* RW--V */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY4 (0x2 << 20) /* RW--V */ - -/* -Audio Port interrupt Enable Register -Configures whether to enable or disable each Interrupt Generation. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ - -/* -3 Wire Audio Serial Output Channel Buffer Underflow -Interrupt Enables -Select enable/disable of Buffer Underflow Interrupts for -3-Wire Audio Serial Output Channels -DISABLED=Interrupt generation disabled. -*/ -#define PS3_AUDIO_AX_IE_ASOBUIE(n) (1 << (3 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO3BUIE (1 << 0) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO2BUIE (1 << 1) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO1BUIE (1 << 2) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO0BUIE (1 << 3) /* RWIVF */ - -/* S/PDIF Output Channel Buffer Underflow Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBUIE(n) (1 << (7 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BUIE (1 << 6) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BUIE (1 << 7) /* RWIVF */ - -/* S/PDIF Output Channel One Block Transfer Completion Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBTCIE(n) (1 << (11 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BTCIE (1 << 10) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BTCIE (1 << 11) /* RWIVF */ - -/* 3-Wire Audio Serial Output Channel Buffer Empty Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_ASOBEIE(n) (1 << (19 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO3BEIE (1 << 16) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO2BEIE (1 << 17) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO1BEIE (1 << 18) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO0BEIE (1 << 19) /* RWIVF */ - -/* S/PDIF Output Channel Buffer Empty Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBEIE(n) (1 << (23 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BEIE (1 << 22) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BEIE (1 << 23) /* RWIVF */ - -/* -Audio Port Interrupt Status Register -Indicates Interrupt status, which interrupt has occurred, and can clear -each interrupt in this register. -Writing 1b to a field containing 1b clears field and de-asserts interrupt. -Writing 0b to a field has no effect. -Field vaules are the following: -0 - Interrupt hasn't occurred. -1 - Interrupt has occurred. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IS - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - - Bit assignment are same as AX_IE -*/ - -/* -Audio Output Master Control Register -Configures Master Clock and other master Audio Output Settings - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0|SCKSE|0|SCKSE| MR0 | MR1 |MCL|MCL|0 0 0 0|0 0 0 0 0 0 0 0| AO_MCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -MCLK Output Control -Controls mclko[1] output. -0 - Disable output (fixed at High) -1 - Output clock produced by clock selected -with scksel1 by mr1 -2 - Reserved -3 - Reserved -*/ - -#define PS3_AUDIO_AO_MCTRL_MCLKC1_MASK (0x3 << 12) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_DISABLED (0x0 << 12) /* RWI-V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_ENABLED (0x1 << 12) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD2 (0x2 << 12) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD3 (0x3 << 12) /* RW--V */ - -/* -MCLK Output Control -Controls mclko[0] output. -0 - Disable output (fixed at High) -1 - Output clock produced by clock selected -with SCKSEL0 by MR0 -2 - Reserved -3 - Reserved -*/ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_MASK (0x3 << 14) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_DISABLED (0x0 << 14) /* RWI-V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_ENABLED (0x1 << 14) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD2 (0x2 << 14) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD3 (0x3 << 14) /* RW--V */ -/* -Master Clock Rate 1 -Sets the divide ration of Master Clock1 (clock output from -mclko[1] for the input clock selected by scksel1. -*/ -#define PS3_AUDIO_AO_MCTRL_MR1_MASK (0xf << 16) -#define PS3_AUDIO_AO_MCTRL_MR1_DEFAULT (0x0 << 16) /* RWI-V */ -/* -Master Clock Rate 0 -Sets the divide ratio of Master Clock0 (clock output from -mclko[0] for the input clock selected by scksel0). -*/ -#define PS3_AUDIO_AO_MCTRL_MR0_MASK (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MR0_DEFAULT (0x0 << 20) /* RWI-V */ -/* -System Clock Select 0/1 -Selects the system clock to be used as Master Clock 0/1 -Input the system clock that is appropriate for the sampling -rate. -*/ -#define PS3_AUDIO_AO_MCTRL_SCKSEL1_MASK (0x7 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_SCKSEL1_DEFAULT (0x2 << 24) /* RWI-V */ - -#define PS3_AUDIO_AO_MCTRL_SCKSEL0_MASK (0x7 << 28) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_SCKSEL0_DEFAULT (0x2 << 28) /* RWI-V */ - - -/* -3-Wire Audio Output Master Control Register -Configures clock, 3-Wire Audio Serial Output Enable, and -other 3-Wire Audio Serial Output Master Settings - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |A|A|A|A|0 0 0|A| ASOSR |0 0 0 0|A|A|A|A|A|A|0|1|0 0 0 0 0 0 0 0| AO_3WMCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - - -/* -LRCKO Polarity -0 - Reserved -1 - default -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK (1 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT (1 << 8) /* RW--V */ - -/* LRCK Output Disable */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD (1 << 10) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_ENABLED (0 << 10) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED (1 << 10) /* RWI-V */ - -/* Bit Clock Output Disable */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_ENABLED (0 << 11) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED (1 << 11) /* RWI-V */ - -/* -3-Wire Audio Serial Output Channel 0-3 Operational -Status. Each bit becomes 1 after each 3-Wire Audio -Serial Output Channel N is in action by setting 1 to -asoen. -Each bit becomes 0 after each 3-Wire Audio Serial Output -Channel N is out of action by setting 0 to asoen. -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN(n) (1 << (15 - (n))) /* R-IVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(n) (0 << (15 - (n))) /* R-I-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(n) (1 << (15 - (n))) /* R---V */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(3) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(3) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(3) - -/* -Sampling Rate -Specifies the divide ratio of the bit clock (clock output -from bclko) used by the 3-wire Audio Output Clock, which -is applied to the master clock selected by mcksel. -Data output is synchronized with this clock. -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_MASK (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV2 (0x1 << 20) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV4 (0x2 << 20) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV8 (0x4 << 20) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV12 (0x6 << 20) /* RW--V */ - -/* -Master Clock Select -0 - Master Clock 0 -1 - Master Clock 1 -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL (1 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK0 (0 << 24) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK1 (1 << 24) /* RW--V */ - -/* -Enables and disables 4ch 3-Wire Audio Serial Output -operation. Each Bit from 0 to 3 corresponds to an -output channel, which means that each output channel -can be enabled or disabled individually. When -multiple channels are enabled at the same time, output -operations are performed in synchronization. -Bit 0 - Output Channel 0 (SDOUT[0]) -Bit 1 - Output Channel 1 (SDOUT[1]) -Bit 2 - Output Channel 2 (SDOUT[2]) -Bit 3 - Output Channel 3 (SDOUT[3]) -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN(n) (1 << (31 - (n))) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(n) (0 << (31 - (n))) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(n) (1 << (31 - (n))) /* RW--V */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(0) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(0) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(0) /* RW--V */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(1) /* RWIVF */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(1) /* RWI-V */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(1) /* RW--V */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(2) /* RWIVF */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(2) /* RWI-V */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(2) /* RW--V */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(3) /* RWIVF */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(3) /* RWI-V */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(3) /* RW--V */ - -/* -3-Wire Audio Serial output Channel 0-3 Control Register -Configures settings for 3-Wire Serial Audio Output Channel 0-3 - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|0 0 0 0|A|0|ASO|0 0 0|0|0|0|0|0| AO_3WCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ -/* -Data Bit Mode -Specifies the number of data bits -0 - 16 bits -1 - reserved -2 - 20 bits -3 - 24 bits -*/ -#define PS3_AUDIO_AO_3WCTRL_ASODB_MASK (0x3 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_16BIT (0x0 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_RESVD (0x1 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_20BIT (0x2 << 8) /* RW--V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_24BIT (0x3 << 8) /* RW--V */ -/* -Data Format Mode -Specifies the data format where (LSB side or MSB) the data(in 20 bit -or 24 bit resolution mode) is put in a 32 bit field. -0 - Data put on LSB side -1 - Data put on MSB side -*/ -#define PS3_AUDIO_AO_3WCTRL_ASODF (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASODF_LSB (0 << 11) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODF_MSB (1 << 11) /* RW--V */ -/* -Buffer Reset -Performs buffer reset. Writing 1 to this bit initializes the -corresponding 3-Wire Audio Output buffers(both L and R). -*/ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST (1 << 16) /* CWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST_IDLE (0 << 16) /* -WI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET (1 << 16) /* -W--T */ - -/* -S/PDIF Audio Output Channel 0/1 Control Register -Configures settings for S/PDIF Audio Output Channel 0/1. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |S|0 0 0|S|0 0|S| SPOSR |0 0|SPO|0 0 0 0|S|0|SPO|0 0 0 0 0 0 0|S| AO_SPDCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -Buffer reset. Writing 1 to this bit initializes the -corresponding S/PDIF output buffer pointer. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST (1 << 0) /* CWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_IDLE (0 << 0) /* -WI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_RESET (1 << 0) /* -W--T */ - -/* -Data Bit Mode -Specifies number of data bits -0 - 16 bits -1 - Reserved -2 - 20 bits -3 - 24 bits -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_MASK (0x3 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_16BIT (0x0 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_RESVD (0x1 << 8) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_20BIT (0x2 << 8) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_24BIT (0x3 << 8) /* RW--V */ -/* -Data format Mode -Specifies the data format, where (LSB side or MSB) -the data(in 20 or 24 bit resolution) is put in the -32 bit field. -0 - LSB Side -1 - MSB Side -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPODF (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPODF_LSB (0 << 11) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODF_MSB (1 << 11) /* RW--V */ -/* -Source Select -Specifies the source of the S/PDIF output. When 0, output -operation is controlled by 3wen[0] of AO_3WMCTRL register. -The SR must have the same setting as the a0_3wmctrl reg. -0 - 3-Wire Audio OUT Ch0 Buffer -1 - S/PDIF buffer -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_MASK (0x3 << 16) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_3WEN (0x0 << 16) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_SPDIF (0x1 << 16) /* RW--V */ -/* -Sampling Rate -Specifies the divide ratio of the bit clock (clock output -from bclko) used by the S/PDIF Output Clock, which -is applied to the master clock selected by mcksel. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV2 (0x1 << 20) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV4 (0x2 << 20) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV8 (0x4 << 20) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV12 (0x6 << 20) /* RW--V */ -/* -Master Clock Select -0 - Master Clock 0 -1 - Master Clock 1 -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL (1 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK0 (0 << 24) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK1 (1 << 24) /* RW--V */ - -/* -S/PDIF Output Channel Operational Status -This bit becomes 1 after S/PDIF Output Channel is in -action by setting 1 to spoen. This bit becomes 0 -after S/PDIF Output Channel is out of action by setting -0 to spoen. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN (1 << 27) /* R-IVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN_STOPPED (0 << 27) /* R-I-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN_RUNNING (1 << 27) /* R---V */ - -/* -S/PDIF Audio Output Channel Output Enable -Enables and disables output operation. This bit is used -only when sposs = 1 -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN (1 << 31) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN_DISABLED (0 << 31) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN_ENABLED (1 << 31) /* RW--V */ - -/* -S/PDIF Audio Output Channel Channel Status -Setting Registers. -Configures channel status bit settings for each block -(192 bits). -Output is performed from the MSB(AO_SPDCS0 register bit 31). -The same value is added for subframes within the same frame. - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | SPOCS | AO_SPDCS - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -S/PDIF Audio Output Channel User Bit Setting -Configures user bit settings for each block (384 bits). -Output is performed from the MSB(ao_spdub0 register bit 31). - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | SPOUB | AO_SPDUB - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/***************************************************************************** - * - * DMAC register - * - *****************************************************************************/ -/* -The PS3_AUDIO_KICK register is used to initiate a DMA transfer and monitor -its status - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0|STATU|0 0 0| EVENT |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|R| KICK - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -The REQUEST field is written to ACTIVE to initiate a DMA request when EVENT -occurs. -It will return to the DONE state when the request is completed. -The registers for a DMA channel should only be written if REQUEST is IDLE. -*/ - -#define PS3_AUDIO_KICK_REQUEST (1 << 0) /* RWIVF */ -#define PS3_AUDIO_KICK_REQUEST_IDLE (0 << 0) /* RWI-V */ -#define PS3_AUDIO_KICK_REQUEST_ACTIVE (1 << 0) /* -W--T */ - -/* - *The EVENT field is used to set the event in which - *the DMA request becomes active. - */ -#define PS3_AUDIO_KICK_EVENT_MASK (0x1f << 16) /* RWIVF */ -#define PS3_AUDIO_KICK_EVENT_ALWAYS (0x00 << 16) /* RWI-V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY (0x01 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_UNDERFLOW (0x02 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_EMPTY (0x03 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_UNDERFLOW (0x04 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_EMPTY (0x05 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_UNDERFLOW (0x06 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_EMPTY (0x07 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_UNDERFLOW (0x08 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_BLOCKTRANSFERCOMPLETE \ - (0x09 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_UNDERFLOW (0x0A << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_EMPTY (0x0B << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_BLOCKTRANSFERCOMPLETE \ - (0x0C << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_UNDERFLOW (0x0D << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_EMPTY (0x0E << 16) /* RW--V */ - -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA(n) \ - ((0x13 + (n)) << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA0 (0x13 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA1 (0x14 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA2 (0x15 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA3 (0x16 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA4 (0x17 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA5 (0x18 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA6 (0x19 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA7 (0x1A << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA8 (0x1B << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA9 (0x1C << 16) /* RW--V */ - -/* -The STATUS field can be used to monitor the progress of a DMA request. -DONE indicates the previous request has completed. -EVENT indicates that the DMA engine is waiting for the EVENT to occur. -PENDING indicates that the DMA engine has not started processing this -request, but the EVENT has occurred. -DMA indicates that the data transfer is in progress. -NOTIFY indicates that the notifier signalling end of transfer is being written. -CLEAR indicated that the previous transfer was cleared. -ERROR indicates the previous transfer requested an unsupported -source/destination combination. -*/ - -#define PS3_AUDIO_KICK_STATUS_MASK (0x7 << 24) /* R-IVF */ -#define PS3_AUDIO_KICK_STATUS_DONE (0x0 << 24) /* R-I-V */ -#define PS3_AUDIO_KICK_STATUS_EVENT (0x1 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_PENDING (0x2 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_DMA (0x3 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_NOTIFY (0x4 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_CLEAR (0x5 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_ERROR (0x6 << 24) /* R---V */ - -/* -The PS3_AUDIO_SOURCE register specifies the source address for transfers. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | START |0 0 0 0 0|TAR| SOURCE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -The Audio DMA engine uses 128-byte transfers, thus the address must be aligned -to a 128 byte boundary. The low seven bits are assumed to be 0. -*/ - -#define PS3_AUDIO_SOURCE_START_MASK (0x01FFFFFF << 7) /* RWIUF */ - -/* -The TARGET field specifies the memory space containing the source address. -*/ - -#define PS3_AUDIO_SOURCE_TARGET_MASK (3 << 0) /* RWIVF */ -#define PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY (2 << 0) /* RW--V */ - -/* -The PS3_AUDIO_DEST register specifies the destination address for transfers. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | START |0 0 0 0 0|TAR| DEST - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -The Audio DMA engine uses 128-byte transfers, thus the address must be aligned -to a 128 byte boundary. The low seven bits are assumed to be 0. -*/ - -#define PS3_AUDIO_DEST_START_MASK (0x01FFFFFF << 7) /* RWIUF */ - -/* -The TARGET field specifies the memory space containing the destination address -AUDIOFIFO = Audio WriteData FIFO, -*/ - -#define PS3_AUDIO_DEST_TARGET_MASK (3 << 0) /* RWIVF */ -#define PS3_AUDIO_DEST_TARGET_AUDIOFIFO (1 << 0) /* RW--V */ - -/* -PS3_AUDIO_DMASIZE specifies the number of 128-byte blocks + 1 to transfer. -So a value of 0 means 128-bytes will get transferred. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| BLOCKS | DMASIZE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - - -#define PS3_AUDIO_DMASIZE_BLOCKS_MASK (0x7f << 0) /* RWIUF */ - -/* - * source/destination address for internal fifos - */ -#define PS3_AUDIO_AO_3W_LDATA(n) (0x1000 + (0x100 * (n))) -#define PS3_AUDIO_AO_3W_RDATA(n) (0x1080 + (0x100 * (n))) - -#define PS3_AUDIO_AO_SPD_DATA(n) (0x2000 + (0x400 * (n))) - - -/* - * field attiribute - * - * Read - * ' ' = Other Information - * '-' = Field is part of a write-only register - * 'C' = Value read is always the same, constant value line follows (C) - * 'R' = Value is read - * - * Write - * ' ' = Other Information - * '-' = Must not be written (D), value ignored when written (R,A,F) - * 'W' = Can be written - * - * Internal State - * ' ' = Other Information - * '-' = No internal state - * 'X' = Internal state, initial value is unknown - * 'I' = Internal state, initial value is known and follows (I) - * - * Declaration/Size - * ' ' = Other Information - * '-' = Does Not Apply - * 'V' = Type is void - * 'U' = Type is unsigned integer - * 'S' = Type is signed integer - * 'F' = Type is IEEE floating point - * '1' = Byte size (008) - * '2' = Short size (016) - * '3' = Three byte size (024) - * '4' = Word size (032) - * '8' = Double size (064) - * - * Define Indicator - * ' ' = Other Information - * 'D' = Device - * 'M' = Memory - * 'R' = Register - * 'A' = Array of Registers - * 'F' = Field - * 'V' = Value - * 'T' = Task - */ - diff --git a/ANDROID_3.4.5/sound/ppc/tumbler.c b/ANDROID_3.4.5/sound/ppc/tumbler.c deleted file mode 100644 index 9cea84c3..00000000 --- a/ANDROID_3.4.5/sound/ppc/tumbler.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* - * PMac Tumbler/Snapper lowlevel functions - * - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Rene Rebe <rene.rebe@gmx.net>: - * * update from shadow registers on wakeup and headphone plug - * * automatically toggle DRC on headphone plug - * - */ - - -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/kmod.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/string.h> -#include <sound/core.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/machdep.h> -#include <asm/pmac_feature.h> -#include "pmac.h" -#include "tumbler_volume.h" - -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt...) printk(KERN_DEBUG fmt) -#else -#define DBG(fmt...) -#endif - -#define IS_G4DA (of_machine_is_compatible("PowerMac3,4")) - -/* i2c address for tumbler */ -#define TAS_I2C_ADDR 0x34 - -/* registers */ -#define TAS_REG_MCS 0x01 /* main control */ -#define TAS_REG_DRC 0x02 -#define TAS_REG_VOL 0x04 -#define TAS_REG_TREBLE 0x05 -#define TAS_REG_BASS 0x06 -#define TAS_REG_INPUT1 0x07 -#define TAS_REG_INPUT2 0x08 - -/* tas3001c */ -#define TAS_REG_PCM TAS_REG_INPUT1 - -/* tas3004 */ -#define TAS_REG_LMIX TAS_REG_INPUT1 -#define TAS_REG_RMIX TAS_REG_INPUT2 -#define TAS_REG_MCS2 0x43 /* main control 2 */ -#define TAS_REG_ACS 0x40 /* analog control */ - -/* mono volumes for tas3001c/tas3004 */ -enum { - VOL_IDX_PCM_MONO, /* tas3001c only */ - VOL_IDX_BASS, VOL_IDX_TREBLE, - VOL_IDX_LAST_MONO -}; - -/* stereo volumes for tas3004 */ -enum { - VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC, - VOL_IDX_LAST_MIX -}; - -struct pmac_gpio { - unsigned int addr; - u8 active_val; - u8 inactive_val; - u8 active_state; -}; - -struct pmac_tumbler { - struct pmac_keywest i2c; - struct pmac_gpio audio_reset; - struct pmac_gpio amp_mute; - struct pmac_gpio line_mute; - struct pmac_gpio line_detect; - struct pmac_gpio hp_mute; - struct pmac_gpio hp_detect; - int headphone_irq; - int lineout_irq; - unsigned int save_master_vol[2]; - unsigned int master_vol[2]; - unsigned int save_master_switch[2]; - unsigned int master_switch[2]; - unsigned int mono_vol[VOL_IDX_LAST_MONO]; - unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */ - int drc_range; - int drc_enable; - int capture_source; - int anded_reset; - int auto_mute_notify; - int reset_on_sleep; - u8 acs; -}; - - -/* - */ - -static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs) -{ - while (*regs > 0) { - int err, count = 10; - do { - err = i2c_smbus_write_byte_data(i2c->client, - regs[0], regs[1]); - if (err >= 0) - break; - DBG("(W) i2c error %d\n", err); - mdelay(10); - } while (count--); - if (err < 0) - return -ENXIO; - regs += 2; - } - return 0; -} - - -static int tumbler_init_client(struct pmac_keywest *i2c) -{ - static unsigned int regs[] = { - /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */ - TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, - 0, /* terminator */ - }; - DBG("(I) tumbler init client\n"); - return send_init_client(i2c, regs); -} - -static int snapper_init_client(struct pmac_keywest *i2c) -{ - static unsigned int regs[] = { - /* normal operation, SCLK=64fps, i2s output, 16bit width */ - TAS_REG_MCS, (1<<6)|(2<<4)|0, - /* normal operation, all-pass mode */ - TAS_REG_MCS2, (1<<1), - /* normal output, no deemphasis, A input, power-up, line-in */ - TAS_REG_ACS, 0, - 0, /* terminator */ - }; - DBG("(I) snapper init client\n"); - return send_init_client(i2c, regs); -} - -/* - * gpio access - */ -#define do_gpio_write(gp, val) \ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) -#define do_gpio_read(gp) \ - pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) -#define tumbler_gpio_free(gp) /* NOP */ - -static void write_audio_gpio(struct pmac_gpio *gp, int active) -{ - if (! gp->addr) - return; - active = active ? gp->active_val : gp->inactive_val; - do_gpio_write(gp, active); - DBG("(I) gpio %x write %d\n", gp->addr, active); -} - -static int check_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - - if (! gp->addr) - return 0; - - ret = do_gpio_read(gp); - - return (ret & 0x1) == (gp->active_val & 0x1); -} - -static int read_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - if (! gp->addr) - return 0; - ret = do_gpio_read(gp); - ret = (ret & 0x02) !=0; - return ret == gp->active_state; -} - -/* - * update master volume - */ -static int tumbler_set_master_volume(struct pmac_tumbler *mix) -{ - unsigned char block[6]; - unsigned int left_vol, right_vol; - - if (! mix->i2c.client) - return -ENODEV; - - if (! mix->master_switch[0]) - left_vol = 0; - else { - left_vol = mix->master_vol[0]; - if (left_vol >= ARRAY_SIZE(master_volume_table)) - left_vol = ARRAY_SIZE(master_volume_table) - 1; - left_vol = master_volume_table[left_vol]; - } - if (! mix->master_switch[1]) - right_vol = 0; - else { - right_vol = mix->master_vol[1]; - if (right_vol >= ARRAY_SIZE(master_volume_table)) - right_vol = ARRAY_SIZE(master_volume_table) - 1; - right_vol = master_volume_table[right_vol]; - } - - block[0] = (left_vol >> 16) & 0xff; - block[1] = (left_vol >> 8) & 0xff; - block[2] = (left_vol >> 0) & 0xff; - - block[3] = (right_vol >> 16) & 0xff; - block[4] = (right_vol >> 8) & 0xff; - block[5] = (right_vol >> 0) & 0xff; - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, - block) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); - return -EINVAL; - } - DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol); - return 0; -} - - -/* output volume */ -static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1; - return 0; -} - -static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.integer.value[0] = mix->master_vol[0]; - ucontrol->value.integer.value[1] = mix->master_vol[1]; - return 0; -} - -static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - unsigned int vol[2]; - int change; - - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] >= ARRAY_SIZE(master_volume_table) || - vol[1] >= ARRAY_SIZE(master_volume_table)) - return -EINVAL; - change = mix->master_vol[0] != vol[0] || - mix->master_vol[1] != vol[1]; - if (change) { - mix->master_vol[0] = vol[0]; - mix->master_vol[1] = vol[1]; - tumbler_set_master_volume(mix); - } - return change; -} - -/* output switch */ -static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.integer.value[0] = mix->master_switch[0]; - ucontrol->value.integer.value[1] = mix->master_switch[1]; - return 0; -} - -static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - int change; - - change = mix->master_switch[0] != ucontrol->value.integer.value[0] || - mix->master_switch[1] != ucontrol->value.integer.value[1]; - if (change) { - mix->master_switch[0] = !!ucontrol->value.integer.value[0]; - mix->master_switch[1] = !!ucontrol->value.integer.value[1]; - tumbler_set_master_volume(mix); - } - return change; -} - - -/* - * TAS3001c dynamic range compression - */ - -#define TAS3001_DRC_MAX 0x5f - -static int tumbler_set_drc(struct pmac_tumbler *mix) -{ - unsigned char val[2]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->drc_enable) { - val[0] = 0xc1; /* enable, 3:1 compression */ - if (mix->drc_range > TAS3001_DRC_MAX) - val[1] = 0xf0; - else if (mix->drc_range < 0) - val[1] = 0x91; - else - val[1] = mix->drc_range + 0x91; - } else { - val[0] = 0; - val[1] = 0; - } - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, - 2, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); - return -EINVAL; - } - DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); - return 0; -} - -/* - * TAS3004 - */ - -#define TAS3004_DRC_MAX 0xef - -static int snapper_set_drc(struct pmac_tumbler *mix) -{ - unsigned char val[6]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->drc_enable) - val[0] = 0x50; /* 3:1 above threshold */ - else - val[0] = 0x51; /* disabled */ - val[1] = 0x02; /* 1:1 below threshold */ - if (mix->drc_range > 0xef) - val[2] = 0xef; - else if (mix->drc_range < 0) - val[2] = 0x00; - else - val[2] = mix->drc_range; - val[3] = 0xb0; - val[4] = 0x60; - val[5] = 0xa0; - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, - 6, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); - return -EINVAL; - } - DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); - return 0; -} - -static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX; - return 0; -} - -static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->drc_range; - return 0; -} - -static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int val; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - val = ucontrol->value.integer.value[0]; - if (chip->model == PMAC_TUMBLER) { - if (val > TAS3001_DRC_MAX) - return -EINVAL; - } else { - if (val > TAS3004_DRC_MAX) - return -EINVAL; - } - change = mix->drc_range != val; - if (change) { - mix->drc_range = val; - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - } - return change; -} - -static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->drc_enable; - return 0; -} - -static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->drc_enable != ucontrol->value.integer.value[0]; - if (change) { - mix->drc_enable = !!ucontrol->value.integer.value[0]; - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - } - return change; -} - - -/* - * mono volumes - */ - -struct tumbler_mono_vol { - int index; - int reg; - int bytes; - unsigned int max; - unsigned int *table; -}; - -static int tumbler_set_mono_volume(struct pmac_tumbler *mix, - struct tumbler_mono_vol *info) -{ - unsigned char block[4]; - unsigned int vol; - int i; - - if (! mix->i2c.client) - return -ENODEV; - - vol = mix->mono_vol[info->index]; - if (vol >= info->max) - vol = info->max - 1; - vol = info->table[vol]; - for (i = 0; i < info->bytes; i++) - block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, - info->bytes, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", - info->index); - return -EINVAL; - } - return 0; -} - -static int tumbler_info_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = info->max - 1; - return 0; -} - -static int tumbler_get_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->mono_vol[info->index]; - return 0; -} - -static int tumbler_put_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int vol; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol = ucontrol->value.integer.value[0]; - if (vol >= info->max) - return -EINVAL; - change = mix->mono_vol[info->index] != vol; - if (change) { - mix->mono_vol[info->index] = vol; - tumbler_set_mono_volume(mix, info); - } - return change; -} - -/* TAS3001c mono volumes */ -static struct tumbler_mono_vol tumbler_pcm_vol_info = { - .index = VOL_IDX_PCM_MONO, - .reg = TAS_REG_PCM, - .bytes = 3, - .max = ARRAY_SIZE(mixer_volume_table), - .table = mixer_volume_table, -}; - -static struct tumbler_mono_vol tumbler_bass_vol_info = { - .index = VOL_IDX_BASS, - .reg = TAS_REG_BASS, - .bytes = 1, - .max = ARRAY_SIZE(bass_volume_table), - .table = bass_volume_table, -}; - -static struct tumbler_mono_vol tumbler_treble_vol_info = { - .index = VOL_IDX_TREBLE, - .reg = TAS_REG_TREBLE, - .bytes = 1, - .max = ARRAY_SIZE(treble_volume_table), - .table = treble_volume_table, -}; - -/* TAS3004 mono volumes */ -static struct tumbler_mono_vol snapper_bass_vol_info = { - .index = VOL_IDX_BASS, - .reg = TAS_REG_BASS, - .bytes = 1, - .max = ARRAY_SIZE(snapper_bass_volume_table), - .table = snapper_bass_volume_table, -}; - -static struct tumbler_mono_vol snapper_treble_vol_info = { - .index = VOL_IDX_TREBLE, - .reg = TAS_REG_TREBLE, - .bytes = 1, - .max = ARRAY_SIZE(snapper_treble_volume_table), - .table = snapper_treble_volume_table, -}; - - -#define DEFINE_MONO(xname,type) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = tumbler_info_mono, \ - .get = tumbler_get_mono, \ - .put = tumbler_put_mono, \ - .private_value = (unsigned long)(&tumbler_##type##_vol_info), \ -} - -#define DEFINE_SNAPPER_MONO(xname,type) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = tumbler_info_mono, \ - .get = tumbler_get_mono, \ - .put = tumbler_put_mono, \ - .private_value = (unsigned long)(&snapper_##type##_vol_info), \ -} - - -/* - * snapper mixer volumes - */ - -static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg) -{ - int i, j, vol; - unsigned char block[9]; - - vol = mix->mix_vol[idx][ch]; - if (vol >= ARRAY_SIZE(mixer_volume_table)) { - vol = ARRAY_SIZE(mixer_volume_table) - 1; - mix->mix_vol[idx][ch] = vol; - } - - for (i = 0; i < 3; i++) { - vol = mix->mix_vol[i][ch]; - vol = mixer_volume_table[vol]; - for (j = 0; j < 3; j++) - block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff; - } - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, - 9, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", reg); - return -EINVAL; - } - return 0; -} - -static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx) -{ - if (! mix->i2c.client) - return -ENODEV; - if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 || - snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0) - return -EINVAL; - return 0; -} - -static int snapper_info_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1; - return 0; -} - -static int snapper_get_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = (int)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->mix_vol[idx][0]; - ucontrol->value.integer.value[1] = mix->mix_vol[idx][1]; - return 0; -} - -static int snapper_put_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = (int)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int vol[2]; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] >= ARRAY_SIZE(mixer_volume_table) || - vol[1] >= ARRAY_SIZE(mixer_volume_table)) - return -EINVAL; - change = mix->mix_vol[idx][0] != vol[0] || - mix->mix_vol[idx][1] != vol[1]; - if (change) { - mix->mix_vol[idx][0] = vol[0]; - mix->mix_vol[idx][1] = vol[1]; - snapper_set_mix_vol(mix, idx); - } - return change; -} - - -/* - * mute switches. FIXME: Turn that into software mute when both outputs are muted - * to avoid codec reset on ibook M7 - */ - -enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE }; - -static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - struct pmac_gpio *gp; - if (! (mix = chip->mixer_data)) - return -ENODEV; - switch(kcontrol->private_value) { - case TUMBLER_MUTE_HP: - gp = &mix->hp_mute; break; - case TUMBLER_MUTE_AMP: - gp = &mix->amp_mute; break; - case TUMBLER_MUTE_LINE: - gp = &mix->line_mute; break; - default: - gp = NULL; - } - if (gp == NULL) - return -EINVAL; - ucontrol->value.integer.value[0] = !check_audio_gpio(gp); - return 0; -} - -static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - struct pmac_gpio *gp; - int val; -#ifdef PMAC_SUPPORT_AUTOMUTE - if (chip->update_automute && chip->auto_mute) - return 0; /* don't touch in the auto-mute mode */ -#endif - if (! (mix = chip->mixer_data)) - return -ENODEV; - switch(kcontrol->private_value) { - case TUMBLER_MUTE_HP: - gp = &mix->hp_mute; break; - case TUMBLER_MUTE_AMP: - gp = &mix->amp_mute; break; - case TUMBLER_MUTE_LINE: - gp = &mix->line_mute; break; - default: - gp = NULL; - } - if (gp == NULL) - return -EINVAL; - val = ! check_audio_gpio(gp); - if (val != ucontrol->value.integer.value[0]) { - write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); - return 1; - } - return 0; -} - -static int snapper_set_capture_source(struct pmac_tumbler *mix) -{ - if (! mix->i2c.client) - return -ENODEV; - if (mix->capture_source) - mix->acs |= 2; - else - mix->acs &= ~2; - return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); -} - -static int snapper_info_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { - "Line", "Mic" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snapper_get_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.enumerated.item[0] = mix->capture_source; - return 0; -} - -static int snapper_put_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - int change; - - change = ucontrol->value.enumerated.item[0] != mix->capture_source; - if (change) { - mix->capture_source = !!ucontrol->value.enumerated.item[0]; - snapper_set_capture_source(mix); - } - return change; -} - -#define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = snapper_info_mix, \ - .get = snapper_get_mix, \ - .put = snapper_put_mix, \ - .index = idx,\ - .private_value = ofs, \ -} - - -/* - */ -static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = tumbler_info_master_volume, - .get = tumbler_get_master_volume, - .put = tumbler_put_master_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = tumbler_get_master_switch, - .put = tumbler_put_master_switch - }, - DEFINE_MONO("Tone Control - Bass", bass), - DEFINE_MONO("Tone Control - Treble", treble), - DEFINE_MONO("PCM Playback Volume", pcm), - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range", - .info = tumbler_info_drc_value, - .get = tumbler_get_drc_value, - .put = tumbler_put_drc_value - }, -}; - -static struct snd_kcontrol_new snapper_mixers[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = tumbler_info_master_volume, - .get = tumbler_get_master_volume, - .put = tumbler_put_master_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = tumbler_get_master_switch, - .put = tumbler_put_master_switch - }, - DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM), - /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */ - DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2), - DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC), - DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), - DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range", - .info = tumbler_info_drc_value, - .get = tumbler_get_drc_value, - .put = tumbler_put_drc_value - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */ - .info = snapper_info_capture_source, - .get = snapper_get_capture_source, - .put = snapper_put_capture_source - }, -}; - -static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_HP, -}; -static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_AMP, -}; -static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Out Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_LINE, -}; -static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_drc_switch, - .put = tumbler_put_drc_switch -}; - - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int tumbler_detect_headphone(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - int detect = 0; - - if (mix->hp_detect.addr) - detect |= read_audio_gpio(&mix->hp_detect); - return detect; -} - -static int tumbler_detect_lineout(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - int detect = 0; - - if (mix->line_detect.addr) - detect |= read_audio_gpio(&mix->line_detect); - return detect; -} - -static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify, - struct snd_kcontrol *sw) -{ - if (check_audio_gpio(gp) != val) { - write_audio_gpio(gp, val); - if (do_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &sw->id); - } -} - -static struct work_struct device_change; -static struct snd_pmac *device_change_chip; - -static void device_change_handler(struct work_struct *work) -{ - struct snd_pmac *chip = device_change_chip; - struct pmac_tumbler *mix; - int headphone, lineout; - - if (!chip) - return; - - mix = chip->mixer_data; - if (snd_BUG_ON(!mix)) - return; - - headphone = tumbler_detect_headphone(chip); - lineout = tumbler_detect_lineout(chip); - - DBG("headphone: %d, lineout: %d\n", headphone, lineout); - - if (headphone || lineout) { - /* unmute headphone/lineout & mute speaker */ - if (headphone) - check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, - chip->master_sw_ctl); - if (lineout && mix->line_mute.addr != 0) - check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, - chip->lineout_sw_ctl); - if (mix->anded_reset) - msleep(10); - check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify, - chip->speaker_sw_ctl); - } else { - /* unmute speaker, mute others */ - check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, - chip->speaker_sw_ctl); - if (mix->anded_reset) - msleep(10); - check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, - chip->master_sw_ctl); - if (mix->line_mute.addr != 0) - check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify, - chip->lineout_sw_ctl); - } - if (mix->auto_mute_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - -#ifdef CONFIG_SND_POWERMAC_AUTO_DRC - mix->drc_enable = ! (headphone || lineout); - if (mix->auto_mute_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->drc_sw_ctl->id); - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); -#endif - - /* reset the master volume so the correct amplification is applied */ - tumbler_set_master_volume(mix); -} - -static void tumbler_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { - struct pmac_tumbler *mix; - mix = chip->mixer_data; - if (snd_BUG_ON(!mix)) - return; - mix->auto_mute_notify = do_notify; - schedule_work(&device_change); - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* interrupt - headphone plug changed */ -static irqreturn_t headphone_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - if (chip->update_automute && chip->initialized) { - chip->update_automute(chip, 1); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* look for audio-gpio device */ -static struct device_node *find_audio_device(const char *name) -{ - struct device_node *gpiop; - struct device_node *np; - - gpiop = of_find_node_by_name(NULL, "gpio"); - if (! gpiop) - return NULL; - - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { - const char *property = of_get_property(np, "audio-gpio", NULL); - if (property && strcmp(property, name) == 0) - break; - } - of_node_put(gpiop); - return np; -} - -/* look for audio-gpio device */ -static struct device_node *find_compatible_audio_device(const char *name) -{ - struct device_node *gpiop; - struct device_node *np; - - gpiop = of_find_node_by_name(NULL, "gpio"); - if (!gpiop) - return NULL; - - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { - if (of_device_is_compatible(np, name)) - break; - } - of_node_put(gpiop); - return np; -} - -/* find an audio device and get its address */ -static long tumbler_find_device(const char *device, const char *platform, - struct pmac_gpio *gp, int is_compatible) -{ - struct device_node *node; - const u32 *base; - u32 addr; - long ret; - - if (is_compatible) - node = find_compatible_audio_device(device); - else - node = find_audio_device(device); - if (! node) { - DBG("(W) cannot find audio device %s !\n", device); - snd_printdd("cannot find device %s\n", device); - return -ENODEV; - } - - base = of_get_property(node, "AAPL,address", NULL); - if (! base) { - base = of_get_property(node, "reg", NULL); - if (!base) { - DBG("(E) cannot find address for device %s !\n", device); - snd_printd("cannot find address for device %s\n", device); - of_node_put(node); - return -ENODEV; - } - addr = *base; - if (addr < 0x50) - addr += 0x50; - } else - addr = *base; - - gp->addr = addr & 0x0000ffff; - /* Try to find the active state, default to 0 ! */ - base = of_get_property(node, "audio-gpio-active-state", NULL); - if (base) { - gp->active_state = *base; - gp->active_val = (*base) ? 0x5 : 0x4; - gp->inactive_val = (*base) ? 0x4 : 0x5; - } else { - const u32 *prop = NULL; - gp->active_state = IS_G4DA - && !strncmp(device, "keywest-gpio1", 13); - gp->active_val = 0x4; - gp->inactive_val = 0x5; - /* Here are some crude hacks to extract the GPIO polarity and - * open collector informations out of the do-platform script - * as we don't yet have an interpreter for these things - */ - if (platform) - prop = of_get_property(node, platform, NULL); - if (prop) { - if (prop[3] == 0x9 && prop[4] == 0x9) { - gp->active_val = 0xd; - gp->inactive_val = 0xc; - } - if (prop[3] == 0x1 && prop[4] == 0x1) { - gp->active_val = 0x5; - gp->inactive_val = 0x4; - } - } - } - - DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", - device, gp->addr, gp->active_state); - - ret = irq_of_parse_and_map(node, 0); - of_node_put(node); - return ret; -} - -/* reset audio */ -static void tumbler_reset_audio(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - if (mix->anded_reset) { - DBG("(I) codec anded reset !\n"); - write_audio_gpio(&mix->hp_mute, 0); - write_audio_gpio(&mix->amp_mute, 0); - msleep(200); - write_audio_gpio(&mix->hp_mute, 1); - write_audio_gpio(&mix->amp_mute, 1); - msleep(100); - write_audio_gpio(&mix->hp_mute, 0); - write_audio_gpio(&mix->amp_mute, 0); - msleep(100); - } else { - DBG("(I) codec normal reset !\n"); - - write_audio_gpio(&mix->audio_reset, 0); - msleep(200); - write_audio_gpio(&mix->audio_reset, 1); - msleep(100); - write_audio_gpio(&mix->audio_reset, 0); - msleep(100); - } -} - -#ifdef CONFIG_PM -/* suspend mixer */ -static void tumbler_suspend(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - if (mix->headphone_irq >= 0) - disable_irq(mix->headphone_irq); - if (mix->lineout_irq >= 0) - disable_irq(mix->lineout_irq); - mix->save_master_switch[0] = mix->master_switch[0]; - mix->save_master_switch[1] = mix->master_switch[1]; - mix->save_master_vol[0] = mix->master_vol[0]; - mix->save_master_vol[1] = mix->master_vol[1]; - mix->master_switch[0] = mix->master_switch[1] = 0; - tumbler_set_master_volume(mix); - if (!mix->anded_reset) { - write_audio_gpio(&mix->amp_mute, 1); - write_audio_gpio(&mix->hp_mute, 1); - } - if (chip->model == PMAC_SNAPPER) { - mix->acs |= 1; - i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); - } - if (mix->anded_reset) { - write_audio_gpio(&mix->amp_mute, 1); - write_audio_gpio(&mix->hp_mute, 1); - } else - write_audio_gpio(&mix->audio_reset, 1); -} - -/* resume mixer */ -static void tumbler_resume(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - mix->acs &= ~1; - mix->master_switch[0] = mix->save_master_switch[0]; - mix->master_switch[1] = mix->save_master_switch[1]; - mix->master_vol[0] = mix->save_master_vol[0]; - mix->master_vol[1] = mix->save_master_vol[1]; - tumbler_reset_audio(chip); - if (mix->i2c.client && mix->i2c.init_client) { - if (mix->i2c.init_client(&mix->i2c) < 0) - printk(KERN_ERR "tumbler_init_client error\n"); - } else - printk(KERN_ERR "tumbler: i2c is not initialized\n"); - if (chip->model == PMAC_TUMBLER) { - tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info); - tumbler_set_mono_volume(mix, &tumbler_bass_vol_info); - tumbler_set_mono_volume(mix, &tumbler_treble_vol_info); - tumbler_set_drc(mix); - } else { - snapper_set_mix_vol(mix, VOL_IDX_PCM); - snapper_set_mix_vol(mix, VOL_IDX_PCM2); - snapper_set_mix_vol(mix, VOL_IDX_ADC); - tumbler_set_mono_volume(mix, &snapper_bass_vol_info); - tumbler_set_mono_volume(mix, &snapper_treble_vol_info); - snapper_set_drc(mix); - snapper_set_capture_source(mix); - } - tumbler_set_master_volume(mix); - if (chip->update_automute) - chip->update_automute(chip, 0); - if (mix->headphone_irq >= 0) { - unsigned char val; - - enable_irq(mix->headphone_irq); - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->hp_detect); - do_gpio_write(&mix->hp_detect, val | 0x80); - } - if (mix->lineout_irq >= 0) - enable_irq(mix->lineout_irq); -} -#endif - -/* initialize tumbler */ -static int __devinit tumbler_init(struct snd_pmac *chip) -{ - int irq; - struct pmac_tumbler *mix = chip->mixer_data; - - if (tumbler_find_device("audio-hw-reset", - "platform-do-hw-reset", - &mix->audio_reset, 0) < 0) - tumbler_find_device("hw-reset", - "platform-do-hw-reset", - &mix->audio_reset, 1); - if (tumbler_find_device("amp-mute", - "platform-do-amp-mute", - &mix->amp_mute, 0) < 0) - tumbler_find_device("amp-mute", - "platform-do-amp-mute", - &mix->amp_mute, 1); - if (tumbler_find_device("headphone-mute", - "platform-do-headphone-mute", - &mix->hp_mute, 0) < 0) - tumbler_find_device("headphone-mute", - "platform-do-headphone-mute", - &mix->hp_mute, 1); - if (tumbler_find_device("line-output-mute", - "platform-do-lineout-mute", - &mix->line_mute, 0) < 0) - tumbler_find_device("line-output-mute", - "platform-do-lineout-mute", - &mix->line_mute, 1); - irq = tumbler_find_device("headphone-detect", - NULL, &mix->hp_detect, 0); - if (irq <= NO_IRQ) - irq = tumbler_find_device("headphone-detect", - NULL, &mix->hp_detect, 1); - if (irq <= NO_IRQ) - irq = tumbler_find_device("keywest-gpio15", - NULL, &mix->hp_detect, 1); - mix->headphone_irq = irq; - irq = tumbler_find_device("line-output-detect", - NULL, &mix->line_detect, 0); - if (irq <= NO_IRQ) - irq = tumbler_find_device("line-output-detect", - NULL, &mix->line_detect, 1); - if (IS_G4DA && irq <= NO_IRQ) - irq = tumbler_find_device("keywest-gpio16", - NULL, &mix->line_detect, 1); - mix->lineout_irq = irq; - - tumbler_reset_audio(chip); - - return 0; -} - -static void tumbler_cleanup(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - if (! mix) - return; - - if (mix->headphone_irq >= 0) - free_irq(mix->headphone_irq, chip); - if (mix->lineout_irq >= 0) - free_irq(mix->lineout_irq, chip); - tumbler_gpio_free(&mix->audio_reset); - tumbler_gpio_free(&mix->amp_mute); - tumbler_gpio_free(&mix->hp_mute); - tumbler_gpio_free(&mix->hp_detect); - snd_pmac_keywest_cleanup(&mix->i2c); - kfree(mix); - chip->mixer_data = NULL; -} - -/* exported */ -int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip) -{ - int i, err; - struct pmac_tumbler *mix; - const u32 *paddr; - struct device_node *tas_node, *np; - char *chipname; - - request_module("i2c-powermac"); - - mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (! mix) - return -ENOMEM; - mix->headphone_irq = -1; - - chip->mixer_data = mix; - chip->mixer_free = tumbler_cleanup; - mix->anded_reset = 0; - mix->reset_on_sleep = 1; - - for (np = chip->node->child; np; np = np->sibling) { - if (!strcmp(np->name, "sound")) { - if (of_get_property(np, "has-anded-reset", NULL)) - mix->anded_reset = 1; - if (of_get_property(np, "layout-id", NULL)) - mix->reset_on_sleep = 0; - break; - } - } - if ((err = tumbler_init(chip)) < 0) - return err; - - /* set up TAS */ - tas_node = of_find_node_by_name(NULL, "deq"); - if (tas_node == NULL) - tas_node = of_find_node_by_name(NULL, "codec"); - if (tas_node == NULL) - return -ENODEV; - - paddr = of_get_property(tas_node, "i2c-address", NULL); - if (paddr == NULL) - paddr = of_get_property(tas_node, "reg", NULL); - if (paddr) - mix->i2c.addr = (*paddr) >> 1; - else - mix->i2c.addr = TAS_I2C_ADDR; - of_node_put(tas_node); - - DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); - - if (chip->model == PMAC_TUMBLER) { - mix->i2c.init_client = tumbler_init_client; - mix->i2c.name = "TAS3001c"; - chipname = "Tumbler"; - } else { - mix->i2c.init_client = snapper_init_client; - mix->i2c.name = "TAS3004"; - chipname = "Snapper"; - } - - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) - return err; - - /* - * build mixers - */ - sprintf(chip->card->mixername, "PowerMac %s", chipname); - - if (chip->model == PMAC_TUMBLER) { - for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0) - return err; - } - } else { - for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0) - return err; - } - } - chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) - return err; - if (mix->line_mute.addr != 0) { - chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) - return err; - } - chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) - return err; - - /* set initial DRC range to 60% */ - if (chip->model == PMAC_TUMBLER) - mix->drc_range = (TAS3001_DRC_MAX * 6) / 10; - else - mix->drc_range = (TAS3004_DRC_MAX * 6) / 10; - mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */ - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - -#ifdef CONFIG_PM - chip->suspend = tumbler_suspend; - chip->resume = tumbler_resume; -#endif - - INIT_WORK(&device_change, device_change_handler); - device_change_chip = chip; - -#ifdef PMAC_SUPPORT_AUTOMUTE - if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) - && (err = snd_pmac_add_automute(chip)) < 0) - return err; - chip->detect_headphone = tumbler_detect_headphone; - chip->update_automute = tumbler_update_automute; - tumbler_update_automute(chip, 0); /* update the status only */ - - /* activate headphone status interrupts */ - if (mix->headphone_irq >= 0) { - unsigned char val; - if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, - "Sound Headphone Detection", chip)) < 0) - return 0; - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->hp_detect); - do_gpio_write(&mix->hp_detect, val | 0x80); - } - if (mix->lineout_irq >= 0) { - unsigned char val; - if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, - "Sound Lineout Detection", chip)) < 0) - return 0; - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->line_detect); - do_gpio_write(&mix->line_detect, val | 0x80); - } -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/tumbler_volume.h b/ANDROID_3.4.5/sound/ppc/tumbler_volume.h deleted file mode 100644 index ef8d85d5..00000000 --- a/ANDROID_3.4.5/sound/ppc/tumbler_volume.h +++ /dev/null @@ -1,250 +0,0 @@ -/* volume tables, taken from TAS3001c data manual */ -/* volume gain values */ -/* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */ -static unsigned int master_volume_table[] = { - 0x00000015, 0x00000016, 0x00000017, - 0x00000019, 0x0000001a, 0x0000001c, - 0x0000001d, 0x0000001f, 0x00000021, - 0x00000023, 0x00000025, 0x00000027, - 0x00000029, 0x0000002c, 0x0000002e, - 0x00000031, 0x00000034, 0x00000037, - 0x0000003a, 0x0000003e, 0x00000042, - 0x00000045, 0x0000004a, 0x0000004e, - 0x00000053, 0x00000057, 0x0000005d, - 0x00000062, 0x00000068, 0x0000006e, - 0x00000075, 0x0000007b, 0x00000083, - 0x0000008b, 0x00000093, 0x0000009b, - 0x000000a5, 0x000000ae, 0x000000b9, - 0x000000c4, 0x000000cf, 0x000000dc, - 0x000000e9, 0x000000f6, 0x00000105, - 0x00000114, 0x00000125, 0x00000136, - 0x00000148, 0x0000015c, 0x00000171, - 0x00000186, 0x0000019e, 0x000001b6, - 0x000001d0, 0x000001eb, 0x00000209, - 0x00000227, 0x00000248, 0x0000026b, - 0x0000028f, 0x000002b6, 0x000002df, - 0x0000030b, 0x00000339, 0x0000036a, - 0x0000039e, 0x000003d5, 0x0000040f, - 0x0000044c, 0x0000048d, 0x000004d2, - 0x0000051c, 0x00000569, 0x000005bb, - 0x00000612, 0x0000066e, 0x000006d0, - 0x00000737, 0x000007a5, 0x00000818, - 0x00000893, 0x00000915, 0x0000099f, - 0x00000a31, 0x00000acc, 0x00000b6f, - 0x00000c1d, 0x00000cd5, 0x00000d97, - 0x00000e65, 0x00000f40, 0x00001027, - 0x0000111c, 0x00001220, 0x00001333, - 0x00001456, 0x0000158a, 0x000016d1, - 0x0000182b, 0x0000199a, 0x00001b1e, - 0x00001cb9, 0x00001e6d, 0x0000203a, - 0x00002223, 0x00002429, 0x0000264e, - 0x00002893, 0x00002afa, 0x00002d86, - 0x00003039, 0x00003314, 0x0000361b, - 0x00003950, 0x00003cb5, 0x0000404e, - 0x0000441d, 0x00004827, 0x00004c6d, - 0x000050f4, 0x000055c0, 0x00005ad5, - 0x00006037, 0x000065ea, 0x00006bf4, - 0x0000725a, 0x00007920, 0x0000804e, - 0x000087e8, 0x00008ff6, 0x0000987d, - 0x0000a186, 0x0000ab19, 0x0000b53c, - 0x0000bff9, 0x0000cb59, 0x0000d766, - 0x0000e429, 0x0000f1ae, 0x00010000, - 0x00010f2b, 0x00011f3d, 0x00013042, - 0x00014249, 0x00015562, 0x0001699c, - 0x00017f09, 0x000195bc, 0x0001adc6, - 0x0001c73d, 0x0001e237, 0x0001feca, - 0x00021d0e, 0x00023d1d, 0x00025f12, - 0x0002830b, 0x0002a925, 0x0002d182, - 0x0002fc42, 0x0003298b, 0x00035983, - 0x00038c53, 0x0003c225, 0x0003fb28, - 0x0004378b, 0x00047783, 0x0004bb44, - 0x0005030a, 0x00054f10, 0x00059f98, - 0x0005f4e5, 0x00064f40, 0x0006aef6, - 0x00071457, 0x00077fbb, 0x0007f17b, -}; - -/* treble table for TAS3001c */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int treble_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x70, - 0x6e, 0x6d, 0x6c, - 0x6b, 0x69, 0x68, - 0x66, 0x65, 0x63, - 0x62, 0x60, 0x5e, - 0x5c, 0x5a, 0x57, - 0x55, 0x52, 0x4f, - 0x4c, 0x49, 0x45, - 0x42, 0x3e, 0x3a, - 0x36, 0x32, 0x2d, - 0x28, 0x22, 0x1c, - 0x16, 0x10, 0x09, - 0x01, -}; - -/* bass table for TAS3001c */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int bass_volume_table[] = { - 0x86, 0x82, 0x7f, - 0x7d, 0x7a, 0x78, - 0x76, 0x74, 0x72, - 0x70, 0x6e, 0x6d, - 0x6b, 0x69, 0x66, - 0x64, 0x61, 0x5f, - 0x5d, 0x5c, 0x5a, - 0x59, 0x58, 0x56, - 0x55, 0x54, 0x53, - 0x51, 0x4f, 0x4d, - 0x4b, 0x49, 0x46, - 0x44, 0x42, 0x40, - 0x3e, 0x3c, 0x3b, - 0x39, 0x38, 0x36, - 0x35, 0x33, 0x31, - 0x30, 0x2e, 0x2c, - 0x2b, 0x29, 0x28, - 0x26, 0x25, 0x23, - 0x21, 0x1f, 0x1c, - 0x19, 0x18, 0x17, - 0x16, 0x14, 0x13, - 0x12, 0x10, 0x0f, - 0x0d, 0x0b, 0x0a, - 0x08, 0x06, 0x03, - 0x01, -}; - -/* mixer (pcm) volume table */ -/* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */ -static unsigned int mixer_volume_table[] = { - 0x00014b, 0x00015f, 0x000174, - 0x00018a, 0x0001a1, 0x0001ba, - 0x0001d4, 0x0001f0, 0x00020d, - 0x00022c, 0x00024d, 0x000270, - 0x000295, 0x0002bc, 0x0002e6, - 0x000312, 0x000340, 0x000372, - 0x0003a6, 0x0003dd, 0x000418, - 0x000456, 0x000498, 0x0004de, - 0x000528, 0x000576, 0x0005c9, - 0x000620, 0x00067d, 0x0006e0, - 0x000748, 0x0007b7, 0x00082c, - 0x0008a8, 0x00092b, 0x0009b6, - 0x000a49, 0x000ae5, 0x000b8b, - 0x000c3a, 0x000cf3, 0x000db8, - 0x000e88, 0x000f64, 0x00104e, - 0x001145, 0x00124b, 0x001361, - 0x001487, 0x0015be, 0x001708, - 0x001865, 0x0019d8, 0x001b60, - 0x001cff, 0x001eb7, 0x002089, - 0x002276, 0x002481, 0x0026ab, - 0x0028f5, 0x002b63, 0x002df5, - 0x0030ae, 0x003390, 0x00369e, - 0x0039db, 0x003d49, 0x0040ea, - 0x0044c3, 0x0048d6, 0x004d27, - 0x0051b9, 0x005691, 0x005bb2, - 0x006121, 0x0066e3, 0x006cfb, - 0x007370, 0x007a48, 0x008186, - 0x008933, 0x009154, 0x0099f1, - 0x00a310, 0x00acba, 0x00b6f6, - 0x00c1cd, 0x00cd49, 0x00d973, - 0x00e655, 0x00f3fb, 0x010270, - 0x0111c0, 0x0121f9, 0x013328, - 0x01455b, 0x0158a2, 0x016d0e, - 0x0182af, 0x019999, 0x01b1de, - 0x01cb94, 0x01e6cf, 0x0203a7, - 0x022235, 0x024293, 0x0264db, - 0x02892c, 0x02afa3, 0x02d862, - 0x03038a, 0x033142, 0x0361af, - 0x0394fa, 0x03cb50, 0x0404de, - 0x0441d5, 0x048268, 0x04c6d0, - 0x050f44, 0x055c04, 0x05ad50, - 0x06036e, 0x065ea5, 0x06bf44, - 0x07259d, 0x079207, 0x0804dc, - 0x087e80, 0x08ff59, 0x0987d5, - 0x0a1866, 0x0ab189, 0x0b53be, - 0x0bff91, 0x0cb591, 0x0d765a, - 0x0e4290, 0x0f1adf, 0x100000, - 0x10f2b4, 0x11f3c9, 0x13041a, - 0x14248e, 0x15561a, 0x1699c0, - 0x17f094, 0x195bb8, 0x1adc61, - 0x1c73d5, 0x1e236d, 0x1fec98, - 0x21d0d9, 0x23d1cd, 0x25f125, - 0x2830af, 0x2a9254, 0x2d1818, - 0x2fc420, 0x3298b0, 0x35982f, - 0x38c528, 0x3c224c, 0x3fb278, - 0x437880, 0x477828, 0x4bb446, - 0x5030a1, 0x54f106, 0x59f980, - 0x5f4e52, 0x64f403, 0x6aef5d, - 0x714575, 0x77fbaa, 0x7f17af, -}; - - -/* treble table for TAS3004 */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int snapper_treble_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x70, - 0x6f, 0x6d, 0x6c, - 0x6b, 0x69, 0x68, - 0x67, 0x65, 0x63, - 0x62, 0x60, 0x5d, - 0x5b, 0x59, 0x56, - 0x53, 0x51, 0x4d, - 0x4a, 0x47, 0x43, - 0x3f, 0x3b, 0x36, - 0x31, 0x2c, 0x26, - 0x20, 0x1a, 0x13, - 0x08, 0x04, 0x01, - 0x01, -}; - -/* bass table for TAS3004 */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int snapper_bass_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x6f, - 0x6e, 0x6d, 0x6b, - 0x6a, 0x69, 0x67, - 0x66, 0x65, 0x63, - 0x62, 0x61, 0x5f, - 0x5d, 0x5b, 0x58, - 0x55, 0x52, 0x4f, - 0x4c, 0x49, 0x46, - 0x43, 0x3f, 0x3b, - 0x37, 0x33, 0x2e, - 0x29, 0x24, 0x1e, - 0x18, 0x11, 0x0a, - 0x01, -}; - |