112bb5b78SClemens Ladisch /* Analog Devices 1889 audio driver 212bb5b78SClemens Ladisch * 312bb5b78SClemens Ladisch * This is a driver for the AD1889 PCI audio chipset found 412bb5b78SClemens Ladisch * on the HP PA-RISC [BCJ]-xxx0 workstations. 512bb5b78SClemens Ladisch * 612bb5b78SClemens Ladisch * Copyright (C) 2004-2005, Kyle McMartin <kyle@parisc-linux.org> 712bb5b78SClemens Ladisch * Copyright (C) 2005, Thibaut Varene <varenet@parisc-linux.org> 812bb5b78SClemens Ladisch * Based on the OSS AD1889 driver by Randolph Chung <tausq@debian.org> 912bb5b78SClemens Ladisch * 1012bb5b78SClemens Ladisch * This program is free software; you can redistribute it and/or modify 1112bb5b78SClemens Ladisch * it under the terms of the GNU General Public License, version 2, as 1212bb5b78SClemens Ladisch * published by the Free Software Foundation. 1312bb5b78SClemens Ladisch * 1412bb5b78SClemens Ladisch * This program is distributed in the hope that it will be useful, 1512bb5b78SClemens Ladisch * but WITHOUT ANY WARRANTY; without even the implied warranty of 1612bb5b78SClemens Ladisch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1712bb5b78SClemens Ladisch * GNU General Public License for more details. 1812bb5b78SClemens Ladisch * 1912bb5b78SClemens Ladisch * You should have received a copy of the GNU General Public License 2012bb5b78SClemens Ladisch * along with this program; if not, write to the Free Software 2112bb5b78SClemens Ladisch * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2212bb5b78SClemens Ladisch * 2312bb5b78SClemens Ladisch * TODO: 2412bb5b78SClemens Ladisch * Do we need to take care of CCS register? 2512bb5b78SClemens Ladisch * Maybe we could use finer grained locking (separate locks for pb/cap)? 2612bb5b78SClemens Ladisch * Wishlist: 2712bb5b78SClemens Ladisch * Control Interface (mixer) support 2812bb5b78SClemens Ladisch * Better AC97 support (VSR...)? 2912bb5b78SClemens Ladisch * PM support 3012bb5b78SClemens Ladisch * MIDI support 3112bb5b78SClemens Ladisch * Game Port support 3212bb5b78SClemens Ladisch * SG DMA support (this will need *alot* of work) 3312bb5b78SClemens Ladisch */ 3412bb5b78SClemens Ladisch 3512bb5b78SClemens Ladisch #include <linux/init.h> 3612bb5b78SClemens Ladisch #include <linux/pci.h> 379d2f928dSTobias Klauser #include <linux/dma-mapping.h> 3812bb5b78SClemens Ladisch #include <linux/slab.h> 3912bb5b78SClemens Ladisch #include <linux/interrupt.h> 4012bb5b78SClemens Ladisch #include <linux/compiler.h> 4112bb5b78SClemens Ladisch #include <linux/delay.h> 4212bb5b78SClemens Ladisch 4312bb5b78SClemens Ladisch #include <sound/driver.h> 4412bb5b78SClemens Ladisch #include <sound/core.h> 4512bb5b78SClemens Ladisch #include <sound/pcm.h> 4612bb5b78SClemens Ladisch #include <sound/initval.h> 4712bb5b78SClemens Ladisch #include <sound/ac97_codec.h> 4812bb5b78SClemens Ladisch 4912bb5b78SClemens Ladisch #include <asm/io.h> 5012bb5b78SClemens Ladisch 5112bb5b78SClemens Ladisch #include "ad1889.h" 5212bb5b78SClemens Ladisch #include "ac97/ac97_id.h" 5312bb5b78SClemens Ladisch 54c6f43290SJaroslav Kysela #define AD1889_DRVVER "Version: 1.7" 5512bb5b78SClemens Ladisch 5612bb5b78SClemens Ladisch MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>"); 5712bb5b78SClemens Ladisch MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver"); 5812bb5b78SClemens Ladisch MODULE_LICENSE("GPL"); 5912bb5b78SClemens Ladisch MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1889}}"); 6012bb5b78SClemens Ladisch 6112bb5b78SClemens Ladisch static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 6212bb5b78SClemens Ladisch module_param_array(index, int, NULL, 0444); 6312bb5b78SClemens Ladisch MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard."); 6412bb5b78SClemens Ladisch 6512bb5b78SClemens Ladisch static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 6612bb5b78SClemens Ladisch module_param_array(id, charp, NULL, 0444); 6712bb5b78SClemens Ladisch MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard."); 6812bb5b78SClemens Ladisch 6912bb5b78SClemens Ladisch static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 7012bb5b78SClemens Ladisch module_param_array(enable, bool, NULL, 0444); 7112bb5b78SClemens Ladisch MODULE_PARM_DESC(enable, "Enable AD1889 soundcard."); 7212bb5b78SClemens Ladisch 7312bb5b78SClemens Ladisch static char *ac97_quirk[SNDRV_CARDS]; 7412bb5b78SClemens Ladisch module_param_array(ac97_quirk, charp, NULL, 0444); 7512bb5b78SClemens Ladisch MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); 7612bb5b78SClemens Ladisch 7712bb5b78SClemens Ladisch #define DEVNAME "ad1889" 7812bb5b78SClemens Ladisch #define PFX DEVNAME ": " 7912bb5b78SClemens Ladisch 8012bb5b78SClemens Ladisch /* let's use the global sound debug interfaces */ 8112bb5b78SClemens Ladisch #define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg) 8212bb5b78SClemens Ladisch 8312bb5b78SClemens Ladisch /* keep track of some hw registers */ 8412bb5b78SClemens Ladisch struct ad1889_register_state { 8512bb5b78SClemens Ladisch u16 reg; /* reg setup */ 8612bb5b78SClemens Ladisch u32 addr; /* dma base address */ 8712bb5b78SClemens Ladisch unsigned long size; /* DMA buffer size */ 8812bb5b78SClemens Ladisch }; 8912bb5b78SClemens Ladisch 9012bb5b78SClemens Ladisch struct snd_ad1889 { 9102c2de69STakashi Iwai struct snd_card *card; 9212bb5b78SClemens Ladisch struct pci_dev *pci; 9312bb5b78SClemens Ladisch 9412bb5b78SClemens Ladisch int irq; 9512bb5b78SClemens Ladisch unsigned long bar; 9612bb5b78SClemens Ladisch void __iomem *iobase; 9712bb5b78SClemens Ladisch 9802c2de69STakashi Iwai struct snd_ac97 *ac97; 9902c2de69STakashi Iwai struct snd_ac97_bus *ac97_bus; 10002c2de69STakashi Iwai struct snd_pcm *pcm; 10102c2de69STakashi Iwai struct snd_info_entry *proc; 10212bb5b78SClemens Ladisch 10302c2de69STakashi Iwai struct snd_pcm_substream *psubs; 10402c2de69STakashi Iwai struct snd_pcm_substream *csubs; 10512bb5b78SClemens Ladisch 10612bb5b78SClemens Ladisch /* playback register state */ 10712bb5b78SClemens Ladisch struct ad1889_register_state wave; 10812bb5b78SClemens Ladisch struct ad1889_register_state ramc; 10912bb5b78SClemens Ladisch 11012bb5b78SClemens Ladisch spinlock_t lock; 11112bb5b78SClemens Ladisch }; 11212bb5b78SClemens Ladisch 11312bb5b78SClemens Ladisch static inline u16 11412bb5b78SClemens Ladisch ad1889_readw(struct snd_ad1889 *chip, unsigned reg) 11512bb5b78SClemens Ladisch { 11612bb5b78SClemens Ladisch return readw(chip->iobase + reg); 11712bb5b78SClemens Ladisch } 11812bb5b78SClemens Ladisch 11912bb5b78SClemens Ladisch static inline void 12012bb5b78SClemens Ladisch ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val) 12112bb5b78SClemens Ladisch { 12212bb5b78SClemens Ladisch writew(val, chip->iobase + reg); 12312bb5b78SClemens Ladisch } 12412bb5b78SClemens Ladisch 12512bb5b78SClemens Ladisch static inline u32 12612bb5b78SClemens Ladisch ad1889_readl(struct snd_ad1889 *chip, unsigned reg) 12712bb5b78SClemens Ladisch { 12812bb5b78SClemens Ladisch return readl(chip->iobase + reg); 12912bb5b78SClemens Ladisch } 13012bb5b78SClemens Ladisch 13112bb5b78SClemens Ladisch static inline void 13212bb5b78SClemens Ladisch ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val) 13312bb5b78SClemens Ladisch { 13412bb5b78SClemens Ladisch writel(val, chip->iobase + reg); 13512bb5b78SClemens Ladisch } 13612bb5b78SClemens Ladisch 13712bb5b78SClemens Ladisch static inline void 13812bb5b78SClemens Ladisch ad1889_unmute(struct snd_ad1889 *chip) 13912bb5b78SClemens Ladisch { 14012bb5b78SClemens Ladisch u16 st; 14112bb5b78SClemens Ladisch st = ad1889_readw(chip, AD_DS_WADA) & 14212bb5b78SClemens Ladisch ~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM); 14312bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WADA, st); 14412bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WADA); 14512bb5b78SClemens Ladisch } 14612bb5b78SClemens Ladisch 14712bb5b78SClemens Ladisch static inline void 14812bb5b78SClemens Ladisch ad1889_mute(struct snd_ad1889 *chip) 14912bb5b78SClemens Ladisch { 15012bb5b78SClemens Ladisch u16 st; 15112bb5b78SClemens Ladisch st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM; 15212bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WADA, st); 15312bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WADA); 15412bb5b78SClemens Ladisch } 15512bb5b78SClemens Ladisch 15612bb5b78SClemens Ladisch static inline void 15712bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address) 15812bb5b78SClemens Ladisch { 15912bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCBA, address); 16012bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCCA, address); 16112bb5b78SClemens Ladisch } 16212bb5b78SClemens Ladisch 16312bb5b78SClemens Ladisch static inline void 16412bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count) 16512bb5b78SClemens Ladisch { 16612bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCBC, count); 16712bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCCC, count); 16812bb5b78SClemens Ladisch } 16912bb5b78SClemens Ladisch 17012bb5b78SClemens Ladisch static inline void 17112bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count) 17212bb5b78SClemens Ladisch { 17312bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCIB, count); 17412bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCIC, count); 17512bb5b78SClemens Ladisch } 17612bb5b78SClemens Ladisch 17712bb5b78SClemens Ladisch static inline void 17812bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address) 17912bb5b78SClemens Ladisch { 18012bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVBA, address); 18112bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVCA, address); 18212bb5b78SClemens Ladisch } 18312bb5b78SClemens Ladisch 18412bb5b78SClemens Ladisch static inline void 18512bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count) 18612bb5b78SClemens Ladisch { 18712bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVBC, count); 18812bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVCC, count); 18912bb5b78SClemens Ladisch } 19012bb5b78SClemens Ladisch 19112bb5b78SClemens Ladisch static inline void 19212bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count) 19312bb5b78SClemens Ladisch { 19412bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVIB, count); 19512bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVIC, count); 19612bb5b78SClemens Ladisch } 19712bb5b78SClemens Ladisch 19812bb5b78SClemens Ladisch static void 19912bb5b78SClemens Ladisch ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel) 20012bb5b78SClemens Ladisch { 20112bb5b78SClemens Ladisch u16 reg; 20212bb5b78SClemens Ladisch 20312bb5b78SClemens Ladisch if (channel & AD_CHAN_WAV) { 20412bb5b78SClemens Ladisch /* Disable wave channel */ 20512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN; 20612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, reg); 20712bb5b78SClemens Ladisch chip->wave.reg = reg; 20812bb5b78SClemens Ladisch 20912bb5b78SClemens Ladisch /* disable IRQs */ 21012bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DMA_WAV); 21112bb5b78SClemens Ladisch reg &= AD_DMA_IM_DIS; 21212bb5b78SClemens Ladisch reg &= ~AD_DMA_LOOP; 21312bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_WAV, reg); 21412bb5b78SClemens Ladisch 21512bb5b78SClemens Ladisch /* clear IRQ and address counters and pointers */ 21612bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(chip, 0x0); 21712bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(chip, 0x0); 21812bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(chip, 0x0); 21912bb5b78SClemens Ladisch 22012bb5b78SClemens Ladisch /* flush */ 22112bb5b78SClemens Ladisch ad1889_readw(chip, AD_DMA_WAV); 22212bb5b78SClemens Ladisch } 22312bb5b78SClemens Ladisch 22412bb5b78SClemens Ladisch if (channel & AD_CHAN_ADC) { 22512bb5b78SClemens Ladisch /* Disable ADC channel */ 22612bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN; 22712bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, reg); 22812bb5b78SClemens Ladisch chip->ramc.reg = reg; 22912bb5b78SClemens Ladisch 23012bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DMA_ADC); 23112bb5b78SClemens Ladisch reg &= AD_DMA_IM_DIS; 23212bb5b78SClemens Ladisch reg &= ~AD_DMA_LOOP; 23312bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_ADC, reg); 23412bb5b78SClemens Ladisch 23512bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(chip, 0x0); 23612bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(chip, 0x0); 23712bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(chip, 0x0); 23812bb5b78SClemens Ladisch 23912bb5b78SClemens Ladisch /* flush */ 24012bb5b78SClemens Ladisch ad1889_readw(chip, AD_DMA_ADC); 24112bb5b78SClemens Ladisch } 24212bb5b78SClemens Ladisch } 24312bb5b78SClemens Ladisch 24412bb5b78SClemens Ladisch static inline u16 24502c2de69STakashi Iwai snd_ad1889_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 24612bb5b78SClemens Ladisch { 24712bb5b78SClemens Ladisch struct snd_ad1889 *chip = ac97->private_data; 24812bb5b78SClemens Ladisch return ad1889_readw(chip, AD_AC97_BASE + reg); 24912bb5b78SClemens Ladisch } 25012bb5b78SClemens Ladisch 25112bb5b78SClemens Ladisch static inline void 25202c2de69STakashi Iwai snd_ad1889_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 25312bb5b78SClemens Ladisch { 25412bb5b78SClemens Ladisch struct snd_ad1889 *chip = ac97->private_data; 25512bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_BASE + reg, val); 25612bb5b78SClemens Ladisch } 25712bb5b78SClemens Ladisch 25812bb5b78SClemens Ladisch static int 25912bb5b78SClemens Ladisch snd_ad1889_ac97_ready(struct snd_ad1889 *chip) 26012bb5b78SClemens Ladisch { 26112bb5b78SClemens Ladisch int retry = 400; /* average needs 352 msec */ 26212bb5b78SClemens Ladisch 26312bb5b78SClemens Ladisch while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY) 26412bb5b78SClemens Ladisch && --retry) 26512bb5b78SClemens Ladisch mdelay(1); 26612bb5b78SClemens Ladisch if (!retry) { 26712bb5b78SClemens Ladisch snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n", 26812bb5b78SClemens Ladisch __FUNCTION__); 26912bb5b78SClemens Ladisch return -EIO; 27012bb5b78SClemens Ladisch } 27112bb5b78SClemens Ladisch ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry); 27212bb5b78SClemens Ladisch 27312bb5b78SClemens Ladisch return 0; 27412bb5b78SClemens Ladisch } 27512bb5b78SClemens Ladisch 27612bb5b78SClemens Ladisch static int 27702c2de69STakashi Iwai snd_ad1889_hw_params(struct snd_pcm_substream *substream, 27802c2de69STakashi Iwai struct snd_pcm_hw_params *hw_params) 27912bb5b78SClemens Ladisch { 28012bb5b78SClemens Ladisch return snd_pcm_lib_malloc_pages(substream, 28112bb5b78SClemens Ladisch params_buffer_bytes(hw_params)); 28212bb5b78SClemens Ladisch } 28312bb5b78SClemens Ladisch 28412bb5b78SClemens Ladisch static int 28502c2de69STakashi Iwai snd_ad1889_hw_free(struct snd_pcm_substream *substream) 28612bb5b78SClemens Ladisch { 28712bb5b78SClemens Ladisch return snd_pcm_lib_free_pages(substream); 28812bb5b78SClemens Ladisch } 28912bb5b78SClemens Ladisch 29002c2de69STakashi Iwai static struct snd_pcm_hardware snd_ad1889_playback_hw = { 29112bb5b78SClemens Ladisch .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 29212bb5b78SClemens Ladisch SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER, 29312bb5b78SClemens Ladisch .formats = SNDRV_PCM_FMTBIT_S16_LE, 29412bb5b78SClemens Ladisch .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, 29512bb5b78SClemens Ladisch .rate_min = 8000, /* docs say 7000, but we're lazy */ 29612bb5b78SClemens Ladisch .rate_max = 48000, 29712bb5b78SClemens Ladisch .channels_min = 1, 29812bb5b78SClemens Ladisch .channels_max = 2, 29912bb5b78SClemens Ladisch .buffer_bytes_max = BUFFER_BYTES_MAX, 30012bb5b78SClemens Ladisch .period_bytes_min = PERIOD_BYTES_MIN, 30112bb5b78SClemens Ladisch .period_bytes_max = PERIOD_BYTES_MAX, 30212bb5b78SClemens Ladisch .periods_min = PERIODS_MIN, 30312bb5b78SClemens Ladisch .periods_max = PERIODS_MAX, 30412bb5b78SClemens Ladisch /*.fifo_size = 0,*/ 30512bb5b78SClemens Ladisch }; 30612bb5b78SClemens Ladisch 30702c2de69STakashi Iwai static struct snd_pcm_hardware snd_ad1889_capture_hw = { 30812bb5b78SClemens Ladisch .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 30912bb5b78SClemens Ladisch SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER, 31012bb5b78SClemens Ladisch .formats = SNDRV_PCM_FMTBIT_S16_LE, 31112bb5b78SClemens Ladisch .rates = SNDRV_PCM_RATE_48000, 31212bb5b78SClemens Ladisch .rate_min = 48000, /* docs say we could to VSR, but we're lazy */ 31312bb5b78SClemens Ladisch .rate_max = 48000, 31412bb5b78SClemens Ladisch .channels_min = 1, 31512bb5b78SClemens Ladisch .channels_max = 2, 31612bb5b78SClemens Ladisch .buffer_bytes_max = BUFFER_BYTES_MAX, 31712bb5b78SClemens Ladisch .period_bytes_min = PERIOD_BYTES_MIN, 31812bb5b78SClemens Ladisch .period_bytes_max = PERIOD_BYTES_MAX, 31912bb5b78SClemens Ladisch .periods_min = PERIODS_MIN, 32012bb5b78SClemens Ladisch .periods_max = PERIODS_MAX, 32112bb5b78SClemens Ladisch /*.fifo_size = 0,*/ 32212bb5b78SClemens Ladisch }; 32312bb5b78SClemens Ladisch 32412bb5b78SClemens Ladisch static int 32502c2de69STakashi Iwai snd_ad1889_playback_open(struct snd_pcm_substream *ss) 32612bb5b78SClemens Ladisch { 32712bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 32802c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime; 32912bb5b78SClemens Ladisch 33012bb5b78SClemens Ladisch chip->psubs = ss; 33112bb5b78SClemens Ladisch rt->hw = snd_ad1889_playback_hw; 33212bb5b78SClemens Ladisch 33312bb5b78SClemens Ladisch return 0; 33412bb5b78SClemens Ladisch } 33512bb5b78SClemens Ladisch 33612bb5b78SClemens Ladisch static int 33702c2de69STakashi Iwai snd_ad1889_capture_open(struct snd_pcm_substream *ss) 33812bb5b78SClemens Ladisch { 33912bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 34002c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime; 34112bb5b78SClemens Ladisch 34212bb5b78SClemens Ladisch chip->csubs = ss; 34312bb5b78SClemens Ladisch rt->hw = snd_ad1889_capture_hw; 34412bb5b78SClemens Ladisch 34512bb5b78SClemens Ladisch return 0; 34612bb5b78SClemens Ladisch } 34712bb5b78SClemens Ladisch 34812bb5b78SClemens Ladisch static int 34902c2de69STakashi Iwai snd_ad1889_playback_close(struct snd_pcm_substream *ss) 35012bb5b78SClemens Ladisch { 35112bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 35212bb5b78SClemens Ladisch chip->psubs = NULL; 35312bb5b78SClemens Ladisch return 0; 35412bb5b78SClemens Ladisch } 35512bb5b78SClemens Ladisch 35612bb5b78SClemens Ladisch static int 35702c2de69STakashi Iwai snd_ad1889_capture_close(struct snd_pcm_substream *ss) 35812bb5b78SClemens Ladisch { 35912bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 36012bb5b78SClemens Ladisch chip->csubs = NULL; 36112bb5b78SClemens Ladisch return 0; 36212bb5b78SClemens Ladisch } 36312bb5b78SClemens Ladisch 36412bb5b78SClemens Ladisch static int 36502c2de69STakashi Iwai snd_ad1889_playback_prepare(struct snd_pcm_substream *ss) 36612bb5b78SClemens Ladisch { 36712bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 36802c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime; 36912bb5b78SClemens Ladisch unsigned int size = snd_pcm_lib_buffer_bytes(ss); 37012bb5b78SClemens Ladisch unsigned int count = snd_pcm_lib_period_bytes(ss); 37112bb5b78SClemens Ladisch u16 reg; 37212bb5b78SClemens Ladisch 37312bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV); 37412bb5b78SClemens Ladisch 37512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC); 37612bb5b78SClemens Ladisch 37712bb5b78SClemens Ladisch /* Mask out 16-bit / Stereo */ 37812bb5b78SClemens Ladisch reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST); 37912bb5b78SClemens Ladisch 38012bb5b78SClemens Ladisch if (snd_pcm_format_width(rt->format) == 16) 38112bb5b78SClemens Ladisch reg |= AD_DS_WSMC_WA16; 38212bb5b78SClemens Ladisch 38312bb5b78SClemens Ladisch if (rt->channels > 1) 38412bb5b78SClemens Ladisch reg |= AD_DS_WSMC_WAST; 38512bb5b78SClemens Ladisch 38612bb5b78SClemens Ladisch /* let's make sure we don't clobber ourselves */ 38712bb5b78SClemens Ladisch spin_lock_irq(&chip->lock); 38812bb5b78SClemens Ladisch 38912bb5b78SClemens Ladisch chip->wave.size = size; 39012bb5b78SClemens Ladisch chip->wave.reg = reg; 39112bb5b78SClemens Ladisch chip->wave.addr = rt->dma_addr; 39212bb5b78SClemens Ladisch 39312bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg); 39412bb5b78SClemens Ladisch 39512bb5b78SClemens Ladisch /* Set sample rates on the codec */ 39612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WAS, rt->rate); 39712bb5b78SClemens Ladisch 39812bb5b78SClemens Ladisch /* Set up DMA */ 39912bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(chip, chip->wave.addr); 40012bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(chip, size); 40112bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(chip, count); 40212bb5b78SClemens Ladisch 40312bb5b78SClemens Ladisch /* writes flush */ 40412bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WSMC); 40512bb5b78SClemens Ladisch 40612bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock); 40712bb5b78SClemens Ladisch 40812bb5b78SClemens Ladisch ad1889_debug("prepare playback: addr = 0x%x, count = %u, " 40912bb5b78SClemens Ladisch "size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr, 41012bb5b78SClemens Ladisch count, size, reg, rt->rate); 41112bb5b78SClemens Ladisch return 0; 41212bb5b78SClemens Ladisch } 41312bb5b78SClemens Ladisch 41412bb5b78SClemens Ladisch static int 41502c2de69STakashi Iwai snd_ad1889_capture_prepare(struct snd_pcm_substream *ss) 41612bb5b78SClemens Ladisch { 41712bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 41802c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime; 41912bb5b78SClemens Ladisch unsigned int size = snd_pcm_lib_buffer_bytes(ss); 42012bb5b78SClemens Ladisch unsigned int count = snd_pcm_lib_period_bytes(ss); 42112bb5b78SClemens Ladisch u16 reg; 42212bb5b78SClemens Ladisch 42312bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_ADC); 42412bb5b78SClemens Ladisch 42512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC); 42612bb5b78SClemens Ladisch 42712bb5b78SClemens Ladisch /* Mask out 16-bit / Stereo */ 42812bb5b78SClemens Ladisch reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST); 42912bb5b78SClemens Ladisch 43012bb5b78SClemens Ladisch if (snd_pcm_format_width(rt->format) == 16) 43112bb5b78SClemens Ladisch reg |= AD_DS_RAMC_AD16; 43212bb5b78SClemens Ladisch 43312bb5b78SClemens Ladisch if (rt->channels > 1) 43412bb5b78SClemens Ladisch reg |= AD_DS_RAMC_ADST; 43512bb5b78SClemens Ladisch 43612bb5b78SClemens Ladisch /* let's make sure we don't clobber ourselves */ 43712bb5b78SClemens Ladisch spin_lock_irq(&chip->lock); 43812bb5b78SClemens Ladisch 43912bb5b78SClemens Ladisch chip->ramc.size = size; 44012bb5b78SClemens Ladisch chip->ramc.reg = reg; 44112bb5b78SClemens Ladisch chip->ramc.addr = rt->dma_addr; 44212bb5b78SClemens Ladisch 44312bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg); 44412bb5b78SClemens Ladisch 44512bb5b78SClemens Ladisch /* Set up DMA */ 44612bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(chip, chip->ramc.addr); 44712bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(chip, size); 44812bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(chip, count); 44912bb5b78SClemens Ladisch 45012bb5b78SClemens Ladisch /* writes flush */ 45112bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_RAMC); 45212bb5b78SClemens Ladisch 45312bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock); 45412bb5b78SClemens Ladisch 45512bb5b78SClemens Ladisch ad1889_debug("prepare capture: addr = 0x%x, count = %u, " 45612bb5b78SClemens Ladisch "size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr, 45712bb5b78SClemens Ladisch count, size, reg, rt->rate); 45812bb5b78SClemens Ladisch return 0; 45912bb5b78SClemens Ladisch } 46012bb5b78SClemens Ladisch 46112bb5b78SClemens Ladisch /* this is called in atomic context with IRQ disabled. 46212bb5b78SClemens Ladisch Must be as fast as possible and not sleep. 46312bb5b78SClemens Ladisch DMA should be *triggered* by this call. 46412bb5b78SClemens Ladisch The WSMC "WAEN" bit triggers DMA Wave On/Off */ 46512bb5b78SClemens Ladisch static int 46602c2de69STakashi Iwai snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) 46712bb5b78SClemens Ladisch { 46812bb5b78SClemens Ladisch u16 wsmc; 46912bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 47012bb5b78SClemens Ladisch 47112bb5b78SClemens Ladisch wsmc = ad1889_readw(chip, AD_DS_WSMC); 47212bb5b78SClemens Ladisch 47312bb5b78SClemens Ladisch switch (cmd) { 47412bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_START: 47512bb5b78SClemens Ladisch /* enable DMA loop & interrupts */ 47612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); 47712bb5b78SClemens Ladisch wsmc |= AD_DS_WSMC_WAEN; 47812bb5b78SClemens Ladisch /* 1 to clear CHSS bit */ 47912bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); 48012bb5b78SClemens Ladisch ad1889_unmute(chip); 48112bb5b78SClemens Ladisch break; 48212bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_STOP: 48312bb5b78SClemens Ladisch ad1889_mute(chip); 48412bb5b78SClemens Ladisch wsmc &= ~AD_DS_WSMC_WAEN; 48512bb5b78SClemens Ladisch break; 48612bb5b78SClemens Ladisch default: 48712bb5b78SClemens Ladisch snd_BUG(); 48812bb5b78SClemens Ladisch return -EINVAL; 48912bb5b78SClemens Ladisch } 49012bb5b78SClemens Ladisch 49112bb5b78SClemens Ladisch chip->wave.reg = wsmc; 49212bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, wsmc); 49312bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WSMC); /* flush */ 49412bb5b78SClemens Ladisch 49512bb5b78SClemens Ladisch /* reset the chip when STOP - will disable IRQs */ 49612bb5b78SClemens Ladisch if (cmd == SNDRV_PCM_TRIGGER_STOP) 49712bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV); 49812bb5b78SClemens Ladisch 49912bb5b78SClemens Ladisch return 0; 50012bb5b78SClemens Ladisch } 50112bb5b78SClemens Ladisch 50212bb5b78SClemens Ladisch /* this is called in atomic context with IRQ disabled. 50312bb5b78SClemens Ladisch Must be as fast as possible and not sleep. 50412bb5b78SClemens Ladisch DMA should be *triggered* by this call. 50512bb5b78SClemens Ladisch The RAMC "ADEN" bit triggers DMA ADC On/Off */ 50612bb5b78SClemens Ladisch static int 50702c2de69STakashi Iwai snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd) 50812bb5b78SClemens Ladisch { 50912bb5b78SClemens Ladisch u16 ramc; 51012bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 51112bb5b78SClemens Ladisch 51212bb5b78SClemens Ladisch ramc = ad1889_readw(chip, AD_DS_RAMC); 51312bb5b78SClemens Ladisch 51412bb5b78SClemens Ladisch switch (cmd) { 51512bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_START: 51612bb5b78SClemens Ladisch /* enable DMA loop & interrupts */ 51712bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT); 51812bb5b78SClemens Ladisch ramc |= AD_DS_RAMC_ADEN; 51912bb5b78SClemens Ladisch /* 1 to clear CHSS bit */ 52012bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS); 52112bb5b78SClemens Ladisch break; 52212bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_STOP: 52312bb5b78SClemens Ladisch ramc &= ~AD_DS_RAMC_ADEN; 52412bb5b78SClemens Ladisch break; 52512bb5b78SClemens Ladisch default: 52612bb5b78SClemens Ladisch return -EINVAL; 52712bb5b78SClemens Ladisch } 52812bb5b78SClemens Ladisch 52912bb5b78SClemens Ladisch chip->ramc.reg = ramc; 53012bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, ramc); 53112bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_RAMC); /* flush */ 53212bb5b78SClemens Ladisch 53312bb5b78SClemens Ladisch /* reset the chip when STOP - will disable IRQs */ 53412bb5b78SClemens Ladisch if (cmd == SNDRV_PCM_TRIGGER_STOP) 53512bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_ADC); 53612bb5b78SClemens Ladisch 53712bb5b78SClemens Ladisch return 0; 53812bb5b78SClemens Ladisch } 53912bb5b78SClemens Ladisch 54012bb5b78SClemens Ladisch /* Called in atomic context with IRQ disabled */ 54112bb5b78SClemens Ladisch static snd_pcm_uframes_t 54202c2de69STakashi Iwai snd_ad1889_playback_pointer(struct snd_pcm_substream *ss) 54312bb5b78SClemens Ladisch { 54412bb5b78SClemens Ladisch size_t ptr = 0; 54512bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 54612bb5b78SClemens Ladisch 54712bb5b78SClemens Ladisch if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN))) 54812bb5b78SClemens Ladisch return 0; 54912bb5b78SClemens Ladisch 55012bb5b78SClemens Ladisch ptr = ad1889_readl(chip, AD_DMA_WAVCA); 55112bb5b78SClemens Ladisch ptr -= chip->wave.addr; 55212bb5b78SClemens Ladisch 55312bb5b78SClemens Ladisch snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0); 55412bb5b78SClemens Ladisch 55512bb5b78SClemens Ladisch return bytes_to_frames(ss->runtime, ptr); 55612bb5b78SClemens Ladisch } 55712bb5b78SClemens Ladisch 55812bb5b78SClemens Ladisch /* Called in atomic context with IRQ disabled */ 55912bb5b78SClemens Ladisch static snd_pcm_uframes_t 56002c2de69STakashi Iwai snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) 56112bb5b78SClemens Ladisch { 56212bb5b78SClemens Ladisch size_t ptr = 0; 56312bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); 56412bb5b78SClemens Ladisch 56512bb5b78SClemens Ladisch if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN))) 56612bb5b78SClemens Ladisch return 0; 56712bb5b78SClemens Ladisch 56812bb5b78SClemens Ladisch ptr = ad1889_readl(chip, AD_DMA_ADCCA); 56912bb5b78SClemens Ladisch ptr -= chip->ramc.addr; 57012bb5b78SClemens Ladisch 57112bb5b78SClemens Ladisch snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0); 57212bb5b78SClemens Ladisch 57312bb5b78SClemens Ladisch return bytes_to_frames(ss->runtime, ptr); 57412bb5b78SClemens Ladisch } 57512bb5b78SClemens Ladisch 57602c2de69STakashi Iwai static struct snd_pcm_ops snd_ad1889_playback_ops = { 57712bb5b78SClemens Ladisch .open = snd_ad1889_playback_open, 57812bb5b78SClemens Ladisch .close = snd_ad1889_playback_close, 57912bb5b78SClemens Ladisch .ioctl = snd_pcm_lib_ioctl, 58012bb5b78SClemens Ladisch .hw_params = snd_ad1889_hw_params, 58112bb5b78SClemens Ladisch .hw_free = snd_ad1889_hw_free, 58212bb5b78SClemens Ladisch .prepare = snd_ad1889_playback_prepare, 58312bb5b78SClemens Ladisch .trigger = snd_ad1889_playback_trigger, 58412bb5b78SClemens Ladisch .pointer = snd_ad1889_playback_pointer, 58512bb5b78SClemens Ladisch }; 58612bb5b78SClemens Ladisch 58702c2de69STakashi Iwai static struct snd_pcm_ops snd_ad1889_capture_ops = { 58812bb5b78SClemens Ladisch .open = snd_ad1889_capture_open, 58912bb5b78SClemens Ladisch .close = snd_ad1889_capture_close, 59012bb5b78SClemens Ladisch .ioctl = snd_pcm_lib_ioctl, 59112bb5b78SClemens Ladisch .hw_params = snd_ad1889_hw_params, 59212bb5b78SClemens Ladisch .hw_free = snd_ad1889_hw_free, 59312bb5b78SClemens Ladisch .prepare = snd_ad1889_capture_prepare, 59412bb5b78SClemens Ladisch .trigger = snd_ad1889_capture_trigger, 59512bb5b78SClemens Ladisch .pointer = snd_ad1889_capture_pointer, 59612bb5b78SClemens Ladisch }; 59712bb5b78SClemens Ladisch 59812bb5b78SClemens Ladisch static irqreturn_t 59912bb5b78SClemens Ladisch snd_ad1889_interrupt(int irq, 60012bb5b78SClemens Ladisch void *dev_id, 60112bb5b78SClemens Ladisch struct pt_regs *regs) 60212bb5b78SClemens Ladisch { 60312bb5b78SClemens Ladisch unsigned long st; 60412bb5b78SClemens Ladisch struct snd_ad1889 *chip = dev_id; 60512bb5b78SClemens Ladisch 60612bb5b78SClemens Ladisch st = ad1889_readl(chip, AD_DMA_DISR); 60712bb5b78SClemens Ladisch 60812bb5b78SClemens Ladisch /* clear ISR */ 60912bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, st); 61012bb5b78SClemens Ladisch 61112bb5b78SClemens Ladisch st &= AD_INTR_MASK; 61212bb5b78SClemens Ladisch 61312bb5b78SClemens Ladisch if (unlikely(!st)) 61412bb5b78SClemens Ladisch return IRQ_NONE; 61512bb5b78SClemens Ladisch 61612bb5b78SClemens Ladisch if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)) 61712bb5b78SClemens Ladisch ad1889_debug("Unexpected master or target abort interrupt!\n"); 61812bb5b78SClemens Ladisch 61912bb5b78SClemens Ladisch if ((st & AD_DMA_DISR_WAVI) && chip->psubs) 62012bb5b78SClemens Ladisch snd_pcm_period_elapsed(chip->psubs); 62112bb5b78SClemens Ladisch if ((st & AD_DMA_DISR_ADCI) && chip->csubs) 62212bb5b78SClemens Ladisch snd_pcm_period_elapsed(chip->csubs); 62312bb5b78SClemens Ladisch 62412bb5b78SClemens Ladisch return IRQ_HANDLED; 62512bb5b78SClemens Ladisch } 62612bb5b78SClemens Ladisch 62712bb5b78SClemens Ladisch static int __devinit 62802c2de69STakashi Iwai snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm) 62912bb5b78SClemens Ladisch { 63012bb5b78SClemens Ladisch int err; 63102c2de69STakashi Iwai struct snd_pcm *pcm; 63212bb5b78SClemens Ladisch 63312bb5b78SClemens Ladisch if (rpcm) 63412bb5b78SClemens Ladisch *rpcm = NULL; 63512bb5b78SClemens Ladisch 63612bb5b78SClemens Ladisch err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm); 63712bb5b78SClemens Ladisch if (err < 0) 63812bb5b78SClemens Ladisch return err; 63912bb5b78SClemens Ladisch 64012bb5b78SClemens Ladisch snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 64112bb5b78SClemens Ladisch &snd_ad1889_playback_ops); 64212bb5b78SClemens Ladisch snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 64312bb5b78SClemens Ladisch &snd_ad1889_capture_ops); 64412bb5b78SClemens Ladisch 64512bb5b78SClemens Ladisch pcm->private_data = chip; 64612bb5b78SClemens Ladisch pcm->info_flags = 0; 64712bb5b78SClemens Ladisch strcpy(pcm->name, chip->card->shortname); 64812bb5b78SClemens Ladisch 64912bb5b78SClemens Ladisch chip->pcm = pcm; 65012bb5b78SClemens Ladisch chip->psubs = NULL; 65112bb5b78SClemens Ladisch chip->csubs = NULL; 65212bb5b78SClemens Ladisch 65312bb5b78SClemens Ladisch err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 65412bb5b78SClemens Ladisch snd_dma_pci_data(chip->pci), 65512bb5b78SClemens Ladisch BUFFER_BYTES_MAX / 2, 65612bb5b78SClemens Ladisch BUFFER_BYTES_MAX); 65712bb5b78SClemens Ladisch 65812bb5b78SClemens Ladisch if (err < 0) { 65912bb5b78SClemens Ladisch snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err); 66012bb5b78SClemens Ladisch return err; 66112bb5b78SClemens Ladisch } 66212bb5b78SClemens Ladisch 66312bb5b78SClemens Ladisch if (rpcm) 66412bb5b78SClemens Ladisch *rpcm = pcm; 66512bb5b78SClemens Ladisch 66612bb5b78SClemens Ladisch return 0; 66712bb5b78SClemens Ladisch } 66812bb5b78SClemens Ladisch 66912bb5b78SClemens Ladisch static void 67002c2de69STakashi Iwai snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 67112bb5b78SClemens Ladisch { 67212bb5b78SClemens Ladisch struct snd_ad1889 *chip = entry->private_data; 67312bb5b78SClemens Ladisch u16 reg; 67412bb5b78SClemens Ladisch int tmp; 67512bb5b78SClemens Ladisch 67612bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC); 67712bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave output: %s\n", 67812bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled"); 67912bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave Channels: %s\n", 68012bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); 68112bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave Quality: %d-bit linear\n", 68212bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WA16) ? 16 : 8); 68312bb5b78SClemens Ladisch 68412bb5b78SClemens Ladisch /* WARQ is at offset 12 */ 68512bb5b78SClemens Ladisch tmp = (reg & AD_DS_WSMC_WARQ) ? 68612bb5b78SClemens Ladisch (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4; 68712bb5b78SClemens Ladisch tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; 68812bb5b78SClemens Ladisch 68912bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp, 69012bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); 69112bb5b78SClemens Ladisch 69212bb5b78SClemens Ladisch 69312bb5b78SClemens Ladisch snd_iprintf(buffer, "Synthesis output: %s\n", 69412bb5b78SClemens Ladisch reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled"); 69512bb5b78SClemens Ladisch 69612bb5b78SClemens Ladisch /* SYRQ is at offset 4 */ 69712bb5b78SClemens Ladisch tmp = (reg & AD_DS_WSMC_SYRQ) ? 69812bb5b78SClemens Ladisch (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4; 69912bb5b78SClemens Ladisch tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; 70012bb5b78SClemens Ladisch 70112bb5b78SClemens Ladisch snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp, 70212bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); 70312bb5b78SClemens Ladisch 70412bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC); 70512bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC input: %s\n", 70612bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled"); 70712bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC Channels: %s\n", 70812bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono"); 70912bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC Quality: %d-bit linear\n", 71012bb5b78SClemens Ladisch (reg & AD_DS_RAMC_AD16) ? 16 : 8); 71112bb5b78SClemens Ladisch 71212bb5b78SClemens Ladisch /* ACRQ is at offset 4 */ 71312bb5b78SClemens Ladisch tmp = (reg & AD_DS_RAMC_ACRQ) ? 71412bb5b78SClemens Ladisch (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4; 71512bb5b78SClemens Ladisch tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; 71612bb5b78SClemens Ladisch 71712bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp, 71812bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono"); 71912bb5b78SClemens Ladisch 72012bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler input: %s\n", 72112bb5b78SClemens Ladisch reg & AD_DS_RAMC_REEN ? "enabled" : "disabled"); 72212bb5b78SClemens Ladisch 72312bb5b78SClemens Ladisch /* RERQ is at offset 12 */ 72412bb5b78SClemens Ladisch tmp = (reg & AD_DS_RAMC_RERQ) ? 72512bb5b78SClemens Ladisch (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4; 72612bb5b78SClemens Ladisch tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; 72712bb5b78SClemens Ladisch 72812bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp, 72912bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); 73012bb5b78SClemens Ladisch 73112bb5b78SClemens Ladisch 73212bb5b78SClemens Ladisch /* doc says LSB represents -1.5dB, but the max value (-94.5dB) 73312bb5b78SClemens Ladisch suggests that LSB is -3dB, which is more coherent with the logarithmic 73412bb5b78SClemens Ladisch nature of the dB scale */ 73512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WADA); 73612bb5b78SClemens Ladisch snd_iprintf(buffer, "Left: %s, -%d dB\n", 73712bb5b78SClemens Ladisch (reg & AD_DS_WADA_LWAM) ? "mute" : "unmute", 73812bb5b78SClemens Ladisch ((reg & AD_DS_WADA_LWAA) >> 8) * 3); 73912bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WADA); 74012bb5b78SClemens Ladisch snd_iprintf(buffer, "Right: %s, -%d dB\n", 74112bb5b78SClemens Ladisch (reg & AD_DS_WADA_RWAM) ? "mute" : "unmute", 74212bb5b78SClemens Ladisch ((reg & AD_DS_WADA_RWAA) >> 8) * 3); 74312bb5b78SClemens Ladisch 74412bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WAS); 74512bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg); 74612bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RES); 74712bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg); 74812bb5b78SClemens Ladisch } 74912bb5b78SClemens Ladisch 75012bb5b78SClemens Ladisch static void __devinit 75112bb5b78SClemens Ladisch snd_ad1889_proc_init(struct snd_ad1889 *chip) 75212bb5b78SClemens Ladisch { 75302c2de69STakashi Iwai struct snd_info_entry *entry; 75412bb5b78SClemens Ladisch 75512bb5b78SClemens Ladisch if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) 756bf850204STakashi Iwai snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read); 75712bb5b78SClemens Ladisch } 75812bb5b78SClemens Ladisch 75912bb5b78SClemens Ladisch static struct ac97_quirk ac97_quirks[] = { 76012bb5b78SClemens Ladisch { 76112bb5b78SClemens Ladisch .subvendor = 0x11d4, /* AD */ 76212bb5b78SClemens Ladisch .subdevice = 0x1889, /* AD1889 */ 76312bb5b78SClemens Ladisch .codec_id = AC97_ID_AD1819, 76412bb5b78SClemens Ladisch .name = "AD1889", 76512bb5b78SClemens Ladisch .type = AC97_TUNE_HP_ONLY 76612bb5b78SClemens Ladisch }, 76712bb5b78SClemens Ladisch { } /* terminator */ 76812bb5b78SClemens Ladisch }; 76912bb5b78SClemens Ladisch 77012bb5b78SClemens Ladisch static void __devinit 77112bb5b78SClemens Ladisch snd_ad1889_ac97_xinit(struct snd_ad1889 *chip) 77212bb5b78SClemens Ladisch { 77312bb5b78SClemens Ladisch u16 reg; 77412bb5b78SClemens Ladisch 77512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_AC97_ACIC); 77612bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ACRD; /* Reset Disable */ 77712bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg); 77812bb5b78SClemens Ladisch ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */ 77912bb5b78SClemens Ladisch udelay(10); 78012bb5b78SClemens Ladisch /* Interface Enable */ 78112bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ACIE; 78212bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg); 78312bb5b78SClemens Ladisch 78412bb5b78SClemens Ladisch snd_ad1889_ac97_ready(chip); 78512bb5b78SClemens Ladisch 78612bb5b78SClemens Ladisch /* Audio Stream Output | Variable Sample Rate Mode */ 78712bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_AC97_ACIC); 78812bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM; 78912bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg); 79012bb5b78SClemens Ladisch ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */ 79112bb5b78SClemens Ladisch 79212bb5b78SClemens Ladisch } 79312bb5b78SClemens Ladisch 79412bb5b78SClemens Ladisch static void 79502c2de69STakashi Iwai snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus) 79612bb5b78SClemens Ladisch { 79712bb5b78SClemens Ladisch struct snd_ad1889 *chip = bus->private_data; 79812bb5b78SClemens Ladisch chip->ac97_bus = NULL; 79912bb5b78SClemens Ladisch } 80012bb5b78SClemens Ladisch 80112bb5b78SClemens Ladisch static void 80202c2de69STakashi Iwai snd_ad1889_ac97_free(struct snd_ac97 *ac97) 80312bb5b78SClemens Ladisch { 80412bb5b78SClemens Ladisch struct snd_ad1889 *chip = ac97->private_data; 80512bb5b78SClemens Ladisch chip->ac97 = NULL; 80612bb5b78SClemens Ladisch } 80712bb5b78SClemens Ladisch 80812bb5b78SClemens Ladisch static int __devinit 80912bb5b78SClemens Ladisch snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override) 81012bb5b78SClemens Ladisch { 81112bb5b78SClemens Ladisch int err; 81202c2de69STakashi Iwai struct snd_ac97_template ac97; 81302c2de69STakashi Iwai static struct snd_ac97_bus_ops ops = { 81412bb5b78SClemens Ladisch .write = snd_ad1889_ac97_write, 81512bb5b78SClemens Ladisch .read = snd_ad1889_ac97_read, 81612bb5b78SClemens Ladisch }; 81712bb5b78SClemens Ladisch 81812bb5b78SClemens Ladisch /* doing that here, it works. */ 81912bb5b78SClemens Ladisch snd_ad1889_ac97_xinit(chip); 82012bb5b78SClemens Ladisch 82112bb5b78SClemens Ladisch err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); 82212bb5b78SClemens Ladisch if (err < 0) 82312bb5b78SClemens Ladisch return err; 82412bb5b78SClemens Ladisch 82512bb5b78SClemens Ladisch chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free; 82612bb5b78SClemens Ladisch 82712bb5b78SClemens Ladisch memset(&ac97, 0, sizeof(ac97)); 82812bb5b78SClemens Ladisch ac97.private_data = chip; 82912bb5b78SClemens Ladisch ac97.private_free = snd_ad1889_ac97_free; 83012bb5b78SClemens Ladisch ac97.pci = chip->pci; 83112bb5b78SClemens Ladisch 83212bb5b78SClemens Ladisch err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); 83312bb5b78SClemens Ladisch if (err < 0) 83412bb5b78SClemens Ladisch return err; 83512bb5b78SClemens Ladisch 83612bb5b78SClemens Ladisch snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override); 83712bb5b78SClemens Ladisch 83812bb5b78SClemens Ladisch return 0; 83912bb5b78SClemens Ladisch } 84012bb5b78SClemens Ladisch 84112bb5b78SClemens Ladisch static int 84212bb5b78SClemens Ladisch snd_ad1889_free(struct snd_ad1889 *chip) 84312bb5b78SClemens Ladisch { 84412bb5b78SClemens Ladisch if (chip->irq < 0) 84512bb5b78SClemens Ladisch goto skip_hw; 84612bb5b78SClemens Ladisch 84712bb5b78SClemens Ladisch spin_lock_irq(&chip->lock); 84812bb5b78SClemens Ladisch 84912bb5b78SClemens Ladisch ad1889_mute(chip); 85012bb5b78SClemens Ladisch 85112bb5b78SClemens Ladisch /* Turn off interrupt on count and zero DMA registers */ 85212bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC); 85312bb5b78SClemens Ladisch 85412bb5b78SClemens Ladisch /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */ 85512bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI); 85612bb5b78SClemens Ladisch ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */ 85712bb5b78SClemens Ladisch 85812bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock); 85912bb5b78SClemens Ladisch 86012bb5b78SClemens Ladisch synchronize_irq(chip->irq); 86112bb5b78SClemens Ladisch 86212bb5b78SClemens Ladisch if (chip->irq >= 0) 86312bb5b78SClemens Ladisch free_irq(chip->irq, (void*)chip); 86412bb5b78SClemens Ladisch 86512bb5b78SClemens Ladisch skip_hw: 86612bb5b78SClemens Ladisch if (chip->iobase) 86712bb5b78SClemens Ladisch iounmap(chip->iobase); 86812bb5b78SClemens Ladisch 86912bb5b78SClemens Ladisch pci_release_regions(chip->pci); 87012bb5b78SClemens Ladisch pci_disable_device(chip->pci); 87112bb5b78SClemens Ladisch 87212bb5b78SClemens Ladisch kfree(chip); 87312bb5b78SClemens Ladisch return 0; 87412bb5b78SClemens Ladisch } 87512bb5b78SClemens Ladisch 87612bb5b78SClemens Ladisch static inline int 87702c2de69STakashi Iwai snd_ad1889_dev_free(struct snd_device *device) 87812bb5b78SClemens Ladisch { 87912bb5b78SClemens Ladisch struct snd_ad1889 *chip = device->device_data; 88012bb5b78SClemens Ladisch return snd_ad1889_free(chip); 88112bb5b78SClemens Ladisch } 88212bb5b78SClemens Ladisch 88312bb5b78SClemens Ladisch static int __devinit 88412bb5b78SClemens Ladisch snd_ad1889_init(struct snd_ad1889 *chip) 88512bb5b78SClemens Ladisch { 88612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */ 88712bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_CCS); /* flush posted write */ 88812bb5b78SClemens Ladisch 88912bb5b78SClemens Ladisch mdelay(10); 89012bb5b78SClemens Ladisch 89112bb5b78SClemens Ladisch /* enable Master and Target abort interrupts */ 89212bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE); 89312bb5b78SClemens Ladisch 89412bb5b78SClemens Ladisch return 0; 89512bb5b78SClemens Ladisch } 89612bb5b78SClemens Ladisch 89712bb5b78SClemens Ladisch static int __devinit 89802c2de69STakashi Iwai snd_ad1889_create(struct snd_card *card, 89912bb5b78SClemens Ladisch struct pci_dev *pci, 90012bb5b78SClemens Ladisch struct snd_ad1889 **rchip) 90112bb5b78SClemens Ladisch { 90212bb5b78SClemens Ladisch int err; 90312bb5b78SClemens Ladisch 90412bb5b78SClemens Ladisch struct snd_ad1889 *chip; 90502c2de69STakashi Iwai static struct snd_device_ops ops = { 90612bb5b78SClemens Ladisch .dev_free = snd_ad1889_dev_free, 90712bb5b78SClemens Ladisch }; 90812bb5b78SClemens Ladisch 90912bb5b78SClemens Ladisch *rchip = NULL; 91012bb5b78SClemens Ladisch 91112bb5b78SClemens Ladisch if ((err = pci_enable_device(pci)) < 0) 91212bb5b78SClemens Ladisch return err; 91312bb5b78SClemens Ladisch 91412bb5b78SClemens Ladisch /* check PCI availability (32bit DMA) */ 9159d2f928dSTobias Klauser if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || 9169d2f928dSTobias Klauser pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { 91712bb5b78SClemens Ladisch printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n"); 91812bb5b78SClemens Ladisch pci_disable_device(pci); 91912bb5b78SClemens Ladisch return -ENXIO; 92012bb5b78SClemens Ladisch } 92112bb5b78SClemens Ladisch 92212bb5b78SClemens Ladisch /* allocate chip specific data with zero-filled memory */ 923e560d8d8STakashi Iwai if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { 92412bb5b78SClemens Ladisch pci_disable_device(pci); 92512bb5b78SClemens Ladisch return -ENOMEM; 92612bb5b78SClemens Ladisch } 92712bb5b78SClemens Ladisch 92812bb5b78SClemens Ladisch chip->card = card; 92912bb5b78SClemens Ladisch card->private_data = chip; 93012bb5b78SClemens Ladisch chip->pci = pci; 93112bb5b78SClemens Ladisch chip->irq = -1; 93212bb5b78SClemens Ladisch 93312bb5b78SClemens Ladisch /* (1) PCI resource allocation */ 93412bb5b78SClemens Ladisch if ((err = pci_request_regions(pci, card->driver)) < 0) 93512bb5b78SClemens Ladisch goto free_and_ret; 93612bb5b78SClemens Ladisch 93712bb5b78SClemens Ladisch chip->bar = pci_resource_start(pci, 0); 93812bb5b78SClemens Ladisch chip->iobase = ioremap_nocache(chip->bar, pci_resource_len(pci, 0)); 93912bb5b78SClemens Ladisch if (chip->iobase == NULL) { 94012bb5b78SClemens Ladisch printk(KERN_ERR PFX "unable to reserve region.\n"); 94112bb5b78SClemens Ladisch err = -EBUSY; 94212bb5b78SClemens Ladisch goto free_and_ret; 94312bb5b78SClemens Ladisch } 94412bb5b78SClemens Ladisch 94512bb5b78SClemens Ladisch pci_set_master(pci); 94612bb5b78SClemens Ladisch 94712bb5b78SClemens Ladisch spin_lock_init(&chip->lock); /* only now can we call ad1889_free */ 94812bb5b78SClemens Ladisch 94912bb5b78SClemens Ladisch if (request_irq(pci->irq, snd_ad1889_interrupt, 95012bb5b78SClemens Ladisch SA_INTERRUPT|SA_SHIRQ, card->driver, (void*)chip)) { 95112bb5b78SClemens Ladisch printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); 95212bb5b78SClemens Ladisch snd_ad1889_free(chip); 95312bb5b78SClemens Ladisch return -EBUSY; 95412bb5b78SClemens Ladisch } 95512bb5b78SClemens Ladisch 95612bb5b78SClemens Ladisch chip->irq = pci->irq; 95712bb5b78SClemens Ladisch synchronize_irq(chip->irq); 95812bb5b78SClemens Ladisch 95912bb5b78SClemens Ladisch /* (2) initialization of the chip hardware */ 96012bb5b78SClemens Ladisch if ((err = snd_ad1889_init(chip)) < 0) { 96112bb5b78SClemens Ladisch snd_ad1889_free(chip); 96212bb5b78SClemens Ladisch return err; 96312bb5b78SClemens Ladisch } 96412bb5b78SClemens Ladisch 96512bb5b78SClemens Ladisch if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 96612bb5b78SClemens Ladisch snd_ad1889_free(chip); 96712bb5b78SClemens Ladisch return err; 96812bb5b78SClemens Ladisch } 96912bb5b78SClemens Ladisch 97012bb5b78SClemens Ladisch snd_card_set_dev(card, &pci->dev); 97112bb5b78SClemens Ladisch 97212bb5b78SClemens Ladisch *rchip = chip; 97312bb5b78SClemens Ladisch 97412bb5b78SClemens Ladisch return 0; 97512bb5b78SClemens Ladisch 97612bb5b78SClemens Ladisch free_and_ret: 97712bb5b78SClemens Ladisch kfree(chip); 97812bb5b78SClemens Ladisch pci_disable_device(pci); 97912bb5b78SClemens Ladisch 98012bb5b78SClemens Ladisch return err; 98112bb5b78SClemens Ladisch } 98212bb5b78SClemens Ladisch 98312bb5b78SClemens Ladisch static int __devinit 98412bb5b78SClemens Ladisch snd_ad1889_probe(struct pci_dev *pci, 98512bb5b78SClemens Ladisch const struct pci_device_id *pci_id) 98612bb5b78SClemens Ladisch { 98712bb5b78SClemens Ladisch int err; 98812bb5b78SClemens Ladisch static int devno; 98902c2de69STakashi Iwai struct snd_card *card; 99012bb5b78SClemens Ladisch struct snd_ad1889 *chip; 99112bb5b78SClemens Ladisch 99212bb5b78SClemens Ladisch /* (1) */ 99312bb5b78SClemens Ladisch if (devno >= SNDRV_CARDS) 99412bb5b78SClemens Ladisch return -ENODEV; 99512bb5b78SClemens Ladisch if (!enable[devno]) { 99612bb5b78SClemens Ladisch devno++; 99712bb5b78SClemens Ladisch return -ENOENT; 99812bb5b78SClemens Ladisch } 99912bb5b78SClemens Ladisch 100012bb5b78SClemens Ladisch /* (2) */ 100112bb5b78SClemens Ladisch card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); 100212bb5b78SClemens Ladisch /* XXX REVISIT: we can probably allocate chip in this call */ 100312bb5b78SClemens Ladisch if (card == NULL) 100412bb5b78SClemens Ladisch return -ENOMEM; 100512bb5b78SClemens Ladisch 100612bb5b78SClemens Ladisch strcpy(card->driver, "AD1889"); 100712bb5b78SClemens Ladisch strcpy(card->shortname, "Analog Devices AD1889"); 100812bb5b78SClemens Ladisch 100912bb5b78SClemens Ladisch /* (3) */ 101012bb5b78SClemens Ladisch err = snd_ad1889_create(card, pci, &chip); 101112bb5b78SClemens Ladisch if (err < 0) 101212bb5b78SClemens Ladisch goto free_and_ret; 101312bb5b78SClemens Ladisch 101412bb5b78SClemens Ladisch /* (4) */ 101512bb5b78SClemens Ladisch sprintf(card->longname, "%s at 0x%lx irq %i", 101612bb5b78SClemens Ladisch card->shortname, chip->bar, chip->irq); 101712bb5b78SClemens Ladisch 101812bb5b78SClemens Ladisch /* (5) */ 101912bb5b78SClemens Ladisch /* register AC97 mixer */ 102012bb5b78SClemens Ladisch err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]); 102112bb5b78SClemens Ladisch if (err < 0) 102212bb5b78SClemens Ladisch goto free_and_ret; 102312bb5b78SClemens Ladisch 102412bb5b78SClemens Ladisch err = snd_ad1889_pcm_init(chip, 0, NULL); 102512bb5b78SClemens Ladisch if (err < 0) 102612bb5b78SClemens Ladisch goto free_and_ret; 102712bb5b78SClemens Ladisch 102812bb5b78SClemens Ladisch /* register proc interface */ 102912bb5b78SClemens Ladisch snd_ad1889_proc_init(chip); 103012bb5b78SClemens Ladisch 103112bb5b78SClemens Ladisch /* (6) */ 103212bb5b78SClemens Ladisch err = snd_card_register(card); 103312bb5b78SClemens Ladisch if (err < 0) 103412bb5b78SClemens Ladisch goto free_and_ret; 103512bb5b78SClemens Ladisch 103612bb5b78SClemens Ladisch /* (7) */ 103712bb5b78SClemens Ladisch pci_set_drvdata(pci, card); 103812bb5b78SClemens Ladisch 103912bb5b78SClemens Ladisch devno++; 104012bb5b78SClemens Ladisch return 0; 104112bb5b78SClemens Ladisch 104212bb5b78SClemens Ladisch free_and_ret: 104312bb5b78SClemens Ladisch snd_card_free(card); 104412bb5b78SClemens Ladisch return err; 104512bb5b78SClemens Ladisch } 104612bb5b78SClemens Ladisch 104712bb5b78SClemens Ladisch static void __devexit 104812bb5b78SClemens Ladisch snd_ad1889_remove(struct pci_dev *pci) 104912bb5b78SClemens Ladisch { 105012bb5b78SClemens Ladisch snd_card_free(pci_get_drvdata(pci)); 105112bb5b78SClemens Ladisch pci_set_drvdata(pci, NULL); 105212bb5b78SClemens Ladisch } 105312bb5b78SClemens Ladisch 1054396c9b92SHenrik Kretzschmar static struct pci_device_id snd_ad1889_ids[] __devinitdata = { 105512bb5b78SClemens Ladisch { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) }, 105612bb5b78SClemens Ladisch { 0, }, 105712bb5b78SClemens Ladisch }; 105812bb5b78SClemens Ladisch MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); 105912bb5b78SClemens Ladisch 106012bb5b78SClemens Ladisch static struct pci_driver ad1889_pci = { 106112bb5b78SClemens Ladisch .name = "AD1889 Audio", 106212bb5b78SClemens Ladisch .id_table = snd_ad1889_ids, 106312bb5b78SClemens Ladisch .probe = snd_ad1889_probe, 106412bb5b78SClemens Ladisch .remove = __devexit_p(snd_ad1889_remove), 106512bb5b78SClemens Ladisch }; 106612bb5b78SClemens Ladisch 106712bb5b78SClemens Ladisch static int __init 106812bb5b78SClemens Ladisch alsa_ad1889_init(void) 106912bb5b78SClemens Ladisch { 107012bb5b78SClemens Ladisch return pci_register_driver(&ad1889_pci); 107112bb5b78SClemens Ladisch } 107212bb5b78SClemens Ladisch 107312bb5b78SClemens Ladisch static void __exit 107412bb5b78SClemens Ladisch alsa_ad1889_fini(void) 107512bb5b78SClemens Ladisch { 107612bb5b78SClemens Ladisch pci_unregister_driver(&ad1889_pci); 107712bb5b78SClemens Ladisch } 107812bb5b78SClemens Ladisch 107912bb5b78SClemens Ladisch module_init(alsa_ad1889_init); 108012bb5b78SClemens Ladisch module_exit(alsa_ad1889_fini); 1081