summaryrefslogtreecommitdiff
path: root/attic/drv/oss_als3xx
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /attic/drv/oss_als3xx
downloadoss4-upstream.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'attic/drv/oss_als3xx')
-rw-r--r--attic/drv/oss_als3xx/.devices2
-rw-r--r--attic/drv/oss_als3xx/.name1
-rw-r--r--attic/drv/oss_als3xx/.params5
-rw-r--r--attic/drv/oss_als3xx/als300.h324
-rw-r--r--attic/drv/oss_als3xx/oss_als3xx.c898
-rw-r--r--attic/drv/oss_als3xx/oss_als3xx.man19
6 files changed, 1249 insertions, 0 deletions
diff --git a/attic/drv/oss_als3xx/.devices b/attic/drv/oss_als3xx/.devices
new file mode 100644
index 0000000..2a4e7aa
--- /dev/null
+++ b/attic/drv/oss_als3xx/.devices
@@ -0,0 +1,2 @@
+oss_als3xx pci4005,300 Avance Logic ALS300
+oss_als3xx pci4005,308 Avance Logic ALS300+
diff --git a/attic/drv/oss_als3xx/.name b/attic/drv/oss_als3xx/.name
new file mode 100644
index 0000000..f588080
--- /dev/null
+++ b/attic/drv/oss_als3xx/.name
@@ -0,0 +1 @@
+Avance Logic ALS300
diff --git a/attic/drv/oss_als3xx/.params b/attic/drv/oss_als3xx/.params
new file mode 100644
index 0000000..4fd5829
--- /dev/null
+++ b/attic/drv/oss_als3xx/.params
@@ -0,0 +1,5 @@
+int als300_mpu_base=0;
+/*
+ * Specify ALS300's MPU Base
+ * Values: 0x300, 0x310, 0x320, 0x330, 0x340, 0x0350, 0x360, 0x370 Default: 0
+ */
diff --git a/attic/drv/oss_als3xx/als300.h b/attic/drv/oss_als3xx/als300.h
new file mode 100644
index 0000000..59635e9
--- /dev/null
+++ b/attic/drv/oss_als3xx/als300.h
@@ -0,0 +1,324 @@
+/*
+ * Purpose: Definitions for the ALS300 driver.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+#define FNO1 374
+#define FNO2 192
+static unsigned int FreqTable1[FNO1] = {
+ 3997, 0x162,
+ 4017, 0x062,
+ 4038, 0x161,
+ 4058, 0x061,
+ 4079, 0x160,
+ 4100, 0x060,
+ 4121, 0x15F,
+ 4143, 0x05F,
+ 4165, 0x15E,
+ 4187, 0x05E,
+ 4209, 0x15D,
+ 4231, 0x05D,
+ 4254, 0x15C,
+ 4277, 0x05C,
+ 4300, 0x15B,
+ 4323, 0x05B,
+ 4347, 0x15A,
+ 4371, 0x05A,
+ 4395, 0x159,
+ 4419, 0x059,
+ 4444, 0x158,
+ 4469, 0x058,
+ 4494, 0x157,
+ 4520, 0x057,
+ 4545, 0x156,
+ 4571, 0x056,
+ 4598, 0x155,
+ 4625, 0x055,
+ 4652, 0x154,
+ 4679, 0x054,
+ 4707, 0x153,
+ 4735, 0x053,
+ 4763, 0x152,
+ 4792, 0x052,
+ 4821, 0x151,
+ 4850, 0x051,
+ 4880, 0x150,
+ 4910, 0x050,
+ 4941, 0x14F,
+ 4972, 0x04F,
+ 5003, 0x14E,
+ 5034, 0x04E,
+ 5066, 0x14D,
+ 5099, 0x04D,
+ 5132, 0x14C,
+ 5165, 0x04C,
+ 5199, 0x14B,
+ 5233, 0x04B,
+ 5268, 0x14A,
+ 5303, 0x04A,
+ 5339, 0x149,
+ 5375, 0x049,
+ 5411, 0x148,
+ 5448, 0x048,
+ 5486, 0x147,
+ 5524, 0x047,
+ 5563, 0x146,
+ 5602, 0x046,
+ 5641, 0x145,
+ 5682, 0x045,
+ 5723, 0x144,
+ 5764, 0x044,
+ 5806, 0x143,
+ 5849, 0x043,
+ 5892, 0x142,
+ 5936, 0x042,
+ 5981, 0x141,
+ 6026, 0x041,
+ 6072, 0x140,
+ 6119, 0x040,
+ 6166, 0x13F,
+ 6214, 0x03F,
+ 6263, 0x13E,
+ 6313, 0x03E,
+ 6364, 0x13D,
+ 6415, 0x03D,
+ 6467, 0x13C,
+ 6520, 0x03C,
+ 6574, 0x13B,
+ 6629, 0x03B,
+ 6684, 0x13A,
+ 6741, 0x03A,
+ 6799, 0x139,
+ 6857, 0x039,
+ 6917, 0x138,
+ 6978, 0x038,
+ 7039, 0x137,
+ 7102, 0x037,
+ 7166, 0x136,
+ 7231, 0x036,
+ 7298, 0x135,
+ 7365, 0x035,
+ 7434, 0x134,
+ 7504, 0x034,
+ 7576, 0x133,
+ 7648, 0x033,
+ 7723, 0x132,
+ 7798, 0x032,
+ 7876, 0x131,
+ 7954, 0x031,
+ 8000, 0x201,
+ 8035, 0x130,
+ 8117, 0x030,
+ 8200, 0x12F,
+ 8286, 0x02F,
+ 8373, 0x12E,
+ 8462, 0x02E,
+ 8553, 0x12D,
+ 8646, 0x02D,
+ 8741, 0x12C,
+ 8838, 0x02C,
+ 8938, 0x12B,
+ 9039, 0x02B,
+ 9143, 0x12A,
+ 9249, 0x02A,
+ 9358, 0x129,
+ 9470, 0x029,
+ 9584, 0x128,
+ 9700, 0x028,
+ 9820, 0x127,
+ 9943, 0x027,
+ 10069, 0x126,
+ 10198, 0x026,
+ 10330, 0x125,
+ 10466, 0x025,
+ 10605, 0x124,
+ 10749, 0x024,
+ 10896, 0x123,
+ 11048, 0x023,
+ 11203, 0x122,
+ 11363, 0x022,
+ 11528, 0x121,
+ 11698, 0x021,
+ 11872, 0x120,
+ 12052, 0x020,
+ 12238, 0x11F,
+ 12429, 0x01F,
+ 12626, 0x11E,
+ 12830, 0x01E,
+ 13040, 0x11D,
+ 13257, 0x01D,
+ 13482, 0x11C,
+ 13714, 0x01C,
+ 13955, 0x11B,
+ 14204, 0x01B,
+ 14463, 0x11A,
+ 14730, 0x01A,
+ 15008, 0x119,
+ 15297, 0x019,
+ 15597, 0x118,
+ 15909, 0x018,
+ 16000, 0x202,
+ 16233, 0x117,
+ 16572, 0x017,
+ 16924, 0x116,
+ 17292, 0x016,
+ 17676, 0x115,
+ 18078, 0x015,
+ 18499, 0x114,
+ 18939, 0x014,
+ 19401, 0x113,
+ 19886, 0x013,
+ 20396, 0x112,
+ 20993, 0x012,
+ 21498, 0x111,
+ 22096, 0x011,
+ 22727, 0x110,
+ 23395, 0x010,
+ 24104, 0x10F,
+ 24858, 0x00F,
+ 25659, 0x10E,
+ 26515, 0x00E,
+ 27429, 0x10D,
+ 28409, 0x00D,
+ 29461, 0x10C,
+ 30594, 0x00C,
+ 31818, 0x10B,
+ 32000, 0x203,
+ 33143, 0x00B,
+ 34584, 0x10A,
+ 36156, 0x00A,
+ 37878, 0x109,
+ 39772, 0x009,
+ 41805, 0x108,
+ 44191, 0x008,
+ 46791, 0x107,
+ 48000, 0x000
+};
+
+
+#if 0
+static unsigned int FreqTable2[FNO2] = {
+ 3977, 0x231,
+ 4018, 0x330,
+ 4059, 0x230,
+ 4100, 0x32F,
+ 4146, 0x22F,
+ 4187, 0x32E,
+ 4231, 0x22E,
+ 4277, 0x32D,
+ 4323, 0x22D,
+ 4371, 0x32C,
+ 4419, 0x22C,
+ 4469, 0x32B,
+ 4520, 0x22B,
+ 4572, 0x32A,
+ 4625, 0x22A,
+ 4679, 0x329,
+ 4735, 0x229,
+ 4792, 0x328,
+ 4850, 0x228,
+ 4910, 0x327,
+ 4972, 0x227,
+ 5035, 0x326,
+ 5099, 0x226,
+ 5165, 0x325,
+ 5233, 0x225,
+ 5303, 0x324,
+ 5375, 0x224,
+ 5448, 0x323,
+ 5524, 0x223,
+ 5602, 0x322,
+ 5682, 0x222,
+ 5764, 0x321,
+ 5849, 0x221,
+ 5936, 0x320,
+ 6026, 0x220,
+ 6119, 0x31F,
+ 6215, 0x21F,
+ 6313, 0x31E,
+ 6415, 0x21E,
+ 6520, 0x31D,
+ 6629, 0x21D,
+ 6741, 0x31C,
+ 6857, 0x21C,
+ 6978, 0x31B,
+ 7102, 0x21B,
+ 7232, 0x31A,
+ 7365, 0x21A,
+ 7504, 0x319,
+ 7649, 0x219,
+ 7799, 0x318,
+ 7955, 0x218,
+ 8000, 0x201,
+ 8117, 0x317,
+ 8286, 0x217,
+ 8462, 0x316,
+ 8646, 0x216,
+ 8838, 0x315,
+ 9039, 0x215,
+ 9250, 0x314,
+ 9470, 0x214,
+ 9701, 0x313,
+ 9943, 0x213,
+ 10198, 0x312,
+ 10497, 0x212,
+ 10749, 0x311,
+ 11048, 0x211,
+ 11364, 0x310,
+ 11698, 0x210,
+ 12052, 0x30F,
+ 12429, 0x20F,
+ 12830, 0x30E,
+ 13258, 0x20E,
+ 13715, 0x30D,
+ 14205, 0x20D,
+ 14731, 0x30C,
+ 15297, 0x20C,
+ 15909, 0x30B,
+ 16000, 0x202,
+ 16572, 0x20B,
+ 17292, 0x30A,
+ 18078, 0x20A,
+ 18939, 0x309,
+ 19886, 0x209,
+ 20903, 0x308,
+ 22096, 0x208,
+ 23396, 0x307,
+ 24858, 0x207,
+ 26515, 0x306,
+ 28409, 0x206,
+ 30594, 0x305,
+ 32000, 0x203,
+ 33144, 0x205,
+ 36157, 0x304,
+ 39772, 0x204,
+ 44191, 0x303,
+ 48000, 0x000
+};
+#endif
+
+#define VERSION_A 0
+#define VERSION_B 1
+#define VERSION_C 2
+#define VERSION_D 3
+#define VERSION_E 4
+#define VERSION_F 5
+#define VERSION_G 6
+#define VERSION_H 7
+#define VERSION_I 8
+#define VERSION_J 9
+#define VERSION_K 10
+#define VERSION_L 11
+#define VERSION_M 12
+#define VERSION_N 13
+#define VERSION_O 14
+#define VERSION_P 15
diff --git a/attic/drv/oss_als3xx/oss_als3xx.c b/attic/drv/oss_als3xx/oss_als3xx.c
new file mode 100644
index 0000000..bfc8fa3
--- /dev/null
+++ b/attic/drv/oss_als3xx/oss_als3xx.c
@@ -0,0 +1,898 @@
+/*
+ * Purpose: Driver for ALS ALS300 PCI audio controller.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include "oss_als3xx_cfg.h"
+#include "oss_pci.h"
+#include "ac97.h"
+#include "als300.h"
+
+#define ALS_VENDOR_ID 0x4005
+#define ALS_300 0x0300
+#define ALS_300P 0x0308
+
+extern int als300_mpu_base;
+
+#define MAX_PORTC 2
+
+typedef struct als300_portc
+{
+ int speed, bits, channels;
+ int open_mode;
+ int audio_enabled;
+ int trigger_bits;
+ int audiodev;
+}
+als300_portc;
+
+typedef struct als300_devc
+{
+ oss_device_t *osdev;
+ oss_native_word base, mpu_base;
+ int mpu_attached, fm_attached;
+ int irq;
+
+ volatile unsigned char intr_mask;
+#define MDL_ALS300 0
+#define MDL_ALS300PLUS 1
+ int model;
+ char *chip_name;
+ unsigned char chip_rev;
+ oss_mutex_t mutex;
+ oss_mutex_t low_mutex;
+
+ /* Audio parameters */
+ int open_mode;
+ als300_portc portc[2];
+ oss_native_word srcode;
+
+ /* Mixer parameters */
+ ac97_devc ac97devc;
+ int mixer_dev;
+}
+als300_devc;
+
+
+void
+gcr_writel (als300_devc * devc, unsigned char index, oss_native_word data)
+{
+ OUTB (devc->osdev, index, devc->base + 0x0c);
+ OUTL (devc->osdev, data, devc->base + 0x08);
+}
+
+
+oss_native_word
+gcr_readl (als300_devc * devc, unsigned char index)
+{
+ oss_native_word bufl;
+ OUTB (devc->osdev, index, devc->base + 0x0c);
+ bufl = INL (devc->osdev, devc->base + 0x08);
+ return (bufl);
+}
+
+static int
+ac97_write (void *devc_, int index, int data)
+{
+ oss_native_word access;
+ unsigned i, N;
+ unsigned char byte;
+ als300_devc *devc = devc_;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ i = 0;
+ N = 1000;
+ do
+ {
+ byte = INB (devc->osdev, devc->base + 6) & 0x80;
+ if (byte == 0x00)
+ goto go;
+ oss_udelay (10);
+ i++;
+ }
+ while (i < N);
+ if (i >= N)
+ cmn_err (CE_WARN, "\n Write AC97 mixer index time out !!");
+go:
+ access = index;
+ access <<= 24; /*index */
+ access &= 0x7fffffff; /*write */
+ access |= data; /*data */
+ OUTL (devc->osdev, access, devc->base);
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return 0;
+}
+
+static int
+ac97_read (void *devc_, int index)
+{
+ oss_native_word access;
+ unsigned int data;
+ unsigned i, N;
+ unsigned char byte;
+ oss_native_word flags;
+ als300_devc *devc = devc_;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ i = 0;
+ N = 1000;
+ do
+ {
+ byte = INB (devc->osdev, devc->base + 6) & 0x80;
+ if (byte == 0x00)
+ goto next;
+ oss_udelay (10);
+ i++;
+ }
+ while (i < N);
+ if (i >= N)
+ cmn_err (CE_WARN, "\n Write AC97 mixer index time out !!");
+next:
+ access = index;
+ access <<= 24; /*index */
+ access |= 0x80000000;
+ OUTL (devc->osdev, access, devc->base);
+
+ i = 0;
+ N = 1000;
+ do
+ {
+ byte = INB (devc->osdev, devc->base + 6);
+ if ((byte & 0x40) != 0)
+ goto next1;
+ oss_udelay (10);
+ i++;
+ }
+ while (i < N);
+ if (i >= N)
+ cmn_err (CE_WARN, "Read AC97 mixer data time out !!");
+next1:
+ data = INW (devc->osdev, devc->base + 0x04);
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+ return data;
+}
+
+static int
+als300intr (oss_device_t * osdev)
+{
+ als300_devc *devc = (als300_devc *) osdev->devc;
+ int i;
+ unsigned int status, mpustatus, serviced = 0;
+
+ /* Get the status */
+ if (devc->model == MDL_ALS300)
+ status = INB (devc->osdev, devc->base + 0x07);
+ else
+ status = INB (devc->osdev, devc->base + 0xF);
+
+ /* if playback - do output */
+ for (i = 0; i < MAX_PORTC; i++)
+ {
+ als300_portc *portc = &devc->portc[i];
+
+ if (status & 0x08)
+ {
+ serviced = 1;
+ if (portc->trigger_bits & PCM_ENABLE_OUTPUT)
+ oss_audio_outputintr (portc->audiodev, 1);
+ }
+
+ /* if record - do input */
+ if (status & 0x04)
+ {
+ serviced = 1;
+ if (portc->trigger_bits & PCM_ENABLE_INPUT)
+ oss_audio_inputintr (portc->audiodev, 0);
+ }
+ }
+
+ /* Handle the UART401 Interrupt */
+ if (devc->model == MDL_ALS300)
+ {
+ mpustatus = INB (devc->osdev, devc->base + 0x0E);
+ if ((mpustatus & 0x10) || (status & 0x80))
+ {
+ serviced = 1;
+/* uart401intr (INT_HANDLER_CALL (devc->irq)); */
+ }
+ }
+ else
+ {
+ if (status & 0x40)
+ {
+ serviced = 1;
+/* uart401intr (INT_HANDLER_CALL (devc->irq)); */
+ }
+ }
+
+ /* Acknowledge the interrupt */
+ if (status)
+ {
+ if (devc->model == MDL_ALS300)
+ {
+ OUTB (devc->osdev, status, devc->base + 0x07); /* acknowledge interrupt */
+ }
+ else
+ {
+ OUTB (devc->osdev, status, devc->base + 0xF); /* acknowledge interrupt */
+ }
+ }
+ return serviced;
+}
+
+static int
+als300_audio_set_rate (int dev, int arg)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+
+ if (arg == 0)
+ return portc->speed;
+
+ if (audio_engines[dev]->flags & ADEV_FIXEDRATE)
+ arg = 48000;
+
+ if (arg > 48000)
+ arg = 48000;
+ if (arg < 5000)
+ arg = 5000;
+ portc->speed = arg;
+ return portc->speed;
+}
+
+static short
+als300_audio_set_channels (int dev, short arg)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+
+ if (arg == 0)
+ return portc->channels;
+
+ if (audio_engines[dev]->flags & ADEV_STEREOONLY)
+ arg = 2;
+
+ if ((arg != 1) && (arg != 2))
+ return portc->channels;
+ portc->channels = arg;
+
+ return portc->channels;
+}
+
+static unsigned int
+als300_audio_set_format (int dev, unsigned int arg)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+
+ if (arg == 0)
+ return portc->bits;
+
+ if (audio_engines[dev]->flags & ADEV_16BITONLY)
+ arg = 16;
+ if (!(arg & (AFMT_U8 | AFMT_S16_LE)))
+ return portc->bits;
+ portc->bits = arg;
+
+ return portc->bits;
+}
+
+/*ARGSUSED*/
+static int
+als300_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+{
+ return OSS_EINVAL;
+}
+
+static void als300_audio_trigger (int dev, int state);
+
+static void
+als300_audio_reset (int dev)
+{
+ als300_audio_trigger (dev, 0);
+}
+
+static void
+als300_audio_reset_input (int dev)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
+}
+
+static void
+als300_audio_reset_output (int dev)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
+}
+
+/*ARGSUSED*/
+static int
+als300_audio_open (int dev, int mode, int open_flags)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_devc *devc = audio_engines[dev]->devc;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ if (portc->open_mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+
+ if (devc->open_mode & mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+
+ devc->open_mode |= mode;
+
+ portc->open_mode = mode;
+ portc->audio_enabled &= ~mode;
+
+ if ((mode & OPEN_READ) && !(audio_engines[dev]->flags & ADEV_NOINPUT))
+ {
+ audio_engines[dev]->fixed_rate = 48000;
+ audio_engines[dev]->flags |=
+ ADEV_FIXEDRATE | ADEV_STEREOONLY | ADEV_16BITONLY;
+ audio_engines[dev]->min_rate = 48000;
+ audio_engines[dev]->max_rate = 48000;
+ }
+ else
+ {
+ audio_engines[dev]->min_rate = 5000;
+ audio_engines[dev]->max_rate = 48000;
+ audio_engines[dev]->fixed_rate = 0;
+ audio_engines[dev]->flags &=
+ ~(ADEV_FIXEDRATE | ADEV_STEREOONLY | ADEV_16BITONLY);
+ }
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+
+ return 0;
+}
+
+static void
+als300_audio_close (int dev, int mode)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_devc *devc = audio_engines[dev]->devc;
+
+ als300_audio_reset (dev);
+ portc->open_mode = 0;
+ devc->open_mode &= ~mode;
+ portc->audio_enabled &= ~mode;
+}
+
+/*ARGSUSED*/
+static void
+als300_audio_output_block (int dev, oss_native_word buf, int count,
+ int fragsize, int intrflag)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+
+ portc->audio_enabled |= PCM_ENABLE_OUTPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+}
+
+/*ARGSUSED*/
+static void
+als300_audio_start_input (int dev, oss_native_word buf, int count,
+ int fragsize, int intrflag)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+
+ portc->audio_enabled |= PCM_ENABLE_INPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+}
+
+static void
+als300_audio_trigger (int dev, int state)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_devc *devc = audio_engines[dev]->devc;
+ oss_native_word old82 = 0, new82 = 0, old85 = 0, new85 = 0, mode = 0;
+ oss_native_word flags;
+ int i;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ if (portc->open_mode & OPEN_WRITE)
+ {
+ if (state & PCM_ENABLE_OUTPUT)
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
+ !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
+ {
+ if (portc->bits == 8)
+ mode = 0x00140000L;
+ else if (portc->bits == 16)
+ mode = 0x00000000L;
+ if (portc->channels == 2)
+ mode |= 0x00000000L;
+ else if (portc->channels == 1)
+ mode |= 0x00080000L;
+
+ old82 = gcr_readl (devc, 0x82);
+ new82 = (old82 & 0x0000ffff) | 0x00010000;
+ new82 = new82 | mode | devc->srcode << 22;
+#if 1
+ for (i = 0; i < 5000; i++)
+ {
+ if ((INB (devc->osdev, devc->base + 6) & 0x08) == 0x00)
+ goto PlayStart;
+ oss_udelay (10);
+ }
+ PlayStart:
+#endif
+ gcr_writel (devc, 0x82, new82);
+ portc->trigger_bits |= PCM_ENABLE_OUTPUT;
+ }
+ }
+ else
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
+ (portc->trigger_bits & PCM_ENABLE_OUTPUT))
+ {
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+ portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
+ gcr_writel (devc, 0x82, 0x00);
+ OUTB (devc->osdev, 0x8, devc->base + 7); /* acknowledge interrupt */
+ }
+ }
+ }
+
+ if (portc->open_mode & OPEN_READ)
+ {
+ if (state & PCM_ENABLE_INPUT)
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
+ !(portc->trigger_bits & PCM_ENABLE_INPUT))
+ {
+ old85 = gcr_readl (devc, 0x85);
+ new85 = (old85 & 0x0000ffff) | 0x00010000;
+#if 1
+ for (i = 0; i < 5000; i++)
+ {
+ if ((INB (devc->osdev, devc->base + 6) & 0x08) == 0x00)
+ goto RecStart;
+ oss_udelay (10);
+ }
+ RecStart:
+#endif
+ gcr_writel (devc, 0x85, new85);
+ portc->trigger_bits |= PCM_ENABLE_INPUT;
+ }
+ }
+ else
+ {
+ if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
+ (portc->trigger_bits & PCM_ENABLE_INPUT))
+ {
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+ portc->audio_enabled &= ~PCM_ENABLE_INPUT;
+ gcr_writel (devc, 0x85, 0x00);
+ OUTB (devc->osdev, 0x04, devc->base + 7); /* acknowledge interrupt */
+ }
+ }
+ }
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+}
+
+/*ARGSUSED*/
+unsigned int
+FindClosestFreq (als300_devc * devc, unsigned int sr)
+{
+ unsigned int i, error = 50000, dif, code = 0;
+
+ for (i = 0; i < FNO1; i += 2)
+ {
+ if (sr < FreqTable1[i])
+ dif = FreqTable1[i] - sr;
+ else
+ dif = sr - FreqTable1[i];
+ if (dif < error)
+ {
+ error = dif;
+ code = FreqTable1[i + 1];
+ }
+ }
+ return code;
+}
+
+/*ARGSUSED*/
+static int
+als300_audio_prepare_for_input (int dev, int bsize, int bcount)
+{
+ als300_devc *devc = audio_engines[dev]->devc;
+ als300_portc *portc = audio_engines[dev]->portc;
+ dmap_t *dmap = audio_engines[dev]->dmap_in;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ gcr_writel (devc, 0x85, dmap->fragment_size - 1);
+ gcr_writel (devc, 0x83, dmap->dmabuf_phys);
+ gcr_writel (devc, 0x84, dmap->dmabuf_phys + dmap->bytes_in_use - 1);
+ portc->audio_enabled &= ~PCM_ENABLE_INPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_INPUT;
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+/*ARGSUSED*/
+static int
+als300_audio_prepare_for_output (int dev, int bsize, int bcount)
+{
+ als300_devc *devc = audio_engines[dev]->devc;
+ als300_portc *portc = audio_engines[dev]->portc;
+ dmap_t *dmap = audio_engines[dev]->dmap_out;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+ devc->srcode = FindClosestFreq (devc, portc->speed);
+ gcr_writel (devc, 0x82, (dmap->fragment_size - 1));
+ gcr_writel (devc, 0x80, dmap->dmabuf_phys);
+ gcr_writel (devc, 0x81, dmap->dmabuf_phys + dmap->bytes_in_use - 1);
+ portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
+ portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+#if 0
+static int
+als300_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
+{
+ als300_portc *portc = audio_engines[dev]->portc;
+ als300_devc *devc = audio_engines[dev]->devc;
+
+ unsigned int ptr = 0;
+
+ if (direction == DMODE_OUTPUT)
+ ptr = gcr_readl (devc, 0x9A);
+ if (direction == DMODE_INPUT)
+ ptr = gcr_readl (devc, 0x9B);
+ return ptr;
+}
+#endif
+
+static audiodrv_t als300_audio_driver = {
+ als300_audio_open,
+ als300_audio_close,
+ als300_audio_output_block,
+ als300_audio_start_input,
+ als300_audio_ioctl,
+ als300_audio_prepare_for_input,
+ als300_audio_prepare_for_output,
+ als300_audio_reset,
+ NULL,
+ NULL,
+ als300_audio_reset_input,
+ als300_audio_reset_output,
+ als300_audio_trigger,
+ als300_audio_set_rate,
+ als300_audio_set_format,
+ als300_audio_set_channels,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* als300_alloc_buffer */
+ NULL, /* als300_free_buffer */
+ NULL,
+ NULL,
+ NULL /* als300_get_buffer_pointer */
+};
+
+#ifdef OBSOLETED_STUFF
+/*
+ * This device has "ISA style" MIDI and FM subsystems. Such devices don't
+ * use PCI config space for the I/O ports and interrupts. Instead the driver
+ * needs to allocate proper resources itself. This functionality is no longer
+ * possible. For this reason the MIDI and FM parts are not accessible.
+ */
+static void
+attach_fm (als300_devc * devc)
+{
+ if (!opl3_detect (0x388, devc->osdev))
+ return;
+ opl3_init (0x388, devc->osdev);
+ devc->fm_attached = 1;
+}
+
+static void
+attach_mpu (als300_devc * devc)
+{
+ struct address_info hw_config;
+
+ hw_config.io_base = devc->mpu_base;
+ hw_config.irq = -devc->irq;
+ hw_config.dma = -1;
+ hw_config.dma2 = -1;
+ hw_config.always_detect = 0;
+ hw_config.name = "ALS300 MPU";
+ hw_config.driver_use_1 = 0;
+ hw_config.driver_use_2 = 0;
+ hw_config.osdev = devc->osdev;
+#ifdef CREATE_OSP
+ CREATE_OSP (hw_config.osdev);
+#endif
+ hw_config.card_subtype = 0;
+
+ if (!probe_uart401 (&hw_config))
+ {
+ cmn_err (CE_WARN, "MPU-401 was not detected\n");
+ return;
+ }
+ devc->mpu_attached = 1;
+ attach_uart401 (&hw_config);
+}
+
+static void
+unload_mpu (als300_devc * devc)
+{
+ struct address_info hw_config;
+
+ hw_config.io_base = devc->mpu_base;
+ hw_config.irq = -devc->irq;
+ hw_config.dma = -1;
+ hw_config.dma2 = -1;
+ hw_config.always_detect = 0;
+ hw_config.name = "ALS300 MPU";
+ hw_config.driver_use_1 = 0;
+ hw_config.driver_use_2 = 0;
+ hw_config.osdev = devc->osdev;
+#ifdef CREATE_OSP
+ CREATE_OSP (hw_config.osdev);
+#endif
+ hw_config.card_subtype = 0;
+
+ devc->mpu_attached = 0;
+ unload_uart401 (&hw_config);
+}
+#endif
+
+static int
+init_als300 (als300_devc * devc)
+{
+ int my_mixer;
+ int i;
+ int adev;
+ oss_native_word dwTemp;
+ int first_dev = 0;
+
+ devc->mpu_attached = devc->fm_attached = 0;
+
+/*
+ * Enable BusMasterMode and IOSpace Access
+ */
+ switch (devc->model)
+ {
+ case MDL_ALS300:
+ dwTemp = gcr_readl (devc, 0x98);
+ dwTemp |= devc->mpu_base >> 4;
+ dwTemp = gcr_readl (devc, 0x98);
+ dwTemp |= (1 << 19 | 1 << 18 | 1 << 17 | 1 << 16);
+ gcr_writel (devc, 0x98, dwTemp);
+ gcr_writel (devc, 0x99, 0);
+ dwTemp = gcr_readl (devc, 0x8c);
+ dwTemp |= 0x50;
+ if (devc->chip_rev < 4)
+ dwTemp &= ~0x8000;
+ else
+ dwTemp |= 0x8000;
+ gcr_writel (devc, 0x8c, (dwTemp | 0x50)); /*enable INTA */
+ break;
+
+ case MDL_ALS300PLUS:
+ dwTemp = ((oss_native_word) 0x200 << 16) | (0x388);
+ dwTemp |= 0x00010000; /* enable Game */
+ dwTemp |= 0x00000001; /* enable FM */
+ gcr_writel (devc, 0xa8, dwTemp);
+ dwTemp = (oss_native_word) (devc->mpu_base << 16);
+ dwTemp |= 0x00010000; /* enable MPU */
+ gcr_writel (devc, 0xa9, dwTemp);
+
+ dwTemp = gcr_readl (devc, 0x8c);
+
+ gcr_writel (devc, 0x8c, dwTemp | 0x308050); /*enable INTA */
+ gcr_writel (devc, 0x99, 0); /* no DDMA */
+ break;
+ }
+
+#ifdef OBSOLETED_STUFF
+ attach_fm (devc);
+
+ if (devc->mpu_base > 0)
+ attach_mpu (devc);
+#endif
+
+ if ((my_mixer =
+ ac97_install (&devc->ac97devc, "ALS300 AC97 Mixer", ac97_read,
+ ac97_write, devc, devc->osdev)) >= 0)
+ {
+ devc->mixer_dev = my_mixer;
+ }
+ else
+ return 0;
+
+ for (i = 0; i < MAX_PORTC; i++)
+ {
+ char tmp_name[100];
+ als300_portc *portc = &devc->portc[i];
+ int caps = ADEV_AUTOMODE;
+
+ if (i == 0)
+ {
+ sprintf (tmp_name, "%s (Rev %c)", devc->chip_name,
+ 'A' + devc->chip_rev);
+ caps |= ADEV_DUPLEX;
+ }
+ else
+ {
+ sprintf (tmp_name, "%s (shadow)", devc->chip_name);
+ caps |= ADEV_DUPLEX | ADEV_SHADOW;
+ }
+
+ if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
+ devc->osdev,
+ devc->osdev,
+ tmp_name,
+ &als300_audio_driver,
+ sizeof (audiodrv_t),
+ caps,
+ AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0)
+ {
+ adev = -1;
+ return 0;
+ }
+ else
+ {
+ if (i == 0)
+ first_dev = adev;
+ audio_engines[adev]->portc = portc;
+ audio_engines[adev]->mixer_dev = my_mixer;
+ audio_engines[adev]->rate_source = first_dev;
+ audio_engines[adev]->mixer_dev = my_mixer;
+ audio_engines[adev]->min_block = 4096;
+ audio_engines[adev]->max_block = 4096;
+ audio_engines[adev]->min_rate = 5000;
+ audio_engines[adev]->max_rate = 48000;
+ audio_engines[adev]->caps |= PCM_CAP_FREERATE;
+
+ portc->open_mode = 0;
+ portc->audiodev = adev;
+ portc->audio_enabled = 0;
+#ifdef CONFIG_OSS_VMIX
+ if (i == 0)
+ vmix_attach_audiodev(devc->osdev, adev, -1, 0);
+#endif
+ }
+
+ }
+
+ return 1;
+}
+
+int
+oss_als3xx_attach (oss_device_t * osdev)
+{
+ unsigned char pci_irq_line, pci_revision;
+ unsigned short pci_command, vendor, device;
+ unsigned int pci_ioaddr;
+ int err;
+ als300_devc *devc;
+
+ DDB (cmn_err (CE_WARN, "Entered ALS ALS300 probe routine\n"));
+
+
+ pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
+ pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
+ pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
+ pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
+ pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr);
+
+ if (vendor != ALS_VENDOR_ID || (device != ALS_300 && device != ALS_300P))
+ return 0;
+
+ DDB (cmn_err (CE_WARN, "rev %x I/O base %04x\n", pci_revision, pci_ioaddr));
+
+ if (pci_ioaddr == 0)
+ {
+ cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
+ return 0;
+ }
+
+ if (pci_irq_line == 0)
+ {
+ cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d).\n", pci_irq_line);
+ return 0;
+ }
+
+ if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
+ {
+ cmn_err (CE_WARN, "Out of memory\n");
+ return 0;
+ }
+
+ devc->osdev = osdev;
+ osdev->devc = devc;
+ devc->open_mode = 0;
+
+ devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr);
+ /* Remove I/O space marker in bit 0. */
+ devc->base &= ~3;
+
+ devc->irq = pci_irq_line;
+ devc->mpu_base = als300_mpu_base;
+
+ pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
+ pci_write_config_word (osdev, PCI_COMMAND, pci_command);
+
+
+ switch (device)
+ {
+ case ALS_300:
+ devc->model = MDL_ALS300;
+ devc->chip_name = "Avance Logic ALS300";
+ devc->chip_rev = pci_revision;
+ break;
+
+ case ALS_300P:
+ devc->model = MDL_ALS300PLUS;
+ devc->chip_name = "Avance Logic ALS300+";
+ devc->chip_rev = pci_revision;
+ break;
+ }
+
+ MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
+ MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
+
+ oss_register_device (osdev, devc->chip_name);
+
+ if ((err = oss_register_interrupts (devc->osdev, 0, als300intr, NULL)) < 0)
+ {
+ cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err);
+ return 0;
+ }
+
+ return init_als300 (devc); /* Detected */
+}
+
+int
+oss_als3xx_detach (oss_device_t * osdev)
+{
+ als300_devc *devc = (als300_devc *) osdev->devc;
+ unsigned int dwTemp;
+
+ if (oss_disable_device (osdev) < 0)
+ return 0;
+
+ if (devc->model == MDL_ALS300PLUS)
+ {
+ dwTemp = gcr_readl (devc, 0x8c);
+ gcr_writel (devc, 0x8c, dwTemp &= ~0x8000);
+ }
+#ifdef OBSOLETED_STUFF
+ if (devc->mpu_attached)
+ unload_mpu (devc);
+#endif
+ oss_unregister_interrupts (devc->osdev);
+
+ MUTEX_CLEANUP (devc->mutex);
+ MUTEX_CLEANUP (devc->low_mutex);
+ UNMAP_PCI_IOADDR (devc->osdev, 0);
+
+ oss_unregister_device (devc->osdev);
+ return 1;
+}
diff --git a/attic/drv/oss_als3xx/oss_als3xx.man b/attic/drv/oss_als3xx/oss_als3xx.man
new file mode 100644
index 0000000..97b9dcf
--- /dev/null
+++ b/attic/drv/oss_als3xx/oss_als3xx.man
@@ -0,0 +1,19 @@
+NAME
+oss_als3xx - Avance Logic ALS300 audio driver.
+
+DESCRIPTION
+Open Sound System driver for Avance Logic ALS300 based soundcards.
+
+OPTIONS
+o als300_mpu_base=<xxx> - set the ALS MPU 401 base I/O adress to one of
+ the legal values as described in the /plaform/i86pc/kernel/drv/als300.conf
+ file. This I/O address must not conflict with any other MIDI devices or
+ any other I/O adapters.
+
+ eg: als3xx_mpu_base=0x300
+FILES
+CONFIGFILEPATH/oss_als3xx.conf
+
+AUTHOR
+4Front Technologies
+