^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for SiS7019 Audio Accelerator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004-2007, David Dillow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Written by David Dillow <dave@thedillows.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Inspired by the Trident 4D-WaveDX/NX driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "sis7019.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_DESCRIPTION("SiS7019");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static bool enable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) module_param(index, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) module_param(id, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) module_param(enable, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) module_param(codecs, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const struct pci_device_id snd_sis7019_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MODULE_DEVICE_TABLE(pci, snd_sis7019_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* There are three timing modes for the voices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * For both playback and capture, when the buffer is one or two periods long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * we use the hardware's built-in Mid-Loop Interrupt and End-Loop Interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * to let us know when the periods have ended.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * When performing playback with more than two periods per buffer, we set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * the "Stop Sample Offset" and tell the hardware to interrupt us when we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * reach it. We then update the offset and continue on until we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * interrupted for the next period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Capture channels do not have a SSO, so we allocate a playback channel to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * use as a timer for the capture periods. We use the SSO on the playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * channel to clock out virtual periods, and adjust the virtual period length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * to maintain synchronization. This algorithm came from the Trident driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * FIXME: It'd be nice to make use of some of the synth features in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * hardware, but a woeful lack of documentation is a significant roadblock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct voice {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u16 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define VOICE_IN_USE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define VOICE_CAPTURE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define VOICE_SSO_TIMING 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define VOICE_SYNC_TIMING 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u16 sync_cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u16 period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u16 buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u16 sync_period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u16 sync_buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 sso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 vperiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct voice *timing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) void __iomem *ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) void __iomem *wave_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) void __iomem *sync_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* We need four pages to store our wave parameters during a suspend. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * we're not doing power management, we still need to allocate a page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * for the silence buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SIS_SUSPEND_PAGES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SIS_SUSPEND_PAGES 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct sis7019 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void __iomem *ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int codecs_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct pci_dev *pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct snd_ac97 *ac97[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Protect against more than one thread hitting the AC97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * registers (in a more polite manner than pounding the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * semaphore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct mutex ac97_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* voice_lock protects allocation/freeing of the voice descriptions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spinlock_t voice_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct voice voices[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct voice capture_voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Allocate pages to store the internal wave state during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * suspends. When we're operating, this can be used as a silence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * buffer for a timing channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void *suspend_state[SIS_SUSPEND_PAGES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int silence_users;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dma_addr_t silence_dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* These values are also used by the module param 'codecs' to indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * which codecs should be present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define SIS_PRIMARY_CODEC_PRESENT 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define SIS_SECONDARY_CODEC_PRESENT 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define SIS_TERTIARY_CODEC_PRESENT 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* The HW offset parameters (Loop End, Stop Sample, End Sample) have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * documented range of 8-0xfff8 samples. Given that they are 0-based,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * that places our period/buffer range at 9-0xfff9 samples. That makes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * max buffer size 0xfff9 samples * 2 channels * 2 bytes per sample, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * max samples / min samples gives us the max periods in a buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * We'll add a constraint upon open that limits the period and buffer sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * size to values that are legal for the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static const struct snd_pcm_hardware sis_playback_hw_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) SNDRV_PCM_INFO_RESUME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .rate_min = 4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .buffer_bytes_max = (0xfff9 * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .period_bytes_min = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .period_bytes_max = (0xfff9 * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .periods_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .periods_max = (0xfff9 / 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static const struct snd_pcm_hardware sis_capture_hw_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) SNDRV_PCM_INFO_RESUME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .rates = SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .rate_min = 4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .buffer_bytes_max = (0xfff9 * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .period_bytes_min = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .period_bytes_max = (0xfff9 * 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .periods_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .periods_max = (0xfff9 / 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void sis_update_sso(struct voice *voice, u16 period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) void __iomem *base = voice->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) voice->sso += period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (voice->sso >= voice->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) voice->sso -= voice->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Enforce the documented hardware minimum offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (voice->sso < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) voice->sso = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* The SSO is in the upper 16 bits of the register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) writew(voice->sso & 0xffff, base + SIS_PLAY_DMA_SSO_ESO + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void sis_update_voice(struct voice *voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (voice->flags & VOICE_SSO_TIMING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) sis_update_sso(voice, voice->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else if (voice->flags & VOICE_SYNC_TIMING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* If we've not hit the end of the virtual period, update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * our records and keep going.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (voice->vperiod > voice->period_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) voice->vperiod -= voice->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (voice->vperiod < voice->period_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) sis_update_sso(voice, voice->vperiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) sis_update_sso(voice, voice->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* Calculate our relative offset between the target and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * the actual CSO value. Since we're operating in a loop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * if the value is more than half way around, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * consider ourselves wrapped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) sync = voice->sync_cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) sync -= readw(voice->sync_base + SIS_CAPTURE_DMA_FORMAT_CSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (sync > (voice->sync_buffer_size / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sync -= voice->sync_buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* If sync is positive, then we interrupted too early, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * we'll need to come back in a few samples and try again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * There's a minimum wait, as it takes some time for the DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * engine to startup, etc...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (sync > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (sync < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) sync = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) sis_update_sso(voice, sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Ok, we interrupted right on time, or (hopefully) just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * a bit late. We'll adjst our next waiting period based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * on how close we got.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * We need to stay just behind the actual channel to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * it really is past a period when we get our interrupt --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * otherwise we'll fall into the early code above and have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * a minimum wait time, which makes us quite late here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * eating into the user's time to refresh the buffer, esp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * if using small periods.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * If we're less than 9 samples behind, we're on target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Otherwise, shorten the next vperiod by the amount we've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * been delayed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (sync > -9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) voice->vperiod = voice->sync_period_size + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) voice->vperiod = voice->sync_period_size + sync + 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (voice->vperiod < voice->buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) sis_update_sso(voice, voice->vperiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) voice->vperiod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) sis_update_sso(voice, voice->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) sync = voice->sync_cso + voice->sync_period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (sync >= voice->sync_buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) sync -= voice->sync_buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) voice->sync_cso = sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) snd_pcm_period_elapsed(voice->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static void sis_voice_irq(u32 status, struct voice *voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) while (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) bit = __ffs(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) status >>= bit + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) voice += bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sis_update_voice(voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) voice++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static irqreturn_t sis_interrupt(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct sis7019 *sis = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) unsigned long io = sis->ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 intr, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* We only use the DMA interrupts, and we don't enable any other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * source of interrupts. But, it is possible to see an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * status that didn't actually interrupt us, so eliminate anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * we're not expecting to avoid falsely claiming an IRQ, and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * ensuing endless loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) intr = inl(io + SIS_GISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) intr &= SIS_GISR_AUDIO_PLAY_DMA_IRQ_STATUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) SIS_GISR_AUDIO_RECORD_DMA_IRQ_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) status = inl(io + SIS_PISR_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sis_voice_irq(status, sis->voices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) outl(status, io + SIS_PISR_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) status = inl(io + SIS_PISR_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) sis_voice_irq(status, &sis->voices[32]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) outl(status, io + SIS_PISR_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) status = inl(io + SIS_RISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) voice = &sis->capture_voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!voice->timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) snd_pcm_period_elapsed(voice->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) outl(status, io + SIS_RISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) outl(intr, io + SIS_GISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) intr = inl(io + SIS_GISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) intr &= SIS_GISR_AUDIO_PLAY_DMA_IRQ_STATUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) SIS_GISR_AUDIO_RECORD_DMA_IRQ_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) } while (intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static u32 sis_rate_to_delta(unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u32 delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* This was copied from the trident driver, but it seems its gotten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * around a bit... nevertheless, it works well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * We special case 44100 and 8000 since rounding with the equation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * does not give us an accurate enough value. For 11025 and 22050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * the equation gives us the best answer. All other frequencies will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * also use the equation. JDW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (rate == 44100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) delta = 0xeb3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) else if (rate == 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) delta = 0x2ab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) else if (rate == 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void __sis_map_silence(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Helper function: must hold sis->voice_lock on entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!sis->silence_users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) sis->silence_dma_addr = dma_map_single(&sis->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) sis->suspend_state[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 4096, DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) sis->silence_users++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void __sis_unmap_silence(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* Helper function: must hold sis->voice_lock on entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) sis->silence_users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!sis->silence_users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dma_unmap_single(&sis->pci->dev, sis->silence_dma_addr, 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void sis_free_voice(struct sis7019 *sis, struct voice *voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) spin_lock_irqsave(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (voice->timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) __sis_unmap_silence(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) voice->timing->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) VOICE_SYNC_TIMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) voice->timing = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) voice->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | VOICE_SYNC_TIMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) spin_unlock_irqrestore(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static struct voice *__sis_alloc_playback_voice(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Must hold the voice_lock on entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) for (i = 0; i < 64; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) voice = &sis->voices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (voice->flags & VOICE_IN_USE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) voice->flags |= VOICE_IN_USE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto found_one;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) voice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) found_one:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static struct voice *sis_alloc_playback_voice(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) spin_lock_irqsave(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) voice = __sis_alloc_playback_voice(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) spin_unlock_irqrestore(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int sis_alloc_timing_voice(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) unsigned int period_size, buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int needed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* If there are one or two periods per buffer, we don't need a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * timing voice, as we can use the capture channel's interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * to clock out the periods.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) period_size = params_period_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) buffer_size = params_buffer_size(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) needed = (period_size != buffer_size &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) period_size != (buffer_size / 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (needed && !voice->timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) spin_lock_irqsave(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) voice->timing = __sis_alloc_playback_voice(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (voice->timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) __sis_map_silence(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) spin_unlock_irqrestore(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (!voice->timing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) voice->timing->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) } else if (!needed && voice->timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) sis_free_voice(sis, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) voice->timing = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int sis_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) voice = sis_alloc_playback_voice(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) runtime->hw = sis_playback_hw_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 9, 0xfff9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 9, 0xfff9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int sis_substream_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) sis_free_voice(sis, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int sis_pcm_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) void __iomem *ctrl_base = voice->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) void __iomem *wave_base = voice->wave_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) u32 format, dma_addr, control, sso_eso, delta, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) u16 leo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* We rely on the PCM core to ensure that the parameters for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * substream do not change on us while we're programming the HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (snd_pcm_format_width(runtime->format) == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) format |= SIS_PLAY_DMA_FORMAT_8BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!snd_pcm_format_signed(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) format |= SIS_PLAY_DMA_FORMAT_UNSIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (runtime->channels == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) format |= SIS_PLAY_DMA_FORMAT_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* The baseline setup is for a single period per buffer, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * we add bells and whistles as needed from there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dma_addr = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) leo = runtime->buffer_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) control = leo | SIS_PLAY_DMA_LOOP | SIS_PLAY_DMA_INTR_AT_LEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) sso_eso = leo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (runtime->period_size == (runtime->buffer_size / 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) control |= SIS_PLAY_DMA_INTR_AT_MLP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) } else if (runtime->period_size != runtime->buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) voice->flags |= VOICE_SSO_TIMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) voice->sso = runtime->period_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) voice->period_size = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) voice->buffer_size = runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) control &= ~SIS_PLAY_DMA_INTR_AT_LEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) control |= SIS_PLAY_DMA_INTR_AT_SSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) sso_eso |= (runtime->period_size - 1) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) delta = sis_rate_to_delta(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* Ok, we're ready to go, set up the channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) writel(format, ctrl_base + SIS_PLAY_DMA_FORMAT_CSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) writel(dma_addr, ctrl_base + SIS_PLAY_DMA_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) writel(control, ctrl_base + SIS_PLAY_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) writel(sso_eso, ctrl_base + SIS_PLAY_DMA_SSO_ESO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) for (reg = 0; reg < SIS_WAVE_SIZE; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) writel(0, wave_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) writel(SIS_WAVE_GENERAL_WAVE_VOLUME, wave_base + SIS_WAVE_GENERAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) writel(delta << 16, wave_base + SIS_WAVE_GENERAL_ARTICULATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) writel(SIS_WAVE_CHANNEL_CONTROL_FIRST_SAMPLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) SIS_WAVE_CHANNEL_CONTROL_AMP_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) SIS_WAVE_CHANNEL_CONTROL_INTERPOLATE_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) wave_base + SIS_WAVE_CHANNEL_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Force PCI writes to post. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) readl(ctrl_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int sis_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) unsigned long io = sis->ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct snd_pcm_substream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) void *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) int starting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) u32 record = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) u32 play[2] = { 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* No locks needed, as the PCM core will hold the locks on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * substreams, and the HW will only start/stop the indicated voices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * without changing the state of the others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) starting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) starting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) snd_pcm_group_for_each_entry(s, substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* Make sure it is for us... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) chip = snd_pcm_substream_chip(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (chip != sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) voice = s->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (voice->flags & VOICE_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) record |= 1 << voice->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) voice = voice->timing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* voice could be NULL if this a recording stream, and it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * doesn't have an external timing channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) play[voice->num / 32] |= 1 << (voice->num & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) snd_pcm_trigger_done(s, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (starting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) outl(record, io + SIS_RECORD_START_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (play[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) outl(play[0], io + SIS_PLAY_START_A_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (play[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) outl(play[1], io + SIS_PLAY_START_B_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) outl(record, io + SIS_RECORD_STOP_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (play[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) outl(play[0], io + SIS_PLAY_STOP_A_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (play[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) outl(play[1], io + SIS_PLAY_STOP_B_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static snd_pcm_uframes_t sis_pcm_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) u32 cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) cso = readl(voice->ctrl_base + SIS_PLAY_DMA_FORMAT_CSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cso &= 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static int sis_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct voice *voice = &sis->capture_voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* FIXME: The driver only supports recording from one channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * at the moment, but it could support more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) spin_lock_irqsave(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (voice->flags & VOICE_IN_USE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) voice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) voice->flags |= VOICE_IN_USE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) spin_unlock_irqrestore(&sis->voice_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (!voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) runtime->hw = sis_capture_hw_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) runtime->hw.rates = sis->ac97[0]->rates[AC97_RATES_ADC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) snd_pcm_limit_hw_rates(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 9, 0xfff9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 9, 0xfff9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static int sis_capture_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) rc = snd_ac97_set_rate(sis->ac97[0], AC97_PCM_LR_ADC_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) params_rate(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) rc = sis_alloc_timing_voice(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static void sis_prepare_timing_voice(struct voice *voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct sis7019 *sis = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct voice *timing = voice->timing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) void __iomem *play_base = timing->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) void __iomem *wave_base = timing->wave_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) u16 buffer_size, period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) u32 format, control, sso_eso, delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) u32 vperiod, sso, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /* Set our initial buffer and period as large as we can given a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * single page of silence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) buffer_size = 4096 / runtime->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) buffer_size /= snd_pcm_format_size(runtime->format, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) period_size = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* Initially, we want to interrupt just a bit behind the end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * the period we're clocking out. 12 samples seems to give a good
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * delay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * We want to spread our interrupts throughout the virtual period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * so that we don't end up with two interrupts back to back at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * end -- this helps minimize the effects of any jitter. Adjust our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * clocking period size so that the last period is at least a fourth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * of a full period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * This is all moot if we don't need to use virtual periods.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) vperiod = runtime->period_size + 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (vperiod > period_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) u16 tail = vperiod % period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u16 quarter_period = period_size / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (tail && tail < quarter_period) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) u16 loops = vperiod / period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) tail = quarter_period - tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) tail += loops - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) tail /= loops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) period_size -= tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) sso = period_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* The initial period will fit inside the buffer, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * don't need to use virtual periods -- disable them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) period_size = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) sso = vperiod - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) vperiod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* The interrupt handler implements the timing synchronization, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * setup its state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) timing->flags |= VOICE_SYNC_TIMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) timing->sync_base = voice->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) timing->sync_cso = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) timing->sync_period_size = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) timing->sync_buffer_size = runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) timing->period_size = period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) timing->buffer_size = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) timing->sso = sso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) timing->vperiod = vperiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* Using unsigned samples with the all-zero silence buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * forces the output to the lower rail, killing playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * So ignore unsigned vs signed -- it doesn't change the timing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (snd_pcm_format_width(runtime->format) == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) format = SIS_CAPTURE_DMA_FORMAT_8BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (runtime->channels == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) format |= SIS_CAPTURE_DMA_FORMAT_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) control = timing->buffer_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) control |= SIS_PLAY_DMA_LOOP | SIS_PLAY_DMA_INTR_AT_SSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) sso_eso = timing->buffer_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) sso_eso |= timing->sso << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) delta = sis_rate_to_delta(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* We've done the math, now configure the channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) writel(format, play_base + SIS_PLAY_DMA_FORMAT_CSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) writel(sis->silence_dma_addr, play_base + SIS_PLAY_DMA_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) writel(control, play_base + SIS_PLAY_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) writel(sso_eso, play_base + SIS_PLAY_DMA_SSO_ESO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) for (reg = 0; reg < SIS_WAVE_SIZE; reg += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) writel(0, wave_base + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) writel(SIS_WAVE_GENERAL_WAVE_VOLUME, wave_base + SIS_WAVE_GENERAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) writel(delta << 16, wave_base + SIS_WAVE_GENERAL_ARTICULATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) writel(SIS_WAVE_CHANNEL_CONTROL_FIRST_SAMPLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) SIS_WAVE_CHANNEL_CONTROL_AMP_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) SIS_WAVE_CHANNEL_CONTROL_INTERPOLATE_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) wave_base + SIS_WAVE_CHANNEL_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int sis_pcm_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) void __iomem *rec_base = voice->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) u32 format, dma_addr, control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) u16 leo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /* We rely on the PCM core to ensure that the parameters for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * substream do not change on us while we're programming the HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (snd_pcm_format_width(runtime->format) == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) format = SIS_CAPTURE_DMA_FORMAT_8BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (!snd_pcm_format_signed(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) format |= SIS_CAPTURE_DMA_FORMAT_UNSIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (runtime->channels == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) format |= SIS_CAPTURE_DMA_FORMAT_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) dma_addr = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) leo = runtime->buffer_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) control = leo | SIS_CAPTURE_DMA_LOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /* If we've got more than two periods per buffer, then we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * use a timing voice to clock out the periods. Otherwise, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * use the capture channel's interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (voice->timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sis_prepare_timing_voice(voice, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) control |= SIS_CAPTURE_DMA_INTR_AT_LEO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (runtime->period_size != runtime->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) control |= SIS_CAPTURE_DMA_INTR_AT_MLP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) writel(format, rec_base + SIS_CAPTURE_DMA_FORMAT_CSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) writel(dma_addr, rec_base + SIS_CAPTURE_DMA_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) writel(control, rec_base + SIS_CAPTURE_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* Force the writes to post. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) readl(rec_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static const struct snd_pcm_ops sis_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .open = sis_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .close = sis_substream_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .prepare = sis_pcm_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .trigger = sis_pcm_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .pointer = sis_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static const struct snd_pcm_ops sis_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .open = sis_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .close = sis_substream_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .hw_params = sis_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .prepare = sis_pcm_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .trigger = sis_pcm_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .pointer = sis_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int sis_pcm_create(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* We have 64 voices, and the driver currently records from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * only one channel, though that could change in the future.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) rc = snd_pcm_new(sis->card, "SiS7019", 0, 64, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) pcm->private_data = sis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) strcpy(pcm->name, "SiS7019");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) sis->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &sis_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &sis_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* Try to preallocate some memory, but it's not the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * world if this fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) &sis->pci->dev, 64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) unsigned long io = sis->ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) unsigned short val = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) u16 rdy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static const u16 codec_ready[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) SIS_AC97_STATUS_CODEC_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) SIS_AC97_STATUS_CODEC2_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) SIS_AC97_STATUS_CODEC3_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) rdy = codec_ready[codec];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* Get the AC97 semaphore -- software first, so we don't spin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * pounding out IO reads on the hardware semaphore...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) mutex_lock(&sis->ac97_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) goto timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* ... and wait for any outstanding commands to complete ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) status = inw(io + SIS_AC97_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if ((status & rdy) && !(status & SIS_AC97_STATUS_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) } while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) goto timeout_sema;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* ... before sending our command and waiting for it to finish ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) outl(cmd, io + SIS_AC97_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* ... and reading the results (if any).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) val = inl(io + SIS_AC97_CMD) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) timeout_sema:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) timeout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) mutex_unlock(&sis->ac97_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (!count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) dev_err(&sis->pci->dev, "ac97 codec %d timeout cmd 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) codec, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static const u32 cmd[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) SIS_AC97_CMD_CODEC_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) SIS_AC97_CMD_CODEC2_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) SIS_AC97_CMD_CODEC3_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) sis_ac97_rw(ac97->private_data, ac97->num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) (val << 16) | (reg << 8) | cmd[ac97->num]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static const u32 cmd[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) SIS_AC97_CMD_CODEC_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) SIS_AC97_CMD_CODEC2_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) SIS_AC97_CMD_CODEC3_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return sis_ac97_rw(ac97->private_data, ac97->num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) (reg << 8) | cmd[ac97->num]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static int sis_mixer_create(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct snd_ac97_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct snd_ac97_template ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) .write = sis_ac97_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) .read = sis_ac97_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) memset(&ac97, 0, sizeof(ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ac97.private_data = sis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) rc = snd_ac97_bus(sis->card, 0, &ops, NULL, &bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (!rc && sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) ac97.num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!rc && (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) ac97.num = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!rc && (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* If we return an error here, then snd_card_free() should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * free up any ac97 codecs that got created, as well as the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static void sis_free_suspend(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) for (i = 0; i < SIS_SUSPEND_PAGES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) kfree(sis->suspend_state[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static int sis_chip_free(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* Reset the chip, and disable all interrputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) udelay(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) outl(0, sis->ioport + SIS_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) outl(0, sis->ioport + SIS_GIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* Now, free everything we allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (sis->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) free_irq(sis->irq, sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) iounmap(sis->ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) pci_release_regions(sis->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) pci_disable_device(sis->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) sis_free_suspend(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static int sis_dev_free(struct snd_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct sis7019 *sis = dev->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return sis_chip_free(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static int sis_chip_init(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) unsigned long io = sis->ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) void __iomem *ioaddr = sis->ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /* Reset the audio controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) udelay(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) outl(0, io + SIS_GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* Get the AC-link semaphore, and reset the codecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) udelay(250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) /* Command complete, we can let go of the semaphore now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* Now that we've finished the reset, find out what's attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * There are some codec/board combinations that take an extremely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * long time to come up. 350+ ms has been observed in the field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * so we'll give them up to 500ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) sis->codecs_present = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) timeout = msecs_to_jiffies(500) + jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) while (time_before_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) status = inl(io + SIS_AC97_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (status & SIS_AC97_STATUS_CODEC_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (status & SIS_AC97_STATUS_CODEC2_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (status & SIS_AC97_STATUS_CODEC3_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (sis->codecs_present == codecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* All done, check for errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!sis->codecs_present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) dev_err(&sis->pci->dev, "could not find any codecs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (sis->codecs_present != codecs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) dev_warn(&sis->pci->dev, "missing codecs, found %0x, expected %0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) sis->codecs_present, codecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /* Let the hardware know that the audio driver is alive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * and enable PCM slots on the AC-link for L/R playback (3 & 4) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * record channels. We're going to want to use Variable Rate Audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * for recording, to avoid needlessly resampling from 48kHZ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) outl(SIS_AC97_CONF_AUDIO_ALIVE, io + SIS_AC97_CONF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) outl(SIS_AC97_CONF_AUDIO_ALIVE | SIS_AC97_CONF_PCM_LR_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) SIS_AC97_CONF_PCM_CAP_MIC_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) SIS_AC97_CONF_PCM_CAP_LR_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) SIS_AC97_CONF_CODEC_VRA_ENABLE, io + SIS_AC97_CONF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /* All AC97 PCM slots should be sourced from sub-mixer 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) outl(0, io + SIS_AC97_PSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* There is only one valid DMA setup for a PCI environment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) outl(SIS_DMA_CSR_PCI_SETTINGS, io + SIS_DMA_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) /* Reset the synchronization groups for all of the channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) * to be asynchronous. If we start doing SPDIF or 5.1 sound, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) * we'll need to change how we handle these. Until then, we just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * assign sub-mixer 0 to all playback channels, and avoid any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * attenuation on the audio.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) outl(0, io + SIS_PLAY_SYNC_GROUP_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) outl(0, io + SIS_PLAY_SYNC_GROUP_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) outl(0, io + SIS_PLAY_SYNC_GROUP_C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) outl(0, io + SIS_PLAY_SYNC_GROUP_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) outl(0, io + SIS_MIXER_SYNC_GROUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) for (i = 0; i < 64; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) writel(i, SIS_MIXER_START_ADDR(ioaddr, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) writel(SIS_MIXER_RIGHT_NO_ATTEN | SIS_MIXER_LEFT_NO_ATTEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) SIS_MIXER_DEST_0, SIS_MIXER_ADDR(ioaddr, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* Don't attenuate any audio set for the wave amplifier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * FIXME: Maximum attenuation is set for the music amp, which will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * need to change if we start using the synth engine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) outl(0xffff0000, io + SIS_WEVCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* Ensure that the wave engine is in normal operating mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) outl(0, io + SIS_WECCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /* Go ahead and enable the DMA interrupts. They won't go live
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * until we start a channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) outl(SIS_GIER_AUDIO_PLAY_DMA_IRQ_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) SIS_GIER_AUDIO_RECORD_DMA_IRQ_ENABLE, io + SIS_GIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static int sis_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct sis7019 *sis = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) void __iomem *ioaddr = sis->ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) snd_ac97_suspend(sis->ac97[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) snd_ac97_suspend(sis->ac97[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) snd_ac97_suspend(sis->ac97[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* snd_pcm_suspend_all() stopped all channels, so we're quiescent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (sis->irq >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) free_irq(sis->irq, sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) sis->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) /* Save the internal state away
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) memcpy_fromio(sis->suspend_state[i], ioaddr, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ioaddr += 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) static int sis_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct pci_dev *pci = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct sis7019 *sis = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) void __iomem *ioaddr = sis->ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (sis_chip_init(sis)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) dev_err(&pci->dev, "unable to re-init controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) KBUILD_MODNAME, sis)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) dev_err(&pci->dev, "unable to regain IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /* Restore saved state, then clear out the page we use for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * silence buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) memcpy_toio(ioaddr, sis->suspend_state[i], 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ioaddr += 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) memset(sis->suspend_state[0], 0, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) sis->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) snd_ac97_resume(sis->ac97[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) snd_ac97_resume(sis->ac97[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) snd_ac97_resume(sis->ac97[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) snd_card_disconnect(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) static SIMPLE_DEV_PM_OPS(sis_pm, sis_suspend, sis_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) #define SIS_PM_OPS &sis_pm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) #define SIS_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static int sis_alloc_suspend(struct sis7019 *sis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /* We need 16K to store the internal wave engine state during a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * suspend, but we don't need it to be contiguous, so play nice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * with the memory system. We'll also use this area for a silence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) for (i = 0; i < SIS_SUSPEND_PAGES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) sis->suspend_state[i] = kmalloc(4096, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (!sis->suspend_state[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) memset(sis->suspend_state[0], 0, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) static int sis_chip_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct sis7019 *sis = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .dev_free = sis_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) rc = pci_enable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) goto error_out_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) memset(sis, 0, sizeof(*sis));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) mutex_init(&sis->ac97_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) spin_lock_init(&sis->voice_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) sis->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) sis->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) sis->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) sis->ioport = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) rc = pci_request_regions(pci, "SiS7019");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) dev_err(&pci->dev, "unable request regions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) goto error_out_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) sis->ioaddr = ioremap(pci_resource_start(pci, 1), 0x4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (!sis->ioaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) goto error_out_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) rc = sis_alloc_suspend(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) dev_err(&pci->dev, "unable to allocate state storage\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) goto error_out_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) rc = sis_chip_init(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) goto error_out_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) goto error_out_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) sis->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) card->sync_irq = sis->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) for (i = 0; i < 64; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) voice = &sis->voices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) voice->num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) voice->ctrl_base = SIS_PLAY_DMA_ADDR(sis->ioaddr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) voice->wave_base = SIS_WAVE_ADDR(sis->ioaddr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) voice = &sis->capture_voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) voice->flags = VOICE_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rc = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sis, &ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) goto error_out_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) error_out_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) sis_chip_free(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) error_out_enabled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) static int snd_sis7019_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct sis7019 *sis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* The user can specify which codecs should be present so that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * can wait for them to show up if they are slow to recover from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * the AC97 cold reset. We default to a single codec, the primary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) SIS_TERTIARY_CODEC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (!codecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) codecs = SIS_PRIMARY_CODEC_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) rc = snd_card_new(&pci->dev, index, id, THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) sizeof(*sis), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) strcpy(card->driver, "SiS7019");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) strcpy(card->shortname, "SiS7019");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) rc = sis_chip_create(card, pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) goto card_error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) sis = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) rc = sis_mixer_create(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) goto card_error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) rc = sis_pcm_create(sis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) goto card_error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) "%s Audio Accelerator with %s at 0x%lx, irq %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) card->shortname, snd_ac97_get_short_name(sis->ac97[0]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) sis->ioport, sis->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) rc = snd_card_register(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) goto card_error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) pci_set_drvdata(pci, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) card_error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) static void snd_sis7019_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) snd_card_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static struct pci_driver sis7019_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) .id_table = snd_sis7019_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) .probe = snd_sis7019_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) .remove = snd_sis7019_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) .pm = SIS_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) module_pci_driver(sis7019_driver);