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