182c29810SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
212bb5b78SClemens Ladisch /* Analog Devices 1889 audio driver
312bb5b78SClemens Ladisch *
412bb5b78SClemens Ladisch * This is a driver for the AD1889 PCI audio chipset found
512bb5b78SClemens Ladisch * on the HP PA-RISC [BCJ]-xxx0 workstations.
612bb5b78SClemens Ladisch *
712bb5b78SClemens Ladisch * Copyright (C) 2004-2005, Kyle McMartin <kyle@parisc-linux.org>
812bb5b78SClemens Ladisch * Copyright (C) 2005, Thibaut Varene <varenet@parisc-linux.org>
912bb5b78SClemens Ladisch * Based on the OSS AD1889 driver by Randolph Chung <tausq@debian.org>
1012bb5b78SClemens Ladisch *
1112bb5b78SClemens Ladisch * TODO:
1212bb5b78SClemens Ladisch * Do we need to take care of CCS register?
1312bb5b78SClemens Ladisch * Maybe we could use finer grained locking (separate locks for pb/cap)?
1412bb5b78SClemens Ladisch * Wishlist:
1512bb5b78SClemens Ladisch * Control Interface (mixer) support
1612bb5b78SClemens Ladisch * Better AC97 support (VSR...)?
1712bb5b78SClemens Ladisch * PM support
1812bb5b78SClemens Ladisch * MIDI support
1912bb5b78SClemens Ladisch * Game Port support
2012bb5b78SClemens Ladisch * SG DMA support (this will need *a lot* of work)
2112bb5b78SClemens Ladisch */
2212bb5b78SClemens Ladisch
2312bb5b78SClemens Ladisch #include <linux/init.h>
2412bb5b78SClemens Ladisch #include <linux/pci.h>
259d2f928dSTobias Klauser #include <linux/dma-mapping.h>
2612bb5b78SClemens Ladisch #include <linux/slab.h>
2712bb5b78SClemens Ladisch #include <linux/interrupt.h>
2812bb5b78SClemens Ladisch #include <linux/compiler.h>
2912bb5b78SClemens Ladisch #include <linux/delay.h>
30da155d5bSPaul Gortmaker #include <linux/module.h>
316cbbfe1cSTakashi Iwai #include <linux/io.h>
3212bb5b78SClemens Ladisch
3312bb5b78SClemens Ladisch #include <sound/core.h>
3412bb5b78SClemens Ladisch #include <sound/pcm.h>
3512bb5b78SClemens Ladisch #include <sound/initval.h>
3612bb5b78SClemens Ladisch #include <sound/ac97_codec.h>
3712bb5b78SClemens Ladisch
3812bb5b78SClemens Ladisch #include "ad1889.h"
3912bb5b78SClemens Ladisch #include "ac97/ac97_id.h"
4012bb5b78SClemens Ladisch
41c6f43290SJaroslav Kysela #define AD1889_DRVVER "Version: 1.7"
4212bb5b78SClemens Ladisch
4312bb5b78SClemens Ladisch MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>");
4412bb5b78SClemens Ladisch MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver");
4512bb5b78SClemens Ladisch MODULE_LICENSE("GPL");
4612bb5b78SClemens Ladisch
4712bb5b78SClemens Ladisch static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
4812bb5b78SClemens Ladisch module_param_array(index, int, NULL, 0444);
4912bb5b78SClemens Ladisch MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard.");
5012bb5b78SClemens Ladisch
5112bb5b78SClemens Ladisch static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
5212bb5b78SClemens Ladisch module_param_array(id, charp, NULL, 0444);
5312bb5b78SClemens Ladisch MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard.");
5412bb5b78SClemens Ladisch
55a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
5612bb5b78SClemens Ladisch module_param_array(enable, bool, NULL, 0444);
5712bb5b78SClemens Ladisch MODULE_PARM_DESC(enable, "Enable AD1889 soundcard.");
5812bb5b78SClemens Ladisch
5912bb5b78SClemens Ladisch static char *ac97_quirk[SNDRV_CARDS];
6012bb5b78SClemens Ladisch module_param_array(ac97_quirk, charp, NULL, 0444);
6112bb5b78SClemens Ladisch MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
6212bb5b78SClemens Ladisch
6312bb5b78SClemens Ladisch #define DEVNAME "ad1889"
6412bb5b78SClemens Ladisch #define PFX DEVNAME ": "
6512bb5b78SClemens Ladisch
6612bb5b78SClemens Ladisch /* keep track of some hw registers */
6712bb5b78SClemens Ladisch struct ad1889_register_state {
6812bb5b78SClemens Ladisch u16 reg; /* reg setup */
6912bb5b78SClemens Ladisch u32 addr; /* dma base address */
7012bb5b78SClemens Ladisch unsigned long size; /* DMA buffer size */
7112bb5b78SClemens Ladisch };
7212bb5b78SClemens Ladisch
7312bb5b78SClemens Ladisch struct snd_ad1889 {
7402c2de69STakashi Iwai struct snd_card *card;
7512bb5b78SClemens Ladisch struct pci_dev *pci;
7612bb5b78SClemens Ladisch
7712bb5b78SClemens Ladisch int irq;
7812bb5b78SClemens Ladisch unsigned long bar;
7912bb5b78SClemens Ladisch void __iomem *iobase;
8012bb5b78SClemens Ladisch
8102c2de69STakashi Iwai struct snd_ac97 *ac97;
8202c2de69STakashi Iwai struct snd_ac97_bus *ac97_bus;
8302c2de69STakashi Iwai struct snd_pcm *pcm;
8402c2de69STakashi Iwai struct snd_info_entry *proc;
8512bb5b78SClemens Ladisch
8602c2de69STakashi Iwai struct snd_pcm_substream *psubs;
8702c2de69STakashi Iwai struct snd_pcm_substream *csubs;
8812bb5b78SClemens Ladisch
8912bb5b78SClemens Ladisch /* playback register state */
9012bb5b78SClemens Ladisch struct ad1889_register_state wave;
9112bb5b78SClemens Ladisch struct ad1889_register_state ramc;
9212bb5b78SClemens Ladisch
9312bb5b78SClemens Ladisch spinlock_t lock;
9412bb5b78SClemens Ladisch };
9512bb5b78SClemens Ladisch
9612bb5b78SClemens Ladisch static inline u16
ad1889_readw(struct snd_ad1889 * chip,unsigned reg)9712bb5b78SClemens Ladisch ad1889_readw(struct snd_ad1889 *chip, unsigned reg)
9812bb5b78SClemens Ladisch {
9912bb5b78SClemens Ladisch return readw(chip->iobase + reg);
10012bb5b78SClemens Ladisch }
10112bb5b78SClemens Ladisch
10212bb5b78SClemens Ladisch static inline void
ad1889_writew(struct snd_ad1889 * chip,unsigned reg,u16 val)10312bb5b78SClemens Ladisch ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val)
10412bb5b78SClemens Ladisch {
10512bb5b78SClemens Ladisch writew(val, chip->iobase + reg);
10612bb5b78SClemens Ladisch }
10712bb5b78SClemens Ladisch
10812bb5b78SClemens Ladisch static inline u32
ad1889_readl(struct snd_ad1889 * chip,unsigned reg)10912bb5b78SClemens Ladisch ad1889_readl(struct snd_ad1889 *chip, unsigned reg)
11012bb5b78SClemens Ladisch {
11112bb5b78SClemens Ladisch return readl(chip->iobase + reg);
11212bb5b78SClemens Ladisch }
11312bb5b78SClemens Ladisch
11412bb5b78SClemens Ladisch static inline void
ad1889_writel(struct snd_ad1889 * chip,unsigned reg,u32 val)11512bb5b78SClemens Ladisch ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val)
11612bb5b78SClemens Ladisch {
11712bb5b78SClemens Ladisch writel(val, chip->iobase + reg);
11812bb5b78SClemens Ladisch }
11912bb5b78SClemens Ladisch
12012bb5b78SClemens Ladisch static inline void
ad1889_unmute(struct snd_ad1889 * chip)12112bb5b78SClemens Ladisch ad1889_unmute(struct snd_ad1889 *chip)
12212bb5b78SClemens Ladisch {
12312bb5b78SClemens Ladisch u16 st;
12412bb5b78SClemens Ladisch st = ad1889_readw(chip, AD_DS_WADA) &
12512bb5b78SClemens Ladisch ~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM);
12612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WADA, st);
12712bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WADA);
12812bb5b78SClemens Ladisch }
12912bb5b78SClemens Ladisch
13012bb5b78SClemens Ladisch static inline void
ad1889_mute(struct snd_ad1889 * chip)13112bb5b78SClemens Ladisch ad1889_mute(struct snd_ad1889 *chip)
13212bb5b78SClemens Ladisch {
13312bb5b78SClemens Ladisch u16 st;
13412bb5b78SClemens Ladisch st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM;
13512bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WADA, st);
13612bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WADA);
13712bb5b78SClemens Ladisch }
13812bb5b78SClemens Ladisch
13912bb5b78SClemens Ladisch static inline void
ad1889_load_adc_buffer_address(struct snd_ad1889 * chip,u32 address)14012bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address)
14112bb5b78SClemens Ladisch {
14212bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCBA, address);
14312bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCCA, address);
14412bb5b78SClemens Ladisch }
14512bb5b78SClemens Ladisch
14612bb5b78SClemens Ladisch static inline void
ad1889_load_adc_buffer_count(struct snd_ad1889 * chip,u32 count)14712bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count)
14812bb5b78SClemens Ladisch {
14912bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCBC, count);
15012bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCCC, count);
15112bb5b78SClemens Ladisch }
15212bb5b78SClemens Ladisch
15312bb5b78SClemens Ladisch static inline void
ad1889_load_adc_interrupt_count(struct snd_ad1889 * chip,u32 count)15412bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count)
15512bb5b78SClemens Ladisch {
15612bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCIB, count);
15712bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_ADCIC, count);
15812bb5b78SClemens Ladisch }
15912bb5b78SClemens Ladisch
16012bb5b78SClemens Ladisch static inline void
ad1889_load_wave_buffer_address(struct snd_ad1889 * chip,u32 address)16112bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address)
16212bb5b78SClemens Ladisch {
16312bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVBA, address);
16412bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVCA, address);
16512bb5b78SClemens Ladisch }
16612bb5b78SClemens Ladisch
16712bb5b78SClemens Ladisch static inline void
ad1889_load_wave_buffer_count(struct snd_ad1889 * chip,u32 count)16812bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count)
16912bb5b78SClemens Ladisch {
17012bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVBC, count);
17112bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVCC, count);
17212bb5b78SClemens Ladisch }
17312bb5b78SClemens Ladisch
17412bb5b78SClemens Ladisch static inline void
ad1889_load_wave_interrupt_count(struct snd_ad1889 * chip,u32 count)17512bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count)
17612bb5b78SClemens Ladisch {
17712bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVIB, count);
17812bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_WAVIC, count);
17912bb5b78SClemens Ladisch }
18012bb5b78SClemens Ladisch
18112bb5b78SClemens Ladisch static void
ad1889_channel_reset(struct snd_ad1889 * chip,unsigned int channel)18212bb5b78SClemens Ladisch ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel)
18312bb5b78SClemens Ladisch {
18412bb5b78SClemens Ladisch u16 reg;
18512bb5b78SClemens Ladisch
18612bb5b78SClemens Ladisch if (channel & AD_CHAN_WAV) {
18712bb5b78SClemens Ladisch /* Disable wave channel */
18812bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN;
18912bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, reg);
19012bb5b78SClemens Ladisch chip->wave.reg = reg;
19112bb5b78SClemens Ladisch
19212bb5b78SClemens Ladisch /* disable IRQs */
19312bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DMA_WAV);
19412bb5b78SClemens Ladisch reg &= AD_DMA_IM_DIS;
19512bb5b78SClemens Ladisch reg &= ~AD_DMA_LOOP;
19612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_WAV, reg);
19712bb5b78SClemens Ladisch
19812bb5b78SClemens Ladisch /* clear IRQ and address counters and pointers */
19912bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(chip, 0x0);
20012bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(chip, 0x0);
20112bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(chip, 0x0);
20212bb5b78SClemens Ladisch
20312bb5b78SClemens Ladisch /* flush */
20412bb5b78SClemens Ladisch ad1889_readw(chip, AD_DMA_WAV);
20512bb5b78SClemens Ladisch }
20612bb5b78SClemens Ladisch
20712bb5b78SClemens Ladisch if (channel & AD_CHAN_ADC) {
20812bb5b78SClemens Ladisch /* Disable ADC channel */
20912bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN;
21012bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, reg);
21112bb5b78SClemens Ladisch chip->ramc.reg = reg;
21212bb5b78SClemens Ladisch
21312bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DMA_ADC);
21412bb5b78SClemens Ladisch reg &= AD_DMA_IM_DIS;
21512bb5b78SClemens Ladisch reg &= ~AD_DMA_LOOP;
21612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_ADC, reg);
21712bb5b78SClemens Ladisch
21812bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(chip, 0x0);
21912bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(chip, 0x0);
22012bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(chip, 0x0);
22112bb5b78SClemens Ladisch
22212bb5b78SClemens Ladisch /* flush */
22312bb5b78SClemens Ladisch ad1889_readw(chip, AD_DMA_ADC);
22412bb5b78SClemens Ladisch }
22512bb5b78SClemens Ladisch }
22612bb5b78SClemens Ladisch
227f40b6890STakashi Iwai static u16
snd_ad1889_ac97_read(struct snd_ac97 * ac97,unsigned short reg)22802c2de69STakashi Iwai snd_ad1889_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
22912bb5b78SClemens Ladisch {
23012bb5b78SClemens Ladisch struct snd_ad1889 *chip = ac97->private_data;
23112bb5b78SClemens Ladisch return ad1889_readw(chip, AD_AC97_BASE + reg);
23212bb5b78SClemens Ladisch }
23312bb5b78SClemens Ladisch
234f40b6890STakashi Iwai static void
snd_ad1889_ac97_write(struct snd_ac97 * ac97,unsigned short reg,unsigned short val)23502c2de69STakashi Iwai snd_ad1889_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
23612bb5b78SClemens Ladisch {
23712bb5b78SClemens Ladisch struct snd_ad1889 *chip = ac97->private_data;
23812bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_BASE + reg, val);
23912bb5b78SClemens Ladisch }
24012bb5b78SClemens Ladisch
24112bb5b78SClemens Ladisch static int
snd_ad1889_ac97_ready(struct snd_ad1889 * chip)24212bb5b78SClemens Ladisch snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
24312bb5b78SClemens Ladisch {
24412bb5b78SClemens Ladisch int retry = 400; /* average needs 352 msec */
24512bb5b78SClemens Ladisch
24612bb5b78SClemens Ladisch while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY)
24712bb5b78SClemens Ladisch && --retry)
2481fa350b6SJia-Ju Bai usleep_range(1000, 2000);
24912bb5b78SClemens Ladisch if (!retry) {
25029633004STakashi Iwai dev_err(chip->card->dev, "[%s] Link is not ready.\n",
2519bf8e7ddSHarvey Harrison __func__);
25212bb5b78SClemens Ladisch return -EIO;
25312bb5b78SClemens Ladisch }
25429633004STakashi Iwai dev_dbg(chip->card->dev, "[%s] ready after %d ms\n", __func__, 400 - retry);
25512bb5b78SClemens Ladisch
25612bb5b78SClemens Ladisch return 0;
25712bb5b78SClemens Ladisch }
25812bb5b78SClemens Ladisch
259dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_ad1889_playback_hw = {
26012bb5b78SClemens Ladisch .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
26112bb5b78SClemens Ladisch SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
26212bb5b78SClemens Ladisch .formats = SNDRV_PCM_FMTBIT_S16_LE,
26312bb5b78SClemens Ladisch .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
26412bb5b78SClemens Ladisch .rate_min = 8000, /* docs say 7000, but we're lazy */
26512bb5b78SClemens Ladisch .rate_max = 48000,
26612bb5b78SClemens Ladisch .channels_min = 1,
26712bb5b78SClemens Ladisch .channels_max = 2,
26812bb5b78SClemens Ladisch .buffer_bytes_max = BUFFER_BYTES_MAX,
26912bb5b78SClemens Ladisch .period_bytes_min = PERIOD_BYTES_MIN,
27012bb5b78SClemens Ladisch .period_bytes_max = PERIOD_BYTES_MAX,
27112bb5b78SClemens Ladisch .periods_min = PERIODS_MIN,
27212bb5b78SClemens Ladisch .periods_max = PERIODS_MAX,
27312bb5b78SClemens Ladisch /*.fifo_size = 0,*/
27412bb5b78SClemens Ladisch };
27512bb5b78SClemens Ladisch
276dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_ad1889_capture_hw = {
27712bb5b78SClemens Ladisch .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
27812bb5b78SClemens Ladisch SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
27912bb5b78SClemens Ladisch .formats = SNDRV_PCM_FMTBIT_S16_LE,
28012bb5b78SClemens Ladisch .rates = SNDRV_PCM_RATE_48000,
28112bb5b78SClemens Ladisch .rate_min = 48000, /* docs say we could to VSR, but we're lazy */
28212bb5b78SClemens Ladisch .rate_max = 48000,
28312bb5b78SClemens Ladisch .channels_min = 1,
28412bb5b78SClemens Ladisch .channels_max = 2,
28512bb5b78SClemens Ladisch .buffer_bytes_max = BUFFER_BYTES_MAX,
28612bb5b78SClemens Ladisch .period_bytes_min = PERIOD_BYTES_MIN,
28712bb5b78SClemens Ladisch .period_bytes_max = PERIOD_BYTES_MAX,
28812bb5b78SClemens Ladisch .periods_min = PERIODS_MIN,
28912bb5b78SClemens Ladisch .periods_max = PERIODS_MAX,
29012bb5b78SClemens Ladisch /*.fifo_size = 0,*/
29112bb5b78SClemens Ladisch };
29212bb5b78SClemens Ladisch
29312bb5b78SClemens Ladisch static int
snd_ad1889_playback_open(struct snd_pcm_substream * ss)29402c2de69STakashi Iwai snd_ad1889_playback_open(struct snd_pcm_substream *ss)
29512bb5b78SClemens Ladisch {
29612bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
29702c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime;
29812bb5b78SClemens Ladisch
29912bb5b78SClemens Ladisch chip->psubs = ss;
30012bb5b78SClemens Ladisch rt->hw = snd_ad1889_playback_hw;
30112bb5b78SClemens Ladisch
30212bb5b78SClemens Ladisch return 0;
30312bb5b78SClemens Ladisch }
30412bb5b78SClemens Ladisch
30512bb5b78SClemens Ladisch static int
snd_ad1889_capture_open(struct snd_pcm_substream * ss)30602c2de69STakashi Iwai snd_ad1889_capture_open(struct snd_pcm_substream *ss)
30712bb5b78SClemens Ladisch {
30812bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
30902c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime;
31012bb5b78SClemens Ladisch
31112bb5b78SClemens Ladisch chip->csubs = ss;
31212bb5b78SClemens Ladisch rt->hw = snd_ad1889_capture_hw;
31312bb5b78SClemens Ladisch
31412bb5b78SClemens Ladisch return 0;
31512bb5b78SClemens Ladisch }
31612bb5b78SClemens Ladisch
31712bb5b78SClemens Ladisch static int
snd_ad1889_playback_close(struct snd_pcm_substream * ss)31802c2de69STakashi Iwai snd_ad1889_playback_close(struct snd_pcm_substream *ss)
31912bb5b78SClemens Ladisch {
32012bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
32112bb5b78SClemens Ladisch chip->psubs = NULL;
32212bb5b78SClemens Ladisch return 0;
32312bb5b78SClemens Ladisch }
32412bb5b78SClemens Ladisch
32512bb5b78SClemens Ladisch static int
snd_ad1889_capture_close(struct snd_pcm_substream * ss)32602c2de69STakashi Iwai snd_ad1889_capture_close(struct snd_pcm_substream *ss)
32712bb5b78SClemens Ladisch {
32812bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
32912bb5b78SClemens Ladisch chip->csubs = NULL;
33012bb5b78SClemens Ladisch return 0;
33112bb5b78SClemens Ladisch }
33212bb5b78SClemens Ladisch
33312bb5b78SClemens Ladisch static int
snd_ad1889_playback_prepare(struct snd_pcm_substream * ss)33402c2de69STakashi Iwai snd_ad1889_playback_prepare(struct snd_pcm_substream *ss)
33512bb5b78SClemens Ladisch {
33612bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
33702c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime;
33812bb5b78SClemens Ladisch unsigned int size = snd_pcm_lib_buffer_bytes(ss);
33912bb5b78SClemens Ladisch unsigned int count = snd_pcm_lib_period_bytes(ss);
34012bb5b78SClemens Ladisch u16 reg;
34112bb5b78SClemens Ladisch
34212bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV);
34312bb5b78SClemens Ladisch
34412bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC);
34512bb5b78SClemens Ladisch
34612bb5b78SClemens Ladisch /* Mask out 16-bit / Stereo */
34712bb5b78SClemens Ladisch reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST);
34812bb5b78SClemens Ladisch
34912bb5b78SClemens Ladisch if (snd_pcm_format_width(rt->format) == 16)
35012bb5b78SClemens Ladisch reg |= AD_DS_WSMC_WA16;
35112bb5b78SClemens Ladisch
35212bb5b78SClemens Ladisch if (rt->channels > 1)
35312bb5b78SClemens Ladisch reg |= AD_DS_WSMC_WAST;
35412bb5b78SClemens Ladisch
35512bb5b78SClemens Ladisch /* let's make sure we don't clobber ourselves */
35612bb5b78SClemens Ladisch spin_lock_irq(&chip->lock);
35712bb5b78SClemens Ladisch
35812bb5b78SClemens Ladisch chip->wave.size = size;
35912bb5b78SClemens Ladisch chip->wave.reg = reg;
36012bb5b78SClemens Ladisch chip->wave.addr = rt->dma_addr;
36112bb5b78SClemens Ladisch
36212bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg);
36312bb5b78SClemens Ladisch
36412bb5b78SClemens Ladisch /* Set sample rates on the codec */
36512bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WAS, rt->rate);
36612bb5b78SClemens Ladisch
36712bb5b78SClemens Ladisch /* Set up DMA */
36812bb5b78SClemens Ladisch ad1889_load_wave_buffer_address(chip, chip->wave.addr);
36912bb5b78SClemens Ladisch ad1889_load_wave_buffer_count(chip, size);
37012bb5b78SClemens Ladisch ad1889_load_wave_interrupt_count(chip, count);
37112bb5b78SClemens Ladisch
37212bb5b78SClemens Ladisch /* writes flush */
37312bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WSMC);
37412bb5b78SClemens Ladisch
37512bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock);
37612bb5b78SClemens Ladisch
37729633004STakashi Iwai dev_dbg(chip->card->dev,
37829633004STakashi Iwai "prepare playback: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n",
37929633004STakashi Iwai chip->wave.addr, count, size, reg, rt->rate);
38012bb5b78SClemens Ladisch return 0;
38112bb5b78SClemens Ladisch }
38212bb5b78SClemens Ladisch
38312bb5b78SClemens Ladisch static int
snd_ad1889_capture_prepare(struct snd_pcm_substream * ss)38402c2de69STakashi Iwai snd_ad1889_capture_prepare(struct snd_pcm_substream *ss)
38512bb5b78SClemens Ladisch {
38612bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
38702c2de69STakashi Iwai struct snd_pcm_runtime *rt = ss->runtime;
38812bb5b78SClemens Ladisch unsigned int size = snd_pcm_lib_buffer_bytes(ss);
38912bb5b78SClemens Ladisch unsigned int count = snd_pcm_lib_period_bytes(ss);
39012bb5b78SClemens Ladisch u16 reg;
39112bb5b78SClemens Ladisch
39212bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_ADC);
39312bb5b78SClemens Ladisch
39412bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC);
39512bb5b78SClemens Ladisch
39612bb5b78SClemens Ladisch /* Mask out 16-bit / Stereo */
39712bb5b78SClemens Ladisch reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);
39812bb5b78SClemens Ladisch
39912bb5b78SClemens Ladisch if (snd_pcm_format_width(rt->format) == 16)
40012bb5b78SClemens Ladisch reg |= AD_DS_RAMC_AD16;
40112bb5b78SClemens Ladisch
40212bb5b78SClemens Ladisch if (rt->channels > 1)
40312bb5b78SClemens Ladisch reg |= AD_DS_RAMC_ADST;
40412bb5b78SClemens Ladisch
40512bb5b78SClemens Ladisch /* let's make sure we don't clobber ourselves */
40612bb5b78SClemens Ladisch spin_lock_irq(&chip->lock);
40712bb5b78SClemens Ladisch
40812bb5b78SClemens Ladisch chip->ramc.size = size;
40912bb5b78SClemens Ladisch chip->ramc.reg = reg;
41012bb5b78SClemens Ladisch chip->ramc.addr = rt->dma_addr;
41112bb5b78SClemens Ladisch
41212bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);
41312bb5b78SClemens Ladisch
41412bb5b78SClemens Ladisch /* Set up DMA */
41512bb5b78SClemens Ladisch ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
41612bb5b78SClemens Ladisch ad1889_load_adc_buffer_count(chip, size);
41712bb5b78SClemens Ladisch ad1889_load_adc_interrupt_count(chip, count);
41812bb5b78SClemens Ladisch
41912bb5b78SClemens Ladisch /* writes flush */
42012bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_RAMC);
42112bb5b78SClemens Ladisch
42212bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock);
42312bb5b78SClemens Ladisch
42429633004STakashi Iwai dev_dbg(chip->card->dev,
42529633004STakashi Iwai "prepare capture: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n",
42629633004STakashi Iwai chip->ramc.addr, count, size, reg, rt->rate);
42712bb5b78SClemens Ladisch return 0;
42812bb5b78SClemens Ladisch }
42912bb5b78SClemens Ladisch
43012bb5b78SClemens Ladisch /* this is called in atomic context with IRQ disabled.
43112bb5b78SClemens Ladisch Must be as fast as possible and not sleep.
43212bb5b78SClemens Ladisch DMA should be *triggered* by this call.
43312bb5b78SClemens Ladisch The WSMC "WAEN" bit triggers DMA Wave On/Off */
43412bb5b78SClemens Ladisch static int
snd_ad1889_playback_trigger(struct snd_pcm_substream * ss,int cmd)43502c2de69STakashi Iwai snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd)
43612bb5b78SClemens Ladisch {
43712bb5b78SClemens Ladisch u16 wsmc;
43812bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
43912bb5b78SClemens Ladisch
44012bb5b78SClemens Ladisch wsmc = ad1889_readw(chip, AD_DS_WSMC);
44112bb5b78SClemens Ladisch
44212bb5b78SClemens Ladisch switch (cmd) {
44312bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_START:
44412bb5b78SClemens Ladisch /* enable DMA loop & interrupts */
44512bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT);
44612bb5b78SClemens Ladisch wsmc |= AD_DS_WSMC_WAEN;
44712bb5b78SClemens Ladisch /* 1 to clear CHSS bit */
44812bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS);
44912bb5b78SClemens Ladisch ad1889_unmute(chip);
45012bb5b78SClemens Ladisch break;
45112bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_STOP:
45212bb5b78SClemens Ladisch ad1889_mute(chip);
45312bb5b78SClemens Ladisch wsmc &= ~AD_DS_WSMC_WAEN;
45412bb5b78SClemens Ladisch break;
45512bb5b78SClemens Ladisch default:
45612bb5b78SClemens Ladisch snd_BUG();
45712bb5b78SClemens Ladisch return -EINVAL;
45812bb5b78SClemens Ladisch }
45912bb5b78SClemens Ladisch
46012bb5b78SClemens Ladisch chip->wave.reg = wsmc;
46112bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_WSMC, wsmc);
46212bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_WSMC); /* flush */
46312bb5b78SClemens Ladisch
46412bb5b78SClemens Ladisch /* reset the chip when STOP - will disable IRQs */
46512bb5b78SClemens Ladisch if (cmd == SNDRV_PCM_TRIGGER_STOP)
46612bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV);
46712bb5b78SClemens Ladisch
46812bb5b78SClemens Ladisch return 0;
46912bb5b78SClemens Ladisch }
47012bb5b78SClemens Ladisch
47112bb5b78SClemens Ladisch /* this is called in atomic context with IRQ disabled.
47212bb5b78SClemens Ladisch Must be as fast as possible and not sleep.
47312bb5b78SClemens Ladisch DMA should be *triggered* by this call.
47412bb5b78SClemens Ladisch The RAMC "ADEN" bit triggers DMA ADC On/Off */
47512bb5b78SClemens Ladisch static int
snd_ad1889_capture_trigger(struct snd_pcm_substream * ss,int cmd)47602c2de69STakashi Iwai snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd)
47712bb5b78SClemens Ladisch {
47812bb5b78SClemens Ladisch u16 ramc;
47912bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
48012bb5b78SClemens Ladisch
48112bb5b78SClemens Ladisch ramc = ad1889_readw(chip, AD_DS_RAMC);
48212bb5b78SClemens Ladisch
48312bb5b78SClemens Ladisch switch (cmd) {
48412bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_START:
48512bb5b78SClemens Ladisch /* enable DMA loop & interrupts */
48612bb5b78SClemens Ladisch ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT);
48712bb5b78SClemens Ladisch ramc |= AD_DS_RAMC_ADEN;
48812bb5b78SClemens Ladisch /* 1 to clear CHSS bit */
48912bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS);
49012bb5b78SClemens Ladisch break;
49112bb5b78SClemens Ladisch case SNDRV_PCM_TRIGGER_STOP:
49212bb5b78SClemens Ladisch ramc &= ~AD_DS_RAMC_ADEN;
49312bb5b78SClemens Ladisch break;
49412bb5b78SClemens Ladisch default:
49512bb5b78SClemens Ladisch return -EINVAL;
49612bb5b78SClemens Ladisch }
49712bb5b78SClemens Ladisch
49812bb5b78SClemens Ladisch chip->ramc.reg = ramc;
49912bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_RAMC, ramc);
50012bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_RAMC); /* flush */
50112bb5b78SClemens Ladisch
50212bb5b78SClemens Ladisch /* reset the chip when STOP - will disable IRQs */
50312bb5b78SClemens Ladisch if (cmd == SNDRV_PCM_TRIGGER_STOP)
50412bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_ADC);
50512bb5b78SClemens Ladisch
50612bb5b78SClemens Ladisch return 0;
50712bb5b78SClemens Ladisch }
50812bb5b78SClemens Ladisch
50912bb5b78SClemens Ladisch /* Called in atomic context with IRQ disabled */
51012bb5b78SClemens Ladisch static snd_pcm_uframes_t
snd_ad1889_playback_pointer(struct snd_pcm_substream * ss)51102c2de69STakashi Iwai snd_ad1889_playback_pointer(struct snd_pcm_substream *ss)
51212bb5b78SClemens Ladisch {
51312bb5b78SClemens Ladisch size_t ptr = 0;
51412bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
51512bb5b78SClemens Ladisch
51612bb5b78SClemens Ladisch if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN)))
51712bb5b78SClemens Ladisch return 0;
51812bb5b78SClemens Ladisch
51912bb5b78SClemens Ladisch ptr = ad1889_readl(chip, AD_DMA_WAVCA);
52012bb5b78SClemens Ladisch ptr -= chip->wave.addr;
52112bb5b78SClemens Ladisch
522da3cec35STakashi Iwai if (snd_BUG_ON(ptr >= chip->wave.size))
523da3cec35STakashi Iwai return 0;
52412bb5b78SClemens Ladisch
52512bb5b78SClemens Ladisch return bytes_to_frames(ss->runtime, ptr);
52612bb5b78SClemens Ladisch }
52712bb5b78SClemens Ladisch
52812bb5b78SClemens Ladisch /* Called in atomic context with IRQ disabled */
52912bb5b78SClemens Ladisch static snd_pcm_uframes_t
snd_ad1889_capture_pointer(struct snd_pcm_substream * ss)53002c2de69STakashi Iwai snd_ad1889_capture_pointer(struct snd_pcm_substream *ss)
53112bb5b78SClemens Ladisch {
53212bb5b78SClemens Ladisch size_t ptr = 0;
53312bb5b78SClemens Ladisch struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
53412bb5b78SClemens Ladisch
53512bb5b78SClemens Ladisch if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN)))
53612bb5b78SClemens Ladisch return 0;
53712bb5b78SClemens Ladisch
53812bb5b78SClemens Ladisch ptr = ad1889_readl(chip, AD_DMA_ADCCA);
53912bb5b78SClemens Ladisch ptr -= chip->ramc.addr;
54012bb5b78SClemens Ladisch
541da3cec35STakashi Iwai if (snd_BUG_ON(ptr >= chip->ramc.size))
542da3cec35STakashi Iwai return 0;
54312bb5b78SClemens Ladisch
54412bb5b78SClemens Ladisch return bytes_to_frames(ss->runtime, ptr);
54512bb5b78SClemens Ladisch }
54612bb5b78SClemens Ladisch
547d602efcaSJulia Lawall static const struct snd_pcm_ops snd_ad1889_playback_ops = {
54812bb5b78SClemens Ladisch .open = snd_ad1889_playback_open,
54912bb5b78SClemens Ladisch .close = snd_ad1889_playback_close,
55012bb5b78SClemens Ladisch .prepare = snd_ad1889_playback_prepare,
55112bb5b78SClemens Ladisch .trigger = snd_ad1889_playback_trigger,
55212bb5b78SClemens Ladisch .pointer = snd_ad1889_playback_pointer,
55312bb5b78SClemens Ladisch };
55412bb5b78SClemens Ladisch
555d602efcaSJulia Lawall static const struct snd_pcm_ops snd_ad1889_capture_ops = {
55612bb5b78SClemens Ladisch .open = snd_ad1889_capture_open,
55712bb5b78SClemens Ladisch .close = snd_ad1889_capture_close,
55812bb5b78SClemens Ladisch .prepare = snd_ad1889_capture_prepare,
55912bb5b78SClemens Ladisch .trigger = snd_ad1889_capture_trigger,
56012bb5b78SClemens Ladisch .pointer = snd_ad1889_capture_pointer,
56112bb5b78SClemens Ladisch };
56212bb5b78SClemens Ladisch
56312bb5b78SClemens Ladisch static irqreturn_t
snd_ad1889_interrupt(int irq,void * dev_id)5647d12e780SDavid Howells snd_ad1889_interrupt(int irq, void *dev_id)
56512bb5b78SClemens Ladisch {
56612bb5b78SClemens Ladisch unsigned long st;
56712bb5b78SClemens Ladisch struct snd_ad1889 *chip = dev_id;
56812bb5b78SClemens Ladisch
56912bb5b78SClemens Ladisch st = ad1889_readl(chip, AD_DMA_DISR);
57012bb5b78SClemens Ladisch
57112bb5b78SClemens Ladisch /* clear ISR */
57212bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, st);
57312bb5b78SClemens Ladisch
57412bb5b78SClemens Ladisch st &= AD_INTR_MASK;
57512bb5b78SClemens Ladisch
57612bb5b78SClemens Ladisch if (unlikely(!st))
57712bb5b78SClemens Ladisch return IRQ_NONE;
57812bb5b78SClemens Ladisch
57912bb5b78SClemens Ladisch if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI))
58029633004STakashi Iwai dev_dbg(chip->card->dev,
58129633004STakashi Iwai "Unexpected master or target abort interrupt!\n");
58212bb5b78SClemens Ladisch
58312bb5b78SClemens Ladisch if ((st & AD_DMA_DISR_WAVI) && chip->psubs)
58412bb5b78SClemens Ladisch snd_pcm_period_elapsed(chip->psubs);
58512bb5b78SClemens Ladisch if ((st & AD_DMA_DISR_ADCI) && chip->csubs)
58612bb5b78SClemens Ladisch snd_pcm_period_elapsed(chip->csubs);
58712bb5b78SClemens Ladisch
58812bb5b78SClemens Ladisch return IRQ_HANDLED;
58912bb5b78SClemens Ladisch }
59012bb5b78SClemens Ladisch
5912f5c1302SBill Pemberton static int
snd_ad1889_pcm_init(struct snd_ad1889 * chip,int device)592a0880094SLars-Peter Clausen snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device)
59312bb5b78SClemens Ladisch {
59412bb5b78SClemens Ladisch int err;
59502c2de69STakashi Iwai struct snd_pcm *pcm;
59612bb5b78SClemens Ladisch
59712bb5b78SClemens Ladisch err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm);
59812bb5b78SClemens Ladisch if (err < 0)
59912bb5b78SClemens Ladisch return err;
60012bb5b78SClemens Ladisch
60112bb5b78SClemens Ladisch snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
60212bb5b78SClemens Ladisch &snd_ad1889_playback_ops);
60312bb5b78SClemens Ladisch snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
60412bb5b78SClemens Ladisch &snd_ad1889_capture_ops);
60512bb5b78SClemens Ladisch
60612bb5b78SClemens Ladisch pcm->private_data = chip;
60712bb5b78SClemens Ladisch pcm->info_flags = 0;
60812bb5b78SClemens Ladisch strcpy(pcm->name, chip->card->shortname);
60912bb5b78SClemens Ladisch
61012bb5b78SClemens Ladisch chip->pcm = pcm;
61112bb5b78SClemens Ladisch chip->psubs = NULL;
61212bb5b78SClemens Ladisch chip->csubs = NULL;
61312bb5b78SClemens Ladisch
61493d6487fSTakashi Iwai snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
61593d6487fSTakashi Iwai BUFFER_BYTES_MAX / 2, BUFFER_BYTES_MAX);
61612bb5b78SClemens Ladisch
61712bb5b78SClemens Ladisch return 0;
61812bb5b78SClemens Ladisch }
61912bb5b78SClemens Ladisch
62012bb5b78SClemens Ladisch static void
snd_ad1889_proc_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)62102c2de69STakashi Iwai snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
62212bb5b78SClemens Ladisch {
62312bb5b78SClemens Ladisch struct snd_ad1889 *chip = entry->private_data;
62412bb5b78SClemens Ladisch u16 reg;
62512bb5b78SClemens Ladisch int tmp;
62612bb5b78SClemens Ladisch
62712bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WSMC);
62812bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave output: %s\n",
62912bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled");
63012bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave Channels: %s\n",
63112bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
63212bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave Quality: %d-bit linear\n",
63312bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WA16) ? 16 : 8);
63412bb5b78SClemens Ladisch
63512bb5b78SClemens Ladisch /* WARQ is at offset 12 */
63612bb5b78SClemens Ladisch tmp = (reg & AD_DS_WSMC_WARQ) ?
637ccbec5eaSJoe Perches ((((reg & AD_DS_WSMC_WARQ) >> 12) & 0x01) ? 12 : 18) : 4;
63812bb5b78SClemens Ladisch tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
63912bb5b78SClemens Ladisch
64012bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
64112bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
64212bb5b78SClemens Ladisch
64312bb5b78SClemens Ladisch
64412bb5b78SClemens Ladisch snd_iprintf(buffer, "Synthesis output: %s\n",
64512bb5b78SClemens Ladisch reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled");
64612bb5b78SClemens Ladisch
64712bb5b78SClemens Ladisch /* SYRQ is at offset 4 */
64812bb5b78SClemens Ladisch tmp = (reg & AD_DS_WSMC_SYRQ) ?
649ccbec5eaSJoe Perches ((((reg & AD_DS_WSMC_SYRQ) >> 4) & 0x01) ? 12 : 18) : 4;
65012bb5b78SClemens Ladisch tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
65112bb5b78SClemens Ladisch
65212bb5b78SClemens Ladisch snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
65312bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
65412bb5b78SClemens Ladisch
65512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RAMC);
65612bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC input: %s\n",
65712bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled");
65812bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC Channels: %s\n",
65912bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
66012bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC Quality: %d-bit linear\n",
66112bb5b78SClemens Ladisch (reg & AD_DS_RAMC_AD16) ? 16 : 8);
66212bb5b78SClemens Ladisch
66312bb5b78SClemens Ladisch /* ACRQ is at offset 4 */
66412bb5b78SClemens Ladisch tmp = (reg & AD_DS_RAMC_ACRQ) ?
665ccbec5eaSJoe Perches ((((reg & AD_DS_RAMC_ACRQ) >> 4) & 0x01) ? 12 : 18) : 4;
66612bb5b78SClemens Ladisch tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
66712bb5b78SClemens Ladisch
66812bb5b78SClemens Ladisch snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
66912bb5b78SClemens Ladisch (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
67012bb5b78SClemens Ladisch
67112bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler input: %s\n",
67212bb5b78SClemens Ladisch reg & AD_DS_RAMC_REEN ? "enabled" : "disabled");
67312bb5b78SClemens Ladisch
67412bb5b78SClemens Ladisch /* RERQ is at offset 12 */
67512bb5b78SClemens Ladisch tmp = (reg & AD_DS_RAMC_RERQ) ?
676ccbec5eaSJoe Perches ((((reg & AD_DS_RAMC_RERQ) >> 12) & 0x01) ? 12 : 18) : 4;
67712bb5b78SClemens Ladisch tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
67812bb5b78SClemens Ladisch
67912bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
68012bb5b78SClemens Ladisch (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
68112bb5b78SClemens Ladisch
68212bb5b78SClemens Ladisch
68312bb5b78SClemens Ladisch /* doc says LSB represents -1.5dB, but the max value (-94.5dB)
68412bb5b78SClemens Ladisch suggests that LSB is -3dB, which is more coherent with the logarithmic
68512bb5b78SClemens Ladisch nature of the dB scale */
68612bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WADA);
68712bb5b78SClemens Ladisch snd_iprintf(buffer, "Left: %s, -%d dB\n",
68812bb5b78SClemens Ladisch (reg & AD_DS_WADA_LWAM) ? "mute" : "unmute",
68912bb5b78SClemens Ladisch ((reg & AD_DS_WADA_LWAA) >> 8) * 3);
69012bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WADA);
69112bb5b78SClemens Ladisch snd_iprintf(buffer, "Right: %s, -%d dB\n",
69212bb5b78SClemens Ladisch (reg & AD_DS_WADA_RWAM) ? "mute" : "unmute",
6939bd0f5c0STakashi Iwai (reg & AD_DS_WADA_RWAA) * 3);
69412bb5b78SClemens Ladisch
69512bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_WAS);
69612bb5b78SClemens Ladisch snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg);
69712bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_DS_RES);
69812bb5b78SClemens Ladisch snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
69912bb5b78SClemens Ladisch }
70012bb5b78SClemens Ladisch
7012f5c1302SBill Pemberton static void
snd_ad1889_proc_init(struct snd_ad1889 * chip)70212bb5b78SClemens Ladisch snd_ad1889_proc_init(struct snd_ad1889 *chip)
70312bb5b78SClemens Ladisch {
70447f2769bSTakashi Iwai snd_card_ro_proc_new(chip->card, chip->card->driver,
70547f2769bSTakashi Iwai chip, snd_ad1889_proc_read);
70612bb5b78SClemens Ladisch }
70712bb5b78SClemens Ladisch
708eab0fbfaSJoe Perches static const struct ac97_quirk ac97_quirks[] = {
70912bb5b78SClemens Ladisch {
71012bb5b78SClemens Ladisch .subvendor = 0x11d4, /* AD */
71112bb5b78SClemens Ladisch .subdevice = 0x1889, /* AD1889 */
71212bb5b78SClemens Ladisch .codec_id = AC97_ID_AD1819,
71312bb5b78SClemens Ladisch .name = "AD1889",
71412bb5b78SClemens Ladisch .type = AC97_TUNE_HP_ONLY
71512bb5b78SClemens Ladisch },
71612bb5b78SClemens Ladisch { } /* terminator */
71712bb5b78SClemens Ladisch };
71812bb5b78SClemens Ladisch
7192f5c1302SBill Pemberton static void
snd_ad1889_ac97_xinit(struct snd_ad1889 * chip)72012bb5b78SClemens Ladisch snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
72112bb5b78SClemens Ladisch {
72212bb5b78SClemens Ladisch u16 reg;
72312bb5b78SClemens Ladisch
72412bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_AC97_ACIC);
72512bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ACRD; /* Reset Disable */
72612bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg);
72712bb5b78SClemens Ladisch ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
72812bb5b78SClemens Ladisch udelay(10);
72912bb5b78SClemens Ladisch /* Interface Enable */
73012bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ACIE;
73112bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg);
73212bb5b78SClemens Ladisch
73312bb5b78SClemens Ladisch snd_ad1889_ac97_ready(chip);
73412bb5b78SClemens Ladisch
73512bb5b78SClemens Ladisch /* Audio Stream Output | Variable Sample Rate Mode */
73612bb5b78SClemens Ladisch reg = ad1889_readw(chip, AD_AC97_ACIC);
73712bb5b78SClemens Ladisch reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM;
73812bb5b78SClemens Ladisch ad1889_writew(chip, AD_AC97_ACIC, reg);
73912bb5b78SClemens Ladisch ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
74012bb5b78SClemens Ladisch
74112bb5b78SClemens Ladisch }
74212bb5b78SClemens Ladisch
7432f5c1302SBill Pemberton static int
snd_ad1889_ac97_init(struct snd_ad1889 * chip,const char * quirk_override)74412bb5b78SClemens Ladisch snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
74512bb5b78SClemens Ladisch {
74612bb5b78SClemens Ladisch int err;
74702c2de69STakashi Iwai struct snd_ac97_template ac97;
74851055da5STakashi Iwai static const struct snd_ac97_bus_ops ops = {
74912bb5b78SClemens Ladisch .write = snd_ad1889_ac97_write,
75012bb5b78SClemens Ladisch .read = snd_ad1889_ac97_read,
75112bb5b78SClemens Ladisch };
75212bb5b78SClemens Ladisch
75312bb5b78SClemens Ladisch /* doing that here, it works. */
75412bb5b78SClemens Ladisch snd_ad1889_ac97_xinit(chip);
75512bb5b78SClemens Ladisch
75612bb5b78SClemens Ladisch err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
75712bb5b78SClemens Ladisch if (err < 0)
75812bb5b78SClemens Ladisch return err;
75912bb5b78SClemens Ladisch
76012bb5b78SClemens Ladisch memset(&ac97, 0, sizeof(ac97));
76112bb5b78SClemens Ladisch ac97.private_data = chip;
76212bb5b78SClemens Ladisch ac97.pci = chip->pci;
76312bb5b78SClemens Ladisch
76412bb5b78SClemens Ladisch err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
76512bb5b78SClemens Ladisch if (err < 0)
76612bb5b78SClemens Ladisch return err;
76712bb5b78SClemens Ladisch
76812bb5b78SClemens Ladisch snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);
76912bb5b78SClemens Ladisch
77012bb5b78SClemens Ladisch return 0;
77112bb5b78SClemens Ladisch }
77212bb5b78SClemens Ladisch
773567f5875STakashi Iwai static void
snd_ad1889_free(struct snd_card * card)774567f5875STakashi Iwai snd_ad1889_free(struct snd_card *card)
77512bb5b78SClemens Ladisch {
776567f5875STakashi Iwai struct snd_ad1889 *chip = card->private_data;
77712bb5b78SClemens Ladisch
77812bb5b78SClemens Ladisch spin_lock_irq(&chip->lock);
77912bb5b78SClemens Ladisch
78012bb5b78SClemens Ladisch ad1889_mute(chip);
78112bb5b78SClemens Ladisch
78212bb5b78SClemens Ladisch /* Turn off interrupt on count and zero DMA registers */
78312bb5b78SClemens Ladisch ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC);
78412bb5b78SClemens Ladisch
78512bb5b78SClemens Ladisch /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */
78612bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI);
78712bb5b78SClemens Ladisch ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */
78812bb5b78SClemens Ladisch
78912bb5b78SClemens Ladisch spin_unlock_irq(&chip->lock);
79012bb5b78SClemens Ladisch }
79112bb5b78SClemens Ladisch
792f40b6890STakashi Iwai static int
snd_ad1889_create(struct snd_card * card,struct pci_dev * pci)793567f5875STakashi Iwai snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
79412bb5b78SClemens Ladisch {
795567f5875STakashi Iwai struct snd_ad1889 *chip = card->private_data;
796567f5875STakashi Iwai int err;
797567f5875STakashi Iwai
798567f5875STakashi Iwai err = pcim_enable_device(pci);
799567f5875STakashi Iwai if (err < 0)
800567f5875STakashi Iwai return err;
801567f5875STakashi Iwai
802567f5875STakashi Iwai /* check PCI availability (32bit DMA) */
803567f5875STakashi Iwai if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
804567f5875STakashi Iwai dev_err(card->dev, "error setting 32-bit DMA mask.\n");
805567f5875STakashi Iwai return -ENXIO;
80612bb5b78SClemens Ladisch }
80712bb5b78SClemens Ladisch
808567f5875STakashi Iwai chip->card = card;
809567f5875STakashi Iwai chip->pci = pci;
810567f5875STakashi Iwai chip->irq = -1;
811567f5875STakashi Iwai
812567f5875STakashi Iwai /* (1) PCI resource allocation */
813567f5875STakashi Iwai err = pcim_iomap_regions(pci, 1 << 0, card->driver);
814567f5875STakashi Iwai if (err < 0)
815567f5875STakashi Iwai return err;
816567f5875STakashi Iwai
817567f5875STakashi Iwai chip->bar = pci_resource_start(pci, 0);
818567f5875STakashi Iwai chip->iobase = pcim_iomap_table(pci)[0];
819567f5875STakashi Iwai
820567f5875STakashi Iwai pci_set_master(pci);
821567f5875STakashi Iwai
822567f5875STakashi Iwai spin_lock_init(&chip->lock); /* only now can we call ad1889_free */
823567f5875STakashi Iwai
824567f5875STakashi Iwai if (devm_request_irq(&pci->dev, pci->irq, snd_ad1889_interrupt,
825567f5875STakashi Iwai IRQF_SHARED, KBUILD_MODNAME, chip)) {
826567f5875STakashi Iwai dev_err(card->dev, "cannot obtain IRQ %d\n", pci->irq);
827567f5875STakashi Iwai return -EBUSY;
828567f5875STakashi Iwai }
829567f5875STakashi Iwai
830567f5875STakashi Iwai chip->irq = pci->irq;
831567f5875STakashi Iwai card->sync_irq = chip->irq;
832567f5875STakashi Iwai card->private_free = snd_ad1889_free;
833567f5875STakashi Iwai
834567f5875STakashi Iwai /* (2) initialization of the chip hardware */
83512bb5b78SClemens Ladisch ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
83612bb5b78SClemens Ladisch ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
83712bb5b78SClemens Ladisch
838621fdf60SJia-Ju Bai usleep_range(10000, 11000);
83912bb5b78SClemens Ladisch
84012bb5b78SClemens Ladisch /* enable Master and Target abort interrupts */
84112bb5b78SClemens Ladisch ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
84212bb5b78SClemens Ladisch
84312bb5b78SClemens Ladisch return 0;
84412bb5b78SClemens Ladisch }
84512bb5b78SClemens Ladisch
8462f5c1302SBill Pemberton static int
__snd_ad1889_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)847*872e5fa0STakashi Iwai __snd_ad1889_probe(struct pci_dev *pci,
84812bb5b78SClemens Ladisch const struct pci_device_id *pci_id)
84912bb5b78SClemens Ladisch {
85012bb5b78SClemens Ladisch int err;
85112bb5b78SClemens Ladisch static int devno;
85202c2de69STakashi Iwai struct snd_card *card;
85312bb5b78SClemens Ladisch struct snd_ad1889 *chip;
85412bb5b78SClemens Ladisch
85512bb5b78SClemens Ladisch /* (1) */
85612bb5b78SClemens Ladisch if (devno >= SNDRV_CARDS)
85712bb5b78SClemens Ladisch return -ENODEV;
85812bb5b78SClemens Ladisch if (!enable[devno]) {
85912bb5b78SClemens Ladisch devno++;
86012bb5b78SClemens Ladisch return -ENOENT;
86112bb5b78SClemens Ladisch }
86212bb5b78SClemens Ladisch
86312bb5b78SClemens Ladisch /* (2) */
864567f5875STakashi Iwai err = snd_devm_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
865567f5875STakashi Iwai sizeof(*chip), &card);
866e58de7baSTakashi Iwai if (err < 0)
867e58de7baSTakashi Iwai return err;
868567f5875STakashi Iwai chip = card->private_data;
86912bb5b78SClemens Ladisch
87012bb5b78SClemens Ladisch strcpy(card->driver, "AD1889");
87112bb5b78SClemens Ladisch strcpy(card->shortname, "Analog Devices AD1889");
87212bb5b78SClemens Ladisch
87312bb5b78SClemens Ladisch /* (3) */
874567f5875STakashi Iwai err = snd_ad1889_create(card, pci);
87512bb5b78SClemens Ladisch if (err < 0)
876567f5875STakashi Iwai return err;
87712bb5b78SClemens Ladisch
87812bb5b78SClemens Ladisch /* (4) */
87912bb5b78SClemens Ladisch sprintf(card->longname, "%s at 0x%lx irq %i",
88012bb5b78SClemens Ladisch card->shortname, chip->bar, chip->irq);
88112bb5b78SClemens Ladisch
88212bb5b78SClemens Ladisch /* (5) */
88312bb5b78SClemens Ladisch /* register AC97 mixer */
88412bb5b78SClemens Ladisch err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
88512bb5b78SClemens Ladisch if (err < 0)
886567f5875STakashi Iwai return err;
88712bb5b78SClemens Ladisch
888a0880094SLars-Peter Clausen err = snd_ad1889_pcm_init(chip, 0);
88912bb5b78SClemens Ladisch if (err < 0)
890567f5875STakashi Iwai return err;
89112bb5b78SClemens Ladisch
89212bb5b78SClemens Ladisch /* register proc interface */
89312bb5b78SClemens Ladisch snd_ad1889_proc_init(chip);
89412bb5b78SClemens Ladisch
89512bb5b78SClemens Ladisch /* (6) */
89612bb5b78SClemens Ladisch err = snd_card_register(card);
89712bb5b78SClemens Ladisch if (err < 0)
898567f5875STakashi Iwai return err;
89912bb5b78SClemens Ladisch
90012bb5b78SClemens Ladisch /* (7) */
90112bb5b78SClemens Ladisch pci_set_drvdata(pci, card);
90212bb5b78SClemens Ladisch
90312bb5b78SClemens Ladisch devno++;
90412bb5b78SClemens Ladisch return 0;
90512bb5b78SClemens Ladisch }
90612bb5b78SClemens Ladisch
snd_ad1889_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)907*872e5fa0STakashi Iwai static int snd_ad1889_probe(struct pci_dev *pci,
908*872e5fa0STakashi Iwai const struct pci_device_id *pci_id)
909*872e5fa0STakashi Iwai {
910*872e5fa0STakashi Iwai return snd_card_free_on_error(&pci->dev, __snd_ad1889_probe(pci, pci_id));
911*872e5fa0STakashi Iwai }
912*872e5fa0STakashi Iwai
9139baa3c34SBenoit Taine static const struct pci_device_id snd_ad1889_ids[] = {
91412bb5b78SClemens Ladisch { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
91512bb5b78SClemens Ladisch { 0, },
91612bb5b78SClemens Ladisch };
91712bb5b78SClemens Ladisch MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
91812bb5b78SClemens Ladisch
919e4d76815SRandy Dunlap static struct pci_driver ad1889_pci_driver = {
9203733e424STakashi Iwai .name = KBUILD_MODNAME,
92112bb5b78SClemens Ladisch .id_table = snd_ad1889_ids,
92212bb5b78SClemens Ladisch .probe = snd_ad1889_probe,
92312bb5b78SClemens Ladisch };
92412bb5b78SClemens Ladisch
925e9f66d9bSTakashi Iwai module_pci_driver(ad1889_pci_driver);
926