aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/trident
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/trident')
-rw-r--r--sound/pci/trident/Makefile10
-rw-r--r--sound/pci/trident/trident.c8
-rw-r--r--sound/pci/trident/trident_main.c71
-rw-r--r--sound/pci/trident/trident_memory.c1
-rw-r--r--sound/pci/trident/trident_synth.c1024
5 files changed, 21 insertions, 1093 deletions
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile
index 65f2c218324c..88676b50f385 100644
--- a/sound/pci/trident/Makefile
+++ b/sound/pci/trident/Makefile
@@ -4,16 +4,6 @@
4# 4#
5 5
6snd-trident-objs := trident.o trident_main.o trident_memory.o 6snd-trident-objs := trident.o trident_main.o trident_memory.o
7snd-trident-synth-objs := trident_synth.o
8
9#
10# this function returns:
11# "m" - CONFIG_SND_SEQUENCER is m
12# <empty string> - CONFIG_SND_SEQUENCER is undefined
13# otherwise parameter #1 value
14#
15sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
16 7
17# Toplevel Module Dependency 8# Toplevel Module Dependency
18obj-$(CONFIG_SND_TRIDENT) += snd-trident.o 9obj-$(CONFIG_SND_TRIDENT) += snd-trident.o
19obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-trident-synth.o
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 84884567df6a..d94b16ffb385 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -21,7 +21,6 @@
21 * 21 *
22 */ 22 */
23 23
24#include <sound/driver.h>
25#include <linux/init.h> 24#include <linux/init.h>
26#include <linux/pci.h> 25#include <linux/pci.h>
27#include <linux/time.h> 26#include <linux/time.h>
@@ -155,13 +154,6 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
155 return err; 154 return err;
156 } 155 }
157 156
158#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
159 if ((err = snd_trident_attach_synthesizer(trident)) < 0) {
160 snd_card_free(card);
161 return err;
162 }
163#endif
164
165 snd_trident_create_gameport(trident); 157 snd_trident_create_gameport(trident);
166 158
167 if ((err = snd_card_register(card)) < 0) { 159 if ((err = snd_card_register(card)) < 0) {
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index a235e034a690..71138ff9b310 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -27,7 +27,6 @@
27 * SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net> 27 * SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net>
28 */ 28 */
29 29
30#include <sound/driver.h>
31#include <linux/delay.h> 30#include <linux/delay.h>
32#include <linux/init.h> 31#include <linux/init.h>
33#include <linux/interrupt.h> 32#include <linux/interrupt.h>
@@ -436,7 +435,7 @@ static void snd_trident_free_synth_channel(struct snd_trident *trident, int chan
436 Description: This routine will complete and write the 5 hardware channel 435 Description: This routine will complete and write the 5 hardware channel
437 registers to hardware. 436 registers to hardware.
438 437
439 Paramters: trident - pointer to target device class for 4DWave. 438 Parameters: trident - pointer to target device class for 4DWave.
440 voice - synthesizer voice structure 439 voice - synthesizer voice structure
441 Each register field. 440 Each register field.
442 441
@@ -514,7 +513,7 @@ EXPORT_SYMBOL(snd_trident_write_voice_regs);
514 Description: This routine will write the new CSO offset 513 Description: This routine will write the new CSO offset
515 register to hardware. 514 register to hardware.
516 515
517 Paramters: trident - pointer to target device class for 4DWave. 516 Parameters: trident - pointer to target device class for 4DWave.
518 voice - synthesizer voice structure 517 voice - synthesizer voice structure
519 CSO - new CSO value 518 CSO - new CSO value
520 519
@@ -540,7 +539,7 @@ static void snd_trident_write_cso_reg(struct snd_trident * trident,
540 Description: This routine will write the new ESO offset 539 Description: This routine will write the new ESO offset
541 register to hardware. 540 register to hardware.
542 541
543 Paramters: trident - pointer to target device class for 4DWave. 542 Parameters: trident - pointer to target device class for 4DWave.
544 voice - synthesizer voice structure 543 voice - synthesizer voice structure
545 ESO - new ESO value 544 ESO - new ESO value
546 545
@@ -566,7 +565,7 @@ static void snd_trident_write_eso_reg(struct snd_trident * trident,
566 Description: This routine will write the new voice volume 565 Description: This routine will write the new voice volume
567 register to hardware. 566 register to hardware.
568 567
569 Paramters: trident - pointer to target device class for 4DWave. 568 Parameters: trident - pointer to target device class for 4DWave.
570 voice - synthesizer voice structure 569 voice - synthesizer voice structure
571 Vol - new voice volume 570 Vol - new voice volume
572 571
@@ -597,7 +596,7 @@ static void snd_trident_write_vol_reg(struct snd_trident * trident,
597 Description: This routine will write the new voice pan 596 Description: This routine will write the new voice pan
598 register to hardware. 597 register to hardware.
599 598
600 Paramters: trident - pointer to target device class for 4DWave. 599 Parameters: trident - pointer to target device class for 4DWave.
601 voice - synthesizer voice structure 600 voice - synthesizer voice structure
602 Pan - new pan value 601 Pan - new pan value
603 602
@@ -619,7 +618,7 @@ static void snd_trident_write_pan_reg(struct snd_trident * trident,
619 Description: This routine will write the new reverb volume 618 Description: This routine will write the new reverb volume
620 register to hardware. 619 register to hardware.
621 620
622 Paramters: trident - pointer to target device class for 4DWave. 621 Parameters: trident - pointer to target device class for 4DWave.
623 voice - synthesizer voice structure 622 voice - synthesizer voice structure
624 RVol - new reverb volume 623 RVol - new reverb volume
625 624
@@ -643,7 +642,7 @@ static void snd_trident_write_rvol_reg(struct snd_trident * trident,
643 Description: This routine will write the new chorus volume 642 Description: This routine will write the new chorus volume
644 register to hardware. 643 register to hardware.
645 644
646 Paramters: trident - pointer to target device class for 4DWave. 645 Parameters: trident - pointer to target device class for 4DWave.
647 voice - synthesizer voice structure 646 voice - synthesizer voice structure
648 CVol - new chorus volume 647 CVol - new chorus volume
649 648
@@ -666,7 +665,7 @@ static void snd_trident_write_cvol_reg(struct snd_trident * trident,
666 665
667 Description: This routine converts rate in HZ to hardware delta value. 666 Description: This routine converts rate in HZ to hardware delta value.
668 667
669 Paramters: trident - pointer to target device class for 4DWave. 668 Parameters: trident - pointer to target device class for 4DWave.
670 rate - Real or Virtual channel number. 669 rate - Real or Virtual channel number.
671 670
672 Returns: Delta value. 671 Returns: Delta value.
@@ -696,7 +695,7 @@ static unsigned int snd_trident_convert_rate(unsigned int rate)
696 695
697 Description: This routine converts rate in HZ to hardware delta value. 696 Description: This routine converts rate in HZ to hardware delta value.
698 697
699 Paramters: trident - pointer to target device class for 4DWave. 698 Parameters: trident - pointer to target device class for 4DWave.
700 rate - Real or Virtual channel number. 699 rate - Real or Virtual channel number.
701 700
702 Returns: Delta value. 701 Returns: Delta value.
@@ -726,7 +725,7 @@ static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
726 725
727 Description: This routine converts rate in HZ to spurious threshold. 726 Description: This routine converts rate in HZ to spurious threshold.
728 727
729 Paramters: trident - pointer to target device class for 4DWave. 728 Parameters: trident - pointer to target device class for 4DWave.
730 rate - Real or Virtual channel number. 729 rate - Real or Virtual channel number.
731 730
732 Returns: Delta value. 731 Returns: Delta value.
@@ -748,7 +747,7 @@ static unsigned int snd_trident_spurious_threshold(unsigned int rate,
748 747
749 Description: This routine returns a control mode for a PCM channel. 748 Description: This routine returns a control mode for a PCM channel.
750 749
751 Paramters: trident - pointer to target device class for 4DWave. 750 Parameters: trident - pointer to target device class for 4DWave.
752 substream - PCM substream 751 substream - PCM substream
753 752
754 Returns: Control value. 753 Returns: Control value.
@@ -781,7 +780,7 @@ static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream
781 780
782 Description: Device I/O control handler for playback/capture parameters. 781 Description: Device I/O control handler for playback/capture parameters.
783 782
784 Paramters: substream - PCM substream class 783 Parameters: substream - PCM substream class
785 cmd - what ioctl message to process 784 cmd - what ioctl message to process
786 arg - additional message infoarg 785 arg - additional message infoarg
787 786
@@ -1664,7 +1663,7 @@ static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *
1664 1663
1665 Description: This routine return the capture position 1664 Description: This routine return the capture position
1666 1665
1667 Paramters: pcm1 - PCM device class 1666 Parameters: pcm1 - PCM device class
1668 1667
1669 Returns: position of buffer 1668 Returns: position of buffer
1670 1669
@@ -2157,7 +2156,7 @@ static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
2157 2156
2158 Description: This routine registers the 4DWave device for PCM support. 2157 Description: This routine registers the 4DWave device for PCM support.
2159 2158
2160 Paramters: trident - pointer to target device class for 4DWave. 2159 Parameters: trident - pointer to target device class for 4DWave.
2161 2160
2162 Returns: None 2161 Returns: None
2163 2162
@@ -2215,7 +2214,7 @@ int __devinit snd_trident_pcm(struct snd_trident * trident,
2215 2214
2216 Description: This routine registers the 4DWave device for foldback PCM support. 2215 Description: This routine registers the 4DWave device for foldback PCM support.
2217 2216
2218 Paramters: trident - pointer to target device class for 4DWave. 2217 Parameters: trident - pointer to target device class for 4DWave.
2219 2218
2220 Returns: None 2219 Returns: None
2221 2220
@@ -2272,7 +2271,7 @@ int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
2272 2271
2273 Description: This routine registers the 4DWave-NX device for SPDIF support. 2272 Description: This routine registers the 4DWave-NX device for SPDIF support.
2274 2273
2275 Paramters: trident - pointer to target device class for 4DWave-NX. 2274 Parameters: trident - pointer to target device class for 4DWave-NX.
2276 2275
2277 Returns: None 2276 Returns: None
2278 2277
@@ -2956,7 +2955,7 @@ static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_tr
2956 2955
2957 Description: This routine registers the 4DWave device for mixer support. 2956 Description: This routine registers the 4DWave device for mixer support.
2958 2957
2959 Paramters: trident - pointer to target device class for 4DWave. 2958 Parameters: trident - pointer to target device class for 4DWave.
2960 2959
2961 Returns: None 2960 Returns: None
2962 2961
@@ -3313,12 +3312,6 @@ static void snd_trident_proc_read(struct snd_info_entry *entry,
3313 snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr)); 3312 snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
3314 } 3313 }
3315 } 3314 }
3316#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3317 snd_iprintf(buffer,"\nWavetable Synth\n");
3318 snd_iprintf(buffer, "Memory Maximum : %d\n", trident->synth.max_size);
3319 snd_iprintf(buffer, "Memory Used : %d\n", trident->synth.current_size);
3320 snd_iprintf(buffer, "Memory Free : %d\n", (trident->synth.max_size-trident->synth.current_size));
3321#endif
3322} 3315}
3323 3316
3324static void __devinit snd_trident_proc_init(struct snd_trident * trident) 3317static void __devinit snd_trident_proc_init(struct snd_trident * trident)
@@ -3344,7 +3337,7 @@ static int snd_trident_dev_free(struct snd_device *device)
3344 Description: Allocate and set up the TLB page table on 4D NX. 3337 Description: Allocate and set up the TLB page table on 4D NX.
3345 Each entry has 4 bytes (physical PCI address). 3338 Each entry has 4 bytes (physical PCI address).
3346 3339
3347 Paramters: trident - pointer to target device class for 4DWave. 3340 Parameters: trident - pointer to target device class for 4DWave.
3348 3341
3349 Returns: 0 or negative error code 3342 Returns: 0 or negative error code
3350 3343
@@ -3521,7 +3514,7 @@ static int snd_trident_sis_init(struct snd_trident *trident)
3521 Description: This routine will create the device specific class for 3514 Description: This routine will create the device specific class for
3522 the 4DWave card. It will also perform basic initialization. 3515 the 4DWave card. It will also perform basic initialization.
3523 3516
3524 Paramters: card - which card to create 3517 Parameters: card - which card to create
3525 pci - interface to PCI bus resource info 3518 pci - interface to PCI bus resource info
3526 dma1ptr - playback dma buffer 3519 dma1ptr - playback dma buffer
3527 dma2ptr - capture dma buffer 3520 dma2ptr - capture dma buffer
@@ -3667,7 +3660,7 @@ int __devinit snd_trident_create(struct snd_card *card,
3667 Description: This routine will free the device specific class for 3660 Description: This routine will free the device specific class for
3668 the 4DWave card. 3661 the 4DWave card.
3669 3662
3670 Paramters: trident - device specific private data for 4DWave card 3663 Parameters: trident - device specific private data for 4DWave card
3671 3664
3672 Returns: None. 3665 Returns: None.
3673 3666
@@ -3705,7 +3698,7 @@ static int snd_trident_free(struct snd_trident *trident)
3705 3698
3706 Description: ISR for Trident 4DWave device 3699 Description: ISR for Trident 4DWave device
3707 3700
3708 Paramters: trident - device specific private data for 4DWave card 3701 Parameters: trident - device specific private data for 4DWave card
3709 3702
3710 Problems: It seems that Trident chips generates interrupts more than 3703 Problems: It seems that Trident chips generates interrupts more than
3711 one time in special cases. The spurious interrupts are 3704 one time in special cases. The spurious interrupts are
@@ -3815,28 +3808,6 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)
3815 return IRQ_HANDLED; 3808 return IRQ_HANDLED;
3816} 3809}
3817 3810
3818/*---------------------------------------------------------------------------
3819 snd_trident_attach_synthesizer
3820
3821 Description: Attach synthesizer hooks
3822
3823 Paramters: trident - device specific private data for 4DWave card
3824
3825 Returns: None.
3826
3827 ---------------------------------------------------------------------------*/
3828int snd_trident_attach_synthesizer(struct snd_trident *trident)
3829{
3830#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
3831 if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT,
3832 sizeof(struct snd_trident *), &trident->seq_dev) >= 0) {
3833 strcpy(trident->seq_dev->name, "4DWave");
3834 *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident;
3835 }
3836#endif
3837 return 0;
3838}
3839
3840struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port) 3811struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port)
3841{ 3812{
3842 struct snd_trident_voice *pvoice; 3813 struct snd_trident_voice *pvoice;
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 847b8c6d5c0a..df9b487fa17e 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -23,7 +23,6 @@
23 * 23 *
24 */ 24 */
25 25
26#include <sound/driver.h>
27#include <asm/io.h> 26#include <asm/io.h>
28#include <linux/pci.h> 27#include <linux/pci.h>
29#include <linux/time.h> 28#include <linux/time.h>
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
deleted file mode 100644
index 9b7dee84743b..000000000000
--- a/sound/pci/trident/trident_synth.c
+++ /dev/null
@@ -1,1024 +0,0 @@
1/*
2 * Routines for Trident 4DWave NX/DX soundcards - Synthesizer
3 * Copyright (c) by Scott McNab <jedi@tartarus.uwa.edu.au>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <asm/io.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/pci.h>
27#include <sound/core.h>
28#include <sound/trident.h>
29#include <sound/seq_device.h>
30
31MODULE_AUTHOR("Scott McNab <jedi@tartarus.uwa.edu.au>");
32MODULE_DESCRIPTION("Routines for Trident 4DWave NX/DX soundcards - Synthesizer");
33MODULE_LICENSE("GPL");
34
35/* linear to log pan conversion table (4.2 channel attenuation format) */
36static unsigned int pan_table[63] = {
37 7959, 7733, 7514, 7301, 7093, 6892, 6697, 6507,
38 6322, 6143, 5968, 5799, 5634, 5475, 5319, 5168,
39 5022, 4879, 4741, 4606, 4475, 4349, 4225, 4105,
40 3989, 3876, 3766, 3659, 3555, 3454, 3356, 3261,
41 3168, 3078, 2991, 2906, 2824, 2744, 2666, 2590,
42 2517, 2445, 2376, 2308, 2243, 2179, 2117, 2057,
43 1999, 1942, 1887, 1833, 1781, 1731, 1682, 1634,
44 1588, 1543, 1499, 1456, 1415, 1375, 1336
45};
46
47#define LOG_TABLE_SIZE 386
48
49/* Linear half-attenuation to log conversion table in the format:
50 * {linear volume, logarithmic attenuation equivalent}, ...
51 *
52 * Provides conversion from a linear half-volume value in the range
53 * [0,8192] to a logarithmic attenuation value in the range 0 to 6.02dB.
54 * Halving the linear volume is equivalent to an additional 6dB of
55 * logarithmic attenuation. The algorithm used in log_from_linear()
56 * therefore uses this table as follows:
57 *
58 * - loop and for every time the volume is less than half the maximum
59 * volume (16384), add another 6dB and halve the maximum value used
60 * for this comparison.
61 * - when the volume is greater than half the maximum volume, take
62 * the difference of the volume to half volume (in the range [0,8192])
63 * and look up the log_table[] to find the nearest entry.
64 * - take the logarithic component of this entry and add it to the
65 * resulting attenuation.
66 *
67 * Thus this routine provides a linear->log conversion for a range of
68 * [0,16384] using only 386 table entries
69 *
70 * Note: although this table stores log attenuation in 8.8 format, values
71 * were only calculated for 6 bits fractional precision, since that is
72 * the most precision offered by the trident hardware.
73 */
74
75static unsigned short log_table[LOG_TABLE_SIZE*2] =
76{
77 4, 0x0604, 19, 0x0600, 34, 0x05fc,
78 49, 0x05f8, 63, 0x05f4, 78, 0x05f0, 93, 0x05ec, 108, 0x05e8,
79 123, 0x05e4, 138, 0x05e0, 153, 0x05dc, 168, 0x05d8, 183, 0x05d4,
80 198, 0x05d0, 213, 0x05cc, 228, 0x05c8, 244, 0x05c4, 259, 0x05c0,
81 274, 0x05bc, 289, 0x05b8, 304, 0x05b4, 320, 0x05b0, 335, 0x05ac,
82 350, 0x05a8, 366, 0x05a4, 381, 0x05a0, 397, 0x059c, 412, 0x0598,
83 428, 0x0594, 443, 0x0590, 459, 0x058c, 474, 0x0588, 490, 0x0584,
84 506, 0x0580, 521, 0x057c, 537, 0x0578, 553, 0x0574, 568, 0x0570,
85 584, 0x056c, 600, 0x0568, 616, 0x0564, 632, 0x0560, 647, 0x055c,
86 663, 0x0558, 679, 0x0554, 695, 0x0550, 711, 0x054c, 727, 0x0548,
87 743, 0x0544, 759, 0x0540, 776, 0x053c, 792, 0x0538, 808, 0x0534,
88 824, 0x0530, 840, 0x052c, 857, 0x0528, 873, 0x0524, 889, 0x0520,
89 906, 0x051c, 922, 0x0518, 938, 0x0514, 955, 0x0510, 971, 0x050c,
90 988, 0x0508, 1004, 0x0504, 1021, 0x0500, 1037, 0x04fc, 1054, 0x04f8,
91 1071, 0x04f4, 1087, 0x04f0, 1104, 0x04ec, 1121, 0x04e8, 1138, 0x04e4,
92 1154, 0x04e0, 1171, 0x04dc, 1188, 0x04d8, 1205, 0x04d4, 1222, 0x04d0,
93 1239, 0x04cc, 1256, 0x04c8, 1273, 0x04c4, 1290, 0x04c0, 1307, 0x04bc,
94 1324, 0x04b8, 1341, 0x04b4, 1358, 0x04b0, 1376, 0x04ac, 1393, 0x04a8,
95 1410, 0x04a4, 1427, 0x04a0, 1445, 0x049c, 1462, 0x0498, 1479, 0x0494,
96 1497, 0x0490, 1514, 0x048c, 1532, 0x0488, 1549, 0x0484, 1567, 0x0480,
97 1584, 0x047c, 1602, 0x0478, 1620, 0x0474, 1637, 0x0470, 1655, 0x046c,
98 1673, 0x0468, 1690, 0x0464, 1708, 0x0460, 1726, 0x045c, 1744, 0x0458,
99 1762, 0x0454, 1780, 0x0450, 1798, 0x044c, 1816, 0x0448, 1834, 0x0444,
100 1852, 0x0440, 1870, 0x043c, 1888, 0x0438, 1906, 0x0434, 1924, 0x0430,
101 1943, 0x042c, 1961, 0x0428, 1979, 0x0424, 1997, 0x0420, 2016, 0x041c,
102 2034, 0x0418, 2053, 0x0414, 2071, 0x0410, 2089, 0x040c, 2108, 0x0408,
103 2127, 0x0404, 2145, 0x0400, 2164, 0x03fc, 2182, 0x03f8, 2201, 0x03f4,
104 2220, 0x03f0, 2239, 0x03ec, 2257, 0x03e8, 2276, 0x03e4, 2295, 0x03e0,
105 2314, 0x03dc, 2333, 0x03d8, 2352, 0x03d4, 2371, 0x03d0, 2390, 0x03cc,
106 2409, 0x03c8, 2428, 0x03c4, 2447, 0x03c0, 2466, 0x03bc, 2485, 0x03b8,
107 2505, 0x03b4, 2524, 0x03b0, 2543, 0x03ac, 2562, 0x03a8, 2582, 0x03a4,
108 2601, 0x03a0, 2621, 0x039c, 2640, 0x0398, 2660, 0x0394, 2679, 0x0390,
109 2699, 0x038c, 2718, 0x0388, 2738, 0x0384, 2758, 0x0380, 2777, 0x037c,
110 2797, 0x0378, 2817, 0x0374, 2837, 0x0370, 2857, 0x036c, 2876, 0x0368,
111 2896, 0x0364, 2916, 0x0360, 2936, 0x035c, 2956, 0x0358, 2976, 0x0354,
112 2997, 0x0350, 3017, 0x034c, 3037, 0x0348, 3057, 0x0344, 3077, 0x0340,
113 3098, 0x033c, 3118, 0x0338, 3138, 0x0334, 3159, 0x0330, 3179, 0x032c,
114 3200, 0x0328, 3220, 0x0324, 3241, 0x0320, 3261, 0x031c, 3282, 0x0318,
115 3303, 0x0314, 3323, 0x0310, 3344, 0x030c, 3365, 0x0308, 3386, 0x0304,
116 3406, 0x0300, 3427, 0x02fc, 3448, 0x02f8, 3469, 0x02f4, 3490, 0x02f0,
117 3511, 0x02ec, 3532, 0x02e8, 3553, 0x02e4, 3575, 0x02e0, 3596, 0x02dc,
118 3617, 0x02d8, 3638, 0x02d4, 3660, 0x02d0, 3681, 0x02cc, 3702, 0x02c8,
119 3724, 0x02c4, 3745, 0x02c0, 3767, 0x02bc, 3788, 0x02b8, 3810, 0x02b4,
120 3831, 0x02b0, 3853, 0x02ac, 3875, 0x02a8, 3896, 0x02a4, 3918, 0x02a0,
121 3940, 0x029c, 3962, 0x0298, 3984, 0x0294, 4006, 0x0290, 4028, 0x028c,
122 4050, 0x0288, 4072, 0x0284, 4094, 0x0280, 4116, 0x027c, 4138, 0x0278,
123 4160, 0x0274, 4182, 0x0270, 4205, 0x026c, 4227, 0x0268, 4249, 0x0264,
124 4272, 0x0260, 4294, 0x025c, 4317, 0x0258, 4339, 0x0254, 4362, 0x0250,
125 4384, 0x024c, 4407, 0x0248, 4430, 0x0244, 4453, 0x0240, 4475, 0x023c,
126 4498, 0x0238, 4521, 0x0234, 4544, 0x0230, 4567, 0x022c, 4590, 0x0228,
127 4613, 0x0224, 4636, 0x0220, 4659, 0x021c, 4682, 0x0218, 4705, 0x0214,
128 4728, 0x0210, 4752, 0x020c, 4775, 0x0208, 4798, 0x0204, 4822, 0x0200,
129 4845, 0x01fc, 4869, 0x01f8, 4892, 0x01f4, 4916, 0x01f0, 4939, 0x01ec,
130 4963, 0x01e8, 4987, 0x01e4, 5010, 0x01e0, 5034, 0x01dc, 5058, 0x01d8,
131 5082, 0x01d4, 5106, 0x01d0, 5130, 0x01cc, 5154, 0x01c8, 5178, 0x01c4,
132 5202, 0x01c0, 5226, 0x01bc, 5250, 0x01b8, 5274, 0x01b4, 5299, 0x01b0,
133 5323, 0x01ac, 5347, 0x01a8, 5372, 0x01a4, 5396, 0x01a0, 5420, 0x019c,
134 5445, 0x0198, 5469, 0x0194, 5494, 0x0190, 5519, 0x018c, 5543, 0x0188,
135 5568, 0x0184, 5593, 0x0180, 5618, 0x017c, 5643, 0x0178, 5668, 0x0174,
136 5692, 0x0170, 5717, 0x016c, 5743, 0x0168, 5768, 0x0164, 5793, 0x0160,
137 5818, 0x015c, 5843, 0x0158, 5868, 0x0154, 5894, 0x0150, 5919, 0x014c,
138 5945, 0x0148, 5970, 0x0144, 5995, 0x0140, 6021, 0x013c, 6047, 0x0138,
139 6072, 0x0134, 6098, 0x0130, 6124, 0x012c, 6149, 0x0128, 6175, 0x0124,
140 6201, 0x0120, 6227, 0x011c, 6253, 0x0118, 6279, 0x0114, 6305, 0x0110,
141 6331, 0x010c, 6357, 0x0108, 6384, 0x0104, 6410, 0x0100, 6436, 0x00fc,
142 6462, 0x00f8, 6489, 0x00f4, 6515, 0x00f0, 6542, 0x00ec, 6568, 0x00e8,
143 6595, 0x00e4, 6621, 0x00e0, 6648, 0x00dc, 6675, 0x00d8, 6702, 0x00d4,
144 6728, 0x00d0, 6755, 0x00cc, 6782, 0x00c8, 6809, 0x00c4, 6836, 0x00c0,
145 6863, 0x00bc, 6890, 0x00b8, 6917, 0x00b4, 6945, 0x00b0, 6972, 0x00ac,
146 6999, 0x00a8, 7027, 0x00a4, 7054, 0x00a0, 7081, 0x009c, 7109, 0x0098,
147 7136, 0x0094, 7164, 0x0090, 7192, 0x008c, 7219, 0x0088, 7247, 0x0084,
148 7275, 0x0080, 7303, 0x007c, 7331, 0x0078, 7359, 0x0074, 7387, 0x0070,
149 7415, 0x006c, 7443, 0x0068, 7471, 0x0064, 7499, 0x0060, 7527, 0x005c,
150 7556, 0x0058, 7584, 0x0054, 7613, 0x0050, 7641, 0x004c, 7669, 0x0048,
151 7698, 0x0044, 7727, 0x0040, 7755, 0x003c, 7784, 0x0038, 7813, 0x0034,
152 7842, 0x0030, 7870, 0x002c, 7899, 0x0028, 7928, 0x0024, 7957, 0x0020,
153 7986, 0x001c, 8016, 0x0018, 8045, 0x0014, 8074, 0x0010, 8103, 0x000c,
154 8133, 0x0008, 8162, 0x0004, 8192, 0x0000
155};
156
157static unsigned short lookup_volume_table( unsigned short value )
158{
159 /* This code is an optimised version of:
160 * int i = 0;
161 * while( volume_table[i*2] < value )
162 * i++;
163 * return volume_table[i*2+1];
164 */
165 unsigned short *ptr = log_table;
166 while( *ptr < value )
167 ptr += 2;
168 return *(ptr+1);
169}
170
171/* this function calculates a 8.8 fixed point logarithmic attenuation
172 * value from a linear volume value in the range 0 to 16384 */
173static unsigned short log_from_linear( unsigned short value )
174{
175 if (value >= 16384)
176 return 0x0000;
177 if (value) {
178 unsigned short result = 0;
179 int v, c;
180 for( c = 0, v = 8192; c < 14; c++, v >>= 1 ) {
181 if( value >= v ) {
182 result += lookup_volume_table( (value - v) << c );
183 return result;
184 }
185 result += 0x0605; /* 6.0205 (result of -20*log10(0.5)) */
186 }
187 }
188 return 0xffff;
189}
190
191/*
192 * Sample handling operations
193 */
194
195static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position);
196static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode);
197static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq);
198static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume);
199static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop);
200static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position);
201static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data);
202
203static struct snd_trident_sample_ops sample_ops =
204{
205 sample_start,
206 sample_stop,
207 sample_freq,
208 sample_volume,
209 sample_loop,
210 sample_pos,
211 sample_private1
212};
213
214static void snd_trident_simple_init(struct snd_trident_voice * voice)
215{
216 //voice->handler_wave = interrupt_wave;
217 //voice->handler_volume = interrupt_volume;
218 //voice->handler_effect = interrupt_effect;
219 //voice->volume_change = NULL;
220 voice->sample_ops = &sample_ops;
221}
222
223static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
224{
225 struct simple_instrument *simple;
226 struct snd_seq_kinstr *instr;
227 unsigned long flags;
228 unsigned int loop_start, loop_end, sample_start, sample_end, start_offset;
229 unsigned int value;
230 unsigned int shift = 0;
231
232 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
233 if (instr == NULL)
234 return;
235 voice->instr = instr->instr; /* copy ID to speedup aliases */
236 simple = KINSTR_DATA(instr);
237
238 spin_lock_irqsave(&trident->reg_lock, flags);
239
240 if (trident->device == TRIDENT_DEVICE_ID_SI7018)
241 voice->GVSel = 1; /* route to Wave volume */
242
243 voice->CTRL = 0;
244 voice->Alpha = 0;
245 voice->FMS = 0;
246
247 loop_start = simple->loop_start >> 4;
248 loop_end = simple->loop_end >> 4;
249 sample_start = (simple->start + position) >> 4;
250 if( sample_start >= simple->size )
251 sample_start = simple->start >> 4;
252 sample_end = simple->size;
253 start_offset = position >> 4;
254
255 if (simple->format & SIMPLE_WAVE_16BIT) {
256 voice->CTRL |= 8;
257 shift++;
258 }
259 if (simple->format & SIMPLE_WAVE_STEREO) {
260 voice->CTRL |= 4;
261 shift++;
262 }
263 if (!(simple->format & SIMPLE_WAVE_UNSIGNED))
264 voice->CTRL |= 2;
265
266 voice->LBA = simple->address.memory;
267
268 if (simple->format & SIMPLE_WAVE_LOOP) {
269 voice->CTRL |= 1;
270 voice->LBA += loop_start << shift;
271 if( start_offset >= loop_start ) {
272 voice->CSO = start_offset - loop_start;
273 voice->negCSO = 0;
274 } else {
275 voice->CSO = loop_start - start_offset;
276 voice->negCSO = 1;
277 }
278 voice->ESO = loop_end - loop_start - 1;
279 } else {
280 voice->LBA += start_offset << shift;
281 voice->CSO = sample_start;
282 voice->ESO = sample_end - 1;
283 voice->negCSO = 0;
284 }
285
286 if (voice->flags & SNDRV_TRIDENT_VFLG_RUNNING) {
287 snd_trident_stop_voice(trident, voice->number);
288 voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
289 }
290
291 /* set CSO sign */
292 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
293 if( voice->negCSO ) {
294 value |= 1 << (voice->number&31);
295 } else {
296 value &= ~(1 << (voice->number&31));
297 }
298 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
299
300 voice->Attribute = 0;
301 snd_trident_write_voice_regs(trident, voice);
302 snd_trident_start_voice(trident, voice->number);
303 voice->flags |= SNDRV_TRIDENT_VFLG_RUNNING;
304 spin_unlock_irqrestore(&trident->reg_lock, flags);
305 snd_seq_instr_free_use(trident->synth.ilist, instr);
306}
307
308static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode)
309{
310 unsigned long flags;
311
312 if (!(voice->flags & SNDRV_TRIDENT_VFLG_RUNNING))
313 return;
314
315 switch (mode) {
316 default:
317 spin_lock_irqsave(&trident->reg_lock, flags);
318 snd_trident_stop_voice(trident, voice->number);
319 voice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
320 spin_unlock_irqrestore(&trident->reg_lock, flags);
321 break;
322 case SAMPLE_STOP_LOOP: /* disable loop only */
323 voice->CTRL &= ~1;
324 spin_lock_irqsave(&trident->reg_lock, flags);
325 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
326 outw((((voice->CTRL << 12) | (voice->EC & 0x0fff)) & 0xffff), CH_GVSEL_PAN_VOL_CTRL_EC);
327 spin_unlock_irqrestore(&trident->reg_lock, flags);
328 break;
329 }
330}
331
332static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq)
333{
334 unsigned long flags;
335 freq >>= 4;
336
337 spin_lock_irqsave(&trident->reg_lock, flags);
338 if (freq == 44100)
339 voice->Delta = 0xeb3;
340 else if (freq == 8000)
341 voice->Delta = 0x2ab;
342 else if (freq == 48000)
343 voice->Delta = 0x1000;
344 else
345 voice->Delta = (((freq << 12) + freq) / 48000) & 0x0000ffff;
346
347 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
348 if (trident->device == TRIDENT_DEVICE_ID_NX) {
349 outb((unsigned char) voice->Delta, TRID_REG(trident, CH_NX_DELTA_CSO + 3));
350 outb((unsigned char) (voice->Delta >> 8), TRID_REG(trident, CH_NX_DELTA_ESO + 3));
351 } else {
352 outw((unsigned short) voice->Delta, TRID_REG(trident, CH_DX_ESO_DELTA));
353 }
354
355 spin_unlock_irqrestore(&trident->reg_lock, flags);
356}
357
358static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume)
359{
360 unsigned long flags;
361 unsigned short value;
362
363 spin_lock_irqsave(&trident->reg_lock, flags);
364 voice->GVSel = 0; /* use global music volume */
365 voice->FMC = 0x03; /* fixme: can we do something useful with FMC? */
366 if (volume->volume >= 0) {
367 volume->volume &= 0x3fff;
368 /* linear volume -> logarithmic attenuation conversion
369 * uses EC register for greater resolution (6.6 bits) than Vol register (5.3 bits)
370 * Vol register used when additional attenuation is required */
371 voice->RVol = 0;
372 voice->CVol = 0;
373 value = log_from_linear( volume->volume );
374 voice->Vol = 0;
375 voice->EC = (value & 0x3fff) >> 2;
376 if (value > 0x3fff) {
377 voice->EC |= 0xfc0;
378 if (value < 0x5f00 )
379 voice->Vol = ((value >> 8) - 0x3f) << 5;
380 else {
381 voice->Vol = 0x3ff;
382 voice->EC = 0xfff;
383 }
384 }
385 }
386 if (volume->lr >= 0) {
387 volume->lr &= 0x3fff;
388 /* approximate linear pan by attenuating channels */
389 if (volume->lr >= 0x2000) { /* attenuate left (pan right) */
390 value = 0x3fff - volume->lr;
391 for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ )
392 if (value >= pan_table[voice->Pan] )
393 break;
394 } else { /* attenuate right (pan left) */
395 for (voice->Pan = 0; voice->Pan < 63; voice->Pan++ )
396 if ((unsigned int)volume->lr >= pan_table[voice->Pan] )
397 break;
398 voice->Pan |= 0x40;
399 }
400 }
401 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
402 outl((voice->GVSel << 31) | ((voice->Pan & 0x0000007f) << 24) |
403 ((voice->Vol & 0x000000ff) << 16) | ((voice->CTRL & 0x0000000f) << 12) |
404 (voice->EC & 0x00000fff), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
405 value = ((voice->FMC & 0x03) << 14) | ((voice->RVol & 0x7f) << 7) | (voice->CVol & 0x7f);
406 outw(value, TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
407 spin_unlock_irqrestore(&trident->reg_lock, flags);
408}
409
410static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop)
411{
412 unsigned long flags;
413 struct simple_instrument *simple;
414 struct snd_seq_kinstr *instr;
415 unsigned int loop_start, loop_end;
416
417 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
418 if (instr == NULL)
419 return;
420 voice->instr = instr->instr; /* copy ID to speedup aliases */
421 simple = KINSTR_DATA(instr);
422
423 loop_start = loop->start >> 4;
424 loop_end = loop->end >> 4;
425
426 spin_lock_irqsave(&trident->reg_lock, flags);
427
428 voice->LBA = simple->address.memory + loop_start;
429 voice->CSO = 0;
430 voice->ESO = loop_end - loop_start - 1;
431
432 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
433 outb((voice->LBA >> 16), TRID_REG(trident, CH_LBA + 2));
434 outw((voice->LBA & 0xffff), TRID_REG(trident, CH_LBA));
435 if (trident->device == TRIDENT_DEVICE_ID_NX) {
436 outb((voice->ESO >> 16), TRID_REG(trident, CH_NX_DELTA_ESO + 2));
437 outw((voice->ESO & 0xffff), TRID_REG(trident, CH_NX_DELTA_ESO));
438 outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));
439 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));
440 } else {
441 outw((voice->ESO & 0xffff), TRID_REG(trident, CH_DX_ESO_DELTA + 2));
442 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));
443 }
444
445 spin_unlock_irqrestore(&trident->reg_lock, flags);
446 snd_seq_instr_free_use(trident->synth.ilist, instr);
447}
448
449static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
450{
451 unsigned long flags;
452 struct simple_instrument *simple;
453 struct snd_seq_kinstr *instr;
454 unsigned int value;
455
456 instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
457 if (instr == NULL)
458 return;
459 voice->instr = instr->instr; /* copy ID to speedup aliases */
460 simple = KINSTR_DATA(instr);
461
462 spin_lock_irqsave(&trident->reg_lock, flags);
463
464 if (simple->format & SIMPLE_WAVE_LOOP) {
465 if( position >= simple->loop_start ) {
466 voice->CSO = (position - simple->loop_start) >> 4;
467 voice->negCSO = 0;
468 } else {
469 voice->CSO = (simple->loop_start - position) >> 4;
470 voice->negCSO = 1;
471 }
472 } else {
473 voice->CSO = position >> 4;
474 voice->negCSO = 0;
475 }
476
477 /* set CSO sign */
478 value = inl(TRID_REG(trident, T4D_SIGN_CSO_A));
479 if( voice->negCSO ) {
480 value |= 1 << (voice->number&31);
481 } else {
482 value &= ~(1 << (voice->number&31));
483 }
484 outl(value,TRID_REG(trident, T4D_SIGN_CSO_A));
485
486
487 outb((unsigned char) voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
488 if (trident->device == TRIDENT_DEVICE_ID_NX) {
489 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_NX_DELTA_CSO));
490 outb((voice->CSO >> 16), TRID_REG(trident, CH_NX_DELTA_CSO + 2));
491 } else {
492 outw((voice->CSO & 0xffff), TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
493 }
494
495 spin_unlock_irqrestore(&trident->reg_lock, flags);
496 snd_seq_instr_free_use(trident->synth.ilist, instr);
497}
498
499static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data)
500{
501}
502
503/*
504 * Memory management / sample loading
505 */
506
507static int snd_trident_simple_put_sample(void *private_data,
508 struct simple_instrument * instr,
509 char __user *data, long len, int atomic)
510{
511 struct snd_trident *trident = private_data;
512 int size = instr->size;
513 int shift = 0;
514
515 if (instr->format & SIMPLE_WAVE_BACKWARD ||
516 instr->format & SIMPLE_WAVE_BIDIR ||
517 instr->format & SIMPLE_WAVE_ULAW)
518 return -EINVAL; /* not supported */
519
520 if (instr->format & SIMPLE_WAVE_16BIT)
521 shift++;
522 if (instr->format & SIMPLE_WAVE_STEREO)
523 shift++;
524 size <<= shift;
525
526 if (trident->synth.current_size + size > trident->synth.max_size)
527 return -ENOMEM;
528
529 if (!access_ok(VERIFY_READ, data, size))
530 return -EFAULT;
531
532 if (trident->tlb.entries) {
533 struct snd_util_memblk *memblk;
534 memblk = snd_trident_synth_alloc(trident, size);
535 if (memblk == NULL)
536 return -ENOMEM;
537 if (snd_trident_synth_copy_from_user(trident, memblk, 0, data, size) ) {
538 snd_trident_synth_free(trident, memblk);
539 return -EFAULT;
540 }
541 instr->address.ptr = (unsigned char*)memblk;
542 instr->address.memory = memblk->offset;
543 } else {
544 struct snd_dma_buffer dmab;
545 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
546 size, &dmab) < 0)
547 return -ENOMEM;
548
549 if (copy_from_user(dmab.area, data, size)) {
550 snd_dma_free_pages(&dmab);
551 return -EFAULT;
552 }
553 instr->address.ptr = dmab.area;
554 instr->address.memory = dmab.addr;
555 }
556
557 trident->synth.current_size += size;
558 return 0;
559}
560
561static int snd_trident_simple_get_sample(void *private_data,
562 struct simple_instrument * instr,
563 char __user *data, long len, int atomic)
564{
565 //struct snd_trident *trident = private_data;
566 int size = instr->size;
567 int shift = 0;
568
569 if (instr->format & SIMPLE_WAVE_16BIT)
570 shift++;
571 if (instr->format & SIMPLE_WAVE_STEREO)
572 shift++;
573 size <<= shift;
574
575 if (!access_ok(VERIFY_WRITE, data, size))
576 return -EFAULT;
577
578 /* FIXME: not implemented yet */
579
580 return -EBUSY;
581}
582
583static int snd_trident_simple_remove_sample(void *private_data,
584 struct simple_instrument * instr,
585 int atomic)
586{
587 struct snd_trident *trident = private_data;
588 int size = instr->size;
589
590 if (instr->format & SIMPLE_WAVE_16BIT)
591 size <<= 1;
592 if (instr->format & SIMPLE_WAVE_STEREO)
593 size <<= 1;
594
595 if (trident->tlb.entries) {
596 struct snd_util_memblk *memblk = (struct snd_util_memblk *)instr->address.ptr;
597 if (memblk)
598 snd_trident_synth_free(trident, memblk);
599 else
600 return -EFAULT;
601 } else {
602 struct snd_dma_buffer dmab;
603 dmab.dev.type = SNDRV_DMA_TYPE_DEV;
604 dmab.dev.dev = snd_dma_pci_data(trident->pci);
605 dmab.area = instr->address.ptr;
606 dmab.addr = instr->address.memory;
607 dmab.bytes = size;
608 snd_dma_free_pages(&dmab);
609 }
610
611 trident->synth.current_size -= size;
612 if (trident->synth.current_size < 0) /* shouldn't need this check... */
613 trident->synth.current_size = 0;
614
615 return 0;
616}
617
618static void select_instrument(struct snd_trident * trident, struct snd_trident_voice * v)
619{
620 struct snd_seq_kinstr *instr;
621 instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1);
622 if (instr != NULL) {
623 if (instr->ops) {
624 if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE))
625 snd_trident_simple_init(v);
626 }
627 snd_seq_instr_free_use(trident->synth.ilist, instr);
628 }
629}
630
631/*
632
633 */
634
635static void event_sample(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
636{
637 if (v->sample_ops && v->sample_ops->sample_stop)
638 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
639 v->instr.std = ev->data.sample.param.sample.std;
640 if (v->instr.std & 0xff000000) { /* private instrument */
641 v->instr.std &= 0x00ffffff;
642 v->instr.std |= (unsigned int)ev->source.client << 24;
643 }
644 v->instr.bank = ev->data.sample.param.sample.bank;
645 v->instr.prg = ev->data.sample.param.sample.prg;
646 select_instrument(p->trident, v);
647}
648
649static void event_cluster(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
650{
651 if (v->sample_ops && v->sample_ops->sample_stop)
652 v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
653 v->instr.cluster = ev->data.sample.param.cluster.cluster;
654 select_instrument(p->trident, v);
655}
656
657static void event_start(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
658{
659 if (v->sample_ops && v->sample_ops->sample_start)
660 v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position);
661}
662
663static void event_stop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
664{
665 if (v->sample_ops && v->sample_ops->sample_stop)
666 v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode);
667}
668
669static void event_freq(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
670{
671 if (v->sample_ops && v->sample_ops->sample_freq)
672 v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency);
673}
674
675static void event_volume(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
676{
677 if (v->sample_ops && v->sample_ops->sample_volume)
678 v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume);
679}
680
681static void event_loop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
682{
683 if (v->sample_ops && v->sample_ops->sample_loop)
684 v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop);
685}
686
687static void event_position(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
688{
689 if (v->sample_ops && v->sample_ops->sample_pos)
690 v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position);
691}
692
693static void event_private1(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
694{
695 if (v->sample_ops && v->sample_ops->sample_private1)
696 v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8);
697}
698
699typedef void (trident_sample_event_handler_t) (struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v);
700
701static trident_sample_event_handler_t *trident_sample_event_handlers[9] =
702{
703 event_sample,
704 event_cluster,
705 event_start,
706 event_stop,
707 event_freq,
708 event_volume,
709 event_loop,
710 event_position,
711 event_private1
712};
713
714static void snd_trident_sample_event(struct snd_seq_event * ev, struct snd_trident_port * p)
715{
716 int idx, voice;
717 struct snd_trident *trident = p->trident;
718 struct snd_trident_voice *v;
719 unsigned long flags;
720
721 idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
722 if (idx < 0 || idx > 8)
723 return;
724 for (voice = 0; voice < 64; voice++) {
725 v = &trident->synth.voices[voice];
726 if (v->use && v->client == ev->source.client &&
727 v->port == ev->source.port &&
728 v->index == ev->data.sample.channel) {
729 spin_lock_irqsave(&trident->event_lock, flags);
730 trident_sample_event_handlers[idx] (ev, p, v);
731 spin_unlock_irqrestore(&trident->event_lock, flags);
732 return;
733 }
734 }
735}
736
737/*
738
739 */
740
741static void snd_trident_synth_free_voices(struct snd_trident * trident, int client, int port)
742{
743 int idx;
744 struct snd_trident_voice *voice;
745
746 for (idx = 0; idx < 32; idx++) {
747 voice = &trident->synth.voices[idx];
748 if (voice->use && voice->client == client && voice->port == port)
749 snd_trident_free_voice(trident, voice);
750 }
751}
752
753static int snd_trident_synth_use(void *private_data, struct snd_seq_port_subscribe * info)
754{
755 struct snd_trident_port *port = private_data;
756 struct snd_trident *trident = port->trident;
757 struct snd_trident_voice *voice;
758 unsigned int idx;
759 unsigned long flags;
760
761 if (info->voices > 32)
762 return -EINVAL;
763 spin_lock_irqsave(&trident->reg_lock, flags);
764 for (idx = 0; idx < info->voices; idx++) {
765 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port);
766 if (voice == NULL) {
767 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
768 spin_unlock_irqrestore(&trident->reg_lock, flags);
769 return -EBUSY;
770 }
771 voice->index = idx;
772 voice->Vol = 0x3ff;
773 voice->EC = 0x0fff;
774 }
775#if 0
776 for (idx = 0; idx < info->midi_voices; idx++) {
777 port->midi_has_voices = 1;
778 voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_MIDI, info->sender.client, info->sender.port);
779 if (voice == NULL) {
780 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
781 spin_unlock_irqrestore(&trident->reg_lock, flags);
782 return -EBUSY;
783 }
784 voice->Vol = 0x3ff;
785 voice->EC = 0x0fff;
786 }
787#endif
788 spin_unlock_irqrestore(&trident->reg_lock, flags);
789 return 0;
790}
791
792static int snd_trident_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info)
793{
794 struct snd_trident_port *port = private_data;
795 struct snd_trident *trident = port->trident;
796 unsigned long flags;
797
798 spin_lock_irqsave(&trident->reg_lock, flags);
799 snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);
800 spin_unlock_irqrestore(&trident->reg_lock, flags);
801 return 0;
802}
803
804/*
805
806 */
807
808static void snd_trident_synth_free_private_instruments(struct snd_trident_port * p, int client)
809{
810 struct snd_seq_instr_header ifree;
811
812 memset(&ifree, 0, sizeof(ifree));
813 ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;
814 snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0);
815}
816
817static int snd_trident_synth_event_input(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
818{
819 struct snd_trident_port *p = (struct snd_trident_port *) private_data;
820
821 if (p == NULL)
822 return -EINVAL;
823 if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&
824 ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) {
825 snd_trident_sample_event(ev, p);
826 return 0;
827 }
828 if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM &&
829 ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) {
830 if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) {
831 snd_trident_synth_free_private_instruments(p, ev->data.addr.client);
832 return 0;
833 }
834 }
835 if (direct) {
836 if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) {
837 snd_seq_instr_event(&p->trident->synth.simple_ops.kops,
838 p->trident->synth.ilist, ev,
839 p->trident->synth.seq_client, atomic, hop);
840 return 0;
841 }
842 }
843 return 0;
844}
845
846static void snd_trident_synth_instr_notify(void *private_data,
847 struct snd_seq_kinstr * instr,
848 int what)
849{
850 int idx;
851 struct snd_trident *trident = private_data;
852 struct snd_trident_voice *pvoice;
853 unsigned long flags;
854
855 spin_lock_irqsave(&trident->event_lock, flags);
856 for (idx = 0; idx < 64; idx++) {
857 pvoice = &trident->synth.voices[idx];
858 if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) {
859 if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) {
860 pvoice->sample_ops->sample_stop(trident, pvoice, SAMPLE_STOP_IMMEDIATELY);
861 } else {
862 snd_trident_stop_voice(trident, pvoice->number);
863 pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;
864 }
865 }
866 }
867 spin_unlock_irqrestore(&trident->event_lock, flags);
868}
869
870/*
871
872 */
873
874static void snd_trident_synth_free_port(void *private_data)
875{
876 struct snd_trident_port *p = (struct snd_trident_port *) private_data;
877
878 if (p)
879 snd_midi_channel_free_set(p->chset);
880}
881
882static int snd_trident_synth_create_port(struct snd_trident * trident, int idx)
883{
884 struct snd_trident_port *p;
885 struct snd_seq_port_callback callbacks;
886 char name[32];
887 char *str;
888 int result;
889
890 p = &trident->synth.seq_ports[idx];
891 p->chset = snd_midi_channel_alloc_set(16);
892 if (p->chset == NULL)
893 return -ENOMEM;
894 p->chset->private_data = p;
895 p->trident = trident;
896 p->client = trident->synth.seq_client;
897
898 memset(&callbacks, 0, sizeof(callbacks));
899 callbacks.owner = THIS_MODULE;
900 callbacks.use = snd_trident_synth_use;
901 callbacks.unuse = snd_trident_synth_unuse;
902 callbacks.event_input = snd_trident_synth_event_input;
903 callbacks.private_free = snd_trident_synth_free_port;
904 callbacks.private_data = p;
905
906 str = "???";
907 switch (trident->device) {
908 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
909 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
910 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
911 }
912 sprintf(name, "%s port %i", str, idx);
913 p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client,
914 &callbacks,
915 SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
916 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
917 SNDRV_SEQ_PORT_TYPE_SYNTH |
918 SNDRV_SEQ_PORT_TYPE_HARDWARE |
919 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
920 16, 0,
921 name);
922 if (p->chset->port < 0) {
923 result = p->chset->port;
924 snd_trident_synth_free_port(p);
925 return result;
926 }
927 p->port = p->chset->port;
928 return 0;
929}
930
931/*
932
933 */
934
935static int snd_trident_synth_new_device(struct snd_seq_device *dev)
936{
937 struct snd_trident *trident;
938 int client, i;
939 struct snd_seq_port_subscribe sub;
940 struct snd_simple_ops *simpleops;
941 char *str;
942
943 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
944 if (trident == NULL)
945 return -EINVAL;
946
947 trident->synth.seq_client = -1;
948
949 /* allocate new client */
950 str = "???";
951 switch (trident->device) {
952 case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
953 case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
954 case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
955 }
956 client = trident->synth.seq_client =
957 snd_seq_create_kernel_client(trident->card, 1, str);
958 if (client < 0)
959 return client;
960
961 for (i = 0; i < 4; i++)
962 snd_trident_synth_create_port(trident, i);
963
964 trident->synth.ilist = snd_seq_instr_list_new();
965 if (trident->synth.ilist == NULL) {
966 snd_seq_delete_kernel_client(client);
967 trident->synth.seq_client = -1;
968 return -ENOMEM;
969 }
970 trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
971
972 simpleops = &trident->synth.simple_ops;
973 snd_seq_simple_init(simpleops, trident, NULL);
974 simpleops->put_sample = snd_trident_simple_put_sample;
975 simpleops->get_sample = snd_trident_simple_get_sample;
976 simpleops->remove_sample = snd_trident_simple_remove_sample;
977 simpleops->notify = snd_trident_synth_instr_notify;
978
979 memset(&sub, 0, sizeof(sub));
980 sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
981 sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
982 sub.dest.client = client;
983 sub.dest.port = 0;
984 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub);
985
986 return 0;
987}
988
989static int snd_trident_synth_delete_device(struct snd_seq_device *dev)
990{
991 struct snd_trident *trident;
992
993 trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
994 if (trident == NULL)
995 return -EINVAL;
996
997 if (trident->synth.seq_client >= 0) {
998 snd_seq_delete_kernel_client(trident->synth.seq_client);
999 trident->synth.seq_client = -1;
1000 }
1001 if (trident->synth.ilist)
1002 snd_seq_instr_list_free(&trident->synth.ilist);
1003 return 0;
1004}
1005
1006static int __init alsa_trident_synth_init(void)
1007{
1008 static struct snd_seq_dev_ops ops =
1009 {
1010 snd_trident_synth_new_device,
1011 snd_trident_synth_delete_device
1012 };
1013
1014 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops,
1015 sizeof(struct snd_trident *));
1016}
1017
1018static void __exit alsa_trident_synth_exit(void)
1019{
1020 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT);
1021}
1022
1023module_init(alsa_trident_synth_init)
1024module_exit(alsa_trident_synth_exit)