1 diff -urN linux-2.4.19-clean/CREDITS linux-2.4.19/CREDITS
2 --- linux-2.4.19-clean/CREDITS Sun Aug 4 03:44:28 2002
3 +++ linux-2.4.19/CREDITS Sun Aug 4 03:52:26 2002
8 +D: Updated PC speaker driver for 2.3
12 E: andreas.bombe@munich.netsurf.de
13 @@ -2698,6 +2700,15 @@
14 S: Sunnyvale, California 94088-4132
18 +E: stssppnn@yahoo.com
19 +W: http://dosemu.sourceforge.net/stas
20 +W: http://www.geocities.com/stssppnn/pcsp.html
21 +D: PC-Speaker driver maintainer
22 +D: vm86 fixes, OSS fixes
27 E: shimon@i-Connect.Net
28 W: http://www.-i-Connect.Net/~shimon
29 diff -urN linux-2.4.19-clean/Documentation/Configure.help linux-2.4.19/Documentation/Configure.help
30 --- linux-2.4.19-clean/Documentation/Configure.help Sun Aug 4 03:44:29 2002
31 +++ linux-2.4.19/Documentation/Configure.help Fri Aug 16 18:52:24 2002
32 @@ -18617,11 +18617,6 @@
33 as <file:Documentation/sound/README.modules>; the module will be
36 - I'm told that even without a sound card, you can make your computer
37 - say more than an occasional beep, by programming the PC speaker.
38 - Kernel patches and supporting utilities to do that are in the pcsp
39 - package, available at <ftp://ftp.infradead.org/pub/pcsp/>.
43 OSS is the Open Sound System suite of sound card drivers. They make
44 @@ -19401,6 +19396,51 @@
45 Maestro 2E. See <file:Documentation/sound/Maestro> for more
48 +Internal PC speaker support
50 + If you don't have a sound card in your computer, you can include a
51 + driver for the PC speaker which allows it to act like a primitive
52 + sound card. You can compile this as a module, in which case only the
53 + timer-interrupt hooks and frequency initialization code will appear
54 + in the kernel, and the rest of the driver will be loaded as a module
55 + whenever you want. Further this driver supports DACs
56 + (Digital-to-Analog-Converter) connected to the parallel port.
58 + You don't need this driver if you only want your computer to beep.
60 +Use doubled modulation frequency
62 + Standard modulation frequency for PC-Speaker is 18.5KHz.
63 + This can produce a high-pitched tone on some motherboards.
64 + If you have this problem, try enabling this option.
65 + It will make PC-Speaker driver use 36KHz if possible, but
66 + it will produce 5-bit sound instead of 6-bit.
70 +PC speaker automatic measurement
71 +CONFIG_PCSP_NO_TEST_SPEED
72 + The PCSP-driver automatically tests the speed of your computer and
73 + configure itself at kernel-startup. If your machine is too slow
74 + (386SX and cannot play with more than 12500 Hz) the driver is disabled
75 + and you here a beep.
77 + However, you can override this if you specify a 'pcsp=SAMPLERATE' at
78 + kernel commandline or by disabling the automatic speed detection.
79 + THIS IS NOT RECOMMENDED, your machine may HANG if you select a
80 + samplerate, which is to high for your machine.
82 + If the measurement switch the driver off but an older version was
83 + working on your machine, please contact me (beck@dresearch.de).
84 + It is safe to answer 'N' here.
86 +PC speaker selected samplerate
88 + If you have disabled the automatically speed test, select here to
89 + real samplerate that is used for PC speaker. The full range from
90 + 12000Hz up to 18356 is allowed. Higher rates results in better
91 + sound quality but may crash your machine if it is too slow (<486DX-33).
93 ESS Maestro3/Allegro driver
95 Say Y or M if you have a sound system driven by ESS's Maestro 3
96 diff -urN linux-2.4.19-clean/Makefile linux-2.4.19/Makefile
97 --- linux-2.4.19-clean/Makefile Sun Aug 4 03:44:29 2002
98 +++ linux-2.4.19/Makefile Sun Aug 4 03:52:27 2002
100 DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
101 DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
103 +ifneq ($(CONFIG_SOUND),y)
105 + DRIVERS-y += drivers/sound/sounddrivers.o
109 DRIVERS := $(DRIVERS-y)
112 diff -urN linux-2.4.19-clean/arch/i386/kernel/time.c linux-2.4.19/arch/i386/kernel/time.c
113 --- linux-2.4.19-clean/arch/i386/kernel/time.c Thu Mar 14 03:37:55 2002
114 +++ linux-2.4.19/arch/i386/kernel/time.c Fri Aug 16 19:04:44 2002
116 #include <linux/mm.h>
117 #include <linux/interrupt.h>
118 #include <linux/time.h>
119 +#include <linux/pcsp.h>
120 #include <linux/delay.h>
121 #include <linux/init.h>
122 #include <linux/smp.h>
125 jiffies_p = jiffies_t;
127 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
129 + * when using PCSP, we must add the accumulated
130 + * clockticks from the PCSP driver
132 + count += pcsp_clockticks - pcsp_timer0_latch;
137 count = ((LATCH-1) - count) * TICK_SIZE;
138 diff -urN linux-2.4.19-clean/drivers/char/joystick/analog.c linux-2.4.19/drivers/char/joystick/analog.c
139 --- linux-2.4.19-clean/drivers/char/joystick/analog.c Fri Oct 26 01:01:51 2001
140 +++ linux-2.4.19/drivers/char/joystick/analog.c Sun Aug 4 03:52:27 2002
142 #include <linux/init.h>
143 #include <linux/input.h>
144 #include <linux/gameport.h>
145 +#include <linux/pcsp.h>
146 #include <asm/timex.h>
148 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
152 #define TSC_PRESENT (test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
153 -#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } } while (0)
154 +#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } x += pcsp_clockticks - pcsp_timer0_latch; } while (0)
155 #define DELTA(x,y) (TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
156 #define TIME_NAME (TSC_PRESENT?"TSC":"PIT")
158 diff -urN linux-2.4.19-clean/drivers/char/joystick/gameport.c linux-2.4.19/drivers/char/joystick/gameport.c
159 --- linux-2.4.19-clean/drivers/char/joystick/gameport.c Sat Sep 15 01:40:00 2001
160 +++ linux-2.4.19/drivers/char/joystick/gameport.c Sun Aug 4 03:52:27 2002
162 #include <linux/isapnp.h>
163 #include <linux/stddef.h>
164 #include <linux/delay.h>
165 +#include <linux/pcsp.h>
167 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
168 MODULE_LICENSE("GPL");
171 #if defined(__i386__) || defined(__x86_64__)
173 -#define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
174 +#define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; x += pcsp_clockticks - pcsp_timer0_latch; } while (0)
175 #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193180L/HZ:0))
177 unsigned int i, t, t1, t2, t3, tx;
178 diff -urN linux-2.4.19-clean/drivers/char/vt.c linux-2.4.19/drivers/char/vt.c
179 --- linux-2.4.19-clean/drivers/char/vt.c Fri Nov 16 21:08:28 2001
180 +++ linux-2.4.19/drivers/char/vt.c Sun Aug 4 03:52:27 2002
182 || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \
183 || defined(__x86_64__)
185 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
186 +extern char pcsp_speaker;
190 kd_nosound(unsigned long ignored)
192 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
193 + /* can't allow usage of counter 2 if /dev/pcsp use it */
197 /* disable counter 2 */
198 outb(inb_p(0x61)&0xFC, 0x61);
201 unsigned int count = 0;
204 +#if defined(CONFIG_PCSP) || defined(CONFIG_PCSP_MODULE)
205 + /* can't allow usage of counter 2 if /dev/pcsp use it */
209 if (hz > 20 && hz < 32767)
210 count = 1193180 / hz;
212 diff -urN linux-2.4.19-clean/drivers/sound/Config.in linux-2.4.19/drivers/sound/Config.in
213 --- linux-2.4.19-clean/drivers/sound/Config.in Sun Aug 4 03:44:50 2002
214 +++ linux-2.4.19/drivers/sound/Config.in Fri Aug 16 18:13:46 2002
216 bool ' Verbose initialisation' CONFIG_SOUND_TRACEINIT
217 bool ' Persistent DMA buffers' CONFIG_SOUND_DMAP
219 + if [ "$ARCH" = "i386" ]; then
220 + dep_tristate ' Internal PC speaker support' CONFIG_PCSP $CONFIG_SOUND_OSS
222 + if [ "$CONFIG_PCSP" = "y" -o "$CONFIG_PCSP" = "m" ]; then
223 + bool ' Use doubled modulation frequency' CONFIG_PCSP_HIGH_FRQ
225 + if [ "$CONFIG_PCSP" = "y" -o "$CONFIG_PCSP" = "m" ]; then
226 + bool ' Disable automatic speed detection' CONFIG_PCSP_NO_TEST_SPEED
227 + if [ "$CONFIG_PCSP_NO_TEST_SPEED" = "y" ] ; then
228 + int ' Enter a samplerate for PCSP [12000-18356]' CONFIG_PCSP_SRATE 18356
232 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
233 dep_tristate ' AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND_OSS
235 diff -urN linux-2.4.19-clean/drivers/sound/Makefile linux-2.4.19/drivers/sound/Makefile
236 --- linux-2.4.19-clean/drivers/sound/Makefile Sun Aug 4 03:44:50 2002
237 +++ linux-2.4.19/drivers/sound/Makefile Sun Aug 4 03:52:27 2002
239 export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
240 msnd.o opl3.o sb_common.o sequencer_syms.o \
241 sound_core.o sound_syms.o uart401.o \
242 - nm256_audio.o ac97.o ac97_codec.o aci.o
243 + nm256_audio.o ac97.o ac97_codec.o aci.o pcsp_stub.o
245 # Each configuration option enables a list of files.
248 obj-$(CONFIG_SOUND_MAESTRO) += maestro.o
249 obj-$(CONFIG_SOUND_MAESTRO3) += maestro3.o ac97_codec.o
250 obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
251 +obj-$(CONFIG_PCSP) += pcsnd.o
252 obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
253 obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
254 obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
256 obj-y += cs4281/cs4281.o
260 + obj-y += pcsp_stub.o
263 subdir-$(CONFIG_DMASOUND) += dmasound
265 ifeq ($(CONFIG_DMASOUND),y)
267 # Declare multi-part drivers.
269 list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
270 - soundcore.o wavefront.o
271 + soundcore.o wavefront.o pcsnd.o
274 dev_table.o soundcard.o sound_syms.o \
276 sb_lib-objs := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
277 vidc_mod-objs := vidc.o vidc_fill.o
278 wavefront-objs := wavfront.o wf_midi.o yss225.o
279 +pcsnd-objs := pcsp.o pcsndriv.o pcsp_mixer.o
282 O_TARGET := sounddrivers.o
284 wavefront.o: $(wavefront-objs)
285 $(LD) -r -o $@ $(wavefront-objs)
287 +pcsnd.o: $(pcsnd-objs)
288 + $(LD) -r -o $@ $(pcsnd-objs)
290 # Firmware files that need translation
292 # The translated files are protected by a file that keeps track
293 diff -urN linux-2.4.19-clean/drivers/sound/pcsndriv.c linux-2.4.19/drivers/sound/pcsndriv.c
294 --- linux-2.4.19-clean/drivers/sound/pcsndriv.c Thu Jan 1 03:00:00 1970
295 +++ linux-2.4.19/drivers/sound/pcsndriv.c Fri Aug 16 19:09:36 2002
298 + * linux/drivers/sound/pcsndriv.c
300 + * /dev/pcsp implementation
302 + * Copyright (C) 1993-1997 Michael Beck
305 +#include <linux/config.h>
306 +#include <linux/soundcard.h>
308 +#include <linux/kernel.h>
309 +#include <linux/sched.h>
310 +#include <linux/errno.h>
311 +#include <linux/ptrace.h>
312 +#include <linux/timex.h>
313 +#include <linux/ioport.h>
314 +#include <linux/mm.h>
315 +#include <linux/slab.h>
316 +#include <linux/init.h>
317 +#include <linux/poll.h>
318 +#include <linux/wait.h>
321 +#include <asm/uaccess.h>
322 +#include <asm/irq.h>
325 +#include <linux/config.h>
326 +#define __NO_VERSION__
327 +#include <linux/module.h>
329 +#define MOD_INC_USE_COUNT
330 +#define MOD_DEC_USE_COUNT
332 +#include <linux/pcsp.h>
333 +#include "sound_config.h"
335 +/* to avoid gcc warning we define dsp_ulaw unused since it is really not used */
336 +#define dsp_ulaw __attribute__((unused)) _unused_junk
339 +#include "pcsp_tables.h"
341 +#ifdef CONFIG_APM_CPU_IDLE
342 +#include <linux/pm.h>
343 +static void (*saved_pm_idle)(void);
347 + * This function will be used to generate a time delay on very fast
348 + * processors; this delay is only needed for the STO1 because it has
349 + * only one latch, so we must wait some time after we write the value
350 + * for the left channel before we can write the right one
352 + * as long as I haven't such, it's empty :-)
355 +//#define PCSP_DEBUG
358 +#define assert(expr)
360 +#define assert(expr) \
362 + printk( "Assertion failed! %s, %s, %s, line=%d\n", \
363 + #expr,__FILE__,__FUNCTION__,__LINE__); \
367 +#define PCSP_NUM_BUFFERS (pcsp.frag_cnt ? pcsp.frag_cnt : PCSP_INIT_BUFFERS)
368 +#define PCSP_BUF_SIZE (pcsp.frag_size ? pcsp.frag_size : pcsp.ablk_size)
369 +#define PCSP_NEXT_BUF(i) ((i + 1) % PCSP_NUM_BUFFERS)
370 +#define PCSP_ULAW_XLAT(i) (pcsp.audio_fmt == AFMT_MU_LAW ? ulaw_dsp[i] : i)
372 +static volatile int pcsp_full = 0;
373 +static volatile int buf_now_written = -1;
374 +static char pcsp_active = 0;
375 +extern int pcsp_sound_dsp;
377 +#define PCSP_CPU_DELAY
379 +/* PCSP internal maximum volume, it's hardcoded */
380 +#define PCSP_MAX_VOLUME 256
383 +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
385 +/* the parallel-ports */
386 +static int pcsp_ports[] = { 0x3bc, 0x378, 0x278 };
387 +static int pcsp_port_enable[] = { 0, 0, 0 };
390 +#define LP_B(port) pcsp_ports[port] /* IO address */
391 +#define LP_S(port) inb_p(LP_B(port) + 1) /* status */
393 +/* general pcsp data */
395 +extern struct pcsp_status pcsp;
399 +static unsigned char vl_tab[256];
400 +static unsigned char left_vol[256], right_vol[256];
403 +extern int pcsp_mixer_ioctl(int dev, unsigned int cmd, caddr_t ptr);
406 +static wait_queue_head_t pcsp_sleep;
408 +extern int pcsp_set_irq(int (*func)(void));
409 +extern int pcsp_release_irq(void);
410 +static void pcsp_stop_timer(void);
411 +void pcsp_close(int dev);
413 +/* test if a parallel port is free */
415 +inline static int pcsp_free_port(int port)
417 + return (pcsp_port_enable[port] || !check_region(LP_B(port), 3));
420 +static void pcsp_reserve_port(int port)
422 + pcsp_port_enable[port] = 1;
423 + request_region(LP_B(port), 3, "pcsp");
426 +void pcsp_free_ports(void)
430 + for (port = 0; port < LP_NO; ++port)
431 + if (pcsp_port_enable[port])
432 + release_region(LP_B(port), 3);
434 +/* test if a Stereo-on-One is on lp(port) */
435 +inline static int stereo1_detect(unsigned port)
437 + if (! pcsp_free_port(port))
439 + outb(0x7F, LP_B(port));
440 + if (LP_S(port) & 0x80) {
441 + outb(0x80, LP_B(port));
442 + return (LP_S(port) & 0x80) ? 0 : 1;
447 +/* test if a new Stereo-Circuit is on lp(port) */
448 +inline static int stereo_nc_detect(unsigned port)
450 + if (! pcsp_free_port(port))
452 + outb(0, LP_B(port));
453 + if (LP_S(port) & 0x40) {
454 + outb(0xFF, LP_B(port));
455 + return (LP_S(port) & 0x40) ? 0 : 1;
460 +/* search for Stereo-on-One, return it's port if found */
461 +static int stereo1_init(void)
465 + for (i = 0; i < LP_NO; ++i)
466 + if (stereo1_detect(i)) {
467 + pcsp_reserve_port(i);
468 + pcsp.port = LP_B(i);
469 + pcsp.act_dev = SNDCARD_STO1;
475 +/* search for Stereo-NC, return it's port if found */
476 +static int stereo_nc_init(void)
480 + for (i = 0; i < LP_NO; ++i)
481 + if (stereo_nc_detect(i)) {
482 + pcsp_reserve_port(i);
483 + pcsp.port = LP_B(i);
484 + pcsp.act_dev = SNDCARD_STNC;
490 +inline static int pcsp_factor(void)
494 + if (pcsp.audio_fmt == AFMT_S16_LE)
496 + if (pcsp.stereo_emu)
502 +static volatile int pcsp_buf_avail(int num)
504 +int i = PCSP_BUF_SIZE - pcsp.in[num]*pcsp_factor();
506 + return ((i > 0) ? i : 0);
509 +static void pcsp_reset_buffers(void)
512 + for(i = 0; i < PCSP_NUM_BUFFERS; i++)
515 + pcsp.xfer = pcsp.index = 0;
516 + pcsp.cur_buf = pcsp.next_buf = 0;
517 + pcsp.buffer = pcsp.buf[pcsp.cur_buf];
520 +static void pcsp_next_buffer(void)
522 + pcsp.xfer -= pcsp.in[pcsp.cur_buf] << 16;
523 + assert(pcsp.xfer >= 0);
526 + pcsp.index = pcsp.xfer >> 16;
527 + pcsp.in[pcsp.cur_buf] = 0;
528 + pcsp.cur_buf = PCSP_NEXT_BUF(pcsp.cur_buf);
529 + pcsp.buffer = pcsp.buf[pcsp.cur_buf];
532 +static int pcsp_find_free_buffer(void)
535 + if (pcsp.in[pcsp.next_buf] == 0)
536 + return pcsp.next_buf;
537 + if (pcsp_buf_avail(pcsp.next_buf) <= 0)
539 + free_buf = PCSP_NEXT_BUF(pcsp.next_buf);
540 + if (free_buf == pcsp.cur_buf)
542 + assert(pcsp.in[free_buf] == 0);
543 + pcsp.in[free_buf] = 0;
547 +static int pcsp_count_free_buffers(void)
550 + next_free_buf = pcsp_find_free_buffer();
551 + if (next_free_buf < 0)
553 + if (next_free_buf >= pcsp.cur_buf)
554 + return PCSP_NUM_BUFFERS - (next_free_buf - pcsp.cur_buf);
555 + return pcsp.cur_buf - next_free_buf;
558 +static int pcsp_count_used_bytes(void)
560 +int i, cnt, free_buf;
561 + free_buf = pcsp_find_free_buffer();
562 + if (free_buf == pcsp.cur_buf)
565 + free_buf = pcsp.cur_buf;
570 + i = PCSP_NEXT_BUF(i);
571 + } while (i != free_buf);
573 +#if 0 /* timidity doesn't like it */
579 + return (cnt * pcsp_factor());
582 +static int pcsp_prep_buffers(int buf_size, int buf_num)
585 +//printk("PCSP: prep_buffers called, size=%i num=%i\n",buf_size, buf_num);
586 + if (buf_size * buf_num > PCSP_TOTAL_SIZE ||
587 + buf_size > pcsp.ablk_size || buf_size < 4
588 + || buf_num > PCSP_MAX_BUFFERS || buf_num < 2)
591 + if (pcsp.timer_on) {
595 + if (pcsp.allocated) {
597 + pcsp.allocated = 0;
599 + if (! (pcsp.data = vmalloc(buf_size * buf_num)))
601 + pcsp.allocated = 1;
603 + for (i = 0; i < buf_num; i++)
604 + pcsp.buf[i] = pcsp.data + buf_size * i;
606 + pcsp_reset_buffers();
611 +/* the timer-int for playing thru PC-Speaker */
612 +static int pcsp_do_timer(void)
614 + if (pcsp.cur_buf == buf_now_written) {
619 + if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
620 + outb(pcsp.e, 0x61);
621 + outb(pcsp.e ^ 1, 0x61);
622 + outb(vl_tab[pcsp.buffer[pcsp.index]], 0x42);
624 + assert(pcsp.si > 0);
625 + pcsp.xfer += pcsp.si;
626 + pcsp.index = pcsp.xfer >> 16;
628 + if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
629 + pcsp_next_buffer();
631 + DMAbuf_outputintr(pcsp_sound_dsp, 1);
633 + if (waitqueue_active(&pcsp_sleep)) {
634 + wake_up_interruptible(&pcsp_sleep);
635 +//printk("PCSP: done block, cur=%i next=%i\n",pcsp.cur_buf,pcsp.next_buf);
639 + if (pcsp.in[pcsp.cur_buf] == 0)
645 + /* workaround for missing locking */
646 + if (waitqueue_active(&pcsp_sleep) && pcsp_full
647 + && (pcsp.in[pcsp.next_buf] == 0)) {
650 + printk("PCSP: Force wake_up!\n");
653 + wake_up_interruptible(&pcsp_sleep);
657 + pcsp_clockticks -= pcsp_timer0_latch;
658 + if (pcsp_clockticks < 0) {
659 + pcsp_clockticks += LATCH;
665 +/* timer-int for playing thru STO1 */
666 +static int pcsp_do_sto1_timer(void)
670 + if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
672 + outb(right_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
673 + outb(1, pcsp.port + 2);
674 + outb(0, pcsp.port + 2);
677 + * I move the following code because
678 + * I need some time delay for the left DAC
680 + * this will hopefully enough or we need some
681 + * really time wasting jumps here
683 + * This time delay will really be a problem for
688 + pcsp_clockticks -= pcsp_timer0_latch;
689 + if (pcsp_clockticks < 0) {
690 + pcsp_clockticks += LATCH;
698 + outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
699 + outb(2, pcsp.port + 2);
700 + outb(0, pcsp.port + 2);
703 + outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
704 + pcsp_clockticks -= pcsp_timer0_latch;
705 + if (pcsp_clockticks < 0) {
706 + pcsp_clockticks += LATCH;
713 + if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
714 + pcsp_next_buffer();
716 + if (waitqueue_active(&pcsp_sleep))
717 + wake_up_interruptible(&pcsp_sleep);
719 + if (pcsp.in[pcsp.cur_buf] == 0)
725 +/* timer-int for playing thru DACs */
726 +static int pcsp_do_dac_timer(void)
728 + if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
729 + if (pcsp.act_dev == SNDCARD_DACS) {
731 + outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
732 + outb(right_vol[pcsp.buffer[pcsp.index++]], pcsp.portS);
735 + outb(left_vol[pcsp.buffer[pcsp.index]], pcsp.port);
736 + outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.portS);
739 + else /* Simple DAC */
740 + outb(left_vol[pcsp.buffer[pcsp.index++]], pcsp.port);
742 + if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
743 + pcsp_next_buffer();
745 + if (waitqueue_active(&pcsp_sleep))
746 + wake_up_interruptible(&pcsp_sleep);
748 + if (pcsp.in[pcsp.cur_buf] == 0)
752 + pcsp_clockticks -= pcsp_timer0_latch;
753 + if (pcsp_clockticks < 0) {
754 + pcsp_clockticks += LATCH;
760 +/* calculate all needed time-consts, return the 'adjusted' samplerate */
761 +static unsigned pcsp_calc_srate(unsigned rate)
763 + pcsp.timerC = (CLOCK_TICK_RATE + rate / 2) / rate;
764 + pcsp.srate = (CLOCK_TICK_RATE + pcsp.timerC / 2) / pcsp.timerC;
766 + /* and now for the PC-Speaker */
767 + pcsp.si = (pcsp.srate << 16) / SRATE;
771 +static void pcsp_start_timer(void)
775 + if (! pcsp.allocated)
778 + if (pcsp.timer_on || !(pcsp.enable_bits & PCM_ENABLE_OUTPUT)) {
782 + if (! pcsp.in[pcsp.cur_buf]) {
783 + pcsp_reset_buffers();
787 + pcsp.buffer = pcsp.buf[pcsp.cur_buf];
789 + if (pcsp.act_dev == SNDCARD_PCSP) {
791 + pcsp.e = inb(0x61) | 0x03;
792 + outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */
793 + outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
794 + outb_p(pcsp.timerCF & 0xFF, 0x40);
795 + outb(pcsp.timerCF >> 8 , 0x40);
796 + if (pcsp_set_irq(pcsp_do_timer) < 0)
797 + panic("PCSP: could not modify timer IRQ!");
798 + pcsp_timer0_latch = pcsp.timerCF;
800 + else { /* it's a DAC */
801 + if (pcsp.act_dev == SNDCARD_STO1)
802 + outb(3,pcsp.port + 2);
804 + /* get the timer */
805 + outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
806 + outb_p(pcsp.timerC & 0xFF, 0x40);
807 + outb(pcsp.timerC >> 8 , 0x40);
808 + if (pcsp.act_dev == SNDCARD_STO1)
809 + result = pcsp_set_irq(pcsp_do_sto1_timer);
811 + result = pcsp_set_irq(pcsp_do_dac_timer);
813 + panic("PCSP: could not modify timer IRQ!");
814 + pcsp_timer0_latch = pcsp.timerC;
816 + pcsp_clockticks = pcsp.last_clocks;
819 +#ifdef CONFIG_APM_CPU_IDLE
820 + saved_pm_idle = pm_idle;
825 +/* reset the timer to 100 Hz and reset old timer-int */
826 +static void pcsp_stop_timer(void)
828 +//printk("PCSP: stop timer\n");
829 + if (pcsp.timer_on) {
830 + /* restore the timer */
831 + outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
832 + outb_p(LATCH & 0xff , 0x40); /* LSB */
833 + outb(LATCH >> 8 , 0x40); /* MSB */
835 + /* clear clock tick counter */
836 + pcsp.last_clocks = pcsp_clockticks;
837 + pcsp_timer0_latch = pcsp_clockticks = LATCH;
839 + if (pcsp_release_irq() < 0)
840 + panic("PCSP: could not reset timer IRQ!");
845 + if (pcsp_active && buf_now_written != -1)
848 + /* reset the buffer */
849 + pcsp_reset_buffers();
853 + if (!pcsp_active) /* NONBLOCK close() */
855 +#ifdef CONFIG_APM_CPU_IDLE
856 + pm_idle = saved_pm_idle;
861 + calculate a translation-table for PC-Speaker
863 +static void pcsp_calc_vol(int volume)
866 + for (i = 0; i < 256; ++i) {
867 + j = (((PCSP_ULAW_XLAT(i) - 128) * volume) / PCSP_MAX_VOLUME) + 128;
868 + vl_tab[i] = sp_tabs[pcsp.gain][j];
872 +/* calculate linear translation table for DACs */
873 +static void pcsp_calc_voltab(int volume, unsigned char *tab)
876 + for (i = 0; i < 256; ++i)
877 + tab[i] = (((PCSP_ULAW_XLAT(i) - 128) * volume) / PCSP_MAX_VOLUME) + 128;
880 +static inline void pcsp_set_voltables(void)
882 + pcsp_calc_voltab(pcsp.left, left_vol);
883 + pcsp_calc_voltab(pcsp.right, right_vol);
884 + pcsp_calc_vol(pcsp.volume);
889 +/* this is called if /dev/pcmixer change Mastervolume */
890 +inline void pcsp_set_volume(unsigned short v, unsigned short g)
892 + pcsp.left = (((unsigned)(v & 0x7F) << 8) + 50) / 100;
893 + pcsp.right = (((unsigned)(v & 0x7F00)) + 50) / 100;
894 + pcsp.volume = (pcsp.right + pcsp.left) >> 1;
895 + pcsp.gain = g & 0xff;
896 + pcsp_set_voltables();
899 +inline unsigned pcsp_get_mode(void)
906 + * set the speed for /dev/pcsp, it's now from 4000 - 99225 Hz,
907 + * but DAC's are bounded by the maximal samplerate
909 +inline unsigned long pcsp_set_speed(unsigned long speed)
918 + if (pcsp.act_dev != SNDCARD_PCSP)
919 + if (speed > pcsp.maxrate)
920 + speed = pcsp.maxrate;
921 + return pcsp_calc_srate(speed);
925 + * set the audio type
927 +int pcsp_set_format(int fmt)
929 + if (fmt != AFMT_QUERY) {
930 + if (! (pcsp.fmt_msk & fmt)) /* Not supported */
931 + fmt = AFMT_U8; /* this is supported */
932 + pcsp.audio_fmt = fmt;
934 + we must recalculate the volume-tables is we change
937 + pcsp_set_voltables();
939 + return pcsp.audio_fmt;
943 + * set the stereo mode if possible
945 +static int pcsp_set_stereo(int flag)
947 + if (pcsp.act_dev == SNDCARD_STO1 ||
948 + pcsp.act_dev == SNDCARD_DACS )
950 + pcsp.stereo_emu = 0;
952 + pcsp.stereo_emu = flag ? 1 : 0;
953 + /* test if the emulation is disabled */
954 + if (! pcsp.enable_emu && pcsp.stereo_emu) {
955 + pcsp.stereo_emu = 0;
960 + pcsp.mode = flag ? 1 : 0;
961 + pcsp_set_voltables();
963 + pcsp.mode = flag ? 1 : 0;
970 +//printk("PCSP: stereo set to %i\n",pcsp.mode);
975 + * wait until the complete buffers are played or a signal has arrised
977 +static void pcsp_sync(void)
979 + while (! signal_pending(current) && pcsp.in[pcsp.cur_buf]) {
980 + if (! pcsp.timer_on)
981 + pcsp_start_timer();
982 + /* Wait until a complete block are ready */
983 + interruptible_sleep_on(&pcsp_sleep);
988 + * the driver functions
990 +void pcsp_close(int dev)
992 + if (pcsp.allocated) {
994 + pcsp.allocated = 0;
1001 +static int pcsp_release(struct inode * inode, struct file * file)
1003 + if (!(file->f_flags & O_NONBLOCK) || pcsp.in[pcsp.cur_buf] == 0) {
1005 + pcsp_stop_timer();
1006 + outb_p(0xb6,0x43); /* binary, mode 2, LSB/MSB, ch 2 */
1009 + else if (!pcsp.timer_on && pcsp.in[pcsp.cur_buf])
1010 + pcsp_start_timer();
1015 +static int pcsp_open(struct inode * inode, struct file * file)
1017 + int ret, minor = MINOR(inode->i_rdev);
1022 + if (pcsp.timer_on)
1023 + pcsp_stop_timer();
1025 + switch (minor & 0xf) {
1026 + case 3: /* DSP device /dev/dsp* */
1028 + pcsp_set_stereo(1);
1029 + if (pcsp_set_format(AFMT_S16_LE) != AFMT_S16_LE)
1031 + pcsp_set_format(AFMT_U8);
1032 + pcsp_set_speed(44100);
1034 + case 4: /* Sun Audio device /dev/audio* */
1035 + pcsp_set_format(AFMT_MU_LAW); /* input is ULAW */
1036 + pcsp_set_stereo(0);
1037 + pcsp_set_speed(PCSP_DEFAULT_RATE);
1041 + printk(KERN_WARNING "PCSP: minor %d (%d) is for unknown device\n",minor,minor& 0xf);
1047 + pcsp.frag_cnt = 0;
1048 + pcsp.enable_bits = PCM_ENABLE_OUTPUT;
1050 + if ((ret=pcsp_prep_buffers(ABLK_SIZE, PCSP_INIT_BUFFERS)) == 0) {
1052 + MOD_INC_USE_COUNT;
1060 + * the new version 2 IOCTL's
1062 +static int pcsp_ioctl(struct inode * inode, struct file * file,
1063 + unsigned int cmd, unsigned long arg)
1066 + int i, *ptr = (int *)arg;
1067 + audio_buf_info info;
1070 + if (((cmd >> 8) & 0xff) == 'M') /* it's a Mixer IOCTL */
1071 + return pcsp_mixer_ioctl(0, cmd, (caddr_t)arg);
1074 + case SNDCTL_DSP_SPEED:
1075 + if (get_user(arg, ptr))
1077 + arg = pcsp_set_speed(arg);
1078 + return put_user(arg, ptr);
1080 + case SOUND_PCM_READ_RATE:
1081 + return put_user(pcsp.srate, ptr);
1083 + case SNDCTL_DSP_CHANNELS: /* same as SOUND_PCM_WRITE_CHANNELS */
1084 + if (get_user(arg, ptr))
1086 + if (arg < 1 || arg > 2)
1088 + return pcsp_set_stereo(arg - 1);
1090 + case SNDCTL_DSP_STEREO:
1091 + if (get_user(arg, ptr))
1093 + return pcsp_set_stereo(arg);
1095 + case SOUND_PCM_READ_CHANNELS:
1096 + return put_user(pcsp.mode + 1, ptr);
1098 + case SNDCTL_DSP_GETBLKSIZE:
1099 + return put_user(PCSP_BUF_SIZE, ptr);
1102 + case SNDCTL_DSP_SYNC: /* syncing, so speed changes work correct */
1104 + pcsp_stop_timer();
1108 + case SNDCTL_DSP_RESET: /* stops output immediately */
1109 + pcsp_stop_timer();
1112 + case SNDCTL_DSP_GETFMTS:
1113 + return put_user(pcsp.fmt_msk, ptr);
1115 + case SNDCTL_DSP_SETFMT: /* same as SNDCTL_DSP_SAMPLESIZE */
1116 + if (get_user(arg, ptr))
1118 + return put_user(pcsp_set_format(arg), ptr);
1120 + case SNDCTL_DSP_GETOSPACE:
1121 + info.fragments = pcsp_count_free_buffers();
1122 + info.fragstotal = PCSP_NUM_BUFFERS;
1123 + info.fragsize = PCSP_BUF_SIZE;
1124 + info.bytes = info.fragments * info.fragsize +
1125 + (pcsp.in[pcsp.next_buf] ?
1126 + pcsp_buf_avail(pcsp.next_buf) : 0);
1127 + if (copy_to_user((void *)arg, &info, sizeof(info)))
1131 + case SNDCTL_DSP_GETODELAY:
1132 + return put_user(pcsp_count_used_bytes(), ptr);
1134 + case SNDCTL_DSP_GETISPACE:
1137 + case SNDCTL_DSP_NONBLOCK:
1139 + file->f_flags |= O_NONBLOCK;
1143 + case SNDCTL_DSP_GETCAPS:
1144 + return put_user((DSP_CAP_REVISION & 1) |
1145 + DSP_CAP_BATCH/* | DSP_CAP_TRIGGER*/, ptr);
1147 + case SOUND_PCM_READ_BITS:
1148 + if (pcsp.audio_fmt == AFMT_S16_LE)
1149 + return put_user(16, ptr);
1150 + return put_user(8, ptr);
1152 + case SNDCTL_DSP_SUBDIVIDE:
1153 + /* Too late to change ? */
1154 + if (get_user(arg, ptr))
1156 + if (pcsp.frag_size || pcsp.frag_cnt)
1158 + if (arg != 1 && arg != 2 && arg != 4)
1160 + pcsp.frag_size = ABLK_SIZE / arg;
1161 + pcsp.frag_cnt = PCSP_INIT_BUFFERS * arg;
1162 + return pcsp_prep_buffers(pcsp.frag_size, pcsp.frag_cnt);
1164 + case SNDCTL_DSP_POST:
1165 + if (! pcsp.timer_on)
1166 + pcsp_start_timer();
1169 + case SNDCTL_DSP_SETFRAGMENT:
1174 + if (get_user(fact, ptr))
1180 + /* Too late to change ? */
1181 + if (pcsp.frag_size || pcsp.frag_cnt)
1184 + bytes = fact & 0xffff;
1185 + count = (fact >> 16) & 0xffff;
1187 + if (bytes < 4 || bytes > 17) /* <16 || > 128k */
1193 + pcsp.frag_size = bytes ? (1 << bytes) : pcsp.ablk_size;
1194 + pcsp.frag_cnt = count;
1196 + if (pcsp.frag_cnt > PCSP_MAX_BUFFERS)
1197 + pcsp.frag_cnt = PCSP_MAX_BUFFERS;
1198 + if (pcsp.frag_size > pcsp.ablk_size)
1199 + pcsp.frag_size = pcsp.ablk_size;
1200 + if (pcsp.frag_size * pcsp.frag_cnt > PCSP_TOTAL_SIZE)
1201 + pcsp.frag_cnt = PCSP_TOTAL_SIZE / pcsp.frag_size;
1203 + if (pcsp_prep_buffers(pcsp.frag_size, pcsp.frag_cnt)<0)
1206 + return put_user(bytes | (count << 16), ptr);
1209 + case PCSP_SET_DEV:
1210 + if (get_user(arg, ptr))
1213 + case SNDCARD_STO1:
1214 + if (stereo1_init() < 0)
1217 + case SNDCARD_PCSP:
1218 + case SNDCARD_DACM:
1219 + case SNDCARD_DACS:
1220 + pcsp.act_dev = arg; break;
1221 + case SNDCARD_STNC:
1222 + if (stereo_nc_init() < 0)
1228 + /* Perhaps we need to adjust the samplerate */
1229 + pcsp.srate = pcsp_set_speed(pcsp.srate);
1232 + case PCSP_GET_DEV:
1233 + return put_user(pcsp.act_dev, ptr);
1235 + case PCSP_SET_PORTS:
1236 + if (get_user(arg, ptr))
1238 + if ((arg & 0xFF) < LP_NO && (arg >> 8) < LP_NO) {
1239 + if (pcsp.act_dev == SNDCARD_STO1) {
1240 + if (stereo1_detect(arg & 0xFF)) {
1241 + pcsp.port = LP_B(arg & 0xFF);
1245 + else if (pcsp.act_dev == SNDCARD_STNC) {
1246 + if (stereo_nc_detect(arg & 0xFF)) {
1247 + pcsp.port = LP_B(arg & 0xFF);
1252 + pcsp.port = LP_B(arg & 0xFF);
1253 + pcsp.portS = LP_B((arg >> 8) & 0xFF);
1259 + case PCSP_GET_PORTS:
1261 + for (i = 0; i < LP_NO; ++i)
1262 + if (LP_B(i) == pcsp.port)
1264 + for (i = 0; i < LP_NO; ++i)
1265 + if (LP_B(i) == pcsp.portS)
1267 + return put_user(ret, ptr);
1269 + case PCSP_GET_MEASURE:
1270 + return put_user(pcsp.maxrate, ptr);
1272 + case PCSP_SET_EMU_MODE:
1274 + if (get_user(arg, ptr))
1276 + if (arg == PCSP_EMULATION_ON) {
1277 + pcsp.enable_emu = 1;
1278 + pcsp.fmt_msk |= AFMT_S16_LE;
1280 + else if (arg == PCSP_EMULATION_OFF) {
1281 + pcsp.enable_emu = 0;
1282 + pcsp.fmt_msk &= ~AFMT_S16_LE;
1284 + return put_user(pcsp.enable_emu, ptr);
1286 + case PCSP_GET_VERSION:
1287 + return put_user(PCSP_SOUND_VERSION, ptr);
1294 +static ssize_t pcsp_read(struct file * file, char * buffer,
1295 + size_t count, loff_t *ppos)
1300 +static ssize_t pcsp_write(struct file * file, const char * buffer,
1301 + size_t count, loff_t *ppos)
1303 +int copy_size, total_bytes_written = 0;
1308 + if (! pcsp.allocated)
1311 + assert(pcsp.timer_on || pcsp.cur_buf == pcsp.next_buf);
1314 + assert(count >= total_bytes_written);
1315 + copy_size = pcsp_buf_avail(pcsp.next_buf); /* can't put it under MIN() - racey! */
1316 + copy_size = MIN(count - total_bytes_written, copy_size);
1318 + if (copy_size > 0) {
1319 + buf_now_written = pcsp.next_buf; /* this is our lock:) */
1322 + p = pcsp.buf[buf_now_written] + pcsp.in[buf_now_written];
1323 + if (pcsp.audio_fmt == AFMT_S16_LE)
1324 + if (pcsp.stereo_emu) {
1325 + for (j = 0; j < copy_size >> 2; ++j) {
1326 + get_user(l, (unsigned char *)&buffer[4*j + 1]);
1327 + get_user(r, (unsigned char *)&buffer[4*j + 3]);
1330 + *p++ = (l + r) >> 1;
1334 + for (j = 0; j < copy_size >> 1; ++j) {
1335 + get_user(*p, &buffer[2*j + 1]);
1339 + else if (pcsp.stereo_emu) {
1340 + for (j = 0; j < copy_size >> 1; ++j) {
1341 + get_user(l, (unsigned char *)&buffer[2*j + 0]);
1342 + get_user(r, (unsigned char *)&buffer[2*j + 1]);
1343 + *p++ = (l + r) >> 1;
1348 + copy_from_user(p, buffer, copy_size);
1349 + pcsp.in[buf_now_written] += copy_size / pcsp_factor();
1350 + if (pcsp_buf_avail(buf_now_written) <= 0) {
1351 + pcsp.next_buf = PCSP_NEXT_BUF(buf_now_written);
1352 + assert(pcsp.next_buf == pcsp.cur_buf ||
1353 + pcsp.in[pcsp.next_buf] == 0);
1355 + buffer += copy_size;
1356 + total_bytes_written += copy_size;
1358 + else if (count > total_bytes_written) {
1359 + buf_now_written = -1;
1360 + assert(! pcsp_full);
1362 + if (! pcsp.timer_on)
1363 + pcsp_start_timer();
1366 + if (file->f_flags & O_NONBLOCK) {
1367 + return total_bytes_written ?
1368 + total_bytes_written : -EAGAIN;
1371 + interruptible_sleep_on(&pcsp_sleep);
1372 + if (signal_pending(current)) {
1373 + return total_bytes_written ?
1374 + total_bytes_written : -EINTR;
1378 + } while (count > total_bytes_written);
1380 + assert(count == total_bytes_written);
1382 + buf_now_written = -1;
1383 +//printk("ret from write(), avail=%i\n",pcsp_buf_avail(pcsp.cur_buf));
1384 + if (! pcsp.timer_on && pcsp_buf_avail(pcsp.cur_buf) <= 0)
1385 + pcsp_start_timer();
1387 + return total_bytes_written;
1390 +static unsigned int pcsp_poll(struct file *file, struct poll_table_struct *wait)
1392 +unsigned int mask = 0;
1393 + poll_wait(file, &pcsp_sleep, wait);
1394 + if ((file->f_mode & FMODE_WRITE) && (pcsp_find_free_buffer() != -1))
1395 + mask |= POLLOUT | POLLWRNORM;
1396 + if (file->f_mode & FMODE_READ)
1401 +int pcsp_open1(int dev, int mode)
1404 +//printk("PCSP: open1 called\n");
1405 + if (!(mode & OPEN_WRITE))
1412 + pcsp.frag_cnt = 0;
1413 + pcsp.enable_bits = PCM_ENABLE_OUTPUT;
1415 + if ((ret=pcsp_prep_buffers(ABLK_SIZE, PCSP_INIT_BUFFERS)) == 0) {
1417 + MOD_INC_USE_COUNT;
1422 +void pcsp_halt(int dev)
1424 + pcsp_stop_timer();
1427 +int pcsp_speed(int dev, int speed)
1429 +//printk("PCSP: speed set to %i\n",speed);
1430 + return pcsp_set_speed(speed);
1433 +short pcsp_set_channels(int dev, short channels)
1436 + return pcsp.mode + 1;
1437 + return pcsp_set_stereo(channels - 1) + 1;
1440 +void pcsp_output_block(int dev, unsigned long physbuf, int count, int intrflag)
1442 + struct audio_operations *adev = audio_devs[dev];
1443 + struct dma_buffparms *dmap = adev->dmap_out;
1445 + (char *)(physbuf - (unsigned long)dmap->raw_buf_phys
1446 + + (unsigned long)dmap->raw_buf);
1447 +//printk("PCSP: output_block called, cur=%i next=%i free=%i\n",
1448 +//pcsp.cur_buf,pcsp.next_buf,pcsp_find_free_buffer());
1449 + pcsp_write(NULL, dma_start, count, NULL);
1452 +int pcsp_ioctl1(int dev, unsigned int cmd, caddr_t arg)
1454 +//printk("PCSP: ioctl called, cmd=%i\n",cmd);
1455 + return pcsp_ioctl(NULL, NULL, cmd, (unsigned long)arg);
1458 +int pcsp_prepare_output(int dev, int size, int count)
1460 +//printk("PCSP: prepare_for_output called, size=%i num=%i rsize=%i rnum=%i\n",
1462 +//audio_devs[dev]->dmap_out->fragment_size, audio_devs[dev]->dmap_out->nbufs);
1463 + pcsp.frag_size = size;
1464 + pcsp.frag_cnt = count;
1465 + audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
1466 + return pcsp_prep_buffers(size, count);
1469 +unsigned int pcsp_set_bits(int dev, unsigned int bits)
1471 +//printk("PCSP: set_bits %i called\n", bits);
1472 +return pcsp_set_format(bits);
1475 +void pcsp_set_triggers(int dev, int bits)
1477 +//printk("PCSP: trigger=%i\n",bits);
1478 + pcsp.enable_bits = bits;
1479 + if (!pcsp.timer_on && (bits & PCM_ENABLE_OUTPUT) &&
1480 + pcsp.in[pcsp.cur_buf])
1481 + pcsp_start_timer();
1484 +struct file_operations pcsp_dsp_fops = {
1485 + owner: THIS_MODULE,
1487 + write: pcsp_write,
1489 + ioctl: pcsp_ioctl,
1491 + release: pcsp_release,
1494 +struct audio_driver pcsp_driver = {
1495 + owner: THIS_MODULE,
1497 + close: pcsp_close,
1498 + output_block: pcsp_output_block,
1499 + ioctl: pcsp_ioctl1,
1500 + prepare_for_output: pcsp_prepare_output,
1501 + halt_io: pcsp_halt,
1502 + trigger: pcsp_set_triggers,
1503 + set_speed: pcsp_speed,
1504 + set_bits: pcsp_set_bits,
1505 + set_channels: pcsp_set_channels,
1508 +int __init pcsp_device_init(void)
1511 + if (! pcsp_enabled)
1515 + init_waitqueue_head(&pcsp_sleep);
1517 + /* do we need a first-time initialisation? */
1518 + if (!pcsp.first_boot)
1521 + pcsp.first_boot = 0;
1522 + pcsp.allocated = 0;
1524 + pcsp_clockticks = pcsp_timer0_latch = pcsp.last_clocks = LATCH;
1527 + pcsp.timer_on = 0;
1529 + pcsp.audio_fmt = AFMT_U8;
1530 + pcsp.fmt_msk = AFMT_QUERY | AFMT_U8 | AFMT_MU_LAW;
1532 + pcsp.fmt_msk |= AFMT_S16_LE;
1534 + pcsp_reset_buffers();
1535 + pcsp.act_dev = SNDCARD_PCSP;
1536 + pcsp.port = pcsp.portS = 0;
1537 + pcsp.left = (PCSP_LEFT_VOL * 256 + 50) / 100;
1538 + pcsp.right = (PCSP_RIGHT_VOL * 256 + 50) / 100;
1539 + pcsp.volume = (pcsp.left + pcsp.right) >> 1;
1540 + pcsp.gain = PCSP_GAIN * PCSP_MAX_GAIN / 100;
1541 + pcsp.ablk_size = ABLK_SIZE;
1542 + pcsp.frag_size = 0;
1543 + pcsp.frag_cnt = 0;
1544 + pcsp_set_speed(PCSP_DEFAULT_RATE);
1545 + pcsp_calc_vol(pcsp.volume);
1546 + pcsp_calc_voltab(PCSP_LEFT_VOL, left_vol);
1547 + pcsp_calc_voltab(PCSP_RIGHT_VOL, right_vol);
1549 + pcsp.stereo_emu = 0;
1550 + pcsp.enable_emu = 1;
1553 + printk(" PC-Speaker");
1555 + i = stereo1_init();
1558 + printk(", Stereo-on-One at lpt%d", i);
1560 + pcsp.ablk_size = 2 * ABLK_SIZE;
1562 + i = stereo_nc_init();
1565 + printk(", New Stereo Circuit at lpt%d", i);
1567 + pcsp.ablk_size = 2 * ABLK_SIZE;
1571 diff -urN linux-2.4.19-clean/drivers/sound/pcsp.c linux-2.4.19/drivers/sound/pcsp.c
1572 --- linux-2.4.19-clean/drivers/sound/pcsp.c Thu Jan 1 03:00:00 1970
1573 +++ linux-2.4.19/drivers/sound/pcsp.c Tue Aug 13 00:19:22 2002
1576 + * linux/drivers/sound/pcsp.c
1578 + * /dev/pcsp implementation
1580 + * Copyright (C) 1993-1997 Michael Beck
1583 +#include <linux/config.h>
1585 +#include <linux/errno.h>
1586 +#include <linux/init.h>
1589 +#include <linux/module.h>
1591 +MODULE_AUTHOR("Michael Beck <beck@DResearch.de>");
1592 +MODULE_DESCRIPTION("PC-Speaker Driver for Linux 2.4.x Version 1.4");
1593 +MODULE_SUPPORTED_DEVICE("pcsp");
1596 +#include <linux/pcsp.h>
1597 +#include "sound_config.h"
1599 +extern struct file_operations pcsp_dsp_fops;
1600 +extern struct audio_driver pcsp_driver;
1601 +extern struct mixer_operations pcsp_mixer_ops;
1602 +extern long pcsp_driver_init(long);
1603 +extern int pcsp_set_format(int);
1604 +extern void pcsp_free_ports(void);
1607 +int pcsp_sound_dsp, pcsp_sound_mixer;
1609 +int pcsp_register_driver(void)
1611 + if ((pcsp_sound_dsp = sound_install_audiodrv(
1612 + AUDIO_DRIVER_VERSION,
1615 + sizeof(pcsp_driver),
1617 + AFMT_U8 | AFMT_MU_LAW
1621 + ,NULL, -1, -1)) < 0) {
1622 + printk(KERN_WARNING "Unable to install PC speaker driver\n");
1626 + unregister_sound_dsp((pcsp_sound_dsp<<4)+3);
1627 + if (register_sound_dsp(&pcsp_dsp_fops, pcsp_sound_dsp) < 0) {
1628 + printk(KERN_ERR "Oops, unable to register PC speaker DSP device!\n");
1632 +// printk("PCSP on device %d\n",pcsp_sound_dsp);
1634 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
1635 + if ((pcsp_sound_mixer = sound_install_mixer (
1636 + MIXER_DRIVER_VERSION,
1639 + sizeof(pcsp_mixer_ops),
1641 + printk(KERN_WARNING "Unable to register PC speaker mixer device\n");
1642 + sound_unload_audiodev(pcsp_sound_dsp);
1645 +// printk("PCSP mixer on device %d\n", pcsp_sound_mixer);
1652 +int __init init_module(void)
1654 + if (! pcsp_enabled) {
1655 + printk("pcsp disabled\n");
1659 + if (! pcsp_register_driver())
1662 + pcsp_device_init();
1664 + pcsp_mixer_init();
1669 +void cleanup_module(void)
1672 + printk("pcsnd: busy - remove delayed\n");
1674 + pcsp_free_ports();
1675 + sound_unload_audiodev(pcsp_sound_dsp);
1676 + sound_unload_mixerdev(pcsp_sound_mixer);
1680 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_mixer.c linux-2.4.19/drivers/sound/pcsp_mixer.c
1681 --- linux-2.4.19-clean/drivers/sound/pcsp_mixer.c Thu Jan 1 03:00:00 1970
1682 +++ linux-2.4.19/drivers/sound/pcsp_mixer.c Mon Aug 12 22:29:50 2002
1685 + * linux/drivers/sound/pcsp_mixer.c
1687 + * /dev/pcsp implementation - simple Mixer routines
1689 + * (C) 1993-1997 Michael Beck
1690 + * Craig Metz (cmetz@thor.tjhsst.edu)
1693 +#include <linux/config.h>
1695 +#include <linux/errno.h>
1698 +#define __NO_VERSION__
1699 +#include <linux/module.h>
1700 +#include <linux/version.h>
1702 +#define MOD_INC_USE_COUNT
1703 +#define MOD_DEC_USE_COUNT
1705 +#include <linux/pcsp.h>
1706 +#include "sound_config.h"
1707 +#include "pcsp_tables.h"
1709 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
1711 +#define IOCTL_OUT(arg, ret) (put_user(ret, (int *)arg))
1714 +#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_OGAIN)
1716 +static unsigned short levels[SOUND_MIXER_NRDEVICES] =
1718 + PCSP_LEFT_VOL | (PCSP_RIGHT_VOL << 8), /* Master Volume */
1719 + /* The next devices are not supported, so they are zero */
1724 + 0, /* PC Speaker */
1728 + 0, /* Recording monitor */
1730 + 0, /* Recording level */
1731 + 0, /* Input gain */
1732 + PCSP_GAIN | (PCSP_GAIN << 8) /* Output gain */
1735 +extern void pcsp_set_volume(unsigned short, unsigned);
1736 +extern unsigned pcsp_get_mode(void);
1738 +int pcsp_mixer_ioctl(int dev, unsigned int cmd, caddr_t ptr)
1740 + int val, left, right;
1742 + if (((cmd >> 8) & 0xff) == 'M') {
1743 + if (cmd & IOC_IN) {
1744 + if (get_user(val, (int *)ptr))
1747 + left = val & 0x7f;
1748 + right = (val & 0x7f00) >> 8;
1755 + switch (cmd & 0xff) {
1756 + case SOUND_MIXER_VOLUME: /* Master volume (0-127) */
1757 + levels[SOUND_MIXER_VOLUME] = left | (right << 8);
1760 + case SOUND_MIXER_OGAIN:
1762 + left = (left * PCSP_MAX_GAIN / 100) * 100 / PCSP_MAX_GAIN;
1763 + if ((levels[SOUND_MIXER_OGAIN] & 0xff) < right) {
1764 + levels[SOUND_MIXER_OGAIN] = left | (left << 8);
1766 + levels[SOUND_MIXER_OGAIN] +=
1767 + (100 / PCSP_MAX_GAIN) | ((100 / PCSP_MAX_GAIN) << 8);
1769 + else if ((levels[SOUND_MIXER_OGAIN] & 0xff) > right) {
1770 + levels[SOUND_MIXER_OGAIN] = left | (left << 8);
1778 + pcsp_set_volume(levels[SOUND_MIXER_VOLUME],
1779 + (levels[SOUND_MIXER_OGAIN] & 0xff) * PCSP_MAX_GAIN / 100);
1781 + return IOCTL_OUT(ptr, val);
1784 + switch (cmd & 0xff) {
1786 + case SOUND_MIXER_RECSRC:
1787 + return IOCTL_OUT(ptr, OFF);
1789 + case SOUND_MIXER_STEREODEVS:
1790 + return IOCTL_OUT(ptr, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_OGAIN));
1792 + case SOUND_MIXER_DEVMASK:
1793 + return IOCTL_OUT(ptr, SUPPORTED_MIXER_DEVICES);
1795 + case SOUND_MIXER_RECMASK:
1796 + return IOCTL_OUT(ptr, OFF);
1798 + case SOUND_MIXER_CAPS:
1799 + return IOCTL_OUT(ptr, 0);
1802 + if ((cmd & 0xff) < SOUND_MIXER_NRDEVICES)
1803 + return IOCTL_OUT(ptr, levels[cmd & 0xff]);
1812 +struct mixer_operations pcsp_mixer_ops = {
1813 + owner: THIS_MODULE,
1815 + name: "PCSP Mixer",
1816 + ioctl: pcsp_mixer_ioctl
1819 +int pcsp_mixer_init(void)
1821 + pcsp_set_volume(levels[SOUND_MIXER_VOLUME],
1822 + (levels[SOUND_MIXER_OGAIN] & 0xff) * PCSP_MAX_GAIN / 100);
1827 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_stub.c linux-2.4.19/drivers/sound/pcsp_stub.c
1828 --- linux-2.4.19-clean/drivers/sound/pcsp_stub.c Thu Jan 1 03:00:00 1970
1829 +++ linux-2.4.19/drivers/sound/pcsp_stub.c Fri Aug 16 19:10:55 2002
1832 + * linux/drivers/sound/pcsp_stub.c
1834 + * /dev/pcsp implementation
1836 + * Copyright (C) 1993-1997 Michael Beck
1838 + * if PCSP is compiled as a module, this part must
1839 + * be linked with the kernel
1842 +#include <linux/config.h>
1843 +#include <linux/module.h>
1844 +#include <linux/fs.h>
1845 +#include <linux/init.h>
1846 +#include <linux/errno.h>
1847 +#include <linux/timex.h>
1848 +#include <linux/interrupt.h>
1849 +#include <linux/random.h>
1850 +#include <linux/smp.h>
1851 +#include <linux/irq.h>
1852 +#ifndef CONFIG_PCSP_MODULE
1853 +#include <linux/sound.h>
1856 +#include <asm/io.h>
1857 +#include <asm/system.h>
1858 +#include <linux/pcsp.h>
1859 +#include "sound_config.h"
1862 + * need this macros
1864 +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
1865 +#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
1867 +/* the maximal samplerange for PC-Speaker: 18357 Hz */
1868 +#ifndef CONFIG_PCSP_HIGH_FRQ
1869 +#define MIN_CONST 65
1871 +#define MIN_CONST 33
1874 +#define MAX_SRATE (CLOCK_TICK_RATE / MIN_CONST)
1878 + * need this to be global
1880 +char pcsp_speaker = 0;
1881 +char pcsp_enabled = -1;
1882 +volatile int pcsp_timer0_latch, pcsp_clockticks;
1883 +volatile int pcsp_test_running;
1885 +struct pcsp_status pcsp;
1887 +static void *sleep = NULL;
1888 +static int (*pcsp_IRQ)(void) = NULL;
1889 +static struct irqaction pcsp_action, *pcsp_old_action = NULL;
1892 + * this is the PCSP IRQ handler
1894 +asmlinkage void pcsp_run_IRQ(int irq, void *dev_id, struct pt_regs *regs)
1896 + struct irqaction * action;
1899 + status = pcsp_IRQ();
1901 + /* Return with this interrupt masked if no action */
1902 + action = pcsp_old_action;
1905 + status |= action->flags;
1906 + action->handler(irq, action->dev_id, regs);
1907 + action = action->next;
1909 + if (status & SA_SAMPLE_RANDOM)
1910 + add_interrupt_randomness(irq);
1916 + * Set the function func to be executed as the timer int.
1917 + * if func returns a 0, the old IRQ0-handler(s) is called
1919 +int pcsp_set_irq(int (*func)(void))
1921 + unsigned long flags;
1922 + struct irqaction * action = irq_desc[0].action;
1925 + if (! pcsp_IRQ || ! action)
1928 + /* fill in the action */
1929 + pcsp_action.handler = pcsp_run_IRQ;
1930 + pcsp_action.flags = 0; /* Do NOT allow other IRQ-handlers */
1931 + pcsp_action.mask = 0;
1932 + pcsp_action.name = "pcsp+timer";
1933 + pcsp_action.next = NULL;
1934 + pcsp_action.dev_id = NULL;
1936 + /* ok, change the handler */
1937 + save_flags(flags);
1939 + irq_desc[0].action = &pcsp_action;
1940 + restore_flags(flags);
1941 + pcsp_old_action = action;
1946 + * reset the IRQ0 to the old handling
1948 +int pcsp_release_irq(void)
1950 + unsigned long flags;
1952 + save_flags(flags);
1954 + irq_desc[0].action = pcsp_old_action;
1955 + restore_flags(flags);
1960 +#ifndef CONFIG_PCSP_NO_TEST_SPEED
1962 + this is a stupid beep which occurs if PCSP is disabled;
1963 + it's not needed because we have the message, but who reads it...
1964 + and this is the PC-Speaker driver :-)
1966 +void __init pcsp_beep(int count, int cycles)
1968 + /* enable counter 2 */
1969 + outb_p(inb_p(0x61)|3, 0x61);
1970 + /* set command for counter 2, 2 byte write */
1971 + outb_p(0xB6, 0x43);
1972 + /* select desired HZ */
1973 + outb_p(count & 0xff, 0x42);
1974 + outb((count >> 8) & 0xff, 0x42);
1978 + /* disable counter 2 */
1979 + outb(inb_p(0x61)&0xFC, 0x61);
1983 + the timer-int for testing cpu-speed, mostly the same as
1986 +static int __init pcsp_test_intspeed(void)
1988 + if (pcsp.index < pcsp.in[pcsp.cur_buf]) {
1989 + outb(pcsp.e, 0x61);
1990 + outb(pcsp.e ^ 1, 0x61);
1991 + outb(pcsp.buffer[pcsp.index], 0x42);
1993 + pcsp.xfer += pcsp.si;
1994 + pcsp.index = pcsp.xfer >> 16;
1996 + if (pcsp.index >= pcsp.in[pcsp.cur_buf]) {
1997 + pcsp.xfer = pcsp.index = 0;
1998 + pcsp.in[pcsp.cur_buf] = 0;
1999 + pcsp.cur_buf ^= 1;
2000 + pcsp.buffer = pcsp.buf[pcsp.cur_buf];
2001 + if (sleep) /* NEVER */
2003 + if (pcsp.in[pcsp.cur_buf] == 0xFFFF)
2004 + pcsp.cur_buf ^= 1;
2007 + ++pcsp_test_running;
2012 + this routine measures the time needed for one timer-int if
2013 + we play thru PC-Speaker. This is kind of ugly but does the
2016 +static int __init pcsp_measurement(unsigned char *buf, int addon)
2019 + unsigned long flags;
2021 + pcsp.timerCF = LATCH;
2023 + pcsp.buffer = buf;
2026 + pcsp.si = 1 << 16;
2027 + pcsp.in[0] = 5 + addon;
2030 + pcsp.e = inb(0x61) & 0xFC;
2032 + pcsp_test_running = 0;
2034 + if (pcsp_set_irq(pcsp_test_intspeed) < 0)
2035 + panic("PCSP could not modify timer IRQ!");
2038 + Currently (0.99.15d) Linux call chr_dev_init with ints
2039 + disabled; so we need a sti() to enable them.
2040 + However, because this can be changed in the future we use
2041 + save_flags() and restore_flags()
2043 + save_flags(flags);
2047 + Perhaps we need some sort of timeout here, but if IRQ0
2048 + isn't working the system hangs later ...
2050 + while (pcsp_test_running < 5);
2051 + restore_flags(flags);
2053 + if (pcsp_release_irq() < 0)
2054 + panic("PCSP could not reset timer IRQ!");
2056 + outb_p(0x00, 0x43); /* latch the count ASAP */
2057 + count = inb_p(0x40); /* read the latched count */
2058 + count |= inb(0x40) << 8;
2059 + return (LATCH - count);
2062 +static int __init pcsp_test_speed(void)
2064 + int worst, worst1, best, best1;
2065 + unsigned char test_buffer[256];
2067 + worst = pcsp_measurement(test_buffer, 0);
2068 + worst1 = pcsp_measurement(test_buffer, 0);
2069 + best = pcsp_measurement(test_buffer, 5);
2070 + best1 = pcsp_measurement(test_buffer, 5);
2072 + worst = MAX(worst, worst1);
2073 + best = MIN(best, best1);
2076 + printk(" PCSP-Timerint needs %d Ticks in worst case\n", worst);
2077 + printk(" PCSP-Timerint needs %d Ticks in best case\n", best);
2079 + /* We allow a CPU-usage of 90 % for the best-case ! */
2080 + pcsp.timerCF = best * 10 / 9;
2081 + pcsp.maxrate = CLOCK_TICK_RATE / pcsp.timerCF;
2082 + printk(" maximal samplerate %d Hz", pcsp.maxrate);
2084 + if (pcsp.maxrate > PCSP_CRITICAL_FREQ) {
2085 + if (MIN_CONST > pcsp.timerCF) {
2086 + pcsp.timerCF = MIN_CONST;
2087 + printk(", %d Hz", MAX_SRATE);
2089 + printk(" used\n");
2093 + printk("\n This is too SLOW! PCSP-driver DISABLED\n");
2095 + /* very ugly beep, but you hopefully never hear it */
2096 + pcsp_beep(12000,800000);
2097 + pcsp_beep(10000,800000);
2103 +void __init pcsp_setup(char *s, int *p)
2105 + if (!strcmp(s, "off")) {
2109 + if (p[0] > 0 && p[1] > 0)
2110 + pcsp.maxrate = p[1];
2115 + * initialise the driver by testing the CPU speed and setting
2116 + * the time constants
2118 +void __init pcsp_driver_init(void)
2121 + if (pcsp_enabled < 0) {
2122 +#ifndef CONFIG_PCSP_NO_TEST_SPEED
2123 + pcsp_enabled = pcsp_test_speed();
2125 + pcsp.maxrate = 44100; /* only a BIG freq */
2126 + pcsp.timerCF = (CLOCK_TICK_RATE + CONFIG_PCSP_SRATE / 2) /
2127 + CONFIG_PCSP_SRATE;
2132 + tmp = MIN(pcsp.maxrate, MAX_SRATE);
2133 + pcsp.timerCF = (CLOCK_TICK_RATE + tmp / 2) / tmp;
2138 + * define the PCSP exports:
2139 + * when PCSP is compiled in, only the timer latch must be exported,
2140 + * else we need some help for the PCSP module from this stub
2142 +EXPORT_SYMBOL(pcsp_timer0_latch);
2143 +EXPORT_SYMBOL(pcsp_clockticks);
2145 +#ifdef CONFIG_PCSP_MODULE
2146 +EXPORT_SYMBOL(pcsp_enabled);
2147 +EXPORT_SYMBOL(pcsp_speaker);
2148 +EXPORT_SYMBOL(pcsp);
2149 +EXPORT_SYMBOL(pcsp_set_irq);
2150 +EXPORT_SYMBOL(pcsp_release_irq);
2154 + * the pcsp_init() function is called in chrdev_init at kernel startup
2156 +#ifndef CONFIG_PCSP_MODULE
2157 +int __init pcsp_init(void)
2159 + extern int pcsp_sound_dsp;
2160 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
2161 + extern int pcsp_sound_mixer;
2165 + /* if disabled in commandline */
2166 + if (! pcsp_enabled) {
2167 + printk("PCSP-device disabled\n");
2171 + /* first time pcsp is loaded */
2172 + pcsp.first_boot = 1;
2174 + if (! pcsp_register_driver())
2177 + major = (PCSP_SOUND_VERSION >> 8);
2178 + minor = (PCSP_SOUND_VERSION & 0xFF);
2179 + if (! (minor & 0xF))
2181 + printk("PCSP %d.%x measurement:", major, minor);
2182 + pcsp_driver_init();
2183 + if (pcsp_enabled) {
2184 + printk("PCSP %d.%x:", major, minor);
2185 + pcsp_device_init();
2186 + printk(" DSP installed on device %d",pcsp_sound_dsp);
2187 +#if defined(PCSP_16BIT) || defined(PCSP_MIXER)
2188 + pcsp_mixer_init();
2189 + printk(", Mixer installed on device %d", pcsp_sound_mixer);
2199 + * this pcsp_init() function is called when the driver itself is
2200 + * compiled as a module once at kernel-startup
2202 +int __init pcsp_init(void)
2206 + /* first time pcsp is loaded */
2207 + pcsp.first_boot = 1;
2209 + major = (PCSP_SOUND_VERSION >> 8);
2210 + minor = (PCSP_SOUND_VERSION & 0xFF);
2211 + if (! (minor & 0xF))
2213 + printk("PCSP %d.%x measurement:", major, minor);
2214 + pcsp_driver_init();
2219 +module_init(pcsp_init);
2220 diff -urN linux-2.4.19-clean/drivers/sound/pcsp_tables.h linux-2.4.19/drivers/sound/pcsp_tables.h
2221 --- linux-2.4.19-clean/drivers/sound/pcsp_tables.h Thu Jan 1 03:00:00 1970
2222 +++ linux-2.4.19/drivers/sound/pcsp_tables.h Fri Aug 16 18:32:01 2002
2225 + * linux/drivers/sound/pcsp_tables.h
2227 + * /dev/pcsp implementation
2229 + * Copyright (C) 2002 Stas Sergeev
2232 +static unsigned char sp_tabs[][256] = {
2233 +#ifndef CONFIG_PCSP_HIGH_FRQ
2235 +64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 60,
2236 +60, 60, 60, 59, 59, 59, 59, 58, 58, 58, 58, 57, 57, 57, 57, 56,
2237 +56, 56, 56, 55, 55, 55, 55, 54, 54, 54, 54, 53, 53, 53, 53, 52,
2238 +52, 52, 52, 51, 51, 51, 51, 50, 50, 50, 50, 49, 49, 49, 49, 48,
2239 +48, 48, 48, 47, 47, 47, 47, 46, 46, 46, 46, 45, 45, 45, 45, 44,
2240 +44, 44, 44, 43, 43, 43, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41,
2241 +40, 40, 40, 40, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37,
2242 +36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33,
2243 +32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29,
2244 +28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25,
2245 +24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21,
2246 +21, 20, 20, 20, 20, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
2247 +17, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13,
2248 +13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9,
2249 + 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5,
2250 + 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1
2253 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63,
2254 +63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 62,
2255 +62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 59, 59, 59, 59,
2256 +59, 58, 58, 58, 58, 58, 57, 57, 57, 57, 56, 56, 56, 56, 55, 55,
2257 +55, 54, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51, 51, 50,
2258 +50, 50, 49, 49, 49, 48, 48, 48, 47, 47, 47, 46, 46, 45, 45, 45,
2259 +44, 44, 44, 43, 43, 43, 42, 42, 41, 41, 41, 40, 40, 40, 39, 39,
2260 +38, 38, 38, 37, 37, 37, 36, 36, 35, 35, 35, 34, 34, 33, 33, 33,
2261 +32, 32, 32, 31, 31, 30, 30, 30, 29, 29, 28, 28, 28, 27, 27, 27,
2262 +26, 26, 25, 25, 25, 24, 24, 24, 23, 23, 22, 22, 22, 21, 21, 21,
2263 +20, 20, 20, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15,
2264 +15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10,
2265 +10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6,
2266 + 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3,
2267 + 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2268 + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2271 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2272 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2273 +64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 63,
2274 +63, 63, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 61, 61, 61, 61,
2275 +61, 60, 60, 60, 60, 60, 59, 59, 59, 59, 58, 58, 58, 57, 57, 57,
2276 +57, 56, 56, 56, 55, 55, 54, 54, 54, 53, 53, 52, 52, 52, 51, 51,
2277 +50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 43, 43, 42,
2278 +42, 41, 41, 40, 39, 39, 38, 38, 37, 36, 36, 35, 35, 34, 33, 33,
2279 +32, 32, 31, 30, 30, 29, 29, 28, 27, 27, 26, 26, 25, 24, 24, 23,
2280 +23, 22, 22, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15,
2281 +14, 14, 13, 13, 13, 12, 12, 11, 11, 11, 10, 10, 9, 9, 9, 8,
2282 + 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4,
2283 + 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2,
2284 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
2285 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2286 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2289 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2290 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2291 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2292 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2293 +64, 64, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62,
2294 +62, 62, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 58, 58, 58, 57,
2295 +57, 56, 56, 55, 55, 54, 54, 53, 52, 52, 51, 50, 50, 49, 48, 47,
2296 +47, 46, 45, 44, 43, 42, 41, 40, 40, 39, 38, 37, 36, 35, 34, 33,
2297 +32, 31, 30, 29, 28, 27, 26, 25, 25, 24, 23, 22, 21, 20, 19, 18,
2298 +18, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9, 8,
2299 + 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3,
2300 + 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
2301 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2302 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2303 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2304 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2307 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2308 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2309 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2310 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2311 +64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
2312 +64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 63, 63, 62, 62,
2313 +62, 62, 61, 61, 61, 60, 60, 59, 59, 58, 58, 57, 56, 55, 55, 54,
2314 +53, 52, 51, 50, 48, 47, 46, 45, 43, 42, 41, 39, 38, 36, 35, 33,
2315 +32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 15, 14, 13, 12,
2316 +11, 10, 10, 9, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3,
2317 + 3, 3, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
2318 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2319 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2320 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2321 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2322 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2326 +32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30,
2327 +30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28,
2328 +28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26,
2329 +26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24,
2330 +24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22,
2331 +22, 22, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 20,
2332 +20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19,
2333 +18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17,
2334 +16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15,
2335 +14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13,
2336 +13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
2337 +11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9,
2338 + 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
2339 + 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5,
2340 + 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
2341 + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1
2344 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2345 +32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
2346 +31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29,
2347 +29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28,
2348 +27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 25, 25,
2349 +25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23, 23,
2350 +22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
2351 +19, 19, 19, 19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17,
2352 +16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14,
2353 +13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11,
2354 +10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8,
2355 + 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6,
2356 + 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
2357 + 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
2358 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
2359 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2362 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2363 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2364 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31,
2365 +31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30,
2366 +30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 28,
2367 +28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 25,
2368 +25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 21,
2369 +21, 21, 20, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
2370 +16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12,
2371 +12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8,
2372 + 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
2373 + 5, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
2374 + 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2375 + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2376 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2377 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2380 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2381 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2382 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2383 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2384 +32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31,
2385 +31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29,
2386 +28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24,
2387 +23, 23, 23, 22, 22, 21, 21, 20, 20, 20, 19, 19, 18, 18, 17, 17,
2388 +16, 16, 15, 15, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 10,
2389 + 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5,
2390 + 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
2391 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
2392 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2393 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2394 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2395 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2398 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2399 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2400 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2401 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2402 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2403 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31,
2404 +31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 27, 27,
2405 +26, 26, 25, 25, 24, 24, 23, 23, 22, 21, 20, 20, 19, 18, 18, 17,
2406 +16, 15, 15, 14, 13, 13, 12, 11, 10, 10, 9, 9, 8, 8, 7, 7,
2407 + 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2,
2408 + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2409 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2410 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2411 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2412 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2413 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2416 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2417 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2418 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2419 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2420 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2421 +32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
2422 +32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 30, 30,
2423 +30, 29, 29, 28, 28, 27, 26, 25, 25, 24, 23, 22, 20, 19, 18, 17,
2424 +16, 15, 14, 13, 11, 10, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3,
2425 + 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
2426 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2427 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2428 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2429 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2430 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2431 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
2436 +#define PCSP_MAX_GAIN (sizeof(sp_tabs)/sizeof(sp_tabs[0]) - 1)
2439 + * The tables were generated with this small program:
2441 +#define _GNU_SOURCE
2444 +#include <stdlib.h>
2450 +double sine(double i) {
2451 + return ((sin(((i * M_PI) / 255) - M_PI_2) + 1) / 2) * 255;
2454 +int fit(double x) {
2455 + return lrint((x / 255) * (MAX_VAL - MIN_VAL) + MIN_VAL);
2458 +int main(int argc, char *argv[]) {
2459 +int i, j, val, amp;
2462 + amp=atoi(argv[1]);
2465 + for(i=1;i<=256;i++) {
2466 + tmp = (double)(256-i);
2467 + for (j=0;j<amp;j++)
2470 + printf("%2i", val);
2480 diff -urN linux-2.4.19-clean/include/linux/pcsp.h linux-2.4.19/include/linux/pcsp.h
2481 --- linux-2.4.19-clean/include/linux/pcsp.h Thu Jan 1 03:00:00 1970
2482 +++ linux-2.4.19/include/linux/pcsp.h Fri Aug 16 19:16:21 2002
2484 +#ifndef _LINUX_PCSP_H
2485 +#define _LINUX_PCSP_H
2487 + * include/linux/pcsp.h
2489 + * /dev/pcsp implementation (dsp & audio for PC Speaker)
2491 + * Copyright (C) 1993-1997 Michael Beck
2494 +#if defined (CONFIG_PCSP) || defined (CONFIG_PCSP_MODULE)
2496 +#include <linux/ioctl.h>
2498 +/* MUST BE defined from 0.5 */
2499 +#define PCSP_SOUND_VERSION 0x104 /* read 1.04 */
2501 +/* card ID, real soundcards use 0 to ... */
2503 +#define SNDCARD_PCSP 128
2504 +#define SNDCARD_STO1 129
2505 +#define SNDCARD_DACM 130
2506 +#define SNDCARD_DACS 131
2507 +#define SNDCARD_STNC 132
2510 +/* IOCTL for changing the play-device, real sample rate etc. */
2512 +#define PCSP_SET_DEV 0x00014350
2513 +#define PCSP_GET_DEV 0x00024350
2514 +#define PCSP_SET_PORTS 0x00034350
2515 +#define PCSP_GET_PORTS 0x00044350
2517 +#define PCSP_SET_VOL 0x00054350
2518 +#define PCSP_GET_VOL 0x00064350
2520 +#define PCSP_SET_SRATE 0x00074350
2521 +#define PCSP_GET_SRATE 0x00084350
2522 +#define PCSP_GET_MEASURE 0x00094350
2523 +#define PCSP_SET_EMU_MODE 0x000A4350
2524 +#define PCSP_GET_VERSION 0x000F4350
2526 +#define PCSP_EMULATION_OFF 0
2527 +#define PCSP_EMULATION_ON 1
2528 +#define PCSP_EMULATION_QUERY 2
2532 +#if defined(MODULE) || defined(__KERNEL__)
2535 + * If defined, pcsp will use an OSS fops rather than its native fops.
2536 + * It is more safe to use OSS fops, but using native fops will produce
2538 + * WARNING: currently pcsp have some problems working with OSS fops.
2539 + * If you know how to fix it, please send me patches.
2541 +#define USE_OSS_FOPS 0
2542 +#define PCSP_16BIT 1
2543 +#define PCSP_MIXER 1
2544 +#define PCSP_LEFT_VOL 100
2545 +#define PCSP_RIGHT_VOL 100
2546 +#define PCSP_GAIN 100
2548 +/* the timer stuff */
2549 +#define TIMER_IRQ 0
2550 +#define SRATE (CLOCK_TICK_RATE / pcsp.timerCF)
2553 + * the default blocksize for playing thru
2554 + * PC-Speaker, STO1 and STNC use twice as much
2557 +#define ABLK_SIZE 16384
2558 +#define PCSP_MAX_BUFFERS 512
2559 +#define PCSP_TOTAL_SIZE 262144
2560 +#define PCSP_INIT_BUFFERS (PCSP_TOTAL_SIZE / ABLK_SIZE)
2562 +/* the default samplerate for /dev/audio */
2563 +#ifndef PCSP_DEFAULT_RATE
2564 +#define PCSP_DEFAULT_RATE 8000
2568 +#define PCSP_DEFAULT_LEFT 100
2569 +#define PCSP_DEFAULT_RIGHT 100
2573 + * the "critical" frequency: if the machine is too slow for this, PCSP
2576 +#ifndef PCSP_CRITICAL_FREQ
2577 +#define PCSP_CRITICAL_FREQ 12500
2580 +struct pcsp_status {
2581 + volatile int last_clocks;
2582 + int allocated; /* memory allocated successfully */
2583 + unsigned char *data; /* one large buffer */
2584 + unsigned char *buf[PCSP_MAX_BUFFERS]; /* fragments */
2585 + unsigned char *buffer; /* current fragment */
2586 + volatile long long in[PCSP_MAX_BUFFERS]; /* fragments fill */
2587 + volatile long long xfer;
2588 + volatile long long index; /* current playing position */
2589 + unsigned enable_bits; /* for triggers */
2590 + unsigned volume; /* volume for pc-speaker */
2591 + unsigned left; /* left volume */
2592 + unsigned right; /* right volume */
2593 + unsigned gain; /* output gain */
2594 + unsigned srate; /* sample rate */
2595 + unsigned si; /* precalculated step const */
2596 + unsigned timerC; /* hardware timer ticks for srate */
2597 + unsigned timerCF; /* for fixed samplerate */
2598 + unsigned act_dev; /* which device is playing */
2599 + unsigned port; /* on which lp-port */
2600 + unsigned portS; /* for Stereo */
2601 + volatile unsigned cur_buf; /* fragment currently playing */
2602 + volatile unsigned next_buf; /* next fragment to fill */
2603 + unsigned maxrate; /* maximum real sample rate */
2604 + unsigned audio_fmt; /* 16 or 8 bit */
2605 + unsigned fmt_msk; /* supported data formats */
2606 + unsigned ablk_size; /* length of one audio-buffer */
2607 + unsigned frag_size; /* length of one audio-fragment */
2608 + unsigned frag_cnt; /* number of fragments */
2610 + volatile char timer_on;
2611 + char mode; /* Mono / Stereo */
2612 + char stereo_emu; /* set if Stereo is emulated */
2613 + char enable_emu; /* set if the emulation is enabled */
2614 + char first_boot; /* first time loaded? */
2620 +extern char pcsp_speaker, pcsp_enabled;
2621 +extern volatile int pcsp_timer0_latch, pcsp_clockticks;
2622 +extern struct pcsp_status pcsp;
2624 +/* in arch/i386/kernel/irq.c */
2625 +extern int pcsp_set_irq(int (*func)(void));
2626 +extern int pcsp_release_irq(void);
2628 +/* in pcsndrv.c and pcsp_mixer.c */
2629 +extern int pcsp_register_driver(void);
2630 +extern int pcsp_device_init(void);
2631 +extern int pcsp_mixer_init(void);