diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/sound/mips | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/sound/mips')
-rw-r--r-- | ANDROID_3.4.5/sound/mips/Kconfig | 37 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/Makefile | 12 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/ad1843.c | 561 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/au1x00.c | 696 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/hal2.c | 938 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/hal2.h | 245 | ||||
-rw-r--r-- | ANDROID_3.4.5/sound/mips/sgio2audio.c | 979 |
7 files changed, 0 insertions, 3468 deletions
diff --git a/ANDROID_3.4.5/sound/mips/Kconfig b/ANDROID_3.4.5/sound/mips/Kconfig deleted file mode 100644 index d2f615ab..00000000 --- a/ANDROID_3.4.5/sound/mips/Kconfig +++ /dev/null @@ -1,37 +0,0 @@ -# ALSA MIPS drivers - -menuconfig SND_MIPS - bool "MIPS sound devices" - depends on MIPS - default y - help - Support for sound devices of MIPS architectures. - -if SND_MIPS - -config SND_SGI_O2 - tristate "SGI O2 Audio" - depends on SGI_IP32 - help - Sound support for the SGI O2 Workstation. - -config SND_SGI_HAL2 - tristate "SGI HAL2 Audio" - depends on SGI_HAS_HAL2 - help - Sound support for the SGI Indy and Indigo2 Workstation. - - -config SND_AU1X00 - tristate "Au1x00 AC97 Port Driver (DEPRECATED)" - depends on MIPS_ALCHEMY - select SND_PCM - select SND_AC97_CODEC - help - ALSA Sound driver for the Au1x00's AC97 port. - - Newer drivers for ASoC are available, please do not use - this driver as it will be removed in the future. - -endif # SND_MIPS - diff --git a/ANDROID_3.4.5/sound/mips/Makefile b/ANDROID_3.4.5/sound/mips/Makefile deleted file mode 100644 index 861ec0a5..00000000 --- a/ANDROID_3.4.5/sound/mips/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# - -snd-au1x00-objs := au1x00.o -snd-sgi-o2-objs := sgio2audio.o ad1843.o -snd-sgi-hal2-objs := hal2.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AU1X00) += snd-au1x00.o -obj-$(CONFIG_SND_SGI_O2) += snd-sgi-o2.o -obj-$(CONFIG_SND_SGI_HAL2) += snd-sgi-hal2.o diff --git a/ANDROID_3.4.5/sound/mips/ad1843.c b/ANDROID_3.4.5/sound/mips/ad1843.c deleted file mode 100644 index c624510e..00000000 --- a/ANDROID_3.4.5/sound/mips/ad1843.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * AD1843 low level driver - * - * Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org> - * Copyright 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de> - * - * inspired from vwsnd.c (SGI VW audio driver) - * Copyright 1999 Silicon Graphics, Inc. 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; 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/sched.h> -#include <linux/errno.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/ad1843.h> - -/* - * AD1843 bitfield definitions. All are named as in the AD1843 data - * sheet, with ad1843_ prepended and individual bit numbers removed. - * - * E.g., bits LSS0 through LSS2 become ad1843_LSS. - * - * Only the bitfields we need are defined. - */ - -struct ad1843_bitfield { - char reg; - char lo_bit; - char nbits; -}; - -static const struct ad1843_bitfield - ad1843_PDNO = { 0, 14, 1 }, /* Converter Power-Down Flag */ - ad1843_INIT = { 0, 15, 1 }, /* Clock Initialization Flag */ - ad1843_RIG = { 2, 0, 4 }, /* Right ADC Input Gain */ - ad1843_RMGE = { 2, 4, 1 }, /* Right ADC Mic Gain Enable */ - ad1843_RSS = { 2, 5, 3 }, /* Right ADC Source Select */ - ad1843_LIG = { 2, 8, 4 }, /* Left ADC Input Gain */ - ad1843_LMGE = { 2, 12, 1 }, /* Left ADC Mic Gain Enable */ - ad1843_LSS = { 2, 13, 3 }, /* Left ADC Source Select */ - ad1843_RD2M = { 3, 0, 5 }, /* Right DAC 2 Mix Gain/Atten */ - ad1843_RD2MM = { 3, 7, 1 }, /* Right DAC 2 Mix Mute */ - ad1843_LD2M = { 3, 8, 5 }, /* Left DAC 2 Mix Gain/Atten */ - ad1843_LD2MM = { 3, 15, 1 }, /* Left DAC 2 Mix Mute */ - ad1843_RX1M = { 4, 0, 5 }, /* Right Aux 1 Mix Gain/Atten */ - ad1843_RX1MM = { 4, 7, 1 }, /* Right Aux 1 Mix Mute */ - ad1843_LX1M = { 4, 8, 5 }, /* Left Aux 1 Mix Gain/Atten */ - ad1843_LX1MM = { 4, 15, 1 }, /* Left Aux 1 Mix Mute */ - ad1843_RX2M = { 5, 0, 5 }, /* Right Aux 2 Mix Gain/Atten */ - ad1843_RX2MM = { 5, 7, 1 }, /* Right Aux 2 Mix Mute */ - ad1843_LX2M = { 5, 8, 5 }, /* Left Aux 2 Mix Gain/Atten */ - ad1843_LX2MM = { 5, 15, 1 }, /* Left Aux 2 Mix Mute */ - ad1843_RMCM = { 7, 0, 5 }, /* Right Mic Mix Gain/Atten */ - ad1843_RMCMM = { 7, 7, 1 }, /* Right Mic Mix Mute */ - ad1843_LMCM = { 7, 8, 5 }, /* Left Mic Mix Gain/Atten */ - ad1843_LMCMM = { 7, 15, 1 }, /* Left Mic Mix Mute */ - ad1843_HPOS = { 8, 4, 1 }, /* Headphone Output Voltage Swing */ - ad1843_HPOM = { 8, 5, 1 }, /* Headphone Output Mute */ - ad1843_MPOM = { 8, 6, 1 }, /* Mono Output Mute */ - ad1843_RDA1G = { 9, 0, 6 }, /* Right DAC1 Analog/Digital Gain */ - ad1843_RDA1GM = { 9, 7, 1 }, /* Right DAC1 Analog Mute */ - ad1843_LDA1G = { 9, 8, 6 }, /* Left DAC1 Analog/Digital Gain */ - ad1843_LDA1GM = { 9, 15, 1 }, /* Left DAC1 Analog Mute */ - ad1843_RDA2G = { 10, 0, 6 }, /* Right DAC2 Analog/Digital Gain */ - ad1843_RDA2GM = { 10, 7, 1 }, /* Right DAC2 Analog Mute */ - ad1843_LDA2G = { 10, 8, 6 }, /* Left DAC2 Analog/Digital Gain */ - ad1843_LDA2GM = { 10, 15, 1 }, /* Left DAC2 Analog Mute */ - ad1843_RDA1AM = { 11, 7, 1 }, /* Right DAC1 Digital Mute */ - ad1843_LDA1AM = { 11, 15, 1 }, /* Left DAC1 Digital Mute */ - ad1843_RDA2AM = { 12, 7, 1 }, /* Right DAC2 Digital Mute */ - ad1843_LDA2AM = { 12, 15, 1 }, /* Left DAC2 Digital Mute */ - ad1843_ADLC = { 15, 0, 2 }, /* ADC Left Sample Rate Source */ - ad1843_ADRC = { 15, 2, 2 }, /* ADC Right Sample Rate Source */ - ad1843_DA1C = { 15, 8, 2 }, /* DAC1 Sample Rate Source */ - ad1843_DA2C = { 15, 10, 2 }, /* DAC2 Sample Rate Source */ - ad1843_C1C = { 17, 0, 16 }, /* Clock 1 Sample Rate Select */ - ad1843_C2C = { 20, 0, 16 }, /* Clock 2 Sample Rate Select */ - ad1843_C3C = { 23, 0, 16 }, /* Clock 3 Sample Rate Select */ - ad1843_DAADL = { 25, 4, 2 }, /* Digital ADC Left Source Select */ - ad1843_DAADR = { 25, 6, 2 }, /* Digital ADC Right Source Select */ - ad1843_DAMIX = { 25, 14, 1 }, /* DAC Digital Mix Enable */ - ad1843_DRSFLT = { 25, 15, 1 }, /* Digital Reampler Filter Mode */ - ad1843_ADLF = { 26, 0, 2 }, /* ADC Left Channel Data Format */ - ad1843_ADRF = { 26, 2, 2 }, /* ADC Right Channel Data Format */ - ad1843_ADTLK = { 26, 4, 1 }, /* ADC Transmit Lock Mode Select */ - ad1843_SCF = { 26, 7, 1 }, /* SCLK Frequency Select */ - ad1843_DA1F = { 26, 8, 2 }, /* DAC1 Data Format Select */ - ad1843_DA2F = { 26, 10, 2 }, /* DAC2 Data Format Select */ - ad1843_DA1SM = { 26, 14, 1 }, /* DAC1 Stereo/Mono Mode Select */ - ad1843_DA2SM = { 26, 15, 1 }, /* DAC2 Stereo/Mono Mode Select */ - ad1843_ADLEN = { 27, 0, 1 }, /* ADC Left Channel Enable */ - ad1843_ADREN = { 27, 1, 1 }, /* ADC Right Channel Enable */ - ad1843_AAMEN = { 27, 4, 1 }, /* Analog to Analog Mix Enable */ - ad1843_ANAEN = { 27, 7, 1 }, /* Analog Channel Enable */ - ad1843_DA1EN = { 27, 8, 1 }, /* DAC1 Enable */ - ad1843_DA2EN = { 27, 9, 1 }, /* DAC2 Enable */ - ad1843_DDMEN = { 27, 12, 1 }, /* DAC2 to DAC1 Mix Enable */ - ad1843_C1EN = { 28, 11, 1 }, /* Clock Generator 1 Enable */ - ad1843_C2EN = { 28, 12, 1 }, /* Clock Generator 2 Enable */ - ad1843_C3EN = { 28, 13, 1 }, /* Clock Generator 3 Enable */ - ad1843_PDNI = { 28, 15, 1 }; /* Converter Power Down */ - -/* - * The various registers of the AD1843 use three different formats for - * specifying gain. The ad1843_gain structure parameterizes the - * formats. - */ - -struct ad1843_gain { - int negative; /* nonzero if gain is negative. */ - const struct ad1843_bitfield *lfield; - const struct ad1843_bitfield *rfield; - const struct ad1843_bitfield *lmute; - const struct ad1843_bitfield *rmute; -}; - -static const struct ad1843_gain ad1843_gain_RECLEV = { - .negative = 0, - .lfield = &ad1843_LIG, - .rfield = &ad1843_RIG -}; -static const struct ad1843_gain ad1843_gain_LINE = { - .negative = 1, - .lfield = &ad1843_LX1M, - .rfield = &ad1843_RX1M, - .lmute = &ad1843_LX1MM, - .rmute = &ad1843_RX1MM -}; -static const struct ad1843_gain ad1843_gain_LINE_2 = { - .negative = 1, - .lfield = &ad1843_LDA2G, - .rfield = &ad1843_RDA2G, - .lmute = &ad1843_LDA2GM, - .rmute = &ad1843_RDA2GM -}; -static const struct ad1843_gain ad1843_gain_MIC = { - .negative = 1, - .lfield = &ad1843_LMCM, - .rfield = &ad1843_RMCM, - .lmute = &ad1843_LMCMM, - .rmute = &ad1843_RMCMM -}; -static const struct ad1843_gain ad1843_gain_PCM_0 = { - .negative = 1, - .lfield = &ad1843_LDA1G, - .rfield = &ad1843_RDA1G, - .lmute = &ad1843_LDA1GM, - .rmute = &ad1843_RDA1GM -}; -static const struct ad1843_gain ad1843_gain_PCM_1 = { - .negative = 1, - .lfield = &ad1843_LD2M, - .rfield = &ad1843_RD2M, - .lmute = &ad1843_LD2MM, - .rmute = &ad1843_RD2MM -}; - -static const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] = -{ - &ad1843_gain_RECLEV, - &ad1843_gain_LINE, - &ad1843_gain_LINE_2, - &ad1843_gain_MIC, - &ad1843_gain_PCM_0, - &ad1843_gain_PCM_1, -}; - -/* read the current value of an AD1843 bitfield. */ - -static int ad1843_read_bits(struct snd_ad1843 *ad1843, - const struct ad1843_bitfield *field) -{ - int w; - - w = ad1843->read(ad1843->chip, field->reg); - return w >> field->lo_bit & ((1 << field->nbits) - 1); -} - -/* - * write a new value to an AD1843 bitfield and return the old value. - */ - -static int ad1843_write_bits(struct snd_ad1843 *ad1843, - const struct ad1843_bitfield *field, - int newval) -{ - int w, mask, oldval, newbits; - - w = ad1843->read(ad1843->chip, field->reg); - mask = ((1 << field->nbits) - 1) << field->lo_bit; - oldval = (w & mask) >> field->lo_bit; - newbits = (newval << field->lo_bit) & mask; - w = (w & ~mask) | newbits; - ad1843->write(ad1843->chip, field->reg, w); - - return oldval; -} - -/* - * ad1843_read_multi reads multiple bitfields from the same AD1843 - * register. It uses a single read cycle to do it. (Reading the - * ad1843 requires 256 bit times at 12.288 MHz, or nearly 20 - * microseconds.) - * - * Called like this. - * - * ad1843_read_multi(ad1843, nfields, - * &ad1843_FIELD1, &val1, - * &ad1843_FIELD2, &val2, ...); - */ - -static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...) -{ - va_list ap; - const struct ad1843_bitfield *fp; - int w = 0, mask, *value, reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const struct ad1843_bitfield *); - value = va_arg(ap, int *); - if (reg == -1) { - reg = fp->reg; - w = ad1843->read(ad1843->chip, reg); - } - - mask = (1 << fp->nbits) - 1; - *value = w >> fp->lo_bit & mask; - } - va_end(ap); -} - -/* - * ad1843_write_multi stores multiple bitfields into the same AD1843 - * register. It uses one read and one write cycle to do it. - * - * Called like this. - * - * ad1843_write_multi(ad1843, nfields, - * &ad1843_FIELD1, val1, - * &ad1843_FIELF2, val2, ...); - */ - -static void ad1843_write_multi(struct snd_ad1843 *ad1843, int argcount, ...) -{ - va_list ap; - int reg; - const struct ad1843_bitfield *fp; - int value; - int w, m, mask, bits; - - mask = 0; - bits = 0; - reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const struct ad1843_bitfield *); - value = va_arg(ap, int); - if (reg == -1) - reg = fp->reg; - else - BUG_ON(reg != fp->reg); - m = ((1 << fp->nbits) - 1) << fp->lo_bit; - mask |= m; - bits |= (value << fp->lo_bit) & m; - } - va_end(ap); - - if (~mask & 0xFFFF) - w = ad1843->read(ad1843->chip, reg); - else - w = 0; - w = (w & ~mask) | bits; - ad1843->write(ad1843->chip, reg, w); -} - -int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id) -{ - const struct ad1843_gain *gp = ad1843_gain[id]; - int ret; - - ret = (1 << gp->lfield->nbits); - if (!gp->lmute) - ret -= 1; - return ret; -} - -/* - * ad1843_get_gain reads the specified register and extracts the gain value - * using the supplied gain type. - */ - -int ad1843_get_gain(struct snd_ad1843 *ad1843, int id) -{ - int lg, rg, lm, rm; - const struct ad1843_gain *gp = ad1843_gain[id]; - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - ad1843_read_multi(ad1843, 2, gp->lfield, &lg, gp->rfield, &rg); - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - if (gp->lmute) { - ad1843_read_multi(ad1843, 2, gp->lmute, &lm, gp->rmute, &rm); - if (lm) - lg = 0; - if (rm) - rg = 0; - } - return lg << 0 | rg << 8; -} - -/* - * Set an audio channel's gain. - * - * Returns the new gain, which may be lower than the old gain. - */ - -int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval) -{ - const struct ad1843_gain *gp = ad1843_gain[id]; - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - int lg = (newval >> 0) & mask; - int rg = (newval >> 8) & mask; - int lm = (lg == 0) ? 1 : 0; - int rm = (rg == 0) ? 1 : 0; - - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - if (gp->lmute) - ad1843_write_multi(ad1843, 2, gp->lmute, lm, gp->rmute, rm); - ad1843_write_multi(ad1843, 2, gp->lfield, lg, gp->rfield, rg); - return ad1843_get_gain(ad1843, id); -} - -/* Returns the current recording source */ - -int ad1843_get_recsrc(struct snd_ad1843 *ad1843) -{ - int val = ad1843_read_bits(ad1843, &ad1843_LSS); - - if (val < 0 || val > 2) { - val = 2; - ad1843_write_multi(ad1843, 2, - &ad1843_LSS, val, &ad1843_RSS, val); - } - return val; -} - -/* - * Set recording source. - * - * Returns newsrc on success, -errno on failure. - */ - -int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc) -{ - if (newsrc < 0 || newsrc > 2) - return -EINVAL; - - ad1843_write_multi(ad1843, 2, &ad1843_LSS, newsrc, &ad1843_RSS, newsrc); - return newsrc; -} - -/* Setup ad1843 for D/A conversion. */ - -void ad1843_setup_dac(struct snd_ad1843 *ad1843, - unsigned int id, - unsigned int framerate, - snd_pcm_format_t fmt, - unsigned int channels) -{ - int ad_fmt = 0, ad_mode = 0; - - switch (fmt) { - case SNDRV_PCM_FORMAT_S8: - ad_fmt = 0; - break; - case SNDRV_PCM_FORMAT_U8: - ad_fmt = 0; - break; - case SNDRV_PCM_FORMAT_S16_LE: - ad_fmt = 1; - break; - case SNDRV_PCM_FORMAT_MU_LAW: - ad_fmt = 2; - break; - case SNDRV_PCM_FORMAT_A_LAW: - ad_fmt = 3; - break; - default: - break; - } - - switch (channels) { - case 2: - ad_mode = 0; - break; - case 1: - ad_mode = 1; - break; - default: - break; - } - - if (id) { - ad1843_write_bits(ad1843, &ad1843_C2C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_DA2SM, ad_mode, - &ad1843_DA2F, ad_fmt); - } else { - ad1843_write_bits(ad1843, &ad1843_C1C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_DA1SM, ad_mode, - &ad1843_DA1F, ad_fmt); - } -} - -void ad1843_shutdown_dac(struct snd_ad1843 *ad1843, unsigned int id) -{ - if (id) - ad1843_write_bits(ad1843, &ad1843_DA2F, 1); - else - ad1843_write_bits(ad1843, &ad1843_DA1F, 1); -} - -void ad1843_setup_adc(struct snd_ad1843 *ad1843, - unsigned int framerate, - snd_pcm_format_t fmt, - unsigned int channels) -{ - int da_fmt = 0; - - switch (fmt) { - case SNDRV_PCM_FORMAT_S8: da_fmt = 0; break; - case SNDRV_PCM_FORMAT_U8: da_fmt = 0; break; - case SNDRV_PCM_FORMAT_S16_LE: da_fmt = 1; break; - case SNDRV_PCM_FORMAT_MU_LAW: da_fmt = 2; break; - case SNDRV_PCM_FORMAT_A_LAW: da_fmt = 3; break; - default: break; - } - - ad1843_write_bits(ad1843, &ad1843_C3C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt); -} - -void ad1843_shutdown_adc(struct snd_ad1843 *ad1843) -{ - /* nothing to do */ -} - -/* - * Fully initialize the ad1843. As described in the AD1843 data - * sheet, section "START-UP SEQUENCE". The numbered comments are - * subsection headings from the data sheet. See the data sheet, pages - * 52-54, for more info. - * - * return 0 on success, -errno on failure. */ - -int ad1843_init(struct snd_ad1843 *ad1843) -{ - unsigned long later; - - if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) { - printk(KERN_ERR "ad1843: AD1843 won't initialize\n"); - return -EIO; - } - - ad1843_write_bits(ad1843, &ad1843_SCF, 1); - - /* 4. Put the conversion resources into standby. */ - ad1843_write_bits(ad1843, &ad1843_PDNI, 0); - later = jiffies + msecs_to_jiffies(500); - - while (ad1843_read_bits(ad1843, &ad1843_PDNO)) { - if (time_after(jiffies, later)) { - printk(KERN_ERR - "ad1843: AD1843 won't power up\n"); - return -EIO; - } - schedule_timeout_interruptible(5); - } - - /* 5. Power up the clock generators and enable clock output pins. */ - ad1843_write_multi(ad1843, 3, - &ad1843_C1EN, 1, - &ad1843_C2EN, 1, - &ad1843_C3EN, 1); - - /* 6. Configure conversion resources while they are in standby. */ - - /* DAC1/2 use clock 1/2 as source, ADC uses clock 3. Always. */ - ad1843_write_multi(ad1843, 4, - &ad1843_DA1C, 1, - &ad1843_DA2C, 2, - &ad1843_ADLC, 3, - &ad1843_ADRC, 3); - - /* 7. Enable conversion resources. */ - ad1843_write_bits(ad1843, &ad1843_ADTLK, 1); - ad1843_write_multi(ad1843, 7, - &ad1843_ANAEN, 1, - &ad1843_AAMEN, 1, - &ad1843_DA1EN, 1, - &ad1843_DA2EN, 1, - &ad1843_DDMEN, 1, - &ad1843_ADLEN, 1, - &ad1843_ADREN, 1); - - /* 8. Configure conversion resources while they are enabled. */ - - /* set gain to 0 for all channels */ - ad1843_set_gain(ad1843, AD1843_GAIN_RECLEV, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_LINE, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_LINE_2, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_MIC, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_PCM_0, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_PCM_1, 0); - - /* Unmute all channels. */ - /* DAC1 */ - ad1843_write_multi(ad1843, 2, &ad1843_LDA1GM, 0, &ad1843_RDA1GM, 0); - /* DAC2 */ - ad1843_write_multi(ad1843, 2, &ad1843_LDA2GM, 0, &ad1843_RDA2GM, 0); - - /* Set default recording source to Line In and set - * mic gain to +20 dB. - */ - ad1843_set_recsrc(ad1843, 2); - ad1843_write_multi(ad1843, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1); - - /* Set Speaker Out level to +/- 4V and unmute it. */ - ad1843_write_multi(ad1843, 3, - &ad1843_HPOS, 1, - &ad1843_HPOM, 0, - &ad1843_MPOM, 0); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/mips/au1x00.c b/ANDROID_3.4.5/sound/mips/au1x00.c deleted file mode 100644 index 3f3ec0be..00000000 --- a/ANDROID_3.4.5/sound/mips/au1x00.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Driver for AMD Au1000 MIPS Processor, AC'97 Sound Port - * - * Copyright 2004 Cooper Street Innovations Inc. - * Author: Charles Eidsness <charles@cooper-street.com> - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * History: - * - * 2004-09-09 Charles Eidsness -- Original verion -- based on - * sa11xx-uda1341.c ALSA driver and the - * au1000.c OSS driver. - * 2004-09-09 Matt Porter -- Added support for ALSA 1.0.6 - * - */ - -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/ac97_codec.h> -#include <asm/mach-au1x00/au1000.h> -#include <asm/mach-au1x00/au1000_dma.h> - -MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>"); -MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}"); - -#define PLAYBACK 0 -#define CAPTURE 1 -#define AC97_SLOT_3 0x01 -#define AC97_SLOT_4 0x02 -#define AC97_SLOT_6 0x08 -#define AC97_CMD_IRQ 31 -#define READ 0 -#define WRITE 1 -#define READ_WAIT 2 -#define RW_DONE 3 - -struct au1000_period -{ - u32 start; - u32 relative_end; /*realtive to start of buffer*/ - struct au1000_period * next; -}; - -/*Au1000 AC97 Port Control Reisters*/ -struct au1000_ac97_reg { - u32 volatile config; - u32 volatile status; - u32 volatile data; - u32 volatile cmd; - u32 volatile cntrl; -}; - -struct audio_stream { - struct snd_pcm_substream *substream; - int dma; - spinlock_t dma_lock; - struct au1000_period * buffer; - unsigned int period_size; - unsigned int periods; -}; - -struct snd_au1000 { - struct snd_card *card; - struct au1000_ac97_reg volatile *ac97_ioport; - - struct resource *ac97_res_port; - spinlock_t ac97_lock; - struct snd_ac97 *ac97; - - struct snd_pcm *pcm; - struct audio_stream *stream[2]; /* playback & capture */ -}; - -/*--------------------------- Local Functions --------------------------------*/ -static void -au1000_set_ac97_xmit_slots(struct snd_au1000 *au1000, long xmit_slots) -{ - u32 volatile ac97_config; - - spin_lock(&au1000->ac97_lock); - ac97_config = au1000->ac97_ioport->config; - ac97_config = ac97_config & ~AC97C_XMIT_SLOTS_MASK; - ac97_config |= (xmit_slots << AC97C_XMIT_SLOTS_BIT); - au1000->ac97_ioport->config = ac97_config; - spin_unlock(&au1000->ac97_lock); -} - -static void -au1000_set_ac97_recv_slots(struct snd_au1000 *au1000, long recv_slots) -{ - u32 volatile ac97_config; - - spin_lock(&au1000->ac97_lock); - ac97_config = au1000->ac97_ioport->config; - ac97_config = ac97_config & ~AC97C_RECV_SLOTS_MASK; - ac97_config |= (recv_slots << AC97C_RECV_SLOTS_BIT); - au1000->ac97_ioport->config = ac97_config; - spin_unlock(&au1000->ac97_lock); -} - - -static void -au1000_release_dma_link(struct audio_stream *stream) -{ - struct au1000_period * pointer; - struct au1000_period * pointer_next; - - stream->period_size = 0; - stream->periods = 0; - pointer = stream->buffer; - if (! pointer) - return; - do { - pointer_next = pointer->next; - kfree(pointer); - pointer = pointer_next; - } while (pointer != stream->buffer); - stream->buffer = NULL; -} - -static int -au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes, - unsigned int periods) -{ - struct snd_pcm_substream *substream = stream->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct au1000_period *pointer; - unsigned long dma_start; - int i; - - dma_start = virt_to_phys(runtime->dma_area); - - if (stream->period_size == period_bytes && - stream->periods == periods) - return 0; /* not changed */ - - au1000_release_dma_link(stream); - - stream->period_size = period_bytes; - stream->periods = periods; - - stream->buffer = kmalloc(sizeof(struct au1000_period), GFP_KERNEL); - if (! stream->buffer) - return -ENOMEM; - pointer = stream->buffer; - for (i = 0; i < periods; i++) { - pointer->start = (u32)(dma_start + (i * period_bytes)); - pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1); - if (i < periods - 1) { - pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL); - if (! pointer->next) { - au1000_release_dma_link(stream); - return -ENOMEM; - } - pointer = pointer->next; - } - } - pointer->next = stream->buffer; - return 0; -} - -static void -au1000_dma_stop(struct audio_stream *stream) -{ - if (snd_BUG_ON(!stream->buffer)) - return; - disable_dma(stream->dma); -} - -static void -au1000_dma_start(struct audio_stream *stream) -{ - if (snd_BUG_ON(!stream->buffer)) - return; - - init_dma(stream->dma); - if (get_dma_active_buffer(stream->dma) == 0) { - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - } else { - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - } - enable_dma_buffers(stream->dma); - start_dma(stream->dma); -} - -static irqreturn_t -au1000_dma_interrupt(int irq, void *dev_id) -{ - struct audio_stream *stream = (struct audio_stream *) dev_id; - struct snd_pcm_substream *substream = stream->substream; - - spin_lock(&stream->dma_lock); - switch (get_dma_buffer_done(stream->dma)) { - case DMA_D0: - stream->buffer = stream->buffer->next; - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - enable_dma_buffer0(stream->dma); - break; - case DMA_D1: - stream->buffer = stream->buffer->next; - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - enable_dma_buffer1(stream->dma); - break; - case (DMA_D0 | DMA_D1): - printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma); - au1000_dma_stop(stream); - au1000_dma_start(stream); - break; - case (~DMA_D0 & ~DMA_D1): - printk(KERN_ERR "DMA %d empty irq.\n",stream->dma); - } - spin_unlock(&stream->dma_lock); - snd_pcm_period_elapsed(substream); - return IRQ_HANDLED; -} - -/*-------------------------- PCM Audio Streams -------------------------------*/ - -static unsigned int rates[] = {8000, 11025, 16000, 22050}; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static struct snd_pcm_hardware snd_au1000_hw = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | \ - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050), - .rate_min = 8000, - .rate_max = 22050, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 128*1024, - .period_bytes_min = 32, - .period_bytes_max = 16*1024, - .periods_min = 8, - .periods_max = 255, - .fifo_size = 16, -}; - -static int -snd_au1000_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[PLAYBACK]->substream = substream; - au1000->stream[PLAYBACK]->buffer = NULL; - substream->private_data = au1000->stream[PLAYBACK]; - substream->runtime->hw = snd_au1000_hw; - return (snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); -} - -static int -snd_au1000_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[CAPTURE]->substream = substream; - au1000->stream[CAPTURE]->buffer = NULL; - substream->private_data = au1000->stream[CAPTURE]; - substream->runtime->hw = snd_au1000_hw; - return (snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); -} - -static int -snd_au1000_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[PLAYBACK]->substream = NULL; - return 0; -} - -static int -snd_au1000_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[CAPTURE]->substream = NULL; - return 0; -} - -static int -snd_au1000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct audio_stream *stream = substream->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - return au1000_setup_dma_link(stream, - params_period_bytes(hw_params), - params_periods(hw_params)); -} - -static int -snd_au1000_hw_free(struct snd_pcm_substream *substream) -{ - struct audio_stream *stream = substream->private_data; - au1000_release_dma_link(stream); - return snd_pcm_lib_free_pages(substream); -} - -static int -snd_au1000_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->channels == 1) - au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4); - else - au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4); - snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); - return 0; -} - -static int -snd_au1000_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->channels == 1) - au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4); - else - au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4); - snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - return 0; -} - -static int -snd_au1000_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct audio_stream *stream = substream->private_data; - int err = 0; - - spin_lock(&stream->dma_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - au1000_dma_start(stream); - break; - case SNDRV_PCM_TRIGGER_STOP: - au1000_dma_stop(stream); - break; - default: - err = -EINVAL; - break; - } - spin_unlock(&stream->dma_lock); - return err; -} - -static snd_pcm_uframes_t -snd_au1000_pointer(struct snd_pcm_substream *substream) -{ - struct audio_stream *stream = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - long location; - - spin_lock(&stream->dma_lock); - location = get_dma_residue(stream->dma); - spin_unlock(&stream->dma_lock); - location = stream->buffer->relative_end - location; - if (location == -1) - location = 0; - return bytes_to_frames(runtime,location); -} - -static struct snd_pcm_ops snd_card_au1000_playback_ops = { - .open = snd_au1000_playback_open, - .close = snd_au1000_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_au1000_hw_params, - .hw_free = snd_au1000_hw_free, - .prepare = snd_au1000_playback_prepare, - .trigger = snd_au1000_trigger, - .pointer = snd_au1000_pointer, -}; - -static struct snd_pcm_ops snd_card_au1000_capture_ops = { - .open = snd_au1000_capture_open, - .close = snd_au1000_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_au1000_hw_params, - .hw_free = snd_au1000_hw_free, - .prepare = snd_au1000_capture_prepare, - .trigger = snd_au1000_trigger, - .pointer = snd_au1000_pointer, -}; - -static int __devinit -snd_au1000_pcm_new(struct snd_au1000 *au1000) -{ - struct snd_pcm *pcm; - int err; - unsigned long flags; - - if ((err = snd_pcm_new(au1000->card, "AU1000 AC97 PCM", 0, 1, 1, &pcm)) < 0) - return err; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), 128*1024, 128*1024); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_card_au1000_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_card_au1000_capture_ops); - - pcm->private_data = au1000; - pcm->info_flags = 0; - strcpy(pcm->name, "Au1000 AC97 PCM"); - - spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock); - spin_lock_init(&au1000->stream[CAPTURE]->dma_lock); - - flags = claim_dma_lock(); - if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, - "AC97 TX", au1000_dma_interrupt, 0, - au1000->stream[PLAYBACK])) < 0) { - release_dma_lock(flags); - return -EBUSY; - } - if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, - "AC97 RX", au1000_dma_interrupt, 0, - au1000->stream[CAPTURE])) < 0){ - release_dma_lock(flags); - return -EBUSY; - } - /* enable DMA coherency in read/write DMA channels */ - set_dma_mode(au1000->stream[PLAYBACK]->dma, - get_dma_mode(au1000->stream[PLAYBACK]->dma) & ~DMA_NC); - set_dma_mode(au1000->stream[CAPTURE]->dma, - get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC); - release_dma_lock(flags); - au1000->pcm = pcm; - return 0; -} - - -/*-------------------------- AC97 CODEC Control ------------------------------*/ - -static unsigned short -snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_au1000 *au1000 = ac97->private_data; - u32 volatile cmd; - u16 volatile data; - int i; - - spin_lock(&au1000->ac97_lock); -/* would rather use the interrupt than this polling but it works and I can't -get the interrupt driven case to work efficiently */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) - printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n"); - - cmd = (u32) reg & AC97C_INDEX_MASK; - cmd |= AC97C_READ; - au1000->ac97_ioport->cmd = cmd; - - /* now wait for the data */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) { - printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n"); - spin_unlock(&au1000->ac97_lock); - return 0; - } - - data = au1000->ac97_ioport->cmd & 0xffff; - spin_unlock(&au1000->ac97_lock); - - return data; - -} - - -static void -snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - struct snd_au1000 *au1000 = ac97->private_data; - u32 cmd; - int i; - - spin_lock(&au1000->ac97_lock); -/* would rather use the interrupt than this polling but it works and I can't -get the interrupt driven case to work efficiently */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) - printk(KERN_ERR "au1000 AC97: AC97 command write timeout\n"); - - cmd = (u32) reg & AC97C_INDEX_MASK; - cmd &= ~AC97C_READ; - cmd |= ((u32) val << AC97C_WD_BIT); - au1000->ac97_ioport->cmd = cmd; - spin_unlock(&au1000->ac97_lock); -} - -static int __devinit -snd_au1000_ac97_new(struct snd_au1000 *au1000) -{ - int err; - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_au1000_ac97_write, - .read = snd_au1000_ac97_read, - }; - - if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG), - 0x100000, "Au1x00 AC97")) == NULL) { - snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n"); - return -EBUSY; - } - au1000->ac97_ioport = (struct au1000_ac97_reg *) - KSEG1ADDR(au1000->ac97_res_port->start); - - spin_lock_init(&au1000->ac97_lock); - - /* configure pins for AC'97 - TODO: move to board_setup.c */ - au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC); - - /* Initialise Au1000's AC'97 Control Block */ - au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE; - udelay(10); - au1000->ac97_ioport->cntrl = AC97C_CE; - udelay(10); - - /* Initialise External CODEC -- cold reset */ - au1000->ac97_ioport->config = AC97C_RESET; - udelay(10); - au1000->ac97_ioport->config = 0x0; - mdelay(5); - - /* Initialise AC97 middle-layer */ - if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = au1000; - if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0) - return err; - - return 0; -} - -/*------------------------------ Setup / Destroy ----------------------------*/ - -void -snd_au1000_free(struct snd_card *card) -{ - struct snd_au1000 *au1000 = card->private_data; - - if (au1000->ac97_res_port) { - /* put internal AC97 block into reset */ - au1000->ac97_ioport->cntrl = AC97C_RS; - au1000->ac97_ioport = NULL; - release_and_free_resource(au1000->ac97_res_port); - } - - if (au1000->stream[PLAYBACK]) { - if (au1000->stream[PLAYBACK]->dma >= 0) - free_au1000_dma(au1000->stream[PLAYBACK]->dma); - kfree(au1000->stream[PLAYBACK]); - } - - if (au1000->stream[CAPTURE]) { - if (au1000->stream[CAPTURE]->dma >= 0) - free_au1000_dma(au1000->stream[CAPTURE]->dma); - kfree(au1000->stream[CAPTURE]); - } -} - - -static struct snd_card *au1000_card; - -static int __init -au1000_init(void) -{ - int err; - struct snd_card *card; - struct snd_au1000 *au1000; - - err = snd_card_create(-1, "AC97", THIS_MODULE, - sizeof(struct snd_au1000), &card); - if (err < 0) - return err; - - card->private_free = snd_au1000_free; - au1000 = card->private_data; - au1000->card = card; - - au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - /* so that snd_au1000_free will work as intended */ - au1000->ac97_res_port = NULL; - if (au1000->stream[PLAYBACK]) - au1000->stream[PLAYBACK]->dma = -1; - if (au1000->stream[CAPTURE ]) - au1000->stream[CAPTURE ]->dma = -1; - - if (au1000->stream[PLAYBACK] == NULL || - au1000->stream[CAPTURE ] == NULL) { - snd_card_free(card); - return -ENOMEM; - } - - if ((err = snd_au1000_ac97_new(au1000)) < 0 ) { - snd_card_free(card); - return err; - } - - if ((err = snd_au1000_pcm_new(au1000)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Au1000-AC97"); - strcpy(card->shortname, "AMD Au1000-AC97"); - sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver"); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - printk(KERN_INFO "ALSA AC97: Driver Initialized\n"); - au1000_card = card; - return 0; -} - -static void __exit au1000_exit(void) -{ - snd_card_free(au1000_card); -} - -module_init(au1000_init); -module_exit(au1000_exit); - diff --git a/ANDROID_3.4.5/sound/mips/hal2.c b/ANDROID_3.4.5/sound/mips/hal2.c deleted file mode 100644 index 5f88d1f0..00000000 --- a/ANDROID_3.4.5/sound/mips/hal2.c +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Driver for A2 audio system used in SGI machines - * Copyright (c) 2008 Thomas Bogendoerfer <tsbogend@alpha.fanken.de> - * - * Based on OSS code from Ladislav Michl <ladis@linux-mips.org>, which - * was based on code from Ulf Carlsson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/module.h> - -#include <asm/sgi/hpc3.h> -#include <asm/sgi/ip22.h> - -#include <sound/core.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/pcm-indirect.h> -#include <sound/initval.h> - -#include "hal2.h" - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SGI HAL2 soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SGI HAL2 soundcard."); -MODULE_DESCRIPTION("ALSA driver for SGI HAL2 audio"); -MODULE_AUTHOR("Thomas Bogendoerfer"); -MODULE_LICENSE("GPL"); - - -#define H2_BLOCK_SIZE 1024 -#define H2_BUF_SIZE 16384 - -struct hal2_pbus { - struct hpc3_pbus_dmacregs *pbus; - int pbusnr; - unsigned int ctrl; /* Current state of pbus->pbdma_ctrl */ -}; - -struct hal2_desc { - struct hpc_dma_desc desc; - u32 pad; /* padding */ -}; - -struct hal2_codec { - struct snd_pcm_indirect pcm_indirect; - struct snd_pcm_substream *substream; - - unsigned char *buffer; - dma_addr_t buffer_dma; - struct hal2_desc *desc; - dma_addr_t desc_dma; - int desc_count; - struct hal2_pbus pbus; - int voices; /* mono/stereo */ - unsigned int sample_rate; - unsigned int master; /* Master frequency */ - unsigned short mod; /* MOD value */ - unsigned short inc; /* INC value */ -}; - -#define H2_MIX_OUTPUT_ATT 0 -#define H2_MIX_INPUT_GAIN 1 - -struct snd_hal2 { - struct snd_card *card; - - struct hal2_ctl_regs *ctl_regs; /* HAL2 ctl registers */ - struct hal2_aes_regs *aes_regs; /* HAL2 aes registers */ - struct hal2_vol_regs *vol_regs; /* HAL2 vol registers */ - struct hal2_syn_regs *syn_regs; /* HAL2 syn registers */ - - struct hal2_codec dac; - struct hal2_codec adc; -}; - -#define H2_INDIRECT_WAIT(regs) while (hal2_read(®s->isr) & H2_ISR_TSTATUS); - -#define H2_READ_ADDR(addr) (addr | (1<<7)) -#define H2_WRITE_ADDR(addr) (addr) - -static inline u32 hal2_read(u32 *reg) -{ - return __raw_readl(reg); -} - -static inline void hal2_write(u32 val, u32 *reg) -{ - __raw_writel(val, reg); -} - - -static u32 hal2_i_read32(struct snd_hal2 *hal2, u16 addr) -{ - u32 ret; - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - ret = hal2_read(®s->idr0) & 0xffff; - hal2_write(H2_READ_ADDR(addr) | 0x1, ®s->iar); - H2_INDIRECT_WAIT(regs); - ret |= (hal2_read(®s->idr0) & 0xffff) << 16; - return ret; -} - -static void hal2_i_write16(struct snd_hal2 *hal2, u16 addr, u16 val) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(val, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_write32(struct snd_hal2 *hal2, u16 addr, u32 val) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(val & 0xffff, ®s->idr0); - hal2_write(val >> 16, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_setbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - hal2_write((hal2_read(®s->idr0) & 0xffff) | bit, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_clearbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - hal2_write((hal2_read(®s->idr0) & 0xffff) & ~bit, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static int hal2_gain_info(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; - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - uinfo->value.integer.max = 31; - break; - case H2_MIX_INPUT_GAIN: - uinfo->value.integer.max = 15; - break; - } - return 0; -} - -static int hal2_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); - u32 tmp; - int l, r; - - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - tmp = hal2_i_read32(hal2, H2I_DAC_C2); - if (tmp & H2I_C2_MUTE) { - l = 0; - r = 0; - } else { - l = 31 - ((tmp >> H2I_C2_L_ATT_SHIFT) & 31); - r = 31 - ((tmp >> H2I_C2_R_ATT_SHIFT) & 31); - } - break; - case H2_MIX_INPUT_GAIN: - tmp = hal2_i_read32(hal2, H2I_ADC_C2); - l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15; - r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15; - break; - } - ucontrol->value.integer.value[0] = l; - ucontrol->value.integer.value[1] = r; - - return 0; -} - -static int hal2_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); - u32 old, new; - int l, r; - - l = ucontrol->value.integer.value[0]; - r = ucontrol->value.integer.value[1]; - - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - old = hal2_i_read32(hal2, H2I_DAC_C2); - new = old & ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); - if (l | r) { - l = 31 - l; - r = 31 - r; - new |= (l << H2I_C2_L_ATT_SHIFT); - new |= (r << H2I_C2_R_ATT_SHIFT); - } else - new |= H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE; - hal2_i_write32(hal2, H2I_DAC_C2, new); - break; - case H2_MIX_INPUT_GAIN: - old = hal2_i_read32(hal2, H2I_ADC_C2); - new = old & ~(H2I_C2_L_GAIN_M | H2I_C2_R_GAIN_M); - new |= (l << H2I_C2_L_GAIN_SHIFT); - new |= (r << H2I_C2_R_GAIN_SHIFT); - hal2_i_write32(hal2, H2I_ADC_C2, new); - break; - } - return old != new; -} - -static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = H2_MIX_OUTPUT_ATT, - .info = hal2_gain_info, - .get = hal2_gain_get, - .put = hal2_gain_put, -}; - -static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = H2_MIX_INPUT_GAIN, - .info = hal2_gain_info, - .get = hal2_gain_get, - .put = hal2_gain_put, -}; - -static int __devinit hal2_mixer_create(struct snd_hal2 *hal2) -{ - int err; - - /* mute DAC */ - hal2_i_write32(hal2, H2I_DAC_C2, - H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); - /* mute ADC */ - hal2_i_write32(hal2, H2I_ADC_C2, 0); - - err = snd_ctl_add(hal2->card, - snd_ctl_new1(&hal2_ctrl_headphone, hal2)); - if (err < 0) - return err; - - err = snd_ctl_add(hal2->card, - snd_ctl_new1(&hal2_ctrl_mic, hal2)); - if (err < 0) - return err; - - return 0; -} - -static irqreturn_t hal2_interrupt(int irq, void *dev_id) -{ - struct snd_hal2 *hal2 = dev_id; - irqreturn_t ret = IRQ_NONE; - - /* decide what caused this interrupt */ - if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { - snd_pcm_period_elapsed(hal2->dac.substream); - ret = IRQ_HANDLED; - } - if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { - snd_pcm_period_elapsed(hal2->adc.substream); - ret = IRQ_HANDLED; - } - return ret; -} - -static int hal2_compute_rate(struct hal2_codec *codec, unsigned int rate) -{ - unsigned short mod; - - if (44100 % rate < 48000 % rate) { - mod = 4 * 44100 / rate; - codec->master = 44100; - } else { - mod = 4 * 48000 / rate; - codec->master = 48000; - } - - codec->inc = 4; - codec->mod = mod; - rate = 4 * codec->master / mod; - - return rate; -} - -static void hal2_set_dac_rate(struct snd_hal2 *hal2) -{ - unsigned int master = hal2->dac.master; - int inc = hal2->dac.inc; - int mod = hal2->dac.mod; - - hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0); - hal2_i_write32(hal2, H2I_BRES1_C2, - ((0xffff & (inc - mod - 1)) << 16) | inc); -} - -static void hal2_set_adc_rate(struct snd_hal2 *hal2) -{ - unsigned int master = hal2->adc.master; - int inc = hal2->adc.inc; - int mod = hal2->adc.mod; - - hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0); - hal2_i_write32(hal2, H2I_BRES2_C2, - ((0xffff & (inc - mod - 1)) << 16) | inc); -} - -static void hal2_setup_dac(struct snd_hal2 *hal2) -{ - unsigned int fifobeg, fifoend, highwater, sample_size; - struct hal2_pbus *pbus = &hal2->dac.pbus; - - /* Now we set up some PBUS information. The PBUS needs information about - * what portion of the fifo it will use. If it's receiving or - * transmitting, and finally whether the stream is little endian or big - * endian. The information is written later, on the start call. - */ - sample_size = 2 * hal2->dac.voices; - /* Fifo should be set to hold exactly four samples. Highwater mark - * should be set to two samples. */ - highwater = (sample_size * 2) >> 1; /* halfwords */ - fifobeg = 0; /* playback is first */ - fifoend = (sample_size * 4) >> 3; /* doublewords */ - pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD | - (highwater << 8) | (fifobeg << 16) | (fifoend << 24); - /* We disable everything before we do anything at all */ - pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); - /* Setup the HAL2 for playback */ - hal2_set_dac_rate(hal2); - /* Set endianess */ - hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX); - /* Set DMA bus */ - hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); - /* We are using 1st Bresenham clock generator for playback */ - hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) - | (1 << H2I_C1_CLKID_SHIFT) - | (hal2->dac.voices << H2I_C1_DATAT_SHIFT)); -} - -static void hal2_setup_adc(struct snd_hal2 *hal2) -{ - unsigned int fifobeg, fifoend, highwater, sample_size; - struct hal2_pbus *pbus = &hal2->adc.pbus; - - sample_size = 2 * hal2->adc.voices; - highwater = (sample_size * 2) >> 1; /* halfwords */ - fifobeg = (4 * 4) >> 3; /* record is second */ - fifoend = (4 * 4 + sample_size * 4) >> 3; /* doublewords */ - pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD | - (highwater << 8) | (fifobeg << 16) | (fifoend << 24); - pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); - /* Setup the HAL2 for record */ - hal2_set_adc_rate(hal2); - /* Set endianess */ - hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR); - /* Set DMA bus */ - hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); - /* We are using 2nd Bresenham clock generator for record */ - hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) - | (2 << H2I_C1_CLKID_SHIFT) - | (hal2->adc.voices << H2I_C1_DATAT_SHIFT)); -} - -static void hal2_start_dac(struct snd_hal2 *hal2) -{ - struct hal2_pbus *pbus = &hal2->dac.pbus; - - pbus->pbus->pbdma_dptr = hal2->dac.desc_dma; - pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; - /* enable DAC */ - hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); -} - -static void hal2_start_adc(struct snd_hal2 *hal2) -{ - struct hal2_pbus *pbus = &hal2->adc.pbus; - - pbus->pbus->pbdma_dptr = hal2->adc.desc_dma; - pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; - /* enable ADC */ - hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); -} - -static inline void hal2_stop_dac(struct snd_hal2 *hal2) -{ - hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - /* The HAL2 itself may remain enabled safely */ -} - -static inline void hal2_stop_adc(struct snd_hal2 *hal2) -{ - hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; -} - -static int hal2_alloc_dmabuf(struct hal2_codec *codec) -{ - struct hal2_desc *desc; - dma_addr_t desc_dma, buffer_dma; - int count = H2_BUF_SIZE / H2_BLOCK_SIZE; - int i; - - codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE, - &buffer_dma, GFP_KERNEL); - if (!codec->buffer) - return -ENOMEM; - desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc), - &desc_dma, GFP_KERNEL); - if (!desc) { - dma_free_noncoherent(NULL, H2_BUF_SIZE, - codec->buffer, buffer_dma); - return -ENOMEM; - } - codec->buffer_dma = buffer_dma; - codec->desc_dma = desc_dma; - codec->desc = desc; - for (i = 0; i < count; i++) { - desc->desc.pbuf = buffer_dma + i * H2_BLOCK_SIZE; - desc->desc.cntinfo = HPCDMA_XIE | H2_BLOCK_SIZE; - desc->desc.pnext = (i == count - 1) ? - desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc); - desc++; - } - dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc), - DMA_TO_DEVICE); - codec->desc_count = count; - return 0; -} - -static void hal2_free_dmabuf(struct hal2_codec *codec) -{ - dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc), - codec->desc, codec->desc_dma); - dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer, - codec->buffer_dma); -} - -static struct snd_pcm_hardware hal2_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 1024, - .period_bytes_max = 65536, - .periods_min = 2, - .periods_max = 1024, -}; - -static int hal2_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int err; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - return err; - - return 0; -} - -static int hal2_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int hal2_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - int err; - - runtime->hw = hal2_pcm_hw; - - err = hal2_alloc_dmabuf(&hal2->dac); - if (err) - return err; - return 0; -} - -static int hal2_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - hal2_free_dmabuf(&hal2->dac); - return 0; -} - -static int hal2_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct hal2_codec *dac = &hal2->dac; - - dac->voices = runtime->channels; - dac->sample_rate = hal2_compute_rate(dac, runtime->rate); - memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); - dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; - dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - dac->substream = substream; - hal2_setup_dac(hal2); - return 0; -} - -static int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma; - hal2->dac.pcm_indirect.hw_data = 0; - substream->ops->ack(substream); - hal2_start_dac(hal2); - break; - case SNDRV_PCM_TRIGGER_STOP: - hal2_stop_dac(hal2); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t -hal2_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *dac = &hal2->dac; - - return snd_pcm_indirect_playback_pointer(substream, &dac->pcm_indirect, - dac->pbus.pbus->pbdma_bptr); -} - -static void hal2_playback_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - unsigned char *buf = hal2->dac.buffer + rec->hw_data; - - memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes); - dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE); - -} - -static int hal2_playback_ack(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *dac = &hal2->dac; - - dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; - snd_pcm_indirect_playback_transfer(substream, - &dac->pcm_indirect, - hal2_playback_transfer); - return 0; -} - -static int hal2_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - int err; - - runtime->hw = hal2_pcm_hw; - - err = hal2_alloc_dmabuf(adc); - if (err) - return err; - return 0; -} - -static int hal2_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - hal2_free_dmabuf(&hal2->adc); - return 0; -} - -static int hal2_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct hal2_codec *adc = &hal2->adc; - - adc->voices = runtime->channels; - adc->sample_rate = hal2_compute_rate(adc, runtime->rate); - memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); - adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; - adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; - adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - adc->substream = substream; - hal2_setup_adc(hal2); - return 0; -} - -static int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma; - hal2->adc.pcm_indirect.hw_data = 0; - printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma); - hal2_start_adc(hal2); - break; - case SNDRV_PCM_TRIGGER_STOP: - hal2_stop_adc(hal2); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t -hal2_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - - return snd_pcm_indirect_capture_pointer(substream, &adc->pcm_indirect, - adc->pbus.pbus->pbdma_bptr); -} - -static void hal2_capture_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - unsigned char *buf = hal2->adc.buffer + rec->hw_data; - - dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE); - memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes); -} - -static int hal2_capture_ack(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - - snd_pcm_indirect_capture_transfer(substream, - &adc->pcm_indirect, - hal2_capture_transfer); - return 0; -} - -static struct snd_pcm_ops hal2_playback_ops = { - .open = hal2_playback_open, - .close = hal2_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = hal2_pcm_hw_params, - .hw_free = hal2_pcm_hw_free, - .prepare = hal2_playback_prepare, - .trigger = hal2_playback_trigger, - .pointer = hal2_playback_pointer, - .ack = hal2_playback_ack, -}; - -static struct snd_pcm_ops hal2_capture_ops = { - .open = hal2_capture_open, - .close = hal2_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = hal2_pcm_hw_params, - .hw_free = hal2_pcm_hw_free, - .prepare = hal2_capture_prepare, - .trigger = hal2_capture_trigger, - .pointer = hal2_capture_pointer, - .ack = hal2_capture_ack, -}; - -static int __devinit hal2_pcm_create(struct snd_hal2 *hal2) -{ - struct snd_pcm *pcm; - int err; - - /* create first pcm device with one outputs and one input */ - err = snd_pcm_new(hal2->card, "SGI HAL2 Audio", 0, 1, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = hal2; - strcpy(pcm->name, "SGI HAL2"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &hal2_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &hal2_capture_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 1024 * 1024); - - return 0; -} - -static int hal2_dev_free(struct snd_device *device) -{ - struct snd_hal2 *hal2 = device->device_data; - - free_irq(SGI_HPCDMA_IRQ, hal2); - kfree(hal2); - return 0; -} - -static struct snd_device_ops hal2_ops = { - .dev_free = hal2_dev_free, -}; - -static void hal2_init_codec(struct hal2_codec *codec, struct hpc3_regs *hpc3, - int index) -{ - codec->pbus.pbusnr = index; - codec->pbus.pbus = &hpc3->pbdma[index]; -} - -static int hal2_detect(struct snd_hal2 *hal2) -{ - unsigned short board, major, minor; - unsigned short rev; - - /* reset HAL2 */ - hal2_write(0, &hal2->ctl_regs->isr); - - /* release reset */ - hal2_write(H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N, - &hal2->ctl_regs->isr); - - - hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE); - rev = hal2_read(&hal2->ctl_regs->rev); - if (rev & H2_REV_AUDIO_PRESENT) - return -ENODEV; - - board = (rev & H2_REV_BOARD_M) >> 12; - major = (rev & H2_REV_MAJOR_CHIP_M) >> 4; - minor = (rev & H2_REV_MINOR_CHIP_M); - - printk(KERN_INFO "SGI HAL2 revision %i.%i.%i\n", - board, major, minor); - - return 0; -} - -static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip) -{ - struct snd_hal2 *hal2; - struct hpc3_regs *hpc3 = hpc3c0; - int err; - - hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL); - if (!hal2) - return -ENOMEM; - - hal2->card = card; - - if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED, - "SGI HAL2", hal2)) { - printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ); - kfree(hal2); - return -EAGAIN; - } - - hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0]; - hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1]; - hal2->vol_regs = (struct hal2_vol_regs *)hpc3->pbus_extregs[2]; - hal2->syn_regs = (struct hal2_syn_regs *)hpc3->pbus_extregs[3]; - - if (hal2_detect(hal2) < 0) { - kfree(hal2); - return -ENODEV; - } - - hal2_init_codec(&hal2->dac, hpc3, 0); - hal2_init_codec(&hal2->adc, hpc3, 1); - - /* - * All DMA channel interfaces in HAL2 are designed to operate with - * PBUS programmed for 2 cycles in D3, 2 cycles in D4 and 2 cycles - * in D5. HAL2 is a 16-bit device which can accept both big and little - * endian format. It assumes that even address bytes are on high - * portion of PBUS (15:8) and assumes that HPC3 is programmed to - * accept a live (unsynchronized) version of P_DREQ_N from HAL2. - */ -#define HAL2_PBUS_DMACFG ((0 << HPC3_DMACFG_D3R_SHIFT) | \ - (2 << HPC3_DMACFG_D4R_SHIFT) | \ - (2 << HPC3_DMACFG_D5R_SHIFT) | \ - (0 << HPC3_DMACFG_D3W_SHIFT) | \ - (2 << HPC3_DMACFG_D4W_SHIFT) | \ - (2 << HPC3_DMACFG_D5W_SHIFT) | \ - HPC3_DMACFG_DS16 | \ - HPC3_DMACFG_EVENHI | \ - HPC3_DMACFG_RTIME | \ - (8 << HPC3_DMACFG_BURST_SHIFT) | \ - HPC3_DMACFG_DRQLIVE) - /* - * Ignore what's mentioned in the specification and write value which - * works in The Real World (TM) - */ - hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844; - hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hal2, &hal2_ops); - if (err < 0) { - free_irq(SGI_HPCDMA_IRQ, hal2); - kfree(hal2); - return err; - } - *rchip = hal2; - return 0; -} - -static int __devinit hal2_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct snd_hal2 *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = hal2_create(card, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - - err = hal2_pcm_create(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - err = hal2_mixer_create(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "SGI HAL2 Audio"); - strcpy(card->shortname, "SGI HAL2 Audio"); - sprintf(card->longname, "%s irq %i", - card->shortname, - SGI_HPCDMA_IRQ); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pdev, card); - return 0; -} - -static int __devexit hal2_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_card_free(card); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver hal2_driver = { - .probe = hal2_probe, - .remove = __devexit_p(hal2_remove), - .driver = { - .name = "sgihal2", - .owner = THIS_MODULE, - } -}; - -module_platform_driver(hal2_driver); diff --git a/ANDROID_3.4.5/sound/mips/hal2.h b/ANDROID_3.4.5/sound/mips/hal2.h deleted file mode 100644 index f19828bc..00000000 --- a/ANDROID_3.4.5/sound/mips/hal2.h +++ /dev/null @@ -1,245 +0,0 @@ -#ifndef __HAL2_H -#define __HAL2_H - -/* - * Driver for HAL2 sound processors - * Copyright (c) 1999 Ulf Carlsson <ulfc@bun.falkenberg.se> - * Copyright (c) 2001, 2002, 2003 Ladislav Michl <ladis@linux-mips.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/types.h> - -/* Indirect status register */ - -#define H2_ISR_TSTATUS 0x01 /* RO: transaction status 1=busy */ -#define H2_ISR_USTATUS 0x02 /* RO: utime status bit 1=armed */ -#define H2_ISR_QUAD_MODE 0x04 /* codec mode 0=indigo 1=quad */ -#define H2_ISR_GLOBAL_RESET_N 0x08 /* chip global reset 0=reset */ -#define H2_ISR_CODEC_RESET_N 0x10 /* codec/synth reset 0=reset */ - -/* Revision register */ - -#define H2_REV_AUDIO_PRESENT 0x8000 /* RO: audio present 0=present */ -#define H2_REV_BOARD_M 0x7000 /* RO: bits 14:12, board revision */ -#define H2_REV_MAJOR_CHIP_M 0x00F0 /* RO: bits 7:4, major chip revision */ -#define H2_REV_MINOR_CHIP_M 0x000F /* RO: bits 3:0, minor chip revision */ - -/* Indirect address register */ - -/* - * Address of indirect internal register to be accessed. A write to this - * register initiates read or write access to the indirect registers in the - * HAL2. Note that there af four indirect data registers for write access to - * registers larger than 16 byte. - */ - -#define H2_IAR_TYPE_M 0xF000 /* bits 15:12, type of functional */ - /* block the register resides in */ - /* 1=DMA Port */ - /* 9=Global DMA Control */ - /* 2=Bresenham */ - /* 3=Unix Timer */ -#define H2_IAR_NUM_M 0x0F00 /* bits 11:8 instance of the */ - /* blockin which the indirect */ - /* register resides */ - /* If IAR_TYPE_M=DMA Port: */ - /* 1=Synth In */ - /* 2=AES In */ - /* 3=AES Out */ - /* 4=DAC Out */ - /* 5=ADC Out */ - /* 6=Synth Control */ - /* If IAR_TYPE_M=Global DMA Control: */ - /* 1=Control */ - /* If IAR_TYPE_M=Bresenham: */ - /* 1=Bresenham Clock Gen 1 */ - /* 2=Bresenham Clock Gen 2 */ - /* 3=Bresenham Clock Gen 3 */ - /* If IAR_TYPE_M=Unix Timer: */ - /* 1=Unix Timer */ -#define H2_IAR_ACCESS_SELECT 0x0080 /* 1=read 0=write */ -#define H2_IAR_PARAM 0x000C /* Parameter Select */ -#define H2_IAR_RB_INDEX_M 0x0003 /* Read Back Index */ - /* 00:word0 */ - /* 01:word1 */ - /* 10:word2 */ - /* 11:word3 */ -/* - * HAL2 internal addressing - * - * The HAL2 has "indirect registers" (idr) which are accessed by writing to the - * Indirect Data registers. Write the address to the Indirect Address register - * to transfer the data. - * - * We define the H2IR_* to the read address and H2IW_* to the write address and - * H2I_* to be fields in whatever register is referred to. - * - * When we write to indirect registers which are larger than one word (16 bit) - * we have to fill more than one indirect register before writing. When we read - * back however we have to read several times, each time with different Read - * Back Indexes (there are defs for doing this easily). - */ - -/* - * Relay Control - */ -#define H2I_RELAY_C 0x9100 -#define H2I_RELAY_C_STATE 0x01 /* state of RELAY pin signal */ - -/* DMA port enable */ - -#define H2I_DMA_PORT_EN 0x9104 -#define H2I_DMA_PORT_EN_SY_IN 0x01 /* Synth_in DMA port */ -#define H2I_DMA_PORT_EN_AESRX 0x02 /* AES receiver DMA port */ -#define H2I_DMA_PORT_EN_AESTX 0x04 /* AES transmitter DMA port */ -#define H2I_DMA_PORT_EN_CODECTX 0x08 /* CODEC transmit DMA port */ -#define H2I_DMA_PORT_EN_CODECR 0x10 /* CODEC receive DMA port */ - -#define H2I_DMA_END 0x9108 /* global dma endian select */ -#define H2I_DMA_END_SY_IN 0x01 /* Synth_in DMA port */ -#define H2I_DMA_END_AESRX 0x02 /* AES receiver DMA port */ -#define H2I_DMA_END_AESTX 0x04 /* AES transmitter DMA port */ -#define H2I_DMA_END_CODECTX 0x08 /* CODEC transmit DMA port */ -#define H2I_DMA_END_CODECR 0x10 /* CODEC receive DMA port */ - /* 0=b_end 1=l_end */ - -#define H2I_DMA_DRV 0x910C /* global PBUS DMA enable */ - -#define H2I_SYNTH_C 0x1104 /* Synth DMA control */ - -#define H2I_AESRX_C 0x1204 /* AES RX dma control */ - -#define H2I_C_TS_EN 0x20 /* Timestamp enable */ -#define H2I_C_TS_FRMT 0x40 /* Timestamp format */ -#define H2I_C_NAUDIO 0x80 /* Sign extend */ - -/* AESRX CTL, 16 bit */ - -#define H2I_AESTX_C 0x1304 /* AES TX DMA control */ -#define H2I_AESTX_C_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */ -#define H2I_AESTX_C_CLKID_M 0x18 -#define H2I_AESTX_C_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */ -#define H2I_AESTX_C_DATAT_M 0x300 - -/* CODEC registers */ - -#define H2I_DAC_C1 0x1404 /* DAC DMA control, 16 bit */ -#define H2I_DAC_C2 0x1408 /* DAC DMA control, 32 bit */ -#define H2I_ADC_C1 0x1504 /* ADC DMA control, 16 bit */ -#define H2I_ADC_C2 0x1508 /* ADC DMA control, 32 bit */ - -/* Bits in CTL1 register */ - -#define H2I_C1_DMA_SHIFT 0 /* DMA channel */ -#define H2I_C1_DMA_M 0x7 -#define H2I_C1_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */ -#define H2I_C1_CLKID_M 0x18 -#define H2I_C1_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */ -#define H2I_C1_DATAT_M 0x300 - -/* Bits in CTL2 register */ - -#define H2I_C2_R_GAIN_SHIFT 0 /* right a/d input gain */ -#define H2I_C2_R_GAIN_M 0xf -#define H2I_C2_L_GAIN_SHIFT 4 /* left a/d input gain */ -#define H2I_C2_L_GAIN_M 0xf0 -#define H2I_C2_R_SEL 0x100 /* right input select */ -#define H2I_C2_L_SEL 0x200 /* left input select */ -#define H2I_C2_MUTE 0x400 /* mute */ -#define H2I_C2_DO1 0x00010000 /* digital output port bit 0 */ -#define H2I_C2_DO2 0x00020000 /* digital output port bit 1 */ -#define H2I_C2_R_ATT_SHIFT 18 /* right d/a output - */ -#define H2I_C2_R_ATT_M 0x007c0000 /* attenuation */ -#define H2I_C2_L_ATT_SHIFT 23 /* left d/a output - */ -#define H2I_C2_L_ATT_M 0x0f800000 /* attenuation */ - -#define H2I_SYNTH_MAP_C 0x1104 /* synth dma handshake ctrl */ - -/* Clock generator CTL 1, 16 bit */ - -#define H2I_BRES1_C1 0x2104 -#define H2I_BRES2_C1 0x2204 -#define H2I_BRES3_C1 0x2304 - -#define H2I_BRES_C1_SHIFT 0 /* 0=48.0 1=44.1 2=aes_rx */ -#define H2I_BRES_C1_M 0x03 - -/* Clock generator CTL 2, 32 bit */ - -#define H2I_BRES1_C2 0x2108 -#define H2I_BRES2_C2 0x2208 -#define H2I_BRES3_C2 0x2308 - -#define H2I_BRES_C2_INC_SHIFT 0 /* increment value */ -#define H2I_BRES_C2_INC_M 0xffff -#define H2I_BRES_C2_MOD_SHIFT 16 /* modcontrol value */ -#define H2I_BRES_C2_MOD_M 0xffff0000 /* modctrl=0xffff&(modinc-1) */ - -/* Unix timer, 64 bit */ - -#define H2I_UTIME 0x3104 -#define H2I_UTIME_0_LD 0xffff /* microseconds, LSB's */ -#define H2I_UTIME_1_LD0 0x0f /* microseconds, MSB's */ -#define H2I_UTIME_1_LD1 0xf0 /* tenths of microseconds */ -#define H2I_UTIME_2_LD 0xffff /* seconds, LSB's */ -#define H2I_UTIME_3_LD 0xffff /* seconds, MSB's */ - -struct hal2_ctl_regs { - u32 _unused0[4]; - u32 isr; /* 0x10 Status Register */ - u32 _unused1[3]; - u32 rev; /* 0x20 Revision Register */ - u32 _unused2[3]; - u32 iar; /* 0x30 Indirect Address Register */ - u32 _unused3[3]; - u32 idr0; /* 0x40 Indirect Data Register 0 */ - u32 _unused4[3]; - u32 idr1; /* 0x50 Indirect Data Register 1 */ - u32 _unused5[3]; - u32 idr2; /* 0x60 Indirect Data Register 2 */ - u32 _unused6[3]; - u32 idr3; /* 0x70 Indirect Data Register 3 */ -}; - -struct hal2_aes_regs { - u32 rx_stat[2]; /* Status registers */ - u32 rx_cr[2]; /* Control registers */ - u32 rx_ud[4]; /* User data window */ - u32 rx_st[24]; /* Channel status data */ - - u32 tx_stat[1]; /* Status register */ - u32 tx_cr[3]; /* Control registers */ - u32 tx_ud[4]; /* User data window */ - u32 tx_st[24]; /* Channel status data */ -}; - -struct hal2_vol_regs { - u32 right; /* Right volume */ - u32 left; /* Left volume */ -}; - -struct hal2_syn_regs { - u32 _unused0[2]; - u32 page; /* DOC Page register */ - u32 regsel; /* DOC Register selection */ - u32 dlow; /* DOC Data low */ - u32 dhigh; /* DOC Data high */ - u32 irq; /* IRQ Status */ - u32 dram; /* DRAM Access */ -}; - -#endif /* __HAL2_H */ diff --git a/ANDROID_3.4.5/sound/mips/sgio2audio.c b/ANDROID_3.4.5/sound/mips/sgio2audio.c deleted file mode 100644 index ceaa593e..00000000 --- a/ANDROID_3.4.5/sound/mips/sgio2audio.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * Sound driver for Silicon Graphics O2 Workstations A/V board audio. - * - * Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org> - * Copyright 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de> - * Mxier part taken from mace_audio.c: - * Copyright 2007 Thorben Jändling <tj.trevelyan@gmail.com> - * - * 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/delay.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/module.h> - -#include <asm/ip32/ip32_ints.h> -#include <asm/ip32/mace.h> - -#include <sound/core.h> -#include <sound/control.h> -#include <sound/pcm.h> -#define SNDRV_GET_ID -#include <sound/initval.h> -#include <sound/ad1843.h> - - -MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org>"); -MODULE_DESCRIPTION("SGI O2 Audio"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Silicon Graphics, O2 Audio}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SGI O2 soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SGI O2 soundcard."); - - -#define AUDIO_CONTROL_RESET BIT(0) /* 1: reset audio interface */ -#define AUDIO_CONTROL_CODEC_PRESENT BIT(1) /* 1: codec detected */ - -#define CODEC_CONTROL_WORD_SHIFT 0 -#define CODEC_CONTROL_READ BIT(16) -#define CODEC_CONTROL_ADDRESS_SHIFT 17 - -#define CHANNEL_CONTROL_RESET BIT(10) /* 1: reset channel */ -#define CHANNEL_DMA_ENABLE BIT(9) /* 1: enable DMA transfer */ -#define CHANNEL_INT_THRESHOLD_DISABLED (0 << 5) /* interrupt disabled */ -#define CHANNEL_INT_THRESHOLD_25 (1 << 5) /* int on buffer >25% full */ -#define CHANNEL_INT_THRESHOLD_50 (2 << 5) /* int on buffer >50% full */ -#define CHANNEL_INT_THRESHOLD_75 (3 << 5) /* int on buffer >75% full */ -#define CHANNEL_INT_THRESHOLD_EMPTY (4 << 5) /* int on buffer empty */ -#define CHANNEL_INT_THRESHOLD_NOT_EMPTY (5 << 5) /* int on buffer !empty */ -#define CHANNEL_INT_THRESHOLD_FULL (6 << 5) /* int on buffer empty */ -#define CHANNEL_INT_THRESHOLD_NOT_FULL (7 << 5) /* int on buffer !empty */ - -#define CHANNEL_RING_SHIFT 12 -#define CHANNEL_RING_SIZE (1 << CHANNEL_RING_SHIFT) -#define CHANNEL_RING_MASK (CHANNEL_RING_SIZE - 1) - -#define CHANNEL_LEFT_SHIFT 40 -#define CHANNEL_RIGHT_SHIFT 8 - -struct snd_sgio2audio_chan { - int idx; - struct snd_pcm_substream *substream; - int pos; - snd_pcm_uframes_t size; - spinlock_t lock; -}; - -/* definition of the chip-specific record */ -struct snd_sgio2audio { - struct snd_card *card; - - /* codec */ - struct snd_ad1843 ad1843; - spinlock_t ad1843_lock; - - /* channels */ - struct snd_sgio2audio_chan channel[3]; - - /* resources */ - void *ring_base; - dma_addr_t ring_base_dma; -}; - -/* AD1843 access */ - -/* - * read_ad1843_reg returns the current contents of a 16 bit AD1843 register. - * - * Returns unsigned register value on success, -errno on failure. - */ -static int read_ad1843_reg(void *priv, int reg) -{ - struct snd_sgio2audio *chip = priv; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->ad1843_lock, flags); - - writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | - CODEC_CONTROL_READ, &mace->perif.audio.codec_control); - wmb(); - val = readq(&mace->perif.audio.codec_control); /* flush bus */ - udelay(200); - - val = readq(&mace->perif.audio.codec_read); - - spin_unlock_irqrestore(&chip->ad1843_lock, flags); - return val; -} - -/* - * write_ad1843_reg writes the specified value to a 16 bit AD1843 register. - */ -static int write_ad1843_reg(void *priv, int reg, int word) -{ - struct snd_sgio2audio *chip = priv; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->ad1843_lock, flags); - - writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | - (word << CODEC_CONTROL_WORD_SHIFT), - &mace->perif.audio.codec_control); - wmb(); - val = readq(&mace->perif.audio.codec_control); /* flush bus */ - udelay(200); - - spin_unlock_irqrestore(&chip->ad1843_lock, flags); - return 0; -} - -static int sgio2audio_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ad1843_get_gain_max(&chip->ad1843, - (int)kcontrol->private_value); - return 0; -} - -static int sgio2audio_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int vol; - - vol = ad1843_get_gain(&chip->ad1843, (int)kcontrol->private_value); - - ucontrol->value.integer.value[0] = (vol >> 8) & 0xFF; - ucontrol->value.integer.value[1] = vol & 0xFF; - - return 0; -} - -static int sgio2audio_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int newvol, oldvol; - - oldvol = ad1843_get_gain(&chip->ad1843, kcontrol->private_value); - newvol = (ucontrol->value.integer.value[0] << 8) | - ucontrol->value.integer.value[1]; - - newvol = ad1843_set_gain(&chip->ad1843, kcontrol->private_value, - newvol); - - return newvol != oldvol; -} - -static int sgio2audio_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "Cam Mic", "Mic", "Line" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= 3) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int sgio2audio_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ad1843_get_recsrc(&chip->ad1843); - return 0; -} - -static int sgio2audio_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int newsrc, oldsrc; - - oldsrc = ad1843_get_recsrc(&chip->ad1843); - newsrc = ad1843_set_recsrc(&chip->ad1843, - ucontrol->value.enumerated.item[0]); - - return newsrc != oldsrc; -} - -/* dac1/pcm0 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_PCM_0, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* dac2/pcm1 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_PCM_1, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* record level mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_RECLEV, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* record level source control */ -static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = sgio2audio_source_info, - .get = sgio2audio_source_get, - .put = sgio2audio_source_put, -}; - -/* line mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Volume", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_LINE, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* cd mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_LINE_2, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* mic mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_MIC, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - - -static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip) -{ - int err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_pcm0, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_pcm1, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_reclevel, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_recsource, chip)); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_line, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_cd, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_mic, chip)); - if (err < 0) - return err; - - return 0; -} - -/* low-level audio interface DMA */ - -/* get data out of bounce buffer, count must be a multiple of 32 */ -/* returns 1 if a period has elapsed */ -static int snd_sgio2audio_dma_pull_frag(struct snd_sgio2audio *chip, - unsigned int ch, unsigned int count) -{ - int ret; - unsigned long src_base, src_pos, dst_mask; - unsigned char *dst_base; - int dst_pos; - u64 *src; - s16 *dst; - u64 x; - unsigned long flags; - struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - src_base = (unsigned long) chip->ring_base | (ch << CHANNEL_RING_SHIFT); - src_pos = readq(&mace->perif.audio.chan[ch].read_ptr); - dst_base = runtime->dma_area; - dst_pos = chip->channel[ch].pos; - dst_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; - - /* check if a period has elapsed */ - chip->channel[ch].size += (count >> 3); /* in frames */ - ret = chip->channel[ch].size >= runtime->period_size; - chip->channel[ch].size %= runtime->period_size; - - while (count) { - src = (u64 *)(src_base + src_pos); - dst = (s16 *)(dst_base + dst_pos); - - x = *src; - dst[0] = (x >> CHANNEL_LEFT_SHIFT) & 0xffff; - dst[1] = (x >> CHANNEL_RIGHT_SHIFT) & 0xffff; - - src_pos = (src_pos + sizeof(u64)) & CHANNEL_RING_MASK; - dst_pos = (dst_pos + 2 * sizeof(s16)) & dst_mask; - count -= sizeof(u64); - } - - writeq(src_pos, &mace->perif.audio.chan[ch].read_ptr); /* in bytes */ - chip->channel[ch].pos = dst_pos; - - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return ret; -} - -/* put some DMA data in bounce buffer, count must be a multiple of 32 */ -/* returns 1 if a period has elapsed */ -static int snd_sgio2audio_dma_push_frag(struct snd_sgio2audio *chip, - unsigned int ch, unsigned int count) -{ - int ret; - s64 l, r; - unsigned long dst_base, dst_pos, src_mask; - unsigned char *src_base; - int src_pos; - u64 *dst; - s16 *src; - unsigned long flags; - struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - dst_base = (unsigned long)chip->ring_base | (ch << CHANNEL_RING_SHIFT); - dst_pos = readq(&mace->perif.audio.chan[ch].write_ptr); - src_base = runtime->dma_area; - src_pos = chip->channel[ch].pos; - src_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; - - /* check if a period has elapsed */ - chip->channel[ch].size += (count >> 3); /* in frames */ - ret = chip->channel[ch].size >= runtime->period_size; - chip->channel[ch].size %= runtime->period_size; - - while (count) { - src = (s16 *)(src_base + src_pos); - dst = (u64 *)(dst_base + dst_pos); - - l = src[0]; /* sign extend */ - r = src[1]; /* sign extend */ - - *dst = ((l & 0x00ffffff) << CHANNEL_LEFT_SHIFT) | - ((r & 0x00ffffff) << CHANNEL_RIGHT_SHIFT); - - dst_pos = (dst_pos + sizeof(u64)) & CHANNEL_RING_MASK; - src_pos = (src_pos + 2 * sizeof(s16)) & src_mask; - count -= sizeof(u64); - } - - writeq(dst_pos, &mace->perif.audio.chan[ch].write_ptr); /* in bytes */ - chip->channel[ch].pos = src_pos; - - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return ret; -} - -static int snd_sgio2audio_dma_start(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - int ch = chan->idx; - - /* reset DMA channel */ - writeq(CHANNEL_CONTROL_RESET, &mace->perif.audio.chan[ch].control); - udelay(10); - writeq(0, &mace->perif.audio.chan[ch].control); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* push a full buffer */ - snd_sgio2audio_dma_push_frag(chip, ch, CHANNEL_RING_SIZE - 32); - } - /* set DMA to wake on 50% empty and enable interrupt */ - writeq(CHANNEL_DMA_ENABLE | CHANNEL_INT_THRESHOLD_50, - &mace->perif.audio.chan[ch].control); - return 0; -} - -static int snd_sgio2audio_dma_stop(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - - writeq(0, &mace->perif.audio.chan[chan->idx].control); - return 0; -} - -static irqreturn_t snd_sgio2audio_dma_in_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - struct snd_sgio2audio *chip; - int count, ch; - - substream = chan->substream; - chip = snd_pcm_substream_chip(substream); - ch = chan->idx; - - /* empty the ring */ - count = CHANNEL_RING_SIZE - - readq(&mace->perif.audio.chan[ch].depth) - 32; - if (snd_sgio2audio_dma_pull_frag(chip, ch, count)) - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static irqreturn_t snd_sgio2audio_dma_out_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - struct snd_sgio2audio *chip; - int count, ch; - - substream = chan->substream; - chip = snd_pcm_substream_chip(substream); - ch = chan->idx; - /* fill the ring */ - count = CHANNEL_RING_SIZE - - readq(&mace->perif.audio.chan[ch].depth) - 32; - if (snd_sgio2audio_dma_push_frag(chip, ch, count)) - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static irqreturn_t snd_sgio2audio_error_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - - substream = chan->substream; - snd_sgio2audio_dma_stop(substream); - snd_sgio2audio_dma_start(substream); - return IRQ_HANDLED; -} - -/* PCM part */ -/* PCM hardware definition */ -static struct snd_pcm_hardware snd_sgio2audio_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 32768, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, -}; - -/* PCM playback open callback */ -static int snd_sgio2audio_playback1_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[1]; - return 0; -} - -static int snd_sgio2audio_playback2_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[2]; - return 0; -} - -/* PCM capture open callback */ -static int snd_sgio2audio_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[0]; - return 0; -} - -/* PCM close callback */ -static int snd_sgio2audio_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->private_data = NULL; - return 0; -} - - -/* hw_params callback */ -static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_sgio2audio_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -/* prepare callback */ -static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - int ch = chan->idx; - unsigned long flags; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - /* Setup the pseudo-dma transfer pointers. */ - chip->channel[ch].pos = 0; - chip->channel[ch].size = 0; - chip->channel[ch].substream = substream; - - /* set AD1843 format */ - /* hardware format is always S16_LE */ - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - ad1843_setup_dac(&chip->ad1843, - ch - 1, - runtime->rate, - SNDRV_PCM_FORMAT_S16_LE, - runtime->channels); - break; - case SNDRV_PCM_STREAM_CAPTURE: - ad1843_setup_adc(&chip->ad1843, - runtime->rate, - SNDRV_PCM_FORMAT_S16_LE, - runtime->channels); - break; - } - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return 0; -} - -/* trigger callback */ -static int snd_sgio2audio_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* start the PCM engine */ - snd_sgio2audio_dma_start(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - /* stop the PCM engine */ - snd_sgio2audio_dma_stop(substream); - break; - default: - return -EINVAL; - } - return 0; -} - -/* pointer callback */ -static snd_pcm_uframes_t -snd_sgio2audio_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - - /* get the current hardware pointer */ - return bytes_to_frames(substream->runtime, - chip->channel[chan->idx].pos); -} - -/* operators */ -static struct snd_pcm_ops snd_sgio2audio_playback1_ops = { - .open = snd_sgio2audio_playback1_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops snd_sgio2audio_playback2_ops = { - .open = snd_sgio2audio_playback2_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops snd_sgio2audio_capture_ops = { - .open = snd_sgio2audio_capture_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -/* - * definitions of capture are omitted here... - */ - -/* create a pcm device */ -static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip) -{ - struct snd_pcm *pcm; - int err; - - /* create first pcm device with one outputs and one input */ - err = snd_pcm_new(chip->card, "SGI O2 Audio", 0, 1, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SGI O2 DAC1"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_sgio2audio_playback1_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_sgio2audio_capture_ops); - - /* create second pcm device with one outputs and no input */ - err = snd_pcm_new(chip->card, "SGI O2 Audio", 1, 1, 0, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SGI O2 DAC2"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_sgio2audio_playback2_ops); - - return 0; -} - -static struct { - int idx; - int irq; - irqreturn_t (*isr)(int, void *); - const char *desc; -} snd_sgio2_isr_table[] = { - { - .idx = 0, - .irq = MACEISA_AUDIO1_DMAT_IRQ, - .isr = snd_sgio2audio_dma_in_isr, - .desc = "Capture DMA Channel 0" - }, { - .idx = 0, - .irq = MACEISA_AUDIO1_OF_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Capture Overflow" - }, { - .idx = 1, - .irq = MACEISA_AUDIO2_DMAT_IRQ, - .isr = snd_sgio2audio_dma_out_isr, - .desc = "Playback DMA Channel 1" - }, { - .idx = 1, - .irq = MACEISA_AUDIO2_MERR_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Memory Error Channel 1" - }, { - .idx = 2, - .irq = MACEISA_AUDIO3_DMAT_IRQ, - .isr = snd_sgio2audio_dma_out_isr, - .desc = "Playback DMA Channel 2" - }, { - .idx = 2, - .irq = MACEISA_AUDIO3_MERR_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Memory Error Channel 2" - } -}; - -/* ALSA driver */ - -static int snd_sgio2audio_free(struct snd_sgio2audio *chip) -{ - int i; - - /* reset interface */ - writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); - udelay(1); - writeq(0, &mace->perif.audio.control); - - /* release IRQ's */ - for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) - free_irq(snd_sgio2_isr_table[i].irq, - &chip->channel[snd_sgio2_isr_table[i].idx]); - - dma_free_coherent(NULL, MACEISA_RINGBUFFERS_SIZE, - chip->ring_base, chip->ring_base_dma); - - /* release card data */ - kfree(chip); - return 0; -} - -static int snd_sgio2audio_dev_free(struct snd_device *device) -{ - struct snd_sgio2audio *chip = device->device_data; - - return snd_sgio2audio_free(chip); -} - -static struct snd_device_ops ops = { - .dev_free = snd_sgio2audio_dev_free, -}; - -static int __devinit snd_sgio2audio_create(struct snd_card *card, - struct snd_sgio2audio **rchip) -{ - struct snd_sgio2audio *chip; - int i, err; - - *rchip = NULL; - - /* check if a codec is attached to the interface */ - /* (Audio or Audio/Video board present) */ - if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT)) - return -ENOENT; - - chip = kzalloc(sizeof(struct snd_sgio2audio), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->card = card; - - chip->ring_base = dma_alloc_coherent(NULL, MACEISA_RINGBUFFERS_SIZE, - &chip->ring_base_dma, GFP_USER); - if (chip->ring_base == NULL) { - printk(KERN_ERR - "sgio2audio: could not allocate ring buffers\n"); - kfree(chip); - return -ENOMEM; - } - - spin_lock_init(&chip->ad1843_lock); - - /* initialize channels */ - for (i = 0; i < 3; i++) { - spin_lock_init(&chip->channel[i].lock); - chip->channel[i].idx = i; - } - - /* allocate IRQs */ - for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) { - if (request_irq(snd_sgio2_isr_table[i].irq, - snd_sgio2_isr_table[i].isr, - 0, - snd_sgio2_isr_table[i].desc, - &chip->channel[snd_sgio2_isr_table[i].idx])) { - snd_sgio2audio_free(chip); - printk(KERN_ERR "sgio2audio: cannot allocate irq %d\n", - snd_sgio2_isr_table[i].irq); - return -EBUSY; - } - } - - /* reset the interface */ - writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); - udelay(1); - writeq(0, &mace->perif.audio.control); - msleep_interruptible(1); /* give time to recover */ - - /* set ring base */ - writeq(chip->ring_base_dma, &mace->perif.ctrl.ringbase); - - /* attach the AD1843 codec */ - chip->ad1843.read = read_ad1843_reg; - chip->ad1843.write = write_ad1843_reg; - chip->ad1843.chip = chip; - - /* initialize the AD1843 codec */ - err = ad1843_init(&chip->ad1843); - if (err < 0) { - snd_sgio2audio_free(chip); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_sgio2audio_free(chip); - return err; - } - *rchip = chip; - return 0; -} - -static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct snd_sgio2audio *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_sgio2audio_create(card, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - - err = snd_sgio2audio_new_pcm(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - err = snd_sgio2audio_new_mixer(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "SGI O2 Audio"); - strcpy(card->shortname, "SGI O2 Audio"); - sprintf(card->longname, "%s irq %i-%i", - card->shortname, - MACEISA_AUDIO1_DMAT_IRQ, - MACEISA_AUDIO3_MERR_IRQ); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_sgio2audio_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_card_free(card); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver sgio2audio_driver = { - .probe = snd_sgio2audio_probe, - .remove = __devexit_p(snd_sgio2audio_remove), - .driver = { - .name = "sgio2audio", - .owner = THIS_MODULE, - } -}; - -module_platform_driver(sgio2audio_driver); |