patch-2.1.106 linux/drivers/sound/dmasound.c
Next file: linux/drivers/sound/gus_wave.c
Previous file: linux/drivers/sound/Makefile
Back to the patch index
Back to the overall index
- Lines: 6329
- Date:
Sat Jun 13 13:23:01 1998
- Orig file:
v2.1.105/linux/drivers/sound/dmasound.c
- Orig date:
Wed Apr 8 19:36:27 1998
diff -u --recursive --new-file v2.1.105/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
@@ -4,6 +4,7 @@
/*
OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k
+Extended to support Power Macintosh for Linux/ppc by Paul Mackerras
(c) 1995 by Michael Schlueter & Michael Marte
@@ -85,7 +86,9 @@
#include <linux/mm.h>
#include <linux/malloc.h>
+#ifdef __mc68000__
#include <asm/setup.h>
+#endif
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
@@ -100,10 +103,23 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/dbdma.h>
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/adb.h>
+#include <asm/pmu.h>
+#endif /* CONFIG_PMAC_PBOOK */
+#include "awacs_defs.h"
+#include <linux/nvram.h>
+#include <linux/vt_kern.h>
+#endif /* CONFIG_PMAC */
#include "dmasound.h"
#include <linux/soundcard.h>
+#define HAS_8BIT_TABLES
#ifdef MODULE
static int chrdev_registered = 0;
@@ -143,6 +159,90 @@
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+/*
+ * Interrupt numbers and addresses, obtained from the device tree.
+ */
+static int awacs_irq, awacs_tx_irq, awacs_rx_irq;
+static volatile struct awacs_regs *awacs;
+static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma;
+static int awacs_rate_index;
+
+/*
+ * Space for the DBDMA command blocks.
+ */
+static void *awacs_tx_cmd_space;
+static volatile struct dbdma_cmd *awacs_tx_cmds;
+
+/*
+ * Cached values of AWACS registers (we can't read them).
+ */
+int awacs_reg[5];
+
+#define HAS_16BIT_TABLES
+#undef HAS_8BIT_TABLES
+
+/*
+ * Stuff for outputting a beep. The values range from -327 to +327
+ * so we can multiply by an amplitude in the range 0..100 to get a
+ * signed short value to put in the output buffer.
+ */
+static short beep_wform[256] = {
+ 0, 40, 79, 117, 153, 187, 218, 245,
+ 269, 288, 304, 316, 323, 327, 327, 324,
+ 318, 310, 299, 288, 275, 262, 249, 236,
+ 224, 213, 204, 196, 190, 186, 183, 182,
+ 182, 183, 186, 189, 192, 196, 200, 203,
+ 206, 208, 209, 209, 209, 207, 204, 201,
+ 197, 193, 188, 183, 179, 174, 170, 166,
+ 163, 161, 160, 159, 159, 160, 161, 162,
+ 164, 166, 168, 169, 171, 171, 171, 170,
+ 169, 167, 163, 159, 155, 150, 144, 139,
+ 133, 128, 122, 117, 113, 110, 107, 105,
+ 103, 103, 103, 103, 104, 104, 105, 105,
+ 105, 103, 101, 97, 92, 86, 78, 68,
+ 58, 45, 32, 18, 3, -11, -26, -41,
+ -55, -68, -79, -88, -95, -100, -102, -102,
+ -99, -93, -85, -75, -62, -48, -33, -16,
+ 0, 16, 33, 48, 62, 75, 85, 93,
+ 99, 102, 102, 100, 95, 88, 79, 68,
+ 55, 41, 26, 11, -3, -18, -32, -45,
+ -58, -68, -78, -86, -92, -97, -101, -103,
+ -105, -105, -105, -104, -104, -103, -103, -103,
+ -103, -105, -107, -110, -113, -117, -122, -128,
+ -133, -139, -144, -150, -155, -159, -163, -167,
+ -169, -170, -171, -171, -171, -169, -168, -166,
+ -164, -162, -161, -160, -159, -159, -160, -161,
+ -163, -166, -170, -174, -179, -183, -188, -193,
+ -197, -201, -204, -207, -209, -209, -209, -208,
+ -206, -203, -200, -196, -192, -189, -186, -183,
+ -182, -182, -183, -186, -190, -196, -204, -213,
+ -224, -236, -249, -262, -275, -288, -299, -310,
+ -318, -324, -327, -327, -323, -316, -304, -288,
+ -269, -245, -218, -187, -153, -117, -79, -40,
+};
+
+#define BEEP_SPEED 2 /* 22050 Hz sample rate */
+#define BEEP_BUFLEN 512
+#define BEEP_VOLUME 15 /* 0 - 100 */
+
+static int beep_volume = BEEP_VOLUME;
+static int beep_playing = 0;
+static short *beep_buf;
+static volatile struct dbdma_cmd *beep_dbdma_cmd;
+static void (*orig_mksound)(unsigned int, unsigned int);
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Stuff for restoring after a sleep.
+ */
+static int awacs_sleep_notify(struct notifier_block *, unsigned long, void *);
+struct notifier_block awacs_sleep_notifier = {
+ awacs_sleep_notify
+};
+#endif /* CONFIG_PMAC_PBOOK */
+
+#endif /* CONFIG_PMAC */
/*** Some declarations *******************************************************/
@@ -150,6 +250,7 @@
#define DMASND_TT 1
#define DMASND_FALCON 2
#define DMASND_AMIGA 3
+#define DMASND_AWACS 4
#define MAX_CATCH_RADIUS 10
#define MIN_BUFFERS 4
@@ -165,164 +266,164 @@
#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
#define IOCTL_IN(arg, ret) \
- do { int error = get_user(ret, (int *)(arg)); \
- if (error) return error; \
- } while (0)
+ do { int error = get_user(ret, (int *)(arg)); \
+ if (error) return error; \
+ } while (0)
#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret)
/*** Some low level helpers **************************************************/
-
+#ifdef HAS_8BIT_TABLES
/* 8 bit mu-law */
static char ulaw2dma8[] = {
- -126, -122, -118, -114, -110, -106, -102, -98,
- -94, -90, -86, -82, -78, -74, -70, -66,
- -63, -61, -59, -57, -55, -53, -51, -49,
- -47, -45, -43, -41, -39, -37, -35, -33,
- -31, -30, -29, -28, -27, -26, -25, -24,
- -23, -22, -21, -20, -19, -18, -17, -16,
- -16, -15, -15, -14, -14, -13, -13, -12,
- -12, -11, -11, -10, -10, -9, -9, -8,
- -8, -8, -7, -7, -7, -7, -6, -6,
- -6, -6, -5, -5, -5, -5, -4, -4,
- -4, -4, -4, -4, -3, -3, -3, -3,
- -3, -3, -3, -3, -2, -2, -2, -2,
- -2, -2, -2, -2, -2, -2, -2, -2,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 0,
- 125, 121, 117, 113, 109, 105, 101, 97,
- 93, 89, 85, 81, 77, 73, 69, 65,
- 62, 60, 58, 56, 54, 52, 50, 48,
- 46, 44, 42, 40, 38, 36, 34, 32,
- 30, 29, 28, 27, 26, 25, 24, 23,
- 22, 21, 20, 19, 18, 17, 16, 15,
- 15, 14, 14, 13, 13, 12, 12, 11,
- 11, 10, 10, 9, 9, 8, 8, 7,
- 7, 7, 6, 6, 6, 6, 5, 5,
- 5, 5, 4, 4, 4, 4, 3, 3,
- 3, 3, 3, 3, 2, 2, 2, 2,
- 2, 2, 2, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ -126, -122, -118, -114, -110, -106, -102, -98,
+ -94, -90, -86, -82, -78, -74, -70, -66,
+ -63, -61, -59, -57, -55, -53, -51, -49,
+ -47, -45, -43, -41, -39, -37, -35, -33,
+ -31, -30, -29, -28, -27, -26, -25, -24,
+ -23, -22, -21, -20, -19, -18, -17, -16,
+ -16, -15, -15, -14, -14, -13, -13, -12,
+ -12, -11, -11, -10, -10, -9, -9, -8,
+ -8, -8, -7, -7, -7, -7, -6, -6,
+ -6, -6, -5, -5, -5, -5, -4, -4,
+ -4, -4, -4, -4, -3, -3, -3, -3,
+ -3, -3, -3, -3, -2, -2, -2, -2,
+ -2, -2, -2, -2, -2, -2, -2, -2,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 0,
+ 125, 121, 117, 113, 109, 105, 101, 97,
+ 93, 89, 85, 81, 77, 73, 69, 65,
+ 62, 60, 58, 56, 54, 52, 50, 48,
+ 46, 44, 42, 40, 38, 36, 34, 32,
+ 30, 29, 28, 27, 26, 25, 24, 23,
+ 22, 21, 20, 19, 18, 17, 16, 15,
+ 15, 14, 14, 13, 13, 12, 12, 11,
+ 11, 10, 10, 9, 9, 8, 8, 7,
+ 7, 7, 6, 6, 6, 6, 5, 5,
+ 5, 5, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 3, 2, 2, 2, 2,
+ 2, 2, 2, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
};
/* 8 bit A-law */
static char alaw2dma8[] = {
- -22, -21, -24, -23, -18, -17, -20, -19,
- -30, -29, -32, -31, -26, -25, -28, -27,
- -11, -11, -12, -12, -9, -9, -10, -10,
- -15, -15, -16, -16, -13, -13, -14, -14,
- -86, -82, -94, -90, -70, -66, -78, -74,
- -118, -114, -126, -122, -102, -98, -110, -106,
- -43, -41, -47, -45, -35, -33, -39, -37,
- -59, -57, -63, -61, -51, -49, -55, -53,
- -2, -2, -2, -2, -2, -2, -2, -2,
- -2, -2, -2, -2, -2, -2, -2, -2,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -6, -6, -6, -6, -5, -5, -5, -5,
- -8, -8, -8, -8, -7, -7, -7, -7,
- -3, -3, -3, -3, -3, -3, -3, -3,
- -4, -4, -4, -4, -4, -4, -4, -4,
- 21, 20, 23, 22, 17, 16, 19, 18,
- 29, 28, 31, 30, 25, 24, 27, 26,
- 10, 10, 11, 11, 8, 8, 9, 9,
- 14, 14, 15, 15, 12, 12, 13, 13,
- 86, 82, 94, 90, 70, 66, 78, 74,
- 118, 114, 126, 122, 102, 98, 110, 106,
- 43, 41, 47, 45, 35, 33, 39, 37,
- 59, 57, 63, 61, 51, 49, 55, 53,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 5, 5, 5, 5, 4, 4, 4, 4,
- 7, 7, 7, 7, 6, 6, 6, 6,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3
+ -22, -21, -24, -23, -18, -17, -20, -19,
+ -30, -29, -32, -31, -26, -25, -28, -27,
+ -11, -11, -12, -12, -9, -9, -10, -10,
+ -15, -15, -16, -16, -13, -13, -14, -14,
+ -86, -82, -94, -90, -70, -66, -78, -74,
+ -118, -114, -126, -122, -102, -98, -110, -106,
+ -43, -41, -47, -45, -35, -33, -39, -37,
+ -59, -57, -63, -61, -51, -49, -55, -53,
+ -2, -2, -2, -2, -2, -2, -2, -2,
+ -2, -2, -2, -2, -2, -2, -2, -2,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -6, -6, -6, -6, -5, -5, -5, -5,
+ -8, -8, -8, -8, -7, -7, -7, -7,
+ -3, -3, -3, -3, -3, -3, -3, -3,
+ -4, -4, -4, -4, -4, -4, -4, -4,
+ 21, 20, 23, 22, 17, 16, 19, 18,
+ 29, 28, 31, 30, 25, 24, 27, 26,
+ 10, 10, 11, 11, 8, 8, 9, 9,
+ 14, 14, 15, 15, 12, 12, 13, 13,
+ 86, 82, 94, 90, 70, 66, 78, 74,
+ 118, 114, 126, 122, 102, 98, 110, 106,
+ 43, 41, 47, 45, 35, 33, 39, 37,
+ 59, 57, 63, 61, 51, 49, 55, 53,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 4, 4, 4, 4,
+ 7, 7, 7, 7, 6, 6, 6, 6,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3
};
-
+#endif /* HAS_8BIT_TABLES */
#ifdef HAS_16BIT_TABLES
/* 16 bit mu-law */
-static char ulaw2dma16[] = {
- -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
- -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
- -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
- -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
- -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
- -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
- -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
- -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
- -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
- -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
- -876, -844, -812, -780, -748, -716, -684, -652,
- -620, -588, -556, -524, -492, -460, -428, -396,
- -372, -356, -340, -324, -308, -292, -276, -260,
- -244, -228, -212, -196, -180, -164, -148, -132,
- -120, -112, -104, -96, -88, -80, -72, -64,
- -56, -48, -40, -32, -24, -16, -8, 0,
- 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
- 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
- 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
- 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
- 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
- 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
- 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
- 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
- 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
- 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
- 876, 844, 812, 780, 748, 716, 684, 652,
- 620, 588, 556, 524, 492, 460, 428, 396,
- 372, 356, 340, 324, 308, 292, 276, 260,
- 244, 228, 212, 196, 180, 164, 148, 132,
- 120, 112, 104, 96, 88, 80, 72, 64,
- 56, 48, 40, 32, 24, 16, 8, 0,
+static short ulaw2dma16[] = {
+ -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
+ -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
+ -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
+ -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
+ -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
+ -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
+ -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+ -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
+ -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
+ -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
+ -876, -844, -812, -780, -748, -716, -684, -652,
+ -620, -588, -556, -524, -492, -460, -428, -396,
+ -372, -356, -340, -324, -308, -292, -276, -260,
+ -244, -228, -212, -196, -180, -164, -148, -132,
+ -120, -112, -104, -96, -88, -80, -72, -64,
+ -56, -48, -40, -32, -24, -16, -8, 0,
+ 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
+ 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
+ 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
+ 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
+ 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
+ 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
+ 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
+ 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
+ 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
+ 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
+ 876, 844, 812, 780, 748, 716, 684, 652,
+ 620, 588, 556, 524, 492, 460, 428, 396,
+ 372, 356, 340, 324, 308, 292, 276, 260,
+ 244, 228, 212, 196, 180, 164, 148, 132,
+ 120, 112, 104, 96, 88, 80, 72, 64,
+ 56, 48, 40, 32, 24, 16, 8, 0,
};
/* 16 bit A-law */
-static char alaw2dma16[] = {
- -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
- -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
- -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
- -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
- -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
- -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
- -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
- -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
- -344, -328, -376, -360, -280, -264, -312, -296,
- -472, -456, -504, -488, -408, -392, -440, -424,
- -88, -72, -120, -104, -24, -8, -56, -40,
- -216, -200, -248, -232, -152, -136, -184, -168,
- -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
- -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
- -688, -656, -752, -720, -560, -528, -624, -592,
- -944, -912, -1008, -976, -816, -784, -880, -848,
- 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
- 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
- 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
- 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
- 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
- 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
- 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
- 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
- 344, 328, 376, 360, 280, 264, 312, 296,
- 472, 456, 504, 488, 408, 392, 440, 424,
- 88, 72, 120, 104, 24, 8, 56, 40,
- 216, 200, 248, 232, 152, 136, 184, 168,
- 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
- 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
- 688, 656, 752, 720, 560, 528, 624, 592,
- 944, 912, 1008, 976, 816, 784, 880, 848,
+static short alaw2dma16[] = {
+ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
+ -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
+ -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
+ -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
+ -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
+ -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
+ -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
+ -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
+ -344, -328, -376, -360, -280, -264, -312, -296,
+ -472, -456, -504, -488, -408, -392, -440, -424,
+ -88, -72, -120, -104, -24, -8, -56, -40,
+ -216, -200, -248, -232, -152, -136, -184, -168,
+ -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
+ -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+ -688, -656, -752, -720, -560, -528, -624, -592,
+ -944, -912, -1008, -976, -816, -784, -880, -848,
+ 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
+ 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
+ 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
+ 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
+ 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+ 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+ 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
+ 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+ 344, 328, 376, 360, 280, 264, 312, 296,
+ 472, 456, 504, 488, 408, 392, 440, 424,
+ 88, 72, 120, 104, 24, 8, 56, 40,
+ 216, 200, 248, 232, 152, 136, 184, 168,
+ 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
+ 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
+ 688, 656, 752, 720, 560, 528, 624, 592,
+ 944, 912, 1008, 976, 816, 784, 880, 848,
};
#endif /* HAS_16BIT_TABLES */
@@ -332,75 +433,75 @@
/* 14 bit mu-law (LSB) */
static char alaw2dma14l[] = {
- 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 49, 17, 49, 17, 49, 17, 49, 17,
- 49, 17, 49, 17, 49, 17, 49, 17,
- 41, 57, 9, 25, 41, 57, 9, 25,
- 41, 57, 9, 25, 41, 57, 9, 25,
- 37, 45, 53, 61, 5, 13, 21, 29,
- 37, 45, 53, 61, 5, 13, 21, 29,
- 35, 39, 43, 47, 51, 55, 59, 63,
- 3, 7, 11, 15, 19, 23, 27, 31,
- 34, 36, 38, 40, 42, 44, 46, 48,
- 50, 52, 54, 56, 58, 60, 62, 0,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 15, 47, 15, 47, 15, 47, 15, 47,
- 15, 47, 15, 47, 15, 47, 15, 47,
- 23, 7, 55, 39, 23, 7, 55, 39,
- 23, 7, 55, 39, 23, 7, 55, 39,
- 27, 19, 11, 3, 59, 51, 43, 35,
- 27, 19, 11, 3, 59, 51, 43, 35,
- 29, 25, 21, 17, 13, 9, 5, 1,
- 61, 57, 53, 49, 45, 41, 37, 33,
- 30, 28, 26, 24, 22, 20, 18, 16,
- 14, 12, 10, 8, 6, 4, 2, 0
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 49, 17, 49, 17, 49, 17, 49, 17,
+ 49, 17, 49, 17, 49, 17, 49, 17,
+ 41, 57, 9, 25, 41, 57, 9, 25,
+ 41, 57, 9, 25, 41, 57, 9, 25,
+ 37, 45, 53, 61, 5, 13, 21, 29,
+ 37, 45, 53, 61, 5, 13, 21, 29,
+ 35, 39, 43, 47, 51, 55, 59, 63,
+ 3, 7, 11, 15, 19, 23, 27, 31,
+ 34, 36, 38, 40, 42, 44, 46, 48,
+ 50, 52, 54, 56, 58, 60, 62, 0,
+ 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63,
+ 15, 47, 15, 47, 15, 47, 15, 47,
+ 15, 47, 15, 47, 15, 47, 15, 47,
+ 23, 7, 55, 39, 23, 7, 55, 39,
+ 23, 7, 55, 39, 23, 7, 55, 39,
+ 27, 19, 11, 3, 59, 51, 43, 35,
+ 27, 19, 11, 3, 59, 51, 43, 35,
+ 29, 25, 21, 17, 13, 9, 5, 1,
+ 61, 57, 53, 49, 45, 41, 37, 33,
+ 30, 28, 26, 24, 22, 20, 18, 16,
+ 14, 12, 10, 8, 6, 4, 2, 0
};
/* 14 bit A-law (LSB) */
static char alaw2dma14l[] = {
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 16, 48, 16, 48, 16, 48, 16, 48,
- 16, 48, 16, 48, 16, 48, 16, 48,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 42, 46, 34, 38, 58, 62, 50, 54,
- 10, 14, 2, 6, 26, 30, 18, 22,
- 42, 46, 34, 38, 58, 62, 50, 54,
- 10, 14, 2, 6, 26, 30, 18, 22,
- 40, 56, 8, 24, 40, 56, 8, 24,
- 40, 56, 8, 24, 40, 56, 8, 24,
- 20, 28, 4, 12, 52, 60, 36, 44,
- 20, 28, 4, 12, 52, 60, 36, 44,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 48, 16, 48, 16, 48, 16, 48, 16,
- 48, 16, 48, 16, 48, 16, 48, 16,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 22, 18, 30, 26, 6, 2, 14, 10,
- 54, 50, 62, 58, 38, 34, 46, 42,
- 22, 18, 30, 26, 6, 2, 14, 10,
- 54, 50, 62, 58, 38, 34, 46, 42,
- 24, 8, 56, 40, 24, 8, 56, 40,
- 24, 8, 56, 40, 24, 8, 56, 40,
- 44, 36, 60, 52, 12, 4, 28, 20,
- 44, 36, 60, 52, 12, 4, 28, 20
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 16, 48, 16, 48, 16, 48, 16, 48,
+ 16, 48, 16, 48, 16, 48, 16, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 42, 46, 34, 38, 58, 62, 50, 54,
+ 10, 14, 2, 6, 26, 30, 18, 22,
+ 42, 46, 34, 38, 58, 62, 50, 54,
+ 10, 14, 2, 6, 26, 30, 18, 22,
+ 40, 56, 8, 24, 40, 56, 8, 24,
+ 40, 56, 8, 24, 40, 56, 8, 24,
+ 20, 28, 4, 12, 52, 60, 36, 44,
+ 20, 28, 4, 12, 52, 60, 36, 44,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 48, 16, 48, 16, 48, 16, 48, 16,
+ 48, 16, 48, 16, 48, 16, 48, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 22, 18, 30, 26, 6, 2, 14, 10,
+ 54, 50, 62, 58, 38, 34, 46, 42,
+ 22, 18, 30, 26, 6, 2, 14, 10,
+ 54, 50, 62, 58, 38, 34, 46, 42,
+ 24, 8, 56, 40, 24, 8, 56, 40,
+ 24, 8, 56, 40, 24, 8, 56, 40,
+ 44, 36, 60, 52, 12, 4, 28, 20,
+ 44, 36, 60, 52, 12, 4, 28, 20
};
#endif /* HAS_14BIT_TABLES */
@@ -456,26 +557,48 @@
u_char frame[], long *frameUsed, long frameLeft);
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+static long pmac_ct_law(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft);
+#endif /* CONFIG_PMAC */
/*** Machine definitions *****************************************************/
typedef struct {
- int type;
- void *(*dma_alloc)(unsigned int, int);
- void (*dma_free)(void *, unsigned int);
- int (*irqinit)(void);
+ int type;
+ void *(*dma_alloc)(unsigned int, int);
+ void (*dma_free)(void *, unsigned int);
+ int (*irqinit)(void);
#ifdef MODULE
- void (*irqcleanup)(void);
+ void (*irqcleanup)(void);
#endif /* MODULE */
- void (*init)(void);
- void (*silence)(void);
- int (*setFormat)(int);
- int (*setVolume)(int);
- int (*setBass)(int);
- int (*setTreble)(int);
- int (*setGain)(int);
- void (*play)(void);
+ void (*init)(void);
+ void (*silence)(void);
+ int (*setFormat)(int);
+ int (*setVolume)(int);
+ int (*setBass)(int);
+ int (*setTreble)(int);
+ int (*setGain)(int);
+ void (*play)(void);
} MACHINE;
@@ -483,38 +606,38 @@
typedef struct {
- int format; /* AFMT_* */
- int stereo; /* 0 = mono, 1 = stereo */
- int size; /* 8/16 bit*/
- int speed; /* speed */
+ int format; /* AFMT_* */
+ int stereo; /* 0 = mono, 1 = stereo */
+ int size; /* 8/16 bit*/
+ int speed; /* speed */
} SETTINGS;
typedef struct {
- long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long);
- long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long);
+ long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long);
} TRANS;
struct sound_settings {
- MACHINE mach; /* machine dependent things */
- SETTINGS hard; /* hardware settings */
- SETTINGS soft; /* software settings */
- SETTINGS dsp; /* /dev/dsp default settings */
- TRANS *trans; /* supported translations */
- int volume_left; /* volume (range is machine dependent) */
- int volume_right;
- int bass; /* tone (range is machine dependent) */
- int treble;
- int gain;
- int minDev; /* minor device number currently open */
-#ifdef CONFIG_ATARI
- int bal; /* balance factor for expanding (not volume!) */
- u_long data; /* data for expanding */
+ MACHINE mach; /* machine dependent things */
+ SETTINGS hard; /* hardware settings */
+ SETTINGS soft; /* software settings */
+ SETTINGS dsp; /* /dev/dsp default settings */
+ TRANS *trans; /* supported translations */
+ int volume_left; /* volume (range is machine dependent) */
+ int volume_right;
+ int bass; /* tone (range is machine dependent) */
+ int treble;
+ int gain;
+ int minDev; /* minor device number currently open */
+#if defined(CONFIG_ATARI) || defined(CONFIG_PMAC)
+ int bal; /* balance factor for expanding (not volume!) */
+ u_long data; /* data for expanding */
#endif /* CONFIG_ATARI */
};
@@ -561,6 +684,26 @@
static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp);
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+static void *PMacAlloc(unsigned int size, int flags);
+static void PMacFree(void *ptr, unsigned int size);
+static int PMacIrqInit(void);
+#ifdef MODULE
+static void PMacIrqCleanup(void);
+#endif /* MODULE */
+static void PMacSilence(void);
+static void PMacInit(void);
+static void PMacPlay(void);
+static int PMacSetFormat(int format);
+static int PMacSetVolume(int volume);
+static void pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs);
+static void pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs);
+static void awacs_write(int val);
+static int awacs_get_volume(int reg, int lshift);
+static int awacs_volume_setter(int volume, int n, int mute, int lshift);
+static void awacs_mksound(unsigned int hz, unsigned int ticks);
+static void awacs_nosound(unsigned long xx);
+#endif /* CONFIG_PMAC */
/*** Mid level stuff *********************************************************/
@@ -574,7 +717,9 @@
#ifdef CONFIG_ATARI
static int sound_set_bass(int bass);
#endif /* CONFIG_ATARI */
+#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA)
static int sound_set_treble(int treble);
+#endif /* CONFIG_ATARI || CONFIG_AMIGA */
static long sound_copy_translate(const u_char *userPtr,
unsigned long userCount,
u_char frame[], long *frameUsed,
@@ -603,29 +748,30 @@
*/
struct sound_queue {
- int max_count, block_size;
- char **buffers;
-
- /* it shouldn't be necessary to declare any of these volatile */
- int front, rear, count;
- int rear_size;
- /*
- * The use of the playing field depends on the hardware
- *
- * Atari: The number of frames that are loaded/playing
- *
- * Amiga: Bit 0 is set: a frame is loaded
- * Bit 1 is set: a frame is playing
- */
- int playing;
- struct wait_queue *write_queue, *open_queue, *sync_queue;
- int open_mode;
- int busy, syncing;
+ int max_count, block_size;
+ char **buffers;
+ int max_active;
+
+ /* it shouldn't be necessary to declare any of these volatile */
+ int front, rear, count;
+ int rear_size;
+ /*
+ * The use of the playing field depends on the hardware
+ *
+ * Atari, PMac: The number of frames that are loaded/playing
+ *
+ * Amiga: Bit 0 is set: a frame is loaded
+ * Bit 1 is set: a frame is playing
+ */
+ int playing;
+ struct wait_queue *write_queue, *open_queue, *sync_queue;
+ int open_mode;
+ int busy, syncing;
#ifdef CONFIG_ATARI
- int ignore_int; /* ++TeSche: used for Falcon */
+ int ignore_int; /* ++TeSche: used for Falcon */
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
- int block_size_half, block_size_quarter;
+ int block_size_half, block_size_quarter;
#endif /* CONFIG_AMIGA */
};
@@ -648,6 +794,7 @@
static void sq_reset(void);
static int sq_sync(void);
static int sq_release(void);
+static void init_settings(void);
/*
@@ -655,9 +802,9 @@
*/
struct sound_state {
- int busy;
- char buf[512];
- int len, ptr;
+ int busy;
+ char buf[512];
+ int len, ptr;
};
static struct sound_state state;
@@ -681,10 +828,10 @@
loff_t *ppos);
static inline int ioctl_return(int *addr, int value)
{
- if (value < 0)
- return(value);
+ if (value < 0)
+ return(value);
- return put_user(value, addr);
+ return put_user(value, addr)? -EFAULT: 0;
}
static int unknown_minor_dev(char *fname, int dev);
static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
@@ -730,554 +877,581 @@
static long ata_ct_law(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
- long count, used;
- u_char *p = &frame[*frameUsed];
-
- count = min(userCount, frameLeft);
- if (sound.soft.stereo)
- count &= ~1;
- used = count;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *p++ = table[data];
- count--;
- }
- *frameUsed += used;
- return(used);
+ char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
+ long count, used;
+ u_char *p = &frame[*frameUsed];
+
+ count = min(userCount, frameLeft);
+ if (sound.soft.stereo)
+ count &= ~1;
+ used = count;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *p++ = table[data];
+ count--;
+ }
+ *frameUsed += used;
+ return(used);
}
static long ata_ct_s8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- void *p = &frame[*frameUsed];
+ long count, used;
+ void *p = &frame[*frameUsed];
- count = min(userCount, frameLeft);
- if (sound.soft.stereo)
- count &= ~1;
- used = count;
- copy_from_user(p, userPtr, count);
- *frameUsed += used;
- return(used);
+ count = min(userCount, frameLeft);
+ if (sound.soft.stereo)
+ count &= ~1;
+ used = count;
+ if (copy_from_user(p, userPtr, count))
+ return -EFAULT;
+ *frameUsed += used;
+ return(used);
}
static long ata_ct_u8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
+ long count, used;
- if (!sound.soft.stereo) {
- u_char *p = &frame[*frameUsed];
- count = min(userCount, frameLeft);
- used = count;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *p++ = data ^ 0x80;
- count--;
- }
- } else {
- u_short *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>1;
- used = count*2;
- while (count > 0) {
- u_short data;
- get_user(data, ((u_short *)userPtr)++);
- *p++ = data ^ 0x8080;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ u_char *p = &frame[*frameUsed];
+ count = min(userCount, frameLeft);
+ used = count;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *p++ = data ^ 0x80;
+ count--;
+ }
+ } else {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>1;
+ used = count*2;
+ while (count > 0) {
+ u_short data;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ *p++ = data ^ 0x8080;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- *p++ = data;
- *p++ = data;
- count--;
- }
- *frameUsed += used*2;
- } else {
- void *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft) & ~3;
- used = count;
- copy_from_user(p, userPtr, count);
- *frameUsed += used;
- }
- return(used);
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ *p++ = data;
+ *p++ = data;
+ count--;
+ }
+ *frameUsed += used*2;
+ } else {
+ void *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft) & ~3;
+ used = count;
+ if (copy_from_user(p, userPtr, count))
+ return -EFAULT;
+ *frameUsed += used;
+ }
+ return(used);
}
static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8000;
- *p++ = data;
- *p++ = data;
- count--;
- }
- *frameUsed += used*2;
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>2;
- used = count*4;
- while (count > 0) {
- get_user(data, ((u_int *)userPtr)++);
- *p++ = data ^ 0x80008000;
- count--;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8000;
+ *p++ = data;
+ *p++ = data;
+ count--;
+ }
+ *frameUsed += used*2;
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>2;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ *p++ = data ^ 0x80008000;
+ count--;
+ }
+ *frameUsed += used;
}
- *frameUsed += used;
- }
- return(used);
+ return(used);
}
static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- count = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data);
- *p++ = data;
- *p++ = data;
- count--;
- }
- *frameUsed += used*2;
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>2;
- used = count*4;
- while (count > 0) {
- get_user(data, ((u_int *)userPtr)++);
- data = le2be16dbl(data);
- *p++ = data;
- count--;
+ count = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data);
+ *p++ = data;
+ *p++ = data;
+ count--;
+ }
+ *frameUsed += used*2;
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>2;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ data = le2be16dbl(data);
+ *p++ = data;
+ count--;
+ }
+ *frameUsed += used;
}
- *frameUsed += used;
- }
- return(used);
+ return(used);
}
static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- count = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data) ^ 0x8000;
- *p++ = data;
- *p++ = data;
- }
- *frameUsed += used*2;
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- count = min(userCount, frameLeft)>>2;
- used = count;
- while (count > 0) {
- get_user(data, ((u_int *)userPtr)++);
- data = le2be16dbl(data) ^ 0x80008000;
- *p++ = data;
- count--;
+ count = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data) ^ 0x8000;
+ *p++ = data;
+ *p++ = data;
+ }
+ *frameUsed += used*2;
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ count = min(userCount, frameLeft)>>2;
+ used = count;
+ while (count > 0) {
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ data = le2be16dbl(data) ^ 0x80008000;
+ *p++ = data;
+ count--;
+ }
+ *frameUsed += used;
}
- *frameUsed += used;
- }
- return(used);
+ return(used);
}
static long ata_ctx_law(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_char *p = &frame[*frameUsed];
- while (frameLeft) {
- u_char c;
- if (bal < 0) {
- if (!userCount)
- break;
- get_user(c, userPtr++);
- data = table[c];
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- } else {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 2) {
- u_char c;
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(c, userPtr++);
- data = table[c] << 8;
- get_user(c, userPtr++);
- data |= table[c];
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 2;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_char *p = &frame[*frameUsed];
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (!userCount)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = table[c];
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ } else {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 2) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = table[c] << 8;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data |= table[c];
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 2;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_char *p = &frame[*frameUsed];
- while (frameLeft) {
- if (bal < 0) {
- if (!userCount)
- break;
- get_user(data, userPtr++);
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- } else {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 2) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 2;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_char *p = &frame[*frameUsed];
+ while (frameLeft) {
+ if (bal < 0) {
+ if (!userCount)
+ break;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ } else {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 2) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 2;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_char *p = &frame[*frameUsed];
- while (frameLeft) {
- if (bal < 0) {
- if (!userCount)
- break;
- get_user(data, userPtr++);
- data ^= 0x80;
- userCount--;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft--;
- bal -= sSpeed;
- }
- } else {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 2) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8080;
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 2;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_char *p = &frame[*frameUsed];
+ while (frameLeft) {
+ if (bal < 0) {
+ if (!userCount)
+ break;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ data ^= 0x80;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ } else {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 2) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8080;
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 2;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 4)
- break;
- get_user(data, ((u_int *)userPtr)++);
- userCount -= 4;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 4)
+ break;
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ userCount -= 4;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8000;
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 4)
- break;
- get_user(data, ((u_int *)userPtr)++);
- data ^= 0x80008000;
- userCount -= 4;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8000;
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 4)
+ break;
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x80008000;
+ userCount -= 4;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data);
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 4)
- break;
- get_user(data, ((u_int *)userPtr)++);
- data = le2be16dbl(data);
- userCount -= 4;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data);
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 4)
+ break;
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ data = le2be16dbl(data);
+ userCount -= 4;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- /* this should help gcc to stuff everything into registers */
- u_long data = sound.data;
- long bal = sound.bal;
- long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
- long used, usedf;
-
- used = userCount;
- usedf = frameLeft;
- if (!sound.soft.stereo) {
- u_short *p = (u_short *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 2)
- break;
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data) ^ 0x8000;
- userCount -= 2;
- bal += hSpeed;
- }
- *p++ = data;
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- } else {
- u_long *p = (u_long *)&frame[*frameUsed];
- while (frameLeft >= 4) {
- if (bal < 0) {
- if (userCount < 4)
- break;
- get_user(data, ((u_int *)userPtr)++);
- data = le2be16dbl(data) ^ 0x80008000;
- userCount -= 4;
- bal += hSpeed;
- }
- *p++ = data;
- frameLeft -= 4;
- bal -= sSpeed;
- }
- }
- sound.bal = bal;
- sound.data = data;
- used -= userCount;
- *frameUsed += usedf-frameLeft;
- return(used);
+ /* this should help gcc to stuff everything into registers */
+ u_long data = sound.data;
+ long bal = sound.bal;
+ long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ long used, usedf;
+
+ used = userCount;
+ usedf = frameLeft;
+ if (!sound.soft.stereo) {
+ u_short *p = (u_short *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 2)
+ break;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data) ^ 0x8000;
+ userCount -= 2;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ } else {
+ u_long *p = (u_long *)&frame[*frameUsed];
+ while (frameLeft >= 4) {
+ if (bal < 0) {
+ if (userCount < 4)
+ break;
+ if (get_user(data, ((u_int *)userPtr)++))
+ return -EFAULT;
+ data = le2be16dbl(data) ^ 0x80008000;
+ userCount -= 4;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft -= 4;
+ bal -= sSpeed;
+ }
+ }
+ sound.bal = bal;
+ sound.data = data;
+ used -= userCount;
+ *frameUsed += usedf-frameLeft;
+ return(used);
}
#endif /* CONFIG_ATARI */
@@ -1286,291 +1460,698 @@
static long ami_ct_law(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
- long count, used;
+ char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
+ long count, used;
- if (!sound.soft.stereo) {
- u_char *p = &frame[*frameUsed];
- count = min(userCount, frameLeft) & ~1;
- used = count;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *p++ = table[data];
- count--;
- }
- } else {
- u_char *left = &frame[*frameUsed>>1];
- u_char *right = left+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *left++ = table[data];
- get_user(data, userPtr++);
- *right++ = table[data];
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ u_char *p = &frame[*frameUsed];
+ count = min(userCount, frameLeft) & ~1;
+ used = count;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *p++ = table[data];
+ count--;
+ }
+ } else {
+ u_char *left = &frame[*frameUsed>>1];
+ u_char *right = left+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *left++ = table[data];
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *right++ = table[data];
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_s8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
+ long count, used;
- if (!sound.soft.stereo) {
- void *p = &frame[*frameUsed];
- count = min(userCount, frameLeft) & ~1;
- used = count;
- copy_from_user(p, userPtr, count);
- } else {
- u_char *left = &frame[*frameUsed>>1];
- u_char *right = left+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- get_user(*left++, userPtr++);
- get_user(*right++, userPtr++);
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ void *p = &frame[*frameUsed];
+ count = min(userCount, frameLeft) & ~1;
+ used = count;
+ if (copy_from_user(p, userPtr, count))
+ return -EFAULT;
+ } else {
+ u_char *left = &frame[*frameUsed>>1];
+ u_char *right = left+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(*left++, userPtr++)
+ || get_user(*right++, userPtr++))
+ return -EFAULT;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_u8(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
+ long count, used;
- if (!sound.soft.stereo) {
- char *p = &frame[*frameUsed];
- count = min(userCount, frameLeft) & ~1;
- used = count;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *p++ = data ^ 0x80;
- count--;
- }
- } else {
- u_char *left = &frame[*frameUsed>>1];
- u_char *right = left+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- u_char data;
- get_user(data, userPtr++);
- *left++ = data ^ 0x80;
- get_user(data, userPtr++);
- *right++ = data ^ 0x80;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ char *p = &frame[*frameUsed];
+ count = min(userCount, frameLeft) & ~1;
+ used = count;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *p++ = data ^ 0x80;
+ count--;
+ }
+ } else {
+ u_char *left = &frame[*frameUsed>>1];
+ u_char *right = left+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *left++ = data ^ 0x80;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ *right++ = data ^ 0x80;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- if (!sound.soft.stereo) {
- u_char *high = &frame[*frameUsed>>1];
- u_char *low = high+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- *high++ = data>>8;
- *low++ = (data>>2) & 0x3f;
- count--;
- }
- } else {
- u_char *lefth = &frame[*frameUsed>>2];
- u_char *leftl = lefth+sq.block_size_quarter;
- u_char *righth = lefth+sq.block_size_half;
- u_char *rightl = righth+sq.block_size_quarter;
- count = min(userCount, frameLeft)>>2 & ~1;
- used = count*4;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- *lefth++ = data>>8;
- *leftl++ = (data>>2) & 0x3f;
- get_user(data, ((u_short *)userPtr)++);
- *righth++ = data>>8;
- *rightl++ = (data>>2) & 0x3f;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ u_char *high = &frame[*frameUsed>>1];
+ u_char *low = high+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ *high++ = data>>8;
+ *low++ = (data>>2) & 0x3f;
+ count--;
+ }
+ } else {
+ u_char *lefth = &frame[*frameUsed>>2];
+ u_char *leftl = lefth+sq.block_size_quarter;
+ u_char *righth = lefth+sq.block_size_half;
+ u_char *rightl = righth+sq.block_size_quarter;
+ count = min(userCount, frameLeft)>>2 & ~1;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ *lefth++ = data>>8;
+ *leftl++ = (data>>2) & 0x3f;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ *righth++ = data>>8;
+ *rightl++ = (data>>2) & 0x3f;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- if (!sound.soft.stereo) {
- u_char *high = &frame[*frameUsed>>1];
- u_char *low = high+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8000;
- *high++ = data>>8;
- *low++ = (data>>2) & 0x3f;
- count--;
- }
- } else {
- u_char *lefth = &frame[*frameUsed>>2];
- u_char *leftl = lefth+sq.block_size_quarter;
- u_char *righth = lefth+sq.block_size_half;
- u_char *rightl = righth+sq.block_size_quarter;
- count = min(userCount, frameLeft)>>2 & ~1;
- used = count*4;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8000;
- *lefth++ = data>>8;
- *leftl++ = (data>>2) & 0x3f;
- get_user(data, ((u_short *)userPtr)++);
- data ^= 0x8000;
- *righth++ = data>>8;
- *rightl++ = (data>>2) & 0x3f;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ u_char *high = &frame[*frameUsed>>1];
+ u_char *low = high+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8000;
+ *high++ = data>>8;
+ *low++ = (data>>2) & 0x3f;
+ count--;
+ }
+ } else {
+ u_char *lefth = &frame[*frameUsed>>2];
+ u_char *leftl = lefth+sq.block_size_quarter;
+ u_char *righth = lefth+sq.block_size_half;
+ u_char *rightl = righth+sq.block_size_quarter;
+ count = min(userCount, frameLeft)>>2 & ~1;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8000;
+ *lefth++ = data>>8;
+ *leftl++ = (data>>2) & 0x3f;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data ^= 0x8000;
+ *righth++ = data>>8;
+ *rightl++ = (data>>2) & 0x3f;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
- if (!sound.soft.stereo) {
- u_char *high = &frame[*frameUsed>>1];
- u_char *low = high+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data);
- *high++ = data>>8;
- *low++ = (data>>2) & 0x3f;
- count--;
- }
- } else {
- u_char *lefth = &frame[*frameUsed>>2];
- u_char *leftl = lefth+sq.block_size_quarter;
- u_char *righth = lefth+sq.block_size_half;
- u_char *rightl = righth+sq.block_size_quarter;
- count = min(userCount, frameLeft)>>2 & ~1;
- used = count*4;
- while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data);
- *lefth++ = data>>8;
- *leftl++ = (data>>2) & 0x3f;
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data);
- *righth++ = data>>8;
- *rightl++ = (data>>2) & 0x3f;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ if (!sound.soft.stereo) {
+ u_char *high = &frame[*frameUsed>>1];
+ u_char *low = high+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data);
+ *high++ = data>>8;
+ *low++ = (data>>2) & 0x3f;
+ count--;
+ }
+ } else {
+ u_char *lefth = &frame[*frameUsed>>2];
+ u_char *leftl = lefth+sq.block_size_quarter;
+ u_char *righth = lefth+sq.block_size_half;
+ u_char *rightl = righth+sq.block_size_quarter;
+ count = min(userCount, frameLeft)>>2 & ~1;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data);
+ *lefth++ = data>>8;
+ *leftl++ = (data>>2) & 0x3f;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data);
+ *righth++ = data>>8;
+ *rightl++ = (data>>2) & 0x3f;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
}
static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount,
u_char frame[], long *frameUsed, long frameLeft)
{
- long count, used;
- u_long data;
+ long count, used;
+ u_long data;
+
+ if (!sound.soft.stereo) {
+ u_char *high = &frame[*frameUsed>>1];
+ u_char *low = high+sq.block_size_half;
+ count = min(userCount, frameLeft)>>1 & ~1;
+ used = count*2;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data) ^ 0x8000;
+ *high++ = data>>8;
+ *low++ = (data>>2) & 0x3f;
+ count--;
+ }
+ } else {
+ u_char *lefth = &frame[*frameUsed>>2];
+ u_char *leftl = lefth+sq.block_size_quarter;
+ u_char *righth = lefth+sq.block_size_half;
+ u_char *rightl = righth+sq.block_size_quarter;
+ count = min(userCount, frameLeft)>>2 & ~1;
+ used = count*4;
+ while (count > 0) {
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data) ^ 0x8000;
+ *lefth++ = data>>8;
+ *leftl++ = (data>>2) & 0x3f;
+ if (get_user(data, ((u_short *)userPtr)++))
+ return -EFAULT;
+ data = le2be16(data) ^ 0x8000;
+ *righth++ = data>>8;
+ *rightl++ = (data>>2) & 0x3f;
+ count--;
+ }
+ }
+ *frameUsed += used;
+ return(used);
+}
+#endif /* CONFIG_AMIGA */
+
+#ifdef CONFIG_PMAC
+static long pmac_ct_law(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16;
+ long count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = table[data];
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = table[data];
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static long pmac_ct_s8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ long count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
+ while (count > 0) {
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = data << 8;
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = data << 8;
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
- if (!sound.soft.stereo) {
- u_char *high = &frame[*frameUsed>>1];
- u_char *low = high+sq.block_size_half;
- count = min(userCount, frameLeft)>>1 & ~1;
- used = count*2;
+static long pmac_ct_u8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ long count, used;
+ short *p = (short *) &frame[*frameUsed];
+ int val, stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ used = count = min(userCount, frameLeft);
while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data) ^ 0x8000;
- *high++ = data>>8;
- *low++ = (data>>2) & 0x3f;
- count--;
- }
- } else {
- u_char *lefth = &frame[*frameUsed>>2];
- u_char *leftl = lefth+sq.block_size_quarter;
- u_char *righth = lefth+sq.block_size_half;
- u_char *rightl = righth+sq.block_size_quarter;
- count = min(userCount, frameLeft)>>2 & ~1;
- used = count*4;
+ u_char data;
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = (data ^ 0x80) << 8;
+ *p++ = val;
+ if (stereo) {
+ if (get_user(data, userPtr++))
+ return -EFAULT;
+ val = (data ^ 0x80) << 8;
+ }
+ *p++ = val;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 2: used;
+}
+
+
+static long pmac_ct_s16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ long count, used;
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
+ if (!stereo) {
+ short *up = (short *) userPtr;
+ while (count > 0) {
+ short data;
+ if (get_user(data, up++))
+ return -EFAULT;
+ *fp++ = data;
+ *fp++ = data;
+ count--;
+ }
+ } else {
+ if (copy_from_user(fp, userPtr, count * 4))
+ return -EFAULT;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+static long pmac_ct_u16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ long count, used;
+ int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+ int stereo = sound.soft.stereo;
+ short *fp = (short *) &frame[*frameUsed];
+ short *up = (short *) userPtr;
+
+ frameLeft >>= 2;
+ userCount >>= (stereo? 2: 1);
+ used = count = min(userCount, frameLeft);
while (count > 0) {
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data) ^ 0x8000;
- *lefth++ = data>>8;
- *leftl++ = (data>>2) & 0x3f;
- get_user(data, ((u_short *)userPtr)++);
- data = le2be16(data) ^ 0x8000;
- *righth++ = data>>8;
- *rightl++ = (data>>2) & 0x3f;
- count--;
- }
- }
- *frameUsed += used;
- return(used);
+ int data;
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ *fp++ = data;
+ if (stereo) {
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ }
+ *fp++ = data;
+ count--;
+ }
+ *frameUsed += used * 4;
+ return stereo? used * 4: used * 2;
+}
+
+
+static long pmac_ctx_law(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ unsigned short *table = (unsigned short *)
+ (sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16);
+ unsigned int data = sound.data;
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ int bal = sound.bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int utotal, ftotal;
+ int stereo = sound.soft.stereo;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = table[c];
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + table[c];
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ sound.bal = bal;
+ sound.data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static long pmac_ctx_s8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = sound.data;
+ int bal = sound.bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = c << 8;
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + (c << 8);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ sound.bal = bal;
+ sound.data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static long pmac_ctx_u8(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = sound.data;
+ int bal = sound.bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ u_char c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (c ^ 0x80) << 8;
+ if (stereo) {
+ if (get_user(c, userPtr++))
+ return -EFAULT;
+ data = (data << 16) + ((c ^ 0x80) << 8);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ sound.bal = bal;
+ sound.data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 2: utotal;
+}
+
+
+static long pmac_ctx_s16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = sound.data;
+ unsigned short *up = (unsigned short *) userPtr;
+ int bal = sound.bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ unsigned short c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(data, up++))
+ return -EFAULT;
+ if (stereo) {
+ if (get_user(c, up++))
+ return -EFAULT;
+ data = (data << 16) + c;
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ sound.bal = bal;
+ sound.data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 4: utotal * 2;
+}
+
+
+static long pmac_ctx_u16(const u_char *userPtr, unsigned long userCount,
+ u_char frame[], long *frameUsed, long frameLeft)
+{
+ int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+ unsigned int *p = (unsigned int *) &frame[*frameUsed];
+ unsigned int data = sound.data;
+ unsigned short *up = (unsigned short *) userPtr;
+ int bal = sound.bal;
+ int hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
+ int stereo = sound.soft.stereo;
+ int utotal, ftotal;
+
+ frameLeft >>= 2;
+ if (stereo)
+ userCount >>= 1;
+ ftotal = frameLeft;
+ utotal = userCount;
+ while (frameLeft) {
+ unsigned short c;
+ if (bal < 0) {
+ if (userCount == 0)
+ break;
+ if (get_user(data, up++))
+ return -EFAULT;
+ data ^= mask;
+ if (stereo) {
+ if (get_user(c, up++))
+ return -EFAULT;
+ data = (data << 16) + (c ^ mask);
+ } else
+ data = (data << 16) + data;
+ userCount--;
+ bal += hSpeed;
+ }
+ *p++ = data;
+ frameLeft--;
+ bal -= sSpeed;
+ }
+ sound.bal = bal;
+ sound.data = data;
+ *frameUsed += (ftotal - frameLeft) * 4;
+ utotal -= userCount;
+ return stereo? utotal * 4: utotal * 2;
}
-#endif /* CONFIG_AMIGA */
+
+#endif /* CONFIG_PMAC */
#ifdef CONFIG_ATARI
static TRANS transTTNormal = {
- ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL
+ ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL
};
static TRANS transTTExpanding = {
- ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL
+ ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL
};
static TRANS transFalconNormal = {
- ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be,
- ata_ct_s16le, ata_ct_u16le
+ ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8,
+ ata_ct_s16be, ata_ct_u16be, ata_ct_s16le, ata_ct_u16le
};
static TRANS transFalconExpanding = {
- ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be,
- ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le
+ ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8,
+ ata_ctx_s16be, ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le
};
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
static TRANS transAmiga = {
- ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be,
- ami_ct_s16le, ami_ct_u16le
+ ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8,
+ ami_ct_s16be, ami_ct_u16be, ami_ct_s16le, ami_ct_u16le
};
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+static TRANS transAwacsNormal = {
+ pmac_ct_law, pmac_ct_law, pmac_ct_s8, pmac_ct_u8,
+ pmac_ct_s16, pmac_ct_u16, pmac_ct_s16, pmac_ct_u16
+};
+
+static TRANS transAwacsExpand = {
+ pmac_ctx_law, pmac_ctx_law, pmac_ctx_s8, pmac_ctx_u8,
+ pmac_ctx_s16, pmac_ctx_u16, pmac_ctx_s16, pmac_ctx_u16
+};
+#endif /* CONFIG_PMAC */
/*** Low level stuff *********************************************************/
@@ -1583,40 +2164,40 @@
static void *AtaAlloc(unsigned int size, int flags)
{
- return( atari_stram_alloc( size, NULL, "dmasound" ));
+ return( atari_stram_alloc( size, NULL, "dmasound" ));
}
static void AtaFree(void *obj, unsigned int size)
{
- atari_stram_free( obj );
+ atari_stram_free( obj );
}
static int AtaIrqInit(void)
{
- /* Set up timer A. Timer A
- will receive a signal upon end of playing from the sound
- hardware. Furthermore Timer A is able to count events
- and will cause an interrupt after a programmed number
- of events. So all we need to keep the music playing is
- to provide the sound hardware with new data upon
- an interrupt from timer A. */
- mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
- mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
- mfp.tim_ct_a = 8; /* Turn on event counting. */
- /* Register interrupt handler. */
- request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW,
- "DMA sound", ata_sq_interrupt);
- mfp.int_en_a |= 0x20; /* Turn interrupt on. */
- mfp.int_mk_a |= 0x20;
- return(1);
+ /* Set up timer A. Timer A
+ will receive a signal upon end of playing from the sound
+ hardware. Furthermore Timer A is able to count events
+ and will cause an interrupt after a programmed number
+ of events. So all we need to keep the music playing is
+ to provide the sound hardware with new data upon
+ an interrupt from timer A. */
+ mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
+ mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
+ mfp.tim_ct_a = 8; /* Turn on event counting. */
+ /* Register interrupt handler. */
+ request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW,
+ "DMA sound", ata_sq_interrupt);
+ mfp.int_en_a |= 0x20; /* Turn interrupt on. */
+ mfp.int_mk_a |= 0x20;
+ return(1);
}
#ifdef MODULE
static void AtaIrqCleanUp(void)
{
- mfp.tim_ct_a = 0; /* stop timer */
- mfp.int_en_a &= ~0x20; /* turn interrupt off */
- free_irq(IRQ_MFP_TIMA, ata_sq_interrupt);
+ mfp.tim_ct_a = 0; /* stop timer */
+ mfp.int_en_a &= ~0x20; /* turn interrupt off */
+ free_irq(IRQ_MFP_TIMA, ata_sq_interrupt);
}
#endif /* MODULE */
@@ -1628,17 +2209,17 @@
static int AtaSetBass(int bass)
{
- sound.bass = TONE_VOXWARE_TO_DB(bass);
- atari_microwire_cmd(MW_LM1992_BASS(sound.bass));
- return(TONE_DB_TO_VOXWARE(sound.bass));
+ sound.bass = TONE_VOXWARE_TO_DB(bass);
+ atari_microwire_cmd(MW_LM1992_BASS(sound.bass));
+ return(TONE_DB_TO_VOXWARE(sound.bass));
}
static int AtaSetTreble(int treble)
{
- sound.treble = TONE_VOXWARE_TO_DB(treble);
- atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
- return(TONE_DB_TO_VOXWARE(sound.treble));
+ sound.treble = TONE_VOXWARE_TO_DB(treble);
+ atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
+ return(TONE_DB_TO_VOXWARE(sound.treble));
}
@@ -1650,86 +2231,86 @@
static void TTSilence(void)
{
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
+ tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+ atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
}
static void TTInit(void)
{
- int mode, i, idx;
- const int freq[4] = {50066, 25033, 12517, 6258};
+ int mode, i, idx;
+ const int freq[4] = {50066, 25033, 12517, 6258};
- /* search a frequency that fits into the allowed error range */
+ /* search a frequency that fits into the allowed error range */
- idx = -1;
- for (i = 0; i < arraysize(freq); i++)
- /* this isn't as much useful for a TT than for a Falcon, but
- * then it doesn't hurt very much to implement it for a TT too.
- */
- if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
- idx = i;
- if (idx > -1) {
- sound.soft.speed = freq[idx];
- sound.trans = &transTTNormal;
- } else
- sound.trans = &transTTExpanding;
-
- TTSilence();
- sound.hard = sound.soft;
-
- if (sound.hard.speed > 50066) {
- /* we would need to squeeze the sound, but we won't do that */
- sound.hard.speed = 50066;
- mode = DMASND_MODE_50KHZ;
- sound.trans = &transTTNormal;
- } else if (sound.hard.speed > 25033) {
- sound.hard.speed = 50066;
- mode = DMASND_MODE_50KHZ;
- } else if (sound.hard.speed > 12517) {
- sound.hard.speed = 25033;
- mode = DMASND_MODE_25KHZ;
- } else if (sound.hard.speed > 6258) {
- sound.hard.speed = 12517;
- mode = DMASND_MODE_12KHZ;
- } else {
- sound.hard.speed = 6258;
- mode = DMASND_MODE_6KHZ;
- }
-
- tt_dmasnd.mode = (sound.hard.stereo ?
- DMASND_MODE_STEREO : DMASND_MODE_MONO) |
- DMASND_MODE_8BIT | mode;
+ idx = -1;
+ for (i = 0; i < arraysize(freq); i++)
+ /* this isn't as much useful for a TT than for a Falcon, but
+ * then it doesn't hurt very much to implement it for a TT too.
+ */
+ if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
+ idx = i;
+ if (idx > -1) {
+ sound.soft.speed = freq[idx];
+ sound.trans = &transTTNormal;
+ } else
+ sound.trans = &transTTExpanding;
+
+ TTSilence();
+ sound.hard = sound.soft;
+
+ if (sound.hard.speed > 50066) {
+ /* we would need to squeeze the sound, but we won't do that */
+ sound.hard.speed = 50066;
+ mode = DMASND_MODE_50KHZ;
+ sound.trans = &transTTNormal;
+ } else if (sound.hard.speed > 25033) {
+ sound.hard.speed = 50066;
+ mode = DMASND_MODE_50KHZ;
+ } else if (sound.hard.speed > 12517) {
+ sound.hard.speed = 25033;
+ mode = DMASND_MODE_25KHZ;
+ } else if (sound.hard.speed > 6258) {
+ sound.hard.speed = 12517;
+ mode = DMASND_MODE_12KHZ;
+ } else {
+ sound.hard.speed = 6258;
+ mode = DMASND_MODE_6KHZ;
+ }
+
+ tt_dmasnd.mode = (sound.hard.stereo ?
+ DMASND_MODE_STEREO : DMASND_MODE_MONO) |
+ DMASND_MODE_8BIT | mode;
- sound.bal = -sound.soft.speed;
+ sound.bal = -sound.soft.speed;
}
static int TTSetFormat(int format)
{
- /* TT sound DMA supports only 8bit modes */
+ /* TT sound DMA supports only 8bit modes */
- switch (format) {
+ switch (format) {
case AFMT_QUERY:
- return(sound.soft.format);
+ return(sound.soft.format);
case AFMT_MU_LAW:
case AFMT_A_LAW:
case AFMT_S8:
case AFMT_U8:
- break;
+ break;
default:
- format = AFMT_S8;
- }
+ format = AFMT_S8;
+ }
- sound.soft.format = format;
- sound.soft.size = 8;
- if (sound.minDev == SND_DEV_DSP) {
- sound.dsp.format = format;
- sound.dsp.size = 8;
- }
- TTInit();
+ sound.soft.format = format;
+ sound.soft.size = 8;
+ if (sound.minDev == SND_DEV_DSP) {
+ sound.dsp.format = format;
+ sound.dsp.size = 8;
+ }
+ TTInit();
- return(format);
+ return(format);
}
@@ -1740,12 +2321,12 @@
static int TTSetVolume(int volume)
{
- sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
- atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left));
- sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
- atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right));
- return(VOLUME_DB_TO_VOXWARE(sound.volume_left) |
- (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
+ sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
+ atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left));
+ sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
+ atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right));
+ return(VOLUME_DB_TO_VOXWARE(sound.volume_left) |
+ (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
}
@@ -1755,9 +2336,9 @@
static int TTSetGain(int gain)
{
- sound.gain = GAIN_VOXWARE_TO_DB(gain);
- atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain));
- return GAIN_DB_TO_VOXWARE(sound.gain);
+ sound.gain = GAIN_VOXWARE_TO_DB(gain);
+ atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain));
+ return GAIN_DB_TO_VOXWARE(sound.gain);
}
@@ -1769,133 +2350,133 @@
static void FalconSilence(void)
{
- /* stop playback, set sample rate 50kHz for PSG sound */
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
- tt_dmasnd.int_div = 0; /* STE compatible divider */
- tt_dmasnd.int_ctrl = 0x0;
- tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
- tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
- tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
- tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
+ /* stop playback, set sample rate 50kHz for PSG sound */
+ tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+ tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
+ tt_dmasnd.int_div = 0; /* STE compatible divider */
+ tt_dmasnd.int_ctrl = 0x0;
+ tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
+ tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
+ tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
+ tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
}
static void FalconInit(void)
{
- int divider, i, idx;
- const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
+ int divider, i, idx;
+ const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
- /* search a frequency that fits into the allowed error range */
+ /* search a frequency that fits into the allowed error range */
- idx = -1;
- for (i = 0; i < arraysize(freq); i++)
- /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
- * be playable without expanding, but that now a kernel runtime
- * option
- */
- if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
- idx = i;
- if (idx > -1) {
- sound.soft.speed = freq[idx];
- sound.trans = &transFalconNormal;
- } else
- sound.trans = &transFalconExpanding;
-
- FalconSilence();
- sound.hard = sound.soft;
+ idx = -1;
+ for (i = 0; i < arraysize(freq); i++)
+ /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
+ * be playable without expanding, but that now a kernel runtime
+ * option
+ */
+ if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
+ idx = i;
+ if (idx > -1) {
+ sound.soft.speed = freq[idx];
+ sound.trans = &transFalconNormal;
+ } else
+ sound.trans = &transFalconExpanding;
- if (sound.hard.size == 16) {
- /* the Falcon can play 16bit samples only in stereo */
- sound.hard.stereo = 1;
- }
+ FalconSilence();
+ sound.hard = sound.soft;
- if (sound.hard.speed > 49170) {
- /* we would need to squeeze the sound, but we won't do that */
- sound.hard.speed = 49170;
- divider = 1;
- sound.trans = &transFalconNormal;
- } else if (sound.hard.speed > 32780) {
- sound.hard.speed = 49170;
- divider = 1;
- } else if (sound.hard.speed > 24585) {
- sound.hard.speed = 32780;
- divider = 2;
- } else if (sound.hard.speed > 19668) {
- sound.hard.speed = 24585;
- divider = 3;
- } else if (sound.hard.speed > 16390) {
- sound.hard.speed = 19668;
- divider = 4;
- } else if (sound.hard.speed > 12292) {
- sound.hard.speed = 16390;
- divider = 5;
- } else if (sound.hard.speed > 9834) {
- sound.hard.speed = 12292;
- divider = 7;
- } else if (sound.hard.speed > 8195) {
- sound.hard.speed = 9834;
- divider = 9;
- } else {
- sound.hard.speed = 8195;
- divider = 11;
- }
- tt_dmasnd.int_div = divider;
-
- /* Setup Falcon sound DMA for playback */
- tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
- tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
- tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
- tt_dmasnd.cbar_dst = 0x0000;
- tt_dmasnd.rec_track_select = 0;
- tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
- tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
-
- tt_dmasnd.mode = (sound.hard.stereo ?
- DMASND_MODE_STEREO : DMASND_MODE_MONO) |
- ((sound.hard.size == 8) ?
- DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
- DMASND_MODE_6KHZ;
+ if (sound.hard.size == 16) {
+ /* the Falcon can play 16bit samples only in stereo */
+ sound.hard.stereo = 1;
+ }
+
+ if (sound.hard.speed > 49170) {
+ /* we would need to squeeze the sound, but we won't do that */
+ sound.hard.speed = 49170;
+ divider = 1;
+ sound.trans = &transFalconNormal;
+ } else if (sound.hard.speed > 32780) {
+ sound.hard.speed = 49170;
+ divider = 1;
+ } else if (sound.hard.speed > 24585) {
+ sound.hard.speed = 32780;
+ divider = 2;
+ } else if (sound.hard.speed > 19668) {
+ sound.hard.speed = 24585;
+ divider = 3;
+ } else if (sound.hard.speed > 16390) {
+ sound.hard.speed = 19668;
+ divider = 4;
+ } else if (sound.hard.speed > 12292) {
+ sound.hard.speed = 16390;
+ divider = 5;
+ } else if (sound.hard.speed > 9834) {
+ sound.hard.speed = 12292;
+ divider = 7;
+ } else if (sound.hard.speed > 8195) {
+ sound.hard.speed = 9834;
+ divider = 9;
+ } else {
+ sound.hard.speed = 8195;
+ divider = 11;
+ }
+ tt_dmasnd.int_div = divider;
+
+ /* Setup Falcon sound DMA for playback */
+ tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
+ tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
+ tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
+ tt_dmasnd.cbar_dst = 0x0000;
+ tt_dmasnd.rec_track_select = 0;
+ tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
+ tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
+
+ tt_dmasnd.mode = (sound.hard.stereo ?
+ DMASND_MODE_STEREO : DMASND_MODE_MONO) |
+ ((sound.hard.size == 8) ?
+ DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
+ DMASND_MODE_6KHZ;
- sound.bal = -sound.soft.speed;
+ sound.bal = -sound.soft.speed;
}
static int FalconSetFormat(int format)
{
- int size;
- /* Falcon sound DMA supports 8bit and 16bit modes */
+ int size;
+ /* Falcon sound DMA supports 8bit and 16bit modes */
- switch (format) {
+ switch (format) {
case AFMT_QUERY:
- return(sound.soft.format);
+ return(sound.soft.format);
case AFMT_MU_LAW:
case AFMT_A_LAW:
case AFMT_U8:
case AFMT_S8:
- size = 8;
- break;
+ size = 8;
+ break;
case AFMT_S16_BE:
case AFMT_U16_BE:
case AFMT_S16_LE:
case AFMT_U16_LE:
- size = 16;
- break;
+ size = 16;
+ break;
default: /* :-) */
- size = 8;
- format = AFMT_S8;
- }
-
- sound.soft.format = format;
- sound.soft.size = size;
- if (sound.minDev == SND_DEV_DSP) {
- sound.dsp.format = format;
- sound.dsp.size = sound.soft.size;
- }
+ size = 8;
+ format = AFMT_S8;
+ }
+
+ sound.soft.format = format;
+ sound.soft.size = size;
+ if (sound.minDev == SND_DEV_DSP) {
+ sound.dsp.format = format;
+ sound.dsp.size = sound.soft.size;
+ }
- FalconInit();
+ FalconInit();
- return(format);
+ return(format);
}
@@ -1909,164 +2490,164 @@
static int FalconSetVolume(int volume)
{
- sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
- sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
- tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4;
- return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
- VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
+ sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
+ sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
+ tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4;
+ return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
+ VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
}
static void ata_sq_play_next_frame(int index)
{
- char *start, *end;
+ char *start, *end;
- /* used by AtaPlay() if all doubts whether there really is something
- * to be played are already wiped out.
- */
- start = sq_block_address(sq.front);
- end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
- /* end might not be a legal virtual address. */
- DMASNDSetEnd(VTOP(end - 1) + 1);
- DMASNDSetBase(VTOP(start));
+ /* used by AtaPlay() if all doubts whether there really is something
+ * to be played are already wiped out.
+ */
+ start = sq_block_address(sq.front);
+ end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
+ /* end might not be a legal virtual address. */
+ DMASNDSetEnd(VTOP(end - 1) + 1);
+ DMASNDSetBase(VTOP(start));
/* Since only an even number of samples per frame can
- be played, we might lose one byte here. (TO DO) */
- sq.front = (sq.front+1) % sq.max_count;
- sq.playing++;
- tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
+ be played, we might lose one byte here. (TO DO) */
+ sq.front = (sq.front+1) % sq.max_count;
+ sq.playing++;
+ tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
}
static void AtaPlay(void)
{
- /* ++TeSche: Note that sq.playing is no longer just a flag but holds
- * the number of frames the DMA is currently programmed for instead,
- * may be 0, 1 (currently being played) or 2 (pre-programmed).
- *
- * Changes done to sq.count and sq.playing are a bit more subtle again
- * so now I must admit I also prefer disabling the irq here rather
- * than considering all possible situations. But the point is that
- * disabling the irq doesn't have any bad influence on this version of
- * the driver as we benefit from having pre-programmed the DMA
- * wherever possible: There's no need to reload the DMA at the exact
- * time of an interrupt but only at some time while the pre-programmed
- * frame is playing!
- */
- atari_disable_irq(IRQ_MFP_TIMA);
+ /* ++TeSche: Note that sq.playing is no longer just a flag but holds
+ * the number of frames the DMA is currently programmed for instead,
+ * may be 0, 1 (currently being played) or 2 (pre-programmed).
+ *
+ * Changes done to sq.count and sq.playing are a bit more subtle again
+ * so now I must admit I also prefer disabling the irq here rather
+ * than considering all possible situations. But the point is that
+ * disabling the irq doesn't have any bad influence on this version of
+ * the driver as we benefit from having pre-programmed the DMA
+ * wherever possible: There's no need to reload the DMA at the exact
+ * time of an interrupt but only at some time while the pre-programmed
+ * frame is playing!
+ */
+ atari_disable_irq(IRQ_MFP_TIMA);
- if (sq.playing == 2 || /* DMA is 'full' */
- sq.count <= 0) { /* nothing to do */
- atari_enable_irq(IRQ_MFP_TIMA);
- return;
- }
+ if (sq.playing == 2 || /* DMA is 'full' */
+ sq.count <= 0) { /* nothing to do */
+ atari_enable_irq(IRQ_MFP_TIMA);
+ return;
+ }
- if (sq.playing == 0) {
- /* looks like there's nothing 'in' the DMA yet, so try
- * to put two frames into it (at least one is available).
- */
- if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) {
- /* hmmm, the only existing frame is not
- * yet filled and we're not syncing?
- */
- atari_enable_irq(IRQ_MFP_TIMA);
- return;
- }
- ata_sq_play_next_frame(1);
- if (sq.count == 1) {
- /* no more frames */
- atari_enable_irq(IRQ_MFP_TIMA);
- return;
- }
- if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
- /* hmmm, there were two frames, but the second
- * one is not yet filled and we're not syncing?
- */
- atari_enable_irq(IRQ_MFP_TIMA);
- return;
- }
- ata_sq_play_next_frame(2);
- } else {
- /* there's already a frame being played so we may only stuff
- * one new into the DMA, but even if this may be the last
- * frame existing the previous one is still on sq.count.
- */
- if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
- /* hmmm, the only existing frame is not
- * yet filled and we're not syncing?
- */
- atari_enable_irq(IRQ_MFP_TIMA);
- return;
- }
- ata_sq_play_next_frame(2);
- }
- atari_enable_irq(IRQ_MFP_TIMA);
+ if (sq.playing == 0) {
+ /* looks like there's nothing 'in' the DMA yet, so try
+ * to put two frames into it (at least one is available).
+ */
+ if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) {
+ /* hmmm, the only existing frame is not
+ * yet filled and we're not syncing?
+ */
+ atari_enable_irq(IRQ_MFP_TIMA);
+ return;
+ }
+ ata_sq_play_next_frame(1);
+ if (sq.count == 1) {
+ /* no more frames */
+ atari_enable_irq(IRQ_MFP_TIMA);
+ return;
+ }
+ if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
+ /* hmmm, there were two frames, but the second
+ * one is not yet filled and we're not syncing?
+ */
+ atari_enable_irq(IRQ_MFP_TIMA);
+ return;
+ }
+ ata_sq_play_next_frame(2);
+ } else {
+ /* there's already a frame being played so we may only stuff
+ * one new into the DMA, but even if this may be the last
+ * frame existing the previous one is still on sq.count.
+ */
+ if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
+ /* hmmm, the only existing frame is not
+ * yet filled and we're not syncing?
+ */
+ atari_enable_irq(IRQ_MFP_TIMA);
+ return;
+ }
+ ata_sq_play_next_frame(2);
+ }
+ atari_enable_irq(IRQ_MFP_TIMA);
}
static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
#if 0
- /* ++TeSche: if you should want to test this... */
- static int cnt = 0;
- if (sq.playing == 2)
- if (++cnt == 10) {
- /* simulate losing an interrupt */
- cnt = 0;
- return;
- }
+ /* ++TeSche: if you should want to test this... */
+ static int cnt = 0;
+ if (sq.playing == 2)
+ if (++cnt == 10) {
+ /* simulate losing an interrupt */
+ cnt = 0;
+ return;
+ }
#endif
- if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) {
- /* ++TeSche: Falcon only: ignore first irq because it comes
- * immediately after starting a frame. after that, irqs come
- * (almost) like on the TT.
- */
- sq.ignore_int = 0;
- return;
- }
+ if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) {
+ /* ++TeSche: Falcon only: ignore first irq because it comes
+ * immediately after starting a frame. after that, irqs come
+ * (almost) like on the TT.
+ */
+ sq.ignore_int = 0;
+ return;
+ }
- if (!sq.playing) {
- /* playing was interrupted and sq_reset() has already cleared
- * the sq variables, so better don't do anything here.
- */
- WAKE_UP(sq.sync_queue);
- return;
- }
+ if (!sq.playing) {
+ /* playing was interrupted and sq_reset() has already cleared
+ * the sq variables, so better don't do anything here.
+ */
+ WAKE_UP(sq.sync_queue);
+ return;
+ }
- /* Probably ;) one frame is finished. Well, in fact it may be that a
- * pre-programmed one is also finished because there has been a long
- * delay in interrupt delivery and we've completely lost one, but
- * there's no way to detect such a situation. In such a case the last
- * frame will be played more than once and the situation will recover
- * as soon as the irq gets through.
- */
- sq.count--;
- sq.playing--;
+ /* Probably ;) one frame is finished. Well, in fact it may be that a
+ * pre-programmed one is also finished because there has been a long
+ * delay in interrupt delivery and we've completely lost one, but
+ * there's no way to detect such a situation. In such a case the last
+ * frame will be played more than once and the situation will recover
+ * as soon as the irq gets through.
+ */
+ sq.count--;
+ sq.playing--;
- if (!sq.playing) {
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- sq.ignore_int = 1;
- }
+ if (!sq.playing) {
+ tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+ sq.ignore_int = 1;
+ }
- WAKE_UP(sq.write_queue);
+ WAKE_UP(sq.write_queue);
/* At least one block of the queue is free now
- so wake up a writing process blocked because
- of a full queue. */
+ so wake up a writing process blocked because
+ of a full queue. */
- if ((sq.playing != 1) || (sq.count != 1))
- /* We must be a bit carefully here: sq.count indicates the
- * number of buffers used and not the number of frames to
- * be played. If sq.count==1 and sq.playing==1 that means
- * the only remaining frame was already programmed earlier
- * (and is currently running) so we mustn't call AtaPlay()
- * here, otherwise we'll play one frame too much.
- */
- AtaPlay();
+ if ((sq.playing != 1) || (sq.count != 1))
+ /* We must be a bit carefully here: sq.count indicates the
+ * number of buffers used and not the number of frames to
+ * be played. If sq.count==1 and sq.playing==1 that means
+ * the only remaining frame was already programmed earlier
+ * (and is currently running) so we mustn't call AtaPlay()
+ * here, otherwise we'll play one frame too much.
+ */
+ AtaPlay();
- if (!sq.playing) WAKE_UP(sq.sync_queue);
+ if (!sq.playing) WAKE_UP(sq.sync_queue);
/* We are not playing after AtaPlay(), so there
- is nothing to play any more. Wake up a process
- waiting for audio output to drain. */
+ is nothing to play any more. Wake up a process
+ waiting for audio output to drain. */
}
#endif /* CONFIG_ATARI */
@@ -2080,107 +2661,107 @@
static void *AmiAlloc(unsigned int size, int flags)
{
- return(amiga_chip_alloc((long)size));
+ return(amiga_chip_alloc((long)size));
}
static void AmiFree(void *obj, unsigned int size)
{
- amiga_chip_free (obj);
+ amiga_chip_free (obj);
}
static int AmiIrqInit(void)
{
- /* turn off DMA for audio channels */
- custom.dmacon = AMI_AUDIO_OFF;
+ /* turn off DMA for audio channels */
+ custom.dmacon = AMI_AUDIO_OFF;
- /* Register interrupt handler. */
- if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0,
- "DMA sound", ami_sq_interrupt))
- return(0);
- return(1);
+ /* Register interrupt handler. */
+ if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0,
+ "DMA sound", ami_sq_interrupt))
+ return(0);
+ return(1);
}
#ifdef MODULE
static void AmiIrqCleanUp(void)
{
- /* turn off DMA for audio channels */
- custom.dmacon = AMI_AUDIO_OFF;
- /* release the interrupt */
- free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt);
+ /* turn off DMA for audio channels */
+ custom.dmacon = AMI_AUDIO_OFF;
+ /* release the interrupt */
+ free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt);
}
#endif /* MODULE */
static void AmiSilence(void)
{
- /* turn off DMA for audio channels */
- custom.dmacon = AMI_AUDIO_OFF;
+ /* turn off DMA for audio channels */
+ custom.dmacon = AMI_AUDIO_OFF;
}
static void AmiInit(void)
{
- int period, i;
+ int period, i;
- AmiSilence();
+ AmiSilence();
- if (sound.soft.speed)
- period = amiga_colorclock/sound.soft.speed-1;
- else
- period = amiga_audio_min_period;
- sound.hard = sound.soft;
- sound.trans = &transAmiga;
-
- if (period < amiga_audio_min_period) {
- /* we would need to squeeze the sound, but we won't do that */
- period = amiga_audio_min_period;
- } else if (period > 65535) {
- period = 65535;
- }
- sound.hard.speed = amiga_colorclock/(period+1);
-
- for (i = 0; i < 4; i++)
- custom.aud[i].audper = period;
- amiga_audio_period = period;
+ if (sound.soft.speed)
+ period = amiga_colorclock/sound.soft.speed-1;
+ else
+ period = amiga_audio_min_period;
+ sound.hard = sound.soft;
+ sound.trans = &transAmiga;
+
+ if (period < amiga_audio_min_period) {
+ /* we would need to squeeze the sound, but we won't do that */
+ period = amiga_audio_min_period;
+ } else if (period > 65535) {
+ period = 65535;
+ }
+ sound.hard.speed = amiga_colorclock/(period+1);
+
+ for (i = 0; i < 4; i++)
+ custom.aud[i].audper = period;
+ amiga_audio_period = period;
- AmiSetTreble(50); /* recommended for newer amiga models */
+ AmiSetTreble(50); /* recommended for newer amiga models */
}
static int AmiSetFormat(int format)
{
- int size;
+ int size;
- /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
+ /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
- switch (format) {
+ switch (format) {
case AFMT_QUERY:
- return(sound.soft.format);
+ return(sound.soft.format);
case AFMT_MU_LAW:
case AFMT_A_LAW:
case AFMT_U8:
case AFMT_S8:
- size = 8;
- break;
+ size = 8;
+ break;
case AFMT_S16_BE:
case AFMT_U16_BE:
case AFMT_S16_LE:
case AFMT_U16_LE:
- size = 16;
- break;
+ size = 16;
+ break;
default: /* :-) */
- size = 8;
- format = AFMT_S8;
- }
-
- sound.soft.format = format;
- sound.soft.size = size;
- if (sound.minDev == SND_DEV_DSP) {
- sound.dsp.format = format;
- sound.dsp.size = sound.soft.size;
- }
- AmiInit();
+ size = 8;
+ format = AFMT_S8;
+ }
+
+ sound.soft.format = format;
+ sound.soft.size = size;
+ if (sound.minDev == SND_DEV_DSP) {
+ sound.dsp.format = format;
+ sound.dsp.size = sound.soft.size;
+ }
+ AmiInit();
- return(format);
+ return(format);
}
@@ -2190,22 +2771,22 @@
static int AmiSetVolume(int volume)
{
- sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
- custom.aud[0].audvol = sound.volume_left;
- sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
- custom.aud[1].audvol = sound.volume_right;
- return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
- (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
+ sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
+ custom.aud[0].audvol = sound.volume_left;
+ sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
+ custom.aud[1].audvol = sound.volume_right;
+ return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
+ (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
}
static int AmiSetTreble(int treble)
{
- sound.treble = treble;
- if (treble < 50)
- ciaa.pra &= ~0x02;
- else
- ciaa.pra |= 0x02;
- return(treble);
+ sound.treble = treble;
+ if (treble < 50)
+ ciaa.pra &= ~0x02;
+ else
+ ciaa.pra |= 0x02;
+ return(treble);
}
@@ -2216,164 +2797,550 @@
static void ami_sq_play_next_frame(int index)
{
- u_char *start, *ch0, *ch1, *ch2, *ch3;
- u_long size;
+ u_char *start, *ch0, *ch1, *ch2, *ch3;
+ u_long size;
- /* used by AmiPlay() if all doubts whether there really is something
- * to be played are already wiped out.
- */
- start = sq_block_address(sq.front);
- size = (sq.count == index ? sq.rear_size : sq.block_size)>>1;
-
- if (sound.hard.stereo) {
- ch0 = start;
- ch1 = start+sq.block_size_half;
- size >>= 1;
- } else {
- ch0 = start;
- ch1 = start;
- }
- if (sound.hard.size == 8) {
- custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
- custom.aud[0].audlen = size;
- custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
- custom.aud[1].audlen = size;
- custom.dmacon = AMI_AUDIO_8;
- } else {
- size >>= 1;
- custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
- custom.aud[0].audlen = size;
- custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
- custom.aud[1].audlen = size;
- if (sound.volume_left == 64 && sound.volume_right == 64) {
- /* We can play pseudo 14-bit only with the maximum volume */
- ch3 = ch0+sq.block_size_quarter;
- ch2 = ch1+sq.block_size_quarter;
- custom.aud[2].audvol = 1; /* we are being affected by the beeps */
- custom.aud[3].audvol = 1; /* restoring volume here helps a bit */
- custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
- custom.aud[2].audlen = size;
- custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
- custom.aud[3].audlen = size;
- custom.dmacon = AMI_AUDIO_14;
- } else
- custom.dmacon = AMI_AUDIO_8;
- }
- sq.front = (sq.front+1) % sq.max_count;
- sq.playing |= AMI_PLAY_LOADED;
+ /* used by AmiPlay() if all doubts whether there really is something
+ * to be played are already wiped out.
+ */
+ start = sq_block_address(sq.front);
+ size = (sq.count == index ? sq.rear_size : sq.block_size)>>1;
+
+ if (sound.hard.stereo) {
+ ch0 = start;
+ ch1 = start+sq.block_size_half;
+ size >>= 1;
+ } else {
+ ch0 = start;
+ ch1 = start;
+ }
+ if (sound.hard.size == 8) {
+ custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
+ custom.aud[0].audlen = size;
+ custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
+ custom.aud[1].audlen = size;
+ custom.dmacon = AMI_AUDIO_8;
+ } else {
+ size >>= 1;
+ custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
+ custom.aud[0].audlen = size;
+ custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
+ custom.aud[1].audlen = size;
+ if (sound.volume_left == 64 && sound.volume_right == 64) {
+ /* We can play pseudo 14-bit only with the maximum volume */
+ ch3 = ch0+sq.block_size_quarter;
+ ch2 = ch1+sq.block_size_quarter;
+ custom.aud[2].audvol = 1; /* we are being affected by the beeps */
+ custom.aud[3].audvol = 1; /* restoring volume here helps a bit */
+ custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
+ custom.aud[2].audlen = size;
+ custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
+ custom.aud[3].audlen = size;
+ custom.dmacon = AMI_AUDIO_14;
+ } else
+ custom.dmacon = AMI_AUDIO_8;
+ }
+ sq.front = (sq.front+1) % sq.max_count;
+ sq.playing |= AMI_PLAY_LOADED;
}
static void AmiPlay(void)
{
- int minframes = 1;
+ int minframes = 1;
- custom.intena = IF_AUD0;
+ custom.intena = IF_AUD0;
- if (sq.playing & AMI_PLAY_LOADED) {
- /* There's already a frame loaded */
- custom.intena = IF_SETCLR | IF_AUD0;
- return;
- }
+ if (sq.playing & AMI_PLAY_LOADED) {
+ /* There's already a frame loaded */
+ custom.intena = IF_SETCLR | IF_AUD0;
+ return;
+ }
- if (sq.playing & AMI_PLAY_PLAYING)
- /* Increase threshold: frame 1 is already being played */
- minframes = 2;
+ if (sq.playing & AMI_PLAY_PLAYING)
+ /* Increase threshold: frame 1 is already being played */
+ minframes = 2;
- if (sq.count < minframes) {
- /* Nothing to do */
- custom.intena = IF_SETCLR | IF_AUD0;
- return;
- }
+ if (sq.count < minframes) {
+ /* Nothing to do */
+ custom.intena = IF_SETCLR | IF_AUD0;
+ return;
+ }
- if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) {
- /* hmmm, the only existing frame is not
- * yet filled and we're not syncing?
- */
- custom.intena = IF_SETCLR | IF_AUD0;
- return;
- }
+ if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) {
+ /* hmmm, the only existing frame is not
+ * yet filled and we're not syncing?
+ */
+ custom.intena = IF_SETCLR | IF_AUD0;
+ return;
+ }
- ami_sq_play_next_frame(minframes);
+ ami_sq_play_next_frame(minframes);
- custom.intena = IF_SETCLR | IF_AUD0;
+ custom.intena = IF_SETCLR | IF_AUD0;
}
static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
- int minframes = 1;
+ int minframes = 1;
- if (!sq.playing) {
- /* Playing was interrupted and sq_reset() has already cleared
- * the sq variables, so better don't do anything here.
- */
- WAKE_UP(sq.sync_queue);
- return;
- }
+ if (!sq.playing) {
+ /* Playing was interrupted and sq_reset() has already cleared
+ * the sq variables, so better don't do anything here.
+ */
+ WAKE_UP(sq.sync_queue);
+ return;
+ }
- if (sq.playing & AMI_PLAY_PLAYING) {
- /* We've just finished a frame */
- sq.count--;
- WAKE_UP(sq.write_queue);
- }
+ if (sq.playing & AMI_PLAY_PLAYING) {
+ /* We've just finished a frame */
+ sq.count--;
+ WAKE_UP(sq.write_queue);
+ }
- if (sq.playing & AMI_PLAY_LOADED)
- /* Increase threshold: frame 1 is already being played */
- minframes = 2;
+ if (sq.playing & AMI_PLAY_LOADED)
+ /* Increase threshold: frame 1 is already being played */
+ minframes = 2;
- /* Shift the flags */
- sq.playing = (sq.playing<<1) & AMI_PLAY_MASK;
+ /* Shift the flags */
+ sq.playing = (sq.playing<<1) & AMI_PLAY_MASK;
- if (!sq.playing)
- /* No frame is playing, disable audio DMA */
- custom.dmacon = AMI_AUDIO_OFF;
+ if (!sq.playing)
+ /* No frame is playing, disable audio DMA */
+ custom.dmacon = AMI_AUDIO_OFF;
+
+ if (sq.count >= minframes)
+ /* Try to play the next frame */
+ AmiPlay();
- if (sq.count >= minframes)
- /* Try to play the next frame */
- AmiPlay();
-
- if (!sq.playing)
- /* Nothing to play anymore.
- Wake up a process waiting for audio output to drain. */
- WAKE_UP(sq.sync_queue);
+ if (!sq.playing)
+ /* Nothing to play anymore.
+ Wake up a process waiting for audio output to drain. */
+ WAKE_UP(sq.sync_queue);
}
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+
+/*
+ * PCI PowerMac, with AWACS and DBDMA.
+ */
+
+static void *PMacAlloc(unsigned int size, int flags)
+{
+ return kmalloc(size, flags);
+}
+
+static void PMacFree(void *ptr, unsigned int size)
+{
+ kfree(ptr);
+}
+
+static int PMacIrqInit(void)
+{
+ if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0)
+ || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0))
+ return 0;
+ return 1;
+}
+
+#ifdef MODULE
+static void PMacIrqCleanup(void)
+{
+ /* turn off output dma */
+ out_le32(&awacs_txdma->control, RUN<<16);
+ /* disable interrupts from awacs interface */
+ out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff);
+ free_irq(awacs_irq, pmac_awacs_intr);
+ free_irq(awacs_tx_irq, pmac_awacs_tx_intr);
+ kfree(awacs_tx_cmd_space);
+ if (beep_buf)
+ kfree(beep_buf);
+ kd_mksound = orig_mksound;
+}
+#endif /* MODULE */
+
+static void PMacSilence(void)
+{
+ /* turn off output dma */
+ out_le32(&awacs_txdma->control, RUN<<16);
+}
+
+static int awacs_freqs[8] = {
+ 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
+};
+
+static void PMacInit(void)
+{
+ int i, tolerance;
+
+ switch (sound.soft.format) {
+ case AFMT_S16_LE:
+ case AFMT_U16_LE:
+ sound.hard.format = AFMT_S16_LE;
+ break;
+ default:
+ sound.hard.format = AFMT_S16_BE;
+ break;
+ }
+ sound.hard.stereo = 1;
+ sound.hard.size = 16;
+
+ /*
+ * If we have a sample rate which is within catchRadius percent
+ * of the requested value, we don't have to expand the samples.
+ * Otherwise choose the next higher rate.
+ */
+ i = 8;
+ do {
+ tolerance = catchRadius * awacs_freqs[--i] / 100;
+ } while (sound.soft.speed > awacs_freqs[i] + tolerance && i > 0);
+ if (sound.soft.speed >= awacs_freqs[i] - tolerance)
+ sound.trans = &transAwacsNormal;
+ else
+ sound.trans = &transAwacsExpand;
+ sound.hard.speed = awacs_freqs[i];
+ awacs_rate_index = i;
+
+ PMacSilence();
+ out_le32(&awacs->control, MASK_IEPC | MASK_IEE | (i << 8) | 0x11);
+ awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3);
+ awacs_write(awacs_reg[1] | MASK_ADDR1);
+ out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
+
+ sound.bal = -sound.soft.speed;
+}
+
+static int PMacSetFormat(int format)
+{
+ int size;
+
+ switch (format) {
+ case AFMT_QUERY:
+ return sound.soft.format;
+ case AFMT_MU_LAW:
+ case AFMT_A_LAW:
+ case AFMT_U8:
+ case AFMT_S8:
+ size = 8;
+ break;
+ case AFMT_S16_BE:
+ case AFMT_U16_BE:
+ case AFMT_S16_LE:
+ case AFMT_U16_LE:
+ size = 16;
+ break;
+ default: /* :-) */
+ printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",
+ format);
+ size = 8;
+ format = AFMT_U8;
+ }
+
+ sound.soft.format = format;
+ sound.soft.size = size;
+ if (sound.minDev == SND_DEV_DSP) {
+ sound.dsp.format = format;
+ sound.dsp.size = size;
+ }
+
+ PMacInit();
+
+ return format;
+}
+
+#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99))
+#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15))
+
+static int awacs_get_volume(int reg, int lshift)
+{
+ int volume;
+
+ volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf);
+ volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8;
+ return volume;
+}
+
+static int awacs_volume_setter(int volume, int n, int mute, int lshift)
+{
+ int r1, rn;
+
+ if (mute && volume == 0) {
+ r1 = awacs_reg[1] | mute;
+ } else {
+ r1 = awacs_reg[1] & ~mute;
+ rn = awacs_reg[n] & ~(0xf | (0xf << lshift));
+ rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift);
+ rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf;
+ awacs_reg[n] = rn;
+ awacs_write((n << 12) | rn);
+ volume = awacs_get_volume(rn, lshift);
+ }
+ if (r1 != awacs_reg[1]) {
+ awacs_reg[1] = r1;
+ awacs_write(r1 | MASK_ADDR1);
+ }
+ return volume;
+}
+
+static int PMacSetVolume(int volume)
+{
+ return awacs_volume_setter(volume, 2, MASK_AMUTE, 6);
+}
+
+static void PMacPlay(void)
+{
+ volatile struct dbdma_cmd *cp;
+ int i, count;
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ if (beep_playing) {
+ /* sound takes precedence over beeps */
+ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+ out_le32(&awacs->control,
+ (in_le32(&awacs->control) & ~0x1f00)
+ || (awacs_rate_index << 8));
+ out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
+ beep_playing = 0;
+ }
+ i = sq.front + sq.playing;
+ if (i >= sq.max_count)
+ i -= sq.max_count;
+ while (sq.playing < 2 && sq.playing < sq.count) {
+ count = (sq.count == sq.playing + 1)? sq.rear_size: sq.block_size;
+ if (count < sq.block_size && !sq.syncing)
+ /* last block not yet filled, and we're not syncing. */
+ break;
+ cp = &awacs_tx_cmds[i];
+ st_le16(&cp->req_count, count);
+ st_le16(&cp->xfer_status, 0);
+ if (++i >= sq.max_count)
+ i = 0;
+ out_le16(&awacs_tx_cmds[i].command, DBDMA_STOP);
+ out_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS);
+ if (sq.playing == 0)
+ out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp));
+ out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
+ ++sq.playing;
+ }
+ restore_flags(flags);
+}
+
+static void
+pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs)
+{
+ int i = sq.front;
+ int stat;
+ volatile struct dbdma_cmd *cp;
+
+ while (sq.playing > 0) {
+ cp = &awacs_tx_cmds[i];
+ stat = ld_le16(&cp->xfer_status);
+ if ((stat & ACTIVE) == 0)
+ break; /* this frame is still going */
+ --sq.count;
+ --sq.playing;
+ if (++i >= sq.max_count)
+ i = 0;
+ }
+ if (i != sq.front)
+ WAKE_UP(sq.write_queue);
+ sq.front = i;
+
+ PMacPlay();
+
+ if (!sq.playing)
+ WAKE_UP(sq.sync_queue);
+}
+
+static void
+pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs)
+{
+ int ctrl = in_le32(&awacs->control);
+
+ if (ctrl & MASK_PORTCHG) {
+ /* do something when headphone is plugged/unplugged? */
+ }
+ if (ctrl & MASK_CNTLERR) {
+ printk(KERN_ERR "AWACS: error, status = %x\n",
+ in_le32(&awacs->codec_stat));
+ }
+ /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */
+ out_le32(&awacs->control, ctrl);
+}
+
+static void
+awacs_write(int val)
+{
+ while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD)
+ ; /* XXX should have timeout */
+ out_le32(&awacs->codec_ctrl, val);
+}
+
+static void awacs_nosound(unsigned long xx)
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ if (beep_playing) {
+ st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
+ beep_playing = 0;
+ }
+ restore_flags(flags);
+}
+
+static struct timer_list beep_timer = {
+ NULL, NULL, 0, 0, awacs_nosound
+};
+
+static void awacs_mksound(unsigned int hz, unsigned int ticks)
+{
+ unsigned long flags;
+ int srate = awacs_freqs[BEEP_SPEED];
+ int period, ncycles, nsamples;
+ int i, j, f;
+ short *p;
+ static int beep_hz_cache;
+ static int beep_nsamples_cache;
+ static int beep_volume_cache;
+
+ if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
+#if 1
+ /* this is a hack for broken X server code */
+ hz = 750;
+ ticks = 12;
+#else
+ /* cancel beep currently playing */
+ awacs_nosound(0);
+ return;
+#endif
+ }
+ save_flags(flags); cli();
+ del_timer(&beep_timer);
+ if (ticks) {
+ beep_timer.expires = jiffies + ticks;
+ add_timer(&beep_timer);
+ }
+ if (beep_playing || sq.playing || beep_buf == NULL) {
+ restore_flags(flags);
+ return; /* too hard, sorry :-( */
+ }
+ beep_playing = 1;
+ st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
+ restore_flags(flags);
+
+ if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {
+ nsamples = beep_nsamples_cache;
+ } else {
+ period = srate * 256 / hz; /* fixed point */
+ ncycles = BEEP_BUFLEN * 256 / period;
+ nsamples = (period * ncycles) >> 8;
+ f = ncycles * 65536 / nsamples;
+ j = 0;
+ p = beep_buf;
+ for (i = 0; i < nsamples; ++i, p += 2) {
+ p[0] = p[1] = beep_wform[j >> 8] * beep_volume;
+ j = (j + f) & 0xffff;
+ }
+ beep_hz_cache = hz;
+ beep_volume_cache = beep_volume;
+ beep_nsamples_cache = nsamples;
+ }
+
+ st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
+ st_le16(&beep_dbdma_cmd->xfer_status, 0);
+ st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
+ st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
+
+ save_flags(flags); cli();
+ if (beep_playing) { /* i.e. haven't been terminated already */
+ out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
+ out_le32(&awacs->control,
+ (in_le32(&awacs->control) & ~0x1f00)
+ | (BEEP_SPEED << 8));
+ out_le32(&awacs->byteswap, 0);
+ out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
+ out_le32(&awacs_txdma->control, RUN | (RUN << 16));
+ }
+ restore_flags(flags);
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Save state when going to sleep, restore it afterwards.
+ */
+static int awacs_sleep_notify(struct notifier_block *this,
+ unsigned long code, void *x)
+{
+ switch (code) {
+ case PBOOK_SLEEP:
+ /* XXX we should stop any dma in progress when going to sleep
+ and restart it when we wake. */
+ PMacSilence();
+ break;
+ case PBOOK_WAKE:
+ out_le32(&awacs->control, MASK_IEPC | MASK_IEE |
+ (awacs_rate_index << 8) | 0x11);
+ awacs_write(awacs_reg[0] | MASK_ADDR0);
+ awacs_write(awacs_reg[1] | MASK_ADDR1);
+ awacs_write(awacs_reg[2] | MASK_ADDR2);
+ awacs_write(awacs_reg[4] | MASK_ADDR4);
+ out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
+ }
+ return NOTIFY_DONE;
+}
+#endif /* CONFIG_PMAC_PBOOK */
+
+#endif /* CONFIG_PMAC */
/*** Machine definitions *****************************************************/
#ifdef CONFIG_ATARI
static MACHINE machTT = {
- DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit,
+ DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit,
#ifdef MODULE
- AtaIrqCleanUp,
+ AtaIrqCleanUp,
#endif /* MODULE */
- TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble,
- TTSetGain,
- AtaPlay
+ TTInit, TTSilence, TTSetFormat, TTSetVolume,
+ AtaSetBass, AtaSetTreble, TTSetGain,
+ AtaPlay
};
static MACHINE machFalcon = {
- DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit,
+ DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit,
#ifdef MODULE
- AtaIrqCleanUp,
+ AtaIrqCleanUp,
#endif /* MODULE */
- FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass,
- AtaSetTreble, NULL, AtaPlay
+ FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume,
+ AtaSetBass, AtaSetTreble, NULL,
+ AtaPlay
};
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
static MACHINE machAmiga = {
- DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit,
+ DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit,
+#ifdef MODULE
+ AmiIrqCleanUp,
+#endif /* MODULE */
+ AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume,
+ NULL, AmiSetTreble, NULL,
+ AmiPlay
+};
+#endif /* CONFIG_AMIGA */
+
+#ifdef CONFIG_PMAC
+static MACHINE machPMac = {
+ DMASND_AWACS, PMacAlloc, PMacFree, PMacIrqInit,
#ifdef MODULE
- AmiIrqCleanUp,
+ PMacIrqCleanup,
#endif /* MODULE */
- AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble,
- NULL,
- AmiPlay
+ PMacInit, PMacSilence, PMacSetFormat, PMacSetVolume,
+ NULL, NULL, NULL, /* bass, treble, gain */
+ PMacPlay
};
#endif /* CONFIG_AMIGA */
@@ -2383,78 +3350,79 @@
static void sound_silence(void)
{
- /* update hardware settings one more */
- (*sound.mach.init)();
+ /* update hardware settings one more */
+ (*sound.mach.init)();
- (*sound.mach.silence)();
+ (*sound.mach.silence)();
}
static void sound_init(void)
{
- (*sound.mach.init)();
+ (*sound.mach.init)();
}
static int sound_set_format(int format)
{
- return(*sound.mach.setFormat)(format);
+ return(*sound.mach.setFormat)(format);
}
static int sound_set_speed(int speed)
{
- if (speed < 0)
- return(sound.soft.speed);
+ if (speed < 0)
+ return(sound.soft.speed);
- sound.soft.speed = speed;
- (*sound.mach.init)();
- if (sound.minDev == SND_DEV_DSP)
- sound.dsp.speed = sound.soft.speed;
+ sound.soft.speed = speed;
+ (*sound.mach.init)();
+ if (sound.minDev == SND_DEV_DSP)
+ sound.dsp.speed = sound.soft.speed;
- return(sound.soft.speed);
+ return(sound.soft.speed);
}
static int sound_set_stereo(int stereo)
{
- if (stereo < 0)
- return(sound.soft.stereo);
+ if (stereo < 0)
+ return(sound.soft.stereo);
- stereo = !!stereo; /* should be 0 or 1 now */
+ stereo = !!stereo; /* should be 0 or 1 now */
- sound.soft.stereo = stereo;
- if (sound.minDev == SND_DEV_DSP)
- sound.dsp.stereo = stereo;
- (*sound.mach.init)();
+ sound.soft.stereo = stereo;
+ if (sound.minDev == SND_DEV_DSP)
+ sound.dsp.stereo = stereo;
+ (*sound.mach.init)();
- return(stereo);
+ return(stereo);
}
static int sound_set_volume(int volume)
{
- return(*sound.mach.setVolume)(volume);
+ return(*sound.mach.setVolume)(volume);
}
#ifdef CONFIG_ATARI
static int sound_set_bass(int bass)
{
- return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
+ return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
}
static int sound_set_gain(int gain)
{
- return sound.mach.setGain ? sound.mach.setGain(gain) : 100;
+ return sound.mach.setGain ? sound.mach.setGain(gain) : 100;
}
#endif /* CONFIG_ATARI */
-
+#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA)
static int sound_set_treble(int treble)
{
- return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50);
+ return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50);
}
+#endif /* CONFIG_ATARI || CONFIG_AMIGA */
static long sound_copy_translate(const u_char *userPtr,
@@ -2462,38 +3430,38 @@
u_char frame[], long *frameUsed,
long frameLeft)
{
- long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL;
+ long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL;
- switch (sound.soft.format) {
+ switch (sound.soft.format) {
case AFMT_MU_LAW:
- ct_func = sound.trans->ct_ulaw;
- break;
+ ct_func = sound.trans->ct_ulaw;
+ break;
case AFMT_A_LAW:
- ct_func = sound.trans->ct_alaw;
- break;
+ ct_func = sound.trans->ct_alaw;
+ break;
case AFMT_S8:
- ct_func = sound.trans->ct_s8;
- break;
+ ct_func = sound.trans->ct_s8;
+ break;
case AFMT_U8:
- ct_func = sound.trans->ct_u8;
- break;
+ ct_func = sound.trans->ct_u8;
+ break;
case AFMT_S16_BE:
- ct_func = sound.trans->ct_s16be;
- break;
+ ct_func = sound.trans->ct_s16be;
+ break;
case AFMT_U16_BE:
- ct_func = sound.trans->ct_u16be;
- break;
+ ct_func = sound.trans->ct_u16be;
+ break;
case AFMT_S16_LE:
- ct_func = sound.trans->ct_s16le;
- break;
+ ct_func = sound.trans->ct_s16le;
+ break;
case AFMT_U16_LE:
- ct_func = sound.trans->ct_u16le;
- break;
- }
- if (ct_func)
- return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
- else
- return(0);
+ ct_func = sound.trans->ct_u16le;
+ break;
+ }
+ if (ct_func)
+ return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
+ else
+ return(0);
}
@@ -2509,201 +3477,308 @@
static void mixer_init(void)
{
- mixer.busy = 0;
- sound.treble = 0;
- sound.bass = 0;
- switch (sound.mach.type) {
+ mixer.busy = 0;
+ sound.treble = 0;
+ sound.bass = 0;
+ switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_TT:
- atari_microwire_cmd(MW_LM1992_VOLUME(0));
- sound.volume_left = 0;
- atari_microwire_cmd(MW_LM1992_BALLEFT(0));
- sound.volume_right = 0;
- atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
- atari_microwire_cmd(MW_LM1992_TREBLE(0));
- atari_microwire_cmd(MW_LM1992_BASS(0));
- break;
+ atari_microwire_cmd(MW_LM1992_VOLUME(0));
+ sound.volume_left = 0;
+ atari_microwire_cmd(MW_LM1992_BALLEFT(0));
+ sound.volume_right = 0;
+ atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
+ atari_microwire_cmd(MW_LM1992_TREBLE(0));
+ atari_microwire_cmd(MW_LM1992_BASS(0));
+ break;
case DMASND_FALCON:
- sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
- sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
- break;
+ sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
+ sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
- sound.volume_left = 64;
- sound.volume_right = 64;
- custom.aud[0].audvol = sound.volume_left;
- custom.aud[3].audvol = 1; /* For pseudo 14bit */
- custom.aud[1].audvol = sound.volume_right;
- custom.aud[2].audvol = 1; /* For pseudo 14bit */
- sound.treble = 50;
- break;
+ sound.volume_left = 64;
+ sound.volume_right = 64;
+ custom.aud[0].audvol = sound.volume_left;
+ custom.aud[3].audvol = 1; /* For pseudo 14bit */
+ custom.aud[1].audvol = sound.volume_right;
+ custom.aud[2].audvol = 1; /* For pseudo 14bit */
+ sound.treble = 50;
+ break;
#endif /* CONFIG_AMIGA */
- }
+ }
}
static int mixer_open(int open_mode)
{
- if (mixer.busy)
- return(-EBUSY);
- mixer.busy = 1;
- return(0);
+ mixer.busy = 1;
+ return(0);
}
static int mixer_release(void)
{
- mixer.busy = 0;
- return(0);
+ mixer.busy = 0;
+ return(0);
}
static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
{
- int data;
- switch (sound.mach.type) {
+ int data;
+ switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_FALCON:
- switch (cmd) {
+ switch (cmd) {
case SOUND_MIXER_READ_DEVMASK:
- return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
+ return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
case SOUND_MIXER_READ_RECMASK:
- return(IOCTL_OUT(arg, SOUND_MASK_MIC));
+ return(IOCTL_OUT(arg, SOUND_MASK_MIC));
case SOUND_MIXER_READ_STEREODEVS:
- return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
+ return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
case SOUND_MIXER_READ_CAPS:
- return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
+ return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
case SOUND_MIXER_READ_VOLUME:
- return(IOCTL_OUT(arg,
- VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
- VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
+ return(IOCTL_OUT(arg,
+ VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
+ VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
case SOUND_MIXER_WRITE_MIC:
- IOCTL_IN(arg, data);
- tt_dmasnd.input_gain =
- RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
- RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
- /* fall thru, return set value */
+ IOCTL_IN(arg, data);
+ tt_dmasnd.input_gain =
+ RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
+ RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
+ /* fall thru, return set value */
case SOUND_MIXER_READ_MIC:
- return(IOCTL_OUT(arg,
- RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
- RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
+ return(IOCTL_OUT(arg,
+ RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
+ RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
case SOUND_MIXER_READ_SPEAKER:
- {
- int porta;
- cli();
- sound_ym.rd_data_reg_sel = 14;
- porta = sound_ym.rd_data_reg_sel;
- sti();
- return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
- }
+ {
+ int porta;
+ cli();
+ sound_ym.rd_data_reg_sel = 14;
+ porta = sound_ym.rd_data_reg_sel;
+ sti();
+ return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+ }
case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_volume(data)));
- case SOUND_MIXER_WRITE_SPEAKER:
- {
- int porta;
IOCTL_IN(arg, data);
- cli();
- sound_ym.rd_data_reg_sel = 14;
- porta = (sound_ym.rd_data_reg_sel & ~0x40) |
- (data < 50 ? 0x40 : 0);
- sound_ym.wd_data = porta;
- sti();
- return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
- }
- }
- break;
+ return(IOCTL_OUT(arg, sound_set_volume(data)));
+ case SOUND_MIXER_WRITE_SPEAKER:
+ {
+ int porta;
+ IOCTL_IN(arg, data);
+ cli();
+ sound_ym.rd_data_reg_sel = 14;
+ porta = (sound_ym.rd_data_reg_sel & ~0x40) |
+ (data < 50 ? 0x40 : 0);
+ sound_ym.wd_data = porta;
+ sti();
+ return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+ }
+ }
+ break;
case DMASND_TT:
- switch (cmd) {
+ switch (cmd) {
case SOUND_MIXER_READ_DEVMASK:
- return(IOCTL_OUT(arg,
- SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
- (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)));
+ return(IOCTL_OUT(arg,
+ SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
+ (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)));
case SOUND_MIXER_READ_RECMASK:
- return(IOCTL_OUT(arg, 0));
+ return(IOCTL_OUT(arg, 0));
case SOUND_MIXER_READ_STEREODEVS:
- return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
+ return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
case SOUND_MIXER_READ_VOLUME:
- return(IOCTL_OUT(arg,
- VOLUME_DB_TO_VOXWARE(sound.volume_left) |
- (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
+ return(IOCTL_OUT(arg,
+ VOLUME_DB_TO_VOXWARE(sound.volume_left) |
+ (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
case SOUND_MIXER_READ_BASS:
- return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
+ return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
case SOUND_MIXER_READ_TREBLE:
- return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
+ return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
case SOUND_MIXER_READ_OGAIN:
- return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain)));
+ return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain)));
case SOUND_MIXER_READ_SPEAKER:
- {
- int porta;
- if (MACH_IS_TT) {
- cli();
- sound_ym.rd_data_reg_sel = 14;
- porta = sound_ym.rd_data_reg_sel;
- sti();
- return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
- } else
- return(-EINVAL);
- }
+ {
+ int porta;
+ if (MACH_IS_TT) {
+ cli();
+ sound_ym.rd_data_reg_sel = 14;
+ porta = sound_ym.rd_data_reg_sel;
+ sti();
+ return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+ } else
+ return(-EINVAL);
+ }
case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_volume(data)));
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_volume(data)));
case SOUND_MIXER_WRITE_BASS:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_bass(data)));
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_bass(data)));
case SOUND_MIXER_WRITE_TREBLE:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_treble(data)));
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_treble(data)));
case SOUND_MIXER_WRITE_OGAIN:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_gain(data)));
- case SOUND_MIXER_WRITE_SPEAKER:
- if (MACH_IS_TT) {
- int porta;
IOCTL_IN(arg, data);
- cli();
- sound_ym.rd_data_reg_sel = 14;
- porta = (sound_ym.rd_data_reg_sel & ~0x40) |
- (data < 50 ? 0x40 : 0);
- sound_ym.wd_data = porta;
- sti();
- return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
- } else
- return(-EINVAL);
- }
- break;
+ return(IOCTL_OUT(arg, sound_set_gain(data)));
+ case SOUND_MIXER_WRITE_SPEAKER:
+ if (MACH_IS_TT) {
+ int porta;
+ IOCTL_IN(arg, data);
+ cli();
+ sound_ym.rd_data_reg_sel = 14;
+ porta = (sound_ym.rd_data_reg_sel & ~0x40) |
+ (data < 50 ? 0x40 : 0);
+ sound_ym.wd_data = porta;
+ sti();
+ return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+ } else
+ return(-EINVAL);
+ }
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
- switch (cmd) {
+ switch (cmd) {
case SOUND_MIXER_READ_DEVMASK:
- return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
+ return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
case SOUND_MIXER_READ_RECMASK:
- return(IOCTL_OUT(arg, 0));
+ return(IOCTL_OUT(arg, 0));
case SOUND_MIXER_READ_STEREODEVS:
- return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
+ return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
case SOUND_MIXER_READ_VOLUME:
- return(IOCTL_OUT(arg,
- VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
- VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
+ return(IOCTL_OUT(arg,
+ VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
+ VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_volume(data)));
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_volume(data)));
case SOUND_MIXER_READ_TREBLE:
- return(IOCTL_OUT(arg, sound.treble));
+ return(IOCTL_OUT(arg, sound.treble));
case SOUND_MIXER_WRITE_TREBLE:
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_treble(data)));
- }
- break;
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_treble(data)));
+ }
+ break;
#endif /* CONFIG_AMIGA */
- }
- return(-EINVAL);
+#ifdef CONFIG_PMAC
+ case DMASND_AWACS:
+ switch (cmd) {
+ case SOUND_MIXER_READ_DEVMASK:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+ | SOUND_MASK_LINE | SOUND_MASK_MIC
+ | SOUND_MASK_CD | SOUND_MASK_RECLEV
+ | SOUND_MASK_ALTPCM;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECMASK:
+ data = SOUND_MASK_LINE | SOUND_MASK_MIC
+ | SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECSRC:
+ data = 0;
+ if (awacs_reg[0] & MASK_MUX_AUDIN)
+ data |= SOUND_MASK_LINE;
+ if (awacs_reg[0] & MASK_MUX_MIC)
+ data |= SOUND_MASK_MIC;
+ if (awacs_reg[0] & MASK_MUX_CD)
+ data |= SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECSRC:
+ IOCTL_IN(arg, data);
+ data &= (SOUND_MASK_LINE
+ | SOUND_MASK_MIC | SOUND_MASK_CD);
+ awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
+ | MASK_MUX_AUDIN);
+ if (data & SOUND_MASK_LINE)
+ awacs_reg[0] |= MASK_MUX_AUDIN;
+ if (data & SOUND_MASK_MIC)
+ awacs_reg[0] |= MASK_MUX_MIC;
+ if (data & SOUND_MASK_CD)
+ awacs_reg[0] |= MASK_MUX_CD;
+ awacs_write(awacs_reg[0] | MASK_ADDR0);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_STEREODEVS:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+ | SOUND_MASK_RECLEV;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_CAPS:
+ return IOCTL_OUT(arg, 0);
+ case SOUND_MIXER_READ_VOLUME:
+ data = (awacs_reg[1] & MASK_AMUTE)? 0:
+ awacs_get_volume(awacs_reg[2], 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_VOLUME:
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_volume(data));
+ case SOUND_MIXER_READ_SPEAKER:
+ data = (awacs_reg[1] & MASK_CMUTE)? 0:
+ awacs_get_volume(awacs_reg[4], 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_SPEAKER:
+ IOCTL_IN(arg, data);
+ data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
+ IOCTL_IN(arg, data);
+ beep_volume = data & 0xff;
+ /* fall through */
+ case SOUND_MIXER_READ_ALTPCM:
+ return IOCTL_OUT(arg, beep_volume);
+ case SOUND_MIXER_WRITE_LINE:
+ IOCTL_IN(arg, data);
+ awacs_reg[0] &= ~MASK_MUX_AUDIN;
+ if ((data & 0xff) >= 50)
+ awacs_reg[0] |= MASK_MUX_AUDIN;
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_LINE:
+ data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_MIC:
+ IOCTL_IN(arg, data);
+ data &= 0xff;
+ awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE);
+ if (data >= 25) {
+ awacs_reg[0] |= MASK_MUX_MIC;
+ if (data >= 75)
+ awacs_reg[0] |= MASK_GAINLINE;
+ }
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_MIC:
+ data = (awacs_reg[0] & MASK_MUX_MIC)?
+ (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_CD:
+ IOCTL_IN(arg, data);
+ awacs_reg[0] &= ~MASK_MUX_CD;
+ if ((data & 0xff) >= 50)
+ awacs_reg[0] |= MASK_MUX_CD;
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_CD:
+ data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECLEV:
+ IOCTL_IN(arg, data);
+ data = awacs_volume_setter(data, 0, 0, 4);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECLEV:
+ data = awacs_get_volume(awacs_reg[0], 4);
+ return IOCTL_OUT(arg, data);
+ }
+ break;
+#endif
+ }
+
+ return(-EINVAL);
}
@@ -2715,62 +3790,88 @@
static void sq_init(int numBufs, int bufSize, char **buffers)
{
- sq.max_count = numBufs;
- sq.block_size = bufSize;
- sq.buffers = buffers;
-
- sq.front = sq.count = 0;
- sq.rear = -1;
- sq.write_queue = sq.open_queue = sq.sync_queue = 0;
- sq.busy = 0;
- sq.syncing = 0;
+#ifdef CONFIG_PMAC
+ int i;
+ volatile struct dbdma_cmd *cp;
+#endif /* CONFIG_PMAC */
+
+ sq.max_count = numBufs;
+ sq.max_active = numBufs;
+ sq.block_size = bufSize;
+ sq.buffers = buffers;
+
+ sq.front = sq.count = 0;
+ sq.rear = -1;
+ sq.write_queue = sq.open_queue = sq.sync_queue = 0;
+ sq.busy = 0;
+ sq.syncing = 0;
- sq.playing = 0;
+ sq.playing = 0;
#ifdef CONFIG_ATARI
- sq.ignore_int = 0;
+ sq.ignore_int = 0;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
- sq.block_size_half = sq.block_size>>1;
- sq.block_size_quarter = sq.block_size_half>>1;
+ sq.block_size_half = sq.block_size>>1;
+ sq.block_size_quarter = sq.block_size_half>>1;
#endif /* CONFIG_AMIGA */
+#ifdef CONFIG_PMAC
+ cp = awacs_tx_cmds;
+ memset((void *) cp, 0, (numBufs + 1) * sizeof(struct dbdma_cmd));
+ for (i = 0; i < numBufs; ++i, ++cp) {
+ st_le32(&cp->phy_addr, virt_to_bus(buffers[i]));
+ }
+ st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
+ st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds));
+ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
+ out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds));
+#endif /* CONFIG_PMAC */
+}
+
+static void
+init_settings(void)
+{
+ /* whatever you like as startup mode for /dev/dsp,
+ * (/dev/audio hasn't got a startup mode). note that
+ * once changed a new open() will *not* restore these!
+ */
+ sound.dsp.format = AFMT_U8;
+ sound.dsp.stereo = 0;
+ sound.dsp.size = 8;
- sound_silence();
-
- /* whatever you like as startup mode for /dev/dsp,
- * (/dev/audio hasn't got a startup mode). note that
- * once changed a new open() will *not* restore these!
- */
- sound.dsp.format = AFMT_S8;
- sound.dsp.stereo = 0;
- sound.dsp.size = 8;
-
- /* set minimum rate possible without expanding */
- switch (sound.mach.type) {
+ /* set minimum rate possible without expanding */
+ switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_TT:
- sound.dsp.speed = 6258;
- break;
+ sound.dsp.speed = 6258;
+ break;
case DMASND_FALCON:
- sound.dsp.speed = 8195;
- break;
+ sound.dsp.speed = 8195;
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
- sound.dsp.speed = 8000;
- break;
+ sound.dsp.speed = 8000;
+ break;
#endif /* CONFIG_AMIGA */
- }
+#ifdef CONFIG_PMAC
+ case DMASND_AWACS:
+ sound.dsp.speed = 8000;
+ break;
+#endif /* CONFIG_PMAC */
+ }
+
+ /* before the first open to /dev/dsp this wouldn't be set */
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
- /* before the first open to /dev/dsp this wouldn't be set */
- sound.soft = sound.dsp;
- sound.hard = sound.dsp;
+ sound_silence();
}
static void sq_play(void)
{
- (*sound.mach.play)();
+ (*sound.mach.play)();
}
@@ -2778,133 +3879,139 @@
static long sq_write(const char *src, unsigned long uLeft)
{
- long uWritten = 0;
- u_char *dest;
- long uUsed, bUsed, bLeft;
-
- /* ++TeSche: Is something like this necessary?
- * Hey, that's an honest question! Or does any other part of the
- * filesystem already checks this situation? I really don't know.
- */
- if (uLeft == 0)
- return(0);
+ long uWritten = 0;
+ u_char *dest;
+ long uUsed, bUsed, bLeft;
+
+ /* ++TeSche: Is something like this necessary?
+ * Hey, that's an honest question! Or does any other part of the
+ * filesystem already checks this situation? I really don't know.
+ */
+ if (uLeft == 0)
+ return(0);
- /* The interrupt doesn't start to play the last, incomplete frame.
- * Thus we can append to it without disabling the interrupts! (Note
- * also that sq.rear isn't affected by the interrupt.)
- */
-
- if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
- dest = sq_block_address(sq.rear);
- bUsed = sq.rear_size;
- uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
- src += uUsed;
- uWritten += uUsed;
- uLeft -= uUsed;
- sq.rear_size = bUsed;
- }
-
- do {
- while (sq.count == sq.max_count) {
- sq_play();
- if (NON_BLOCKING(sq.open_mode))
- return(uWritten > 0 ? uWritten : -EAGAIN);
- SLEEP(sq.write_queue, ONE_SECOND);
- if (SIGNAL_RECEIVED)
- return(uWritten > 0 ? uWritten : -EINTR);
- }
-
- /* Here, we can avoid disabling the interrupt by first
- * copying and translating the data, and then updating
- * the sq variables. Until this is done, the interrupt
- * won't see the new frame and we can work on it
- * undisturbed.
+ /* The interrupt doesn't start to play the last, incomplete frame.
+ * Thus we can append to it without disabling the interrupts! (Note
+ * also that sq.rear isn't affected by the interrupt.)
*/
- dest = sq_block_address((sq.rear+1) % sq.max_count);
- bUsed = 0;
- bLeft = sq.block_size;
- uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
- src += uUsed;
- uWritten += uUsed;
- uLeft -= uUsed;
- if (bUsed) {
- sq.rear = (sq.rear+1) % sq.max_count;
- sq.rear_size = bUsed;
- sq.count++;
- }
- } while (bUsed); /* uUsed may have been 0 */
+ if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
+ dest = sq_block_address(sq.rear);
+ bUsed = sq.rear_size;
+ uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
+ if (uUsed <= 0)
+ return uUsed;
+ src += uUsed;
+ uWritten += uUsed;
+ uLeft -= uUsed;
+ sq.rear_size = bUsed;
+ }
+
+ do {
+ while (sq.count == sq.max_active) {
+ sq_play();
+ if (NON_BLOCKING(sq.open_mode))
+ return(uWritten > 0 ? uWritten : -EAGAIN);
+ SLEEP(sq.write_queue, ONE_SECOND);
+ if (SIGNAL_RECEIVED)
+ return(uWritten > 0 ? uWritten : -EINTR);
+ }
- sq_play();
+ /* Here, we can avoid disabling the interrupt by first
+ * copying and translating the data, and then updating
+ * the sq variables. Until this is done, the interrupt
+ * won't see the new frame and we can work on it
+ * undisturbed.
+ */
+
+ dest = sq_block_address((sq.rear+1) % sq.max_count);
+ bUsed = 0;
+ bLeft = sq.block_size;
+ uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
+ if (uUsed <= 0)
+ break;
+ src += uUsed;
+ uWritten += uUsed;
+ uLeft -= uUsed;
+ if (bUsed) {
+ sq.rear = (sq.rear+1) % sq.max_count;
+ sq.rear_size = bUsed;
+ sq.count++;
+ }
+ } while (bUsed); /* uUsed may have been 0 */
- return(uWritten);
+ sq_play();
+
+ return(uUsed < 0? uUsed: uWritten);
}
static int sq_open(int open_mode)
{
- if (sq.busy) {
- if (NON_BLOCKING(open_mode))
- return(-EBUSY);
- while (sq.busy) {
- SLEEP(sq.open_queue, ONE_SECOND);
- if (SIGNAL_RECEIVED)
- return(-EINTR);
- }
- }
- sq.open_mode = open_mode;
- sq.busy = 1;
+ if (sq.busy) {
+ if (NON_BLOCKING(open_mode))
+ return(-EBUSY);
+ while (sq.busy) {
+ SLEEP(sq.open_queue, ONE_SECOND);
+ if (SIGNAL_RECEIVED)
+ return(-EINTR);
+ }
+ }
+ sq_init(numBufs, bufSize << 10, sound_buffers);
+ sq.open_mode = open_mode;
+ sq.busy = 1;
#ifdef CONFIG_ATARI
- sq.ignore_int = 1;
+ sq.ignore_int = 1;
#endif /* CONFIG_ATARI */
- return(0);
+ return(0);
}
static void sq_reset(void)
{
- sound_silence();
- sq.playing = 0;
- sq.count = 0;
- sq.front = (sq.rear+1) % sq.max_count;
+ sound_silence();
+ sq.playing = 0;
+ sq.count = 0;
+ sq.front = (sq.rear+1) % sq.max_count;
}
static int sq_sync(void)
{
- int rc = 0;
+ int rc = 0;
- sq.syncing = 1;
- sq_play(); /* there may be an incomplete frame waiting */
+ sq.syncing = 1;
+ sq_play(); /* there may be an incomplete frame waiting */
- while (sq.playing) {
- SLEEP(sq.sync_queue, ONE_SECOND);
- if (SIGNAL_RECEIVED) {
- /* While waiting for audio output to drain, an interrupt occurred.
- Stop audio output immediately and clear the queue. */
- sq_reset();
- rc = -EINTR;
- break;
+ while (sq.playing) {
+ SLEEP(sq.sync_queue, ONE_SECOND);
+ if (SIGNAL_RECEIVED) {
+ /* While waiting for audio output to drain, an
+ * interrupt occurred. Stop audio output immediately
+ * and clear the queue. */
+ sq_reset();
+ rc = -EINTR;
+ break;
+ }
}
- }
- sq.syncing = 0;
- return(rc);
+ sq.syncing = 0;
+ return(rc);
}
static int sq_release(void)
{
- int rc = 0;
- if (sq.busy) {
- rc = sq_sync();
- sq.busy = 0;
- WAKE_UP(sq.open_queue);
- /* Wake up a process waiting for the queue being released.
- Note: There may be several processes waiting for a call to open()
- returning. */
- }
- return(rc);
+ int rc = 0;
+ if (sq.busy) {
+ rc = sq_sync();
+ sq.busy = 0;
+ WAKE_UP(sq.open_queue);
+ /* Wake up a process waiting for the queue being released.
+ * Note: There may be several processes waiting for a call
+ * to open() returning. */
+ }
+ return(rc);
}
@@ -2916,7 +4023,7 @@
static void state_init(void)
{
- state.busy = 0;
+ state.busy = 0;
}
@@ -2924,118 +4031,125 @@
static int state_open(int open_mode)
{
- char *buffer = state.buf, *mach = "";
- int len = 0;
+ char *buffer = state.buf, *mach = "";
+ int len = 0;
- if (state.busy)
- return(-EBUSY);
+ if (state.busy)
+ return(-EBUSY);
- state.ptr = 0;
- state.busy = 1;
+ state.ptr = 0;
+ state.busy = 1;
- switch (sound.mach.type) {
+ switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_TT:
case DMASND_FALCON:
- mach = "Atari ";
- break;
+ mach = "Atari ";
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
- mach = "Amiga ";
- break;
+ mach = "Amiga ";
+ break;
#endif /* CONFIG_AMIGA */
- }
- len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
+#ifdef CONFIG_PMAC
+ case DMASND_AWACS:
+ mach = "PowerMac ";
+ break;
+#endif /* CONFIG_PMAC */
+ }
+ len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
- len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
- switch (sound.soft.format) {
+ len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
+ switch (sound.soft.format) {
case AFMT_MU_LAW:
- len += sprintf(buffer+len, " (mu-law)");
- break;
+ len += sprintf(buffer+len, " (mu-law)");
+ break;
case AFMT_A_LAW:
- len += sprintf(buffer+len, " (A-law)");
- break;
+ len += sprintf(buffer+len, " (A-law)");
+ break;
case AFMT_U8:
- len += sprintf(buffer+len, " (unsigned 8 bit)");
- break;
+ len += sprintf(buffer+len, " (unsigned 8 bit)");
+ break;
case AFMT_S8:
- len += sprintf(buffer+len, " (signed 8 bit)");
- break;
+ len += sprintf(buffer+len, " (signed 8 bit)");
+ break;
case AFMT_S16_BE:
- len += sprintf(buffer+len, " (signed 16 bit big)");
- break;
+ len += sprintf(buffer+len, " (signed 16 bit big)");
+ break;
case AFMT_U16_BE:
- len += sprintf(buffer+len, " (unsigned 16 bit big)");
- break;
+ len += sprintf(buffer+len, " (unsigned 16 bit big)");
+ break;
case AFMT_S16_LE:
- len += sprintf(buffer+len, " (signed 16 bit little)");
- break;
+ len += sprintf(buffer+len, " (signed 16 bit little)");
+ break;
case AFMT_U16_LE:
- len += sprintf(buffer+len, " (unsigned 16 bit little)");
- break;
- }
- len += sprintf(buffer+len, "\n");
- len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
- sound.soft.speed, sound.hard.speed);
- len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
- sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
- switch (sound.mach.type) {
+ len += sprintf(buffer+len, " (unsigned 16 bit little)");
+ break;
+ }
+ len += sprintf(buffer+len, "\n");
+ len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
+ sound.soft.speed, sound.hard.speed);
+ len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
+ sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
+ switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_TT:
- len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n",
- sound.volume_left);
- len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n",
- sound.volume_right);
- len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n",
- sound.bass);
- len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n",
- sound.treble);
- break;
+ len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n",
+ sound.volume_left);
+ len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n",
+ sound.volume_right);
+ len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n",
+ sound.bass);
+ len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n",
+ sound.treble);
+ break;
case DMASND_FALCON:
- len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n",
- sound.volume_left);
- len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n",
- sound.volume_right);
- break;
+ len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n",
+ sound.volume_left);
+ len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n",
+ sound.volume_right);
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
- len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
- sound.volume_left);
- len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
- sound.volume_right);
- break;
+ len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
+ sound.volume_left);
+ len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
+ sound.volume_right);
+ break;
#endif /* CONFIG_AMIGA */
- }
- len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n",
- sq.block_size, sq.max_count);
- len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
- sq.rear_size);
- len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
- sq.playing, sq.syncing);
- state.len = len;
- return(0);
+ }
+ len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d"
+ " sq.max_active = %d\n",
+ sq.block_size, sq.max_count, sq.max_active);
+ len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
+ sq.rear_size);
+ len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
+ sq.playing, sq.syncing);
+ state.len = len;
+ return(0);
}
static int state_release(void)
{
- state.busy = 0;
- return(0);
+ state.busy = 0;
+ return(0);
}
static long state_read(char *dest, unsigned long count)
{
- int n = state.len-state.ptr;
- if (n > count)
- n = count;
- if (n <= 0)
- return(0);
- copy_to_user(dest, &state.buf[state.ptr], n);
- state.ptr += n;
- return(n);
+ int n = state.len-state.ptr;
+ if (n > count)
+ n = count;
+ if (n <= 0)
+ return(0);
+ if (copy_to_user(dest, &state.buf[state.ptr], n))
+ return -EFAULT;
+ state.ptr += n;
+ return(n);
}
@@ -3045,230 +4159,252 @@
static int sound_open(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev) & 0x0f;
- int rc = 0;
+ int dev = MINOR(inode->i_rdev) & 0x0f;
+ int rc = 0;
- switch (dev) {
+ switch (dev) {
case SND_DEV_STATUS:
- rc = state_open(file->f_flags);
- break;
+ rc = state_open(file->f_flags);
+ break;
case SND_DEV_CTL:
- rc = mixer_open(file->f_flags);
- break;
+ rc = mixer_open(file->f_flags);
+ break;
case SND_DEV_DSP:
case SND_DEV_AUDIO:
- rc = sq_open(file->f_flags);
- if (rc == 0) {
- sound.minDev = dev;
- sound.soft = sound.dsp;
- sound.hard = sound.dsp;
- sound_init();
- if (dev == SND_DEV_AUDIO) {
- sound_set_speed(8000);
- sound_set_stereo(0);
- sound_set_format(AFMT_MU_LAW);
+ rc = sq_open(file->f_flags);
+ if (rc == 0) {
+ sound.minDev = dev;
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
+ sound_init();
+ if (dev == SND_DEV_AUDIO) {
+ sound_set_speed(8000);
+ sound_set_stereo(0);
+ sound_set_format(AFMT_MU_LAW);
+ }
}
- }
- break;
+ break;
default:
- rc = -ENXIO;
- }
+ rc = -ENXIO;
+ }
#ifdef MODULE
- if (rc >= 0)
- MOD_INC_USE_COUNT;
+ if (rc >= 0)
+ MOD_INC_USE_COUNT;
#endif
- return(rc);
+ return(rc);
}
static int sound_fsync(struct file *filp, struct dentry *dentry)
{
- int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f;
+ int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f;
- switch (dev) {
+ switch (dev) {
case SND_DEV_STATUS:
case SND_DEV_CTL:
- return(0);
+ return(0);
case SND_DEV_DSP:
case SND_DEV_AUDIO:
- return(sq_sync());
+ return(sq_sync());
default:
- return(unknown_minor_dev("sound_fsync", dev));
- }
+ return(unknown_minor_dev("sound_fsync", dev));
+ }
}
static int sound_release(struct inode *inode, struct file *file)
{
- int dev = MINOR(inode->i_rdev);
+ int dev = MINOR(inode->i_rdev);
- switch (dev & 0x0f) {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- state_release();
- break;
+ state_release();
+ break;
case SND_DEV_CTL:
- mixer_release();
- break;
+ mixer_release();
+ break;
case SND_DEV_DSP:
case SND_DEV_AUDIO:
- sq_release();
- sound.soft = sound.dsp;
- sound.hard = sound.dsp;
- sound_silence();
- break;
+ sq_release();
+ sound.soft = sound.dsp;
+ sound.hard = sound.dsp;
+ sound_silence();
+ break;
default:
- return unknown_minor_dev("sound_release", dev);
- }
+ return unknown_minor_dev("sound_release", dev);
+ }
#ifdef MODULE
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
#endif
- return 0;
+ return 0;
}
static long long sound_lseek(struct file *file, long long offset, int orig)
{
- return -ESPIPE;
+ return -ESPIPE;
}
static ssize_t sound_read(struct file *file, char *buf, size_t count,
loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
- int dev = MINOR(inode->i_rdev);
+ struct inode *inode = file->f_dentry->d_inode;
+ int dev = MINOR(inode->i_rdev);
- switch (dev & 0x0f) {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- return(state_read(buf, count));
+ return(state_read(buf, count));
case SND_DEV_CTL:
case SND_DEV_DSP:
case SND_DEV_AUDIO:
- return(-EPERM);
+ return(-EPERM);
default:
- return(unknown_minor_dev("sound_read", dev));
- }
+ return(unknown_minor_dev("sound_read", dev));
+ }
}
static ssize_t sound_write(struct file *file, const char *buf, size_t count,
loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
- int dev = MINOR(inode->i_rdev);
+ struct inode *inode = file->f_dentry->d_inode;
+ int dev = MINOR(inode->i_rdev);
- switch (dev & 0x0f) {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
case SND_DEV_CTL:
- return(-EPERM);
+ return(-EPERM);
case SND_DEV_DSP:
case SND_DEV_AUDIO:
- return(sq_write(buf, count));
+ return(sq_write(buf, count));
default:
- return(unknown_minor_dev("sound_write", dev));
- }
+ return(unknown_minor_dev("sound_write", dev));
+ }
}
static int unknown_minor_dev(char *fname, int dev)
{
- /* printk("%s: Unknown minor device %d\n", fname, dev); */
- return(-ENXIO);
+ /* printk("%s: Unknown minor device %d\n", fname, dev); */
+ return(-ENXIO);
}
static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
{
- int dev = MINOR(inode->i_rdev);
- u_long fmt;
- int data;
+ int dev = MINOR(inode->i_rdev);
+ u_long fmt;
+ int data;
+ int size, nbufs;
- switch (dev & 0x0f) {
+ switch (dev & 0x0f) {
case SND_DEV_STATUS:
- return(-EPERM);
+ return(-EPERM);
case SND_DEV_CTL:
- return(mixer_ioctl(inode, file, cmd, arg));
+ return(mixer_ioctl(inode, file, cmd, arg));
case SND_DEV_AUDIO:
case SND_DEV_DSP:
- switch (cmd) {
+ switch (cmd) {
case SNDCTL_DSP_RESET:
- sq_reset();
- return(0);
+ sq_reset();
+ return(0);
case SNDCTL_DSP_POST:
case SNDCTL_DSP_SYNC:
- return(sound_fsync(file, file->f_dentry));
+ return(sound_fsync(file, file->f_dentry));
- /* ++TeSche: before changing any of these it's probably wise to
- * wait until sound playing has settled down
- */
+ /* ++TeSche: before changing any of these it's
+ * probably wise to wait until sound playing has
+ * settled down. */
case SNDCTL_DSP_SPEED:
- sound_fsync(file, file->f_dentry);
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_speed(data)));
+ sound_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_speed(data)));
case SNDCTL_DSP_STEREO:
- sound_fsync(file, file->f_dentry);
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_stereo(data)));
+ sound_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_stereo(data)));
case SOUND_PCM_WRITE_CHANNELS:
- sound_fsync(file, file->f_dentry);
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1));
+ sound_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1));
case SNDCTL_DSP_SETFMT:
- sound_fsync(file, file->f_dentry);
- IOCTL_IN(arg, data);
- return(IOCTL_OUT(arg, sound_set_format(data)));
+ sound_fsync(file, file->f_dentry);
+ IOCTL_IN(arg, data);
+ return(IOCTL_OUT(arg, sound_set_format(data)));
case SNDCTL_DSP_GETFMTS:
- fmt = 0;
- if (sound.trans) {
- if (sound.trans->ct_ulaw)
- fmt |= AFMT_MU_LAW;
- if (sound.trans->ct_alaw)
- fmt |= AFMT_A_LAW;
- if (sound.trans->ct_s8)
- fmt |= AFMT_S8;
- if (sound.trans->ct_u8)
- fmt |= AFMT_U8;
- if (sound.trans->ct_s16be)
- fmt |= AFMT_S16_BE;
- if (sound.trans->ct_u16be)
- fmt |= AFMT_U16_BE;
- if (sound.trans->ct_s16le)
- fmt |= AFMT_S16_LE;
- if (sound.trans->ct_u16le)
- fmt |= AFMT_U16_LE;
- }
- return(IOCTL_OUT(arg, fmt));
+ fmt = 0;
+ if (sound.trans) {
+ if (sound.trans->ct_ulaw)
+ fmt |= AFMT_MU_LAW;
+ if (sound.trans->ct_alaw)
+ fmt |= AFMT_A_LAW;
+ if (sound.trans->ct_s8)
+ fmt |= AFMT_S8;
+ if (sound.trans->ct_u8)
+ fmt |= AFMT_U8;
+ if (sound.trans->ct_s16be)
+ fmt |= AFMT_S16_BE;
+ if (sound.trans->ct_u16be)
+ fmt |= AFMT_U16_BE;
+ if (sound.trans->ct_s16le)
+ fmt |= AFMT_S16_LE;
+ if (sound.trans->ct_u16le)
+ fmt |= AFMT_U16_LE;
+ }
+ return(IOCTL_OUT(arg, fmt));
case SNDCTL_DSP_GETBLKSIZE:
- return(IOCTL_OUT(arg, 10240));
+ size = sq.block_size
+ * sound.soft.size * (sound.soft.stereo + 1)
+ / (sound.hard.size * (sound.hard.stereo + 1));
+ return(IOCTL_OUT(arg, size));
case SNDCTL_DSP_SUBDIVIDE:
+ break;
case SNDCTL_DSP_SETFRAGMENT:
- break;
+ if (sq.count || sq.playing || sq.syncing)
+ return -EINVAL;
+ IOCTL_IN(arg, size);
+ nbufs = size >> 16;
+ if (nbufs < 2 || nbufs > numBufs)
+ nbufs = numBufs;
+ size &= 0xffff;
+ if (size >= 8 && size <= 30) {
+ size = 1 << size;
+ size *= sound.hard.size * (sound.hard.stereo + 1);
+ size /= sound.soft.size * (sound.soft.stereo + 1);
+ if (size > (bufSize << 10))
+ size = bufSize << 10;
+ } else
+ size = bufSize << 10;
+ sq_init(numBufs, size, sound_buffers);
+ sq.max_active = nbufs;
+ break;
default:
- return(mixer_ioctl(inode, file, cmd, arg));
- }
- break;
+ return(mixer_ioctl(inode, file, cmd, arg));
+ }
+ break;
default:
- return(unknown_minor_dev("sound_ioctl", dev));
- }
- return(-EINVAL);
+ return(unknown_minor_dev("sound_ioctl", dev));
+ }
+ return(-EINVAL);
}
static struct file_operations sound_fops =
{
- sound_lseek,
- sound_read,
- sound_write,
- NULL,
- NULL, /* select */
- sound_ioctl,
- NULL,
- sound_open,
- sound_release,
- sound_fsync
+ sound_lseek,
+ sound_read,
+ sound_write,
+ NULL,
+ NULL, /* select */
+ sound_ioctl,
+ NULL,
+ sound_open,
+ sound_release,
+ sound_fsync
};
@@ -3278,87 +4414,142 @@
void soundcard_init(void)
{
- int has_sound = 0;
- int i;
+ int has_sound = 0;
+ int i;
- switch (m68k_machtype) {
+#ifdef __mc68000__
+ switch (m68k_machtype) {
#ifdef CONFIG_ATARI
case MACH_ATARI:
- if (ATARIHW_PRESENT(PCM_8BIT)) {
- if (ATARIHW_PRESENT(CODEC))
- sound.mach = machFalcon;
- else if (ATARIHW_PRESENT(MICROWIRE))
- sound.mach = machTT;
- else
- break;
- if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
- has_sound = 1;
- else
- printk("DMA sound driver: Timer A interrupt already in use\n");
- }
- break;
+ if (ATARIHW_PRESENT(PCM_8BIT)) {
+ if (ATARIHW_PRESENT(CODEC))
+ sound.mach = machFalcon;
+ else if (ATARIHW_PRESENT(MICROWIRE))
+ sound.mach = machTT;
+ else
+ break;
+ if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
+ has_sound = 1;
+ else
+ printk("DMA sound driver: Timer A interrupt already in use\n");
+ }
+ break;
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
case MACH_AMIGA:
- if (AMIGAHW_PRESENT(AMI_AUDIO)) {
- sound.mach = machAmiga;
- has_sound = 1;
- }
- break;
+ if (AMIGAHW_PRESENT(AMI_AUDIO)) {
+ sound.mach = machAmiga;
+ has_sound = 1;
+ }
+ break;
#endif /* CONFIG_AMIGA */
- }
- if (!has_sound)
- return;
+ }
+#endif /* __mc68000__ */
- /* Set up sound queue, /dev/audio and /dev/dsp. */
- sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
- if (!sound_buffers) {
-out_of_memory:
- printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
- return;
- }
- for (i = 0; i < numBufs; i++) {
- sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
- if (!sound_buffers[i]) {
- while (i--)
- sound.mach.dma_free (sound_buffers[i], bufSize << 10);
- kfree (sound_buffers);
- sound_buffers = 0;
- goto out_of_memory;
- }
- }
+#ifdef CONFIG_PMAC
+ struct device_node *np;
+
+ np = find_devices("awacs");
+ if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) {
+ int vol;
+ sound.mach = machPMac;
+ has_sound = 1;
+ awacs = (volatile struct awacs_regs *)
+ ioremap(np->addrs[0].address, 0x80);
+ awacs_txdma = (volatile struct dbdma_regs *)
+ ioremap(np->addrs[1].address, 0x100);
+ awacs_rxdma = (volatile struct dbdma_regs *)
+ ioremap(np->addrs[2].address, 0x100);
+ awacs_irq = np->intrs[0].line;
+ awacs_tx_irq = np->intrs[1].line;
+ awacs_rx_irq = np->intrs[2].line;
+ awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd),
+ GFP_KERNEL);
+ if (awacs_tx_cmd_space == NULL)
+ goto out_of_memory;
+ awacs_tx_cmds = (volatile struct dbdma_cmd *)
+ DBDMA_ALIGN(awacs_tx_cmd_space);
+ awacs_reg[0] = MASK_MUX_CD;
+ awacs_reg[1] = MASK_LOOPTHRU | MASK_PAROUT;
+ /* get default volume from nvram */
+ vol = (~nvram_read_byte(0x1308) & 7) << 1;
+ awacs_reg[2] = vol + (vol << 6);
+ awacs_reg[4] = vol + (vol << 6);
+ awacs_write(awacs_reg[0] + MASK_ADDR0);
+ awacs_write(awacs_reg[1] + MASK_ADDR1);
+ awacs_write(awacs_reg[2] + MASK_ADDR2);
+ awacs_write(awacs_reg[4] + MASK_ADDR4);
+
+ /* Initialize beep stuff */
+ beep_dbdma_cmd = awacs_tx_cmds + (numBufs + 1);
+ orig_mksound = kd_mksound;
+ kd_mksound = awacs_mksound;
+ beep_buf = (short *) kmalloc(BEEP_BUFLEN * 2, GFP_KERNEL);
+ if (beep_buf == NULL)
+ printk(KERN_WARNING "dmasound: no memory for "
+ "beep buffer\n");
+#ifdef CONFIG_PMAC_PBOOK
+ notifier_chain_register(&sleep_notifier_list,
+ &awacs_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+ }
+#endif /* CONFIG_PMAC */
+
+ if (!has_sound)
+ return;
+
+ /* Set up sound queue, /dev/audio and /dev/dsp. */
+ sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+ if (!sound_buffers) {
+ out_of_memory:
+ printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
+ return;
+ }
+ for (i = 0; i < numBufs; i++) {
+ sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+ if (!sound_buffers[i]) {
+ while (i--)
+ sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+ kfree (sound_buffers);
+ sound_buffers = 0;
+ goto out_of_memory;
+ }
+ }
#ifndef MODULE
- /* Register driver with the VFS. */
- register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
+ /* Register driver with the VFS. */
+ register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
#endif
- sq_init(numBufs, bufSize << 10, sound_buffers);
+ sq_init(numBufs, bufSize << 10, sound_buffers);
- /* Set up /dev/sndstat. */
- state_init();
+ /* Set default settings. */
+ init_settings();
- /* Set up /dev/mixer. */
- mixer_init();
+ /* Set up /dev/sndstat. */
+ state_init();
- if (!sound.mach.irqinit()) {
- printk("DMA sound driver: Interrupt initialization failed\n");
- return;
- }
+ /* Set up /dev/mixer. */
+ mixer_init();
+
+ if (!sound.mach.irqinit()) {
+ printk("DMA sound driver: Interrupt initialization failed\n");
+ return;
+ }
#ifdef MODULE
- irq_installed = 1;
+ irq_installed = 1;
#endif
- printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
- bufSize);
+ printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
+ bufSize);
- return;
+ return;
}
void sound_setup(char *str, int *ints)
{
- /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
+ /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
}
@@ -3366,30 +4557,30 @@
void dmasound_setup(char *str, int *ints)
{
- /* check the bootstrap parameter for "dmasound=" */
+ /* check the bootstrap parameter for "dmasound=" */
- switch (ints[0]) {
+ switch (ints[0]) {
case 3:
- if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
- printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
- else
- catchRadius = ints[3];
- /* fall through */
+ if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
+ printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
+ else
+ catchRadius = ints[3];
+ /* fall through */
case 2:
- if (ints[1] < MIN_BUFFERS)
- printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs);
- else
- numBufs = ints[1];
- if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
- printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
- else
- bufSize = ints[2];
- break;
+ if (ints[1] < MIN_BUFFERS)
+ printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs);
+ else
+ numBufs = ints[1];
+ if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
+ printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
+ else
+ bufSize = ints[2];
+ break;
case 0:
- break;
+ break;
default:
- printk("dmasound_setup: illegal number of arguments\n");
- }
+ printk("dmasound_setup: illegal number of arguments\n");
+ }
}
@@ -3399,48 +4590,48 @@
int init_module(void)
{
- int err, i = 0;
- int ints[MAXARGS+1];
+ int err, i = 0;
+ int ints[MAXARGS+1];
+
+ while (i < MAXARGS && dmasound[i])
+ ints[i + 1] = dmasound[i++];
+ ints[0] = i;
- while (i < MAXARGS && dmasound[i])
- ints[i + 1] = dmasound[i++];
- ints[0] = i;
-
- if (i)
- dmasound_setup("dmasound=", ints);
-
- err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
- if (err) {
- printk("dmasound: driver already loaded/included in kernel\n");
- return err;
- }
- chrdev_registered = 1;
- soundcard_init();
+ if (i)
+ dmasound_setup("dmasound=", ints);
+
+ err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
+ if (err) {
+ printk("dmasound: driver already loaded/included in kernel\n");
+ return err;
+ }
+ chrdev_registered = 1;
+ soundcard_init();
- return 0;
+ return 0;
}
void cleanup_module(void)
{
- int i;
+ int i;
- if (MOD_IN_USE)
- return;
+ if (MOD_IN_USE)
+ return;
- if (chrdev_registered)
- unregister_chrdev(SOUND_MAJOR, "sound");
+ if (chrdev_registered)
+ unregister_chrdev(SOUND_MAJOR, "sound");
- if (irq_installed) {
- sound_silence();
- sound.mach.irqcleanup();
- }
+ if (irq_installed) {
+ sound_silence();
+ sound.mach.irqcleanup();
+ }
- if (sound_buffers) {
- for (i = 0; i < numBufs; i++)
- sound.mach.dma_free(sound_buffers[i], bufSize << 10);
- kfree(sound_buffers);
- }
+ if (sound_buffers) {
+ for (i = 0; i < numBufs; i++)
+ sound.mach.dma_free(sound_buffers[i], bufSize << 10);
+ kfree(sound_buffers);
+ }
}
#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov