diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
commit | 1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch) | |
tree | 4495d23e7b54ab5700e3839081e797c1eafe0db9 /kernel/drv | |
download | oss4-upstream.tar.gz |
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'kernel/drv')
242 files changed, 102767 insertions, 0 deletions
diff --git a/kernel/drv/.config b/kernel/drv/.config new file mode 100644 index 0000000..8969ff4 --- /dev/null +++ b/kernel/drv/.config @@ -0,0 +1 @@ +mode=module diff --git a/kernel/drv/oss_ali5455/.devices b/kernel/drv/oss_ali5455/.devices new file mode 100644 index 0000000..4eff6e6 --- /dev/null +++ b/kernel/drv/oss_ali5455/.devices @@ -0,0 +1 @@ +oss_ali5455 pci10b9,5455 ALI M5455 diff --git a/kernel/drv/oss_ali5455/.name b/kernel/drv/oss_ali5455/.name new file mode 100644 index 0000000..d3bc019 --- /dev/null +++ b/kernel/drv/oss_ali5455/.name @@ -0,0 +1 @@ +ALI M5455 chipset diff --git a/kernel/drv/oss_ali5455/oss_ali5455.c b/kernel/drv/oss_ali5455/oss_ali5455.c new file mode 100644 index 0000000..ce96844 --- /dev/null +++ b/kernel/drv/oss_ali5455/oss_ali5455.c @@ -0,0 +1,979 @@ +/* + * Purpose: Driver for the ALI 5455 (AC97) 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_ali5455_cfg.h" +#include <oss_pci.h> +#include <ac97.h> + +#define ALI_VENDOR_ID 0x10b9 +#define ALI_DEVICE_5455 0x5455 + +#define MAX_ALI5455 1 +#define MAX_PORTC 3 +#define BDL_SIZE 32 + +#ifdef OSS_BIG_ENDIAN +static __inline__ unsigned int +swap32 (unsigned int x) +{ + return ((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24); +} + +static __inline__ unsigned short +swap16 (unsigned short x) +{ + return ((x >> 8) & 0xff) | ((x & 0xff) << 8); +} + +#define SWAP32(x) swap32(x) +#define SWAP16(x) swap16(x) +#else +#define SWAP32(x) x +#define SWAP16(x) x +#endif + +typedef struct +{ + int open_mode; + int speed, bits, channels; + int audio_enabled; + int trigger_bits; + int audiodev; + int port_type; +#define DF_PCM 0 +#define DF_SPDIF 1 +} +ALI_portc; + +typedef struct +{ + unsigned int addr; + unsigned short size; + unsigned short flags; +} +bdl_t; + +typedef struct ALI_devc +{ + oss_device_t *osdev; + oss_native_word base; + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* Mixer */ + ac97_devc ac97devc; + int mixer_dev; + + /* Audio parameters */ + int open_mode; + + /* Buffer Descriptor List */ + char *bdlBuffer; + bdl_t *playBDL, *recBDL, *spdifBDL; + oss_native_word playBDL_phys, recBDL_phys, spdifBDL_phys; + oss_dma_handle_t bdl_dma_handle; + + int play_currbuf, play_currfrag; + int spdif_currbuf, spdif_currfrag; + int rec_currbuf, rec_currfrag; + char *chip_name; + ALI_portc portc[MAX_PORTC]; + int play_frag_index[BDL_SIZE]; + int rec_frag_index[BDL_SIZE]; + int spdif_frag_index[BDL_SIZE]; +} +ALI_devc; + +static int +ac97_read (void *devc_, int reg) +{ + ALI_devc *devc = devc_; + int i = 100; + unsigned int status; + unsigned int data = 0; + unsigned short read_reg = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + status = INB (devc->osdev, devc->base + 0x34); + + /* wait for the Codec Access Semaphore bit to be set */ + while (i-- && (INL (devc->osdev, devc->base + 0x3c) & 0x80000000)) + oss_udelay (1); + + for (i = 0; i < 100; i++) + { + status = INB (devc->osdev, devc->base + 0x38); + if (status & 0x08) + break; + } + if (i == 100) + { + cmn_err (CE_WARN, "AC97 not ready for read\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + OUTW (devc->osdev, reg | 0x80, devc->base + 0x22); + + for (i = 0; i < 100; i++) + { + status = INB (devc->osdev, devc->base + 0x38); + + if (status & 0x02) + { + + data = INW (devc->osdev, devc->base + 0x24); + read_reg = INW (devc->osdev, devc->base + 0x26); + break; + } + } + + if (i == 100) + { + cmn_err (CE_WARN, "AC97 read timed out \n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + if (read_reg != reg) + { + cmn_err (CE_WARN, "AC97 invalid reg read %x (%x)\n", read_reg, reg); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return data; +} + +static int +ac97_write (void *devc_, int reg, int data) +{ + ALI_devc *devc = devc_; + int i = 100, status; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* wait for the Codec Access Semaphore bit to be set */ + while (i-- && (INL (devc->osdev, devc->base + 0x3c) & 0x80000000)) + oss_udelay (1); + + /* wait until command port is ready for write */ + for (i = 0; i < 100; i++) + { + status = INB (devc->osdev, devc->base + 0x38); + if (status & 0x01) + break; + } + + if (i == 100) + { + cmn_err (CE_WARN, "AC97 timed out for write\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + OUTL (devc->osdev, reg << 16 | data, devc->base + 0x20); + + for (i = 0; i < 100; i++) + { + status = INB (devc->osdev, devc->base + 0x38); + if (status & 0x01) + break; + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +ALIintr (oss_device_t * osdev) +{ + int status, global_status, p, f, i; + int serviced = 0; + ALI_devc *devc = (ALI_devc *) osdev->devc; + ALI_portc *portc; + /* oss_native_word flags; */ + + /* Handle playback */ + /* + * TODO: Fix mutexes and move the inputintr/outputintr calls outside the + * mutex block. + */ + + /* MUTEX_ENTER (devc->mutex, flags); */ + /* Handle Global Interrupts */ + global_status = INL (devc->osdev, devc->base + 0x18); + OUTL (devc->osdev, global_status, devc->base + 0x18); + + if (!(global_status & (0x10000 | 0x20000 | 0x80000 | 0x100000 | 0x200000))) + { + /* MUTEX_EXIT (devc->mutex, flags); */ + return serviced; + } + + /* Handle Playback Interrupts */ + + status = INB (devc->osdev, devc->base + 0x56); + + if ((status & 0x08) && (global_status & 0x20000)) + for (i = 0; i < MAX_PORTC - 1; i++) + { + portc = &devc->portc[i]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + p = INB (devc->osdev, devc->base + 0x54); + + if (p != devc->play_currbuf) + { + p = devc->play_currbuf; + f = devc->play_currfrag; + devc->playBDL[p].addr = + SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size)); + + devc->playBDL[p].size = SWAP16 (dmap->fragment_size / 2); + devc->playBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */ + + OUTB (devc->osdev, p, devc->base + 0x55); /* Set LVD */ + devc->play_frag_index[p] = f; + devc->play_currbuf = (p + 1) % BDL_SIZE; + devc->play_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_outputintr (portc->audiodev, 1); + } + } + OUTB (devc->osdev, status, devc->base + 0x56); /* Clear interrupts */ + +/*--------------------------------------------------------------------------*/ + /* handle SPDIF interrupts */ + + status = INB (devc->osdev, devc->base + 0x76); + if ((status & 0x08) && (global_status & 0x80000)) + { + portc = &devc->portc[2]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + p = INB (devc->osdev, devc->base + 0x74); + + if (p != devc->spdif_currbuf) + { + p = devc->spdif_currbuf; + f = devc->spdif_currfrag; + devc->spdifBDL[p].addr = + SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size)); + + devc->spdifBDL[p].size = SWAP16 (dmap->fragment_size / 2); + devc->spdifBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */ + + OUTB (devc->osdev, p, devc->base + 0x75); /* Set LVD */ + devc->spdif_frag_index[p] = f; + devc->spdif_currbuf = (p + 1) % BDL_SIZE; + devc->spdif_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_outputintr (portc->audiodev, 1); + } + } + OUTB (devc->osdev, status, devc->base + 0x76); /* Clear interrupts */ +/*---------------------------------------------------------------------------*/ + + /* Handle Recording Interrupts */ + status = INB (devc->osdev, devc->base + 0x46); + + if ((status & 0x08) && (global_status & 0x10000)) + for (i = 0; i < MAX_PORTC - 1; i++) + { + portc = &devc->portc[i]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_INPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in; + p = INB (devc->osdev, devc->base + 0x44); + + if (p != devc->rec_currbuf) + { + p = devc->rec_currbuf; + f = devc->rec_currfrag; + devc->recBDL[p].addr = + SWAP32 (dmap->dmabuf_phys + (f * dmap->fragment_size)); + + /* SIS uses bytes, ali5455 uses samples */ + devc->recBDL[p].size = SWAP16 (dmap->fragment_size / 2); + + devc->recBDL[p].flags = SWAP16 (0xc000); /* IOC interrupts */ + + OUTB (devc->osdev, p, devc->base + 0x45); /* Set LVD */ + devc->rec_frag_index[p] = f; + devc->rec_currbuf = (p + 1) % BDL_SIZE; + devc->rec_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_inputintr (portc->audiodev, 0); + } + } + OUTB (devc->osdev, status, devc->base + 0x46); /* Clear int */ + + /* MUTEX_EXIT (devc->mutex, flags); */ + return serviced; +} + +/* + * Audio routines + */ + +static int +ALI_audio_set_rate (int dev, int arg) +{ + ALI_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 +ALI_audio_set_channels (int dev, short arg) +{ + ALI_portc *portc = audio_engines[dev]->portc; + + if ((arg == 1) || (arg == 2)) + { + audio_engines[dev]->flags |= ADEV_STEREOONLY; + arg = 2; + } + else + audio_engines[dev]->flags &= ~ADEV_STEREOONLY; + + if (arg>6) + arg=6; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +ALI_audio_set_format (int dev, unsigned int arg) +{ + ALI_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +ALI_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void ALI_audio_trigger (int dev, int state); + +static void +ALI_audio_reset (int dev) +{ + ALI_audio_trigger (dev, 0); +} + +static void +ALI_audio_reset_input (int dev) +{ + ALI_portc *portc = audio_engines[dev]->portc; + ALI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +ALI_audio_reset_output (int dev) +{ + ALI_portc *portc = audio_engines[dev]->portc; + ALI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +ALI_audio_open (int dev, int mode, int openflags) +{ + ALI_portc *portc = audio_engines[dev]->portc; + ALI_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 (portc->port_type == DF_SPDIF) + { + if (mode & OPEN_READ) + { + cmn_err (CE_WARN, + "ICH: The S/PDIF device supports only playback\n"); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EIO; + } + } + else + { + 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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +ALI_audio_close (int dev, int mode) +{ + ALI_portc *portc = audio_engines[dev]->portc; + ALI_devc *devc = audio_engines[dev]->devc; + + ALI_audio_reset (dev); + portc->open_mode = 0; + + if (portc->port_type != DF_SPDIF) + devc->open_mode &= ~mode; + + + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +ALI_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ALI_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +ALI_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ALI_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +ALI_audio_trigger (int dev, int state) +{ + ALI_devc *devc = audio_engines[dev]->devc; + ALI_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + 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->port_type == DF_SPDIF) + { + OUTB (devc->osdev, 0x1d, devc->base + 0x7b); /* Setup intr */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x08, devc->base + 0x08); /* start DMA */ + } + + if (portc->port_type == DF_PCM) + { + OUTB (devc->osdev, 0x1d, devc->base + 0x5b); /* setup intr */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x02, devc->base + 0x08); /* start DMA */ + } + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + if (portc->port_type == DF_SPDIF) + { + OUTB (devc->osdev, 0x00, devc->base + 0x7b); /* reset */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x08, devc->base + 0x08); /* stop DMA */ + } + + if (portc->port_type == DF_PCM) + { + OUTB (devc->osdev, 0x00, devc->base + 0x5b); /* reset */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x02, devc->base + 0x08); /* stop DMA */ + } + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + OUTB (devc->osdev, 0x1d, devc->base + 0x4b); /* Kickstart */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) | 0x01, devc->base + 0x08); /* stop DMA */ + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + OUTB (devc->osdev, 0x00, devc->base + 0x4b); /* reset */ + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x08) & ~0x01, devc->base + 0x08); /* stop DMA */ + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +ALI_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + ALI_devc *devc = audio_engines[dev]->devc; + ALI_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int i, n; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + OUTB (devc->osdev, 0x02, devc->base + 0x4b); /* Reset */ + OUTL (devc->osdev, devc->recBDL_phys, devc->base + 0x40); /* BDL base */ + + ac97_recrate (&devc->ac97devc, portc->speed); + + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->recBDL[i].addr = + SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size)); + devc->recBDL[i].size = SWAP16 (dmap->fragment_size / 2); + devc->recBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */ + devc->rec_frag_index[i] = i; + } + OUTB (devc->osdev, n - 1, devc->base + 0x45); /* Set last valid descriptor */ + + devc->rec_currbuf = n % BDL_SIZE; + devc->rec_currfrag = n; + if (devc->rec_currfrag >= dmap->nfrags) + devc->rec_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +ALI_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + ALI_devc *devc = audio_engines[dev]->devc; + ALI_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int i, n; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_AUDIO, SNDCTL_MIX_WRITE, 0); + ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits); + + if (portc->bits == AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + } + + /* do SPDIF out */ + if (portc->port_type == DF_SPDIF) + { + ac97_playrate (&devc->ac97devc, portc->speed); + OUTB (devc->osdev, 0x02, devc->base + 0x7b); /* Reset */ + OUTL (devc->osdev, devc->spdifBDL_phys, devc->base + 0x70); + + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->spdifBDL[i].addr = + SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size)); + devc->spdifBDL[i].size = SWAP16 (dmap->fragment_size / 2); + devc->spdifBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */ + devc->spdif_frag_index[i] = i; + } + OUTB (devc->osdev, n - 1, devc->base + 0x75); /* Set LVI descriptor */ + devc->spdif_currbuf = n % BDL_SIZE; + devc->spdif_currfrag = n; + if (devc->spdif_currfrag >= dmap->nfrags) + devc->spdif_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + /* else do PCM */ + OUTB (devc->osdev, 0x02, devc->base + 0x5b); /* Reset */ + OUTL (devc->osdev, devc->playBDL_phys, devc->base + 0x50); + + ac97_playrate (&devc->ac97devc, portc->speed); + + /* set default to 2 channel mode */ + if (portc->channels == 2) + OUTW (devc->osdev, INW (devc->osdev, devc->base + 0x00) & ~0x300, + devc->base + 0x00); + if (portc->channels == 4) + OUTW (devc->osdev, + (INW (devc->osdev, devc->base + 0x00) & ~0x300) | 0x100, + devc->base + 0x00); + if (portc->channels == 6) + OUTW (devc->osdev, + (INW (devc->osdev, devc->base + 0x00) & ~0x300) | 0x200, + devc->base + 0x00); + + + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->playBDL[i].addr = + SWAP32 (dmap->dmabuf_phys + (i * dmap->fragment_size)); + devc->playBDL[i].size = SWAP16 (dmap->fragment_size / 2); + devc->playBDL[i].flags = SWAP16 (0xc000); /* IOC interrupts */ + devc->play_frag_index[i] = i; + } + OUTB (devc->osdev, n - 1, devc->base + 0x55); /* Set last valid descriptor */ + + devc->play_currbuf = n % BDL_SIZE; + devc->play_currfrag = n; + if (devc->play_currfrag >= dmap->nfrags) + devc->play_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static const audiodrv_t ALI_audio_driver = { + ALI_audio_open, + ALI_audio_close, + ALI_audio_output_block, + ALI_audio_start_input, + ALI_audio_ioctl, + ALI_audio_prepare_for_input, + ALI_audio_prepare_for_output, + ALI_audio_reset, + NULL, + NULL, + ALI_audio_reset_input, + ALI_audio_reset_output, + ALI_audio_trigger, + ALI_audio_set_rate, + ALI_audio_set_format, + ALI_audio_set_channels +}; + +static int +init_ALI (ALI_devc * devc) +{ + int my_mixer, my_dev, opts; + oss_native_word phaddr; + int i; + + /* ACLink on, warm reset */ + OUTL (devc->osdev, 0x80008003, devc->base + 0x00); /*reset SCR */ + OUTL (devc->osdev, 0x83838383, devc->base + 0x0c); /*reset pcm in/out FIFO */ + OUTL (devc->osdev, 0x83838383, devc->base + 0x1c); /*reset SPDIF/LFEr FIFO */ + OUTL (devc->osdev, 0x0028000a, devc->base + 0x10); /*set spdif/pcm in/out */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0xFC) | 0x3, + devc->base + 0xFC); + + /* set up Codec SPDIFOUT slot to 10/11 */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x00) | 0x300000, + devc->base + 0x00); + /* disable interrupts */ + OUTL (devc->osdev, 0x00, devc->base + 0x14); + OUTL (devc->osdev, 0x00, devc->base + 0x18); + + devc->bdlBuffer = + CONTIG_MALLOC (devc->osdev, 4 * 32 * 32, MEMLIMIT_32BITS, &phaddr, devc->bdl_dma_handle); + if (devc->bdlBuffer == NULL) + { + cmn_err (CE_WARN, "Failed to allocate BDL\n"); + return 0; + } + + devc->playBDL = (bdl_t *) devc->bdlBuffer; + devc->playBDL_phys = phaddr; + devc->recBDL = (bdl_t *) (devc->bdlBuffer + (1 * 32 * 32)); + devc->recBDL_phys = phaddr + (1 * 32 * 32); + devc->spdifBDL = (bdl_t *) (devc->bdlBuffer + (2 * 32 * 32)); + devc->spdifBDL_phys = phaddr + (2 * 32 * 32); + +/* + * Init mixer + */ + my_mixer = + ac97_install (&devc->ac97devc, "AC97 Mixer", ac97_read, ac97_write, devc, + devc->osdev); + + if (my_mixer == -1) + return 0; /* No mixer */ + + devc->mixer_dev = my_mixer; + + /* enable S/PDIF */ + devc->ac97devc.spdif_slot = SPDIF_SLOT1011; + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1); + +#if 0 + /* enable variable rate mode */ + ac97_write (devc, 0x2a, ac97_read (devc, 0x2a) | 9); + if (!(ac97_read (devc, 0x2a) & 1)) + DDB (cmn_err (CE_WARN, "VRA not supported...using GRC\n")); +#endif + + for (i = 0; i < MAX_PORTC; i++) + { + ALI_portc *portc = &devc->portc[i]; + char tmp_name[100]; + int port_fmt = DF_PCM; + int formats = AFMT_S16_LE | AFMT_AC3; + strcpy (tmp_name, devc->chip_name); + opts = ADEV_AUTOMODE | ADEV_16BITONLY | ADEV_STEREOONLY; + portc->port_type = DF_PCM; + + if (!ac97_varrate (&devc->ac97devc)) + { + opts |= ADEV_FIXEDRATE; + } + + if (i == 0) + { + opts |= ADEV_DUPLEX; + strcpy (tmp_name, devc->chip_name); + } + if (i == 1) + { + opts |= ADEV_DUPLEX | ADEV_SHADOW; + strcpy (tmp_name, devc->chip_name); + } + + if (i == 2) + { + sprintf (tmp_name, "%s (S/PDIF)", devc->chip_name); + opts |= ADEV_NOINPUT | ADEV_SPECIAL | ADEV_FIXEDRATE; + port_fmt = DF_SPDIF; + } + + if ((my_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &ALI_audio_driver, + sizeof (audiodrv_t), opts, + formats, devc, -1)) < 0) + { + my_dev = -1; + return 0; + } + else + { + audio_engines[my_dev]->portc = portc; + audio_engines[my_dev]->mixer_dev = my_mixer; + audio_engines[my_dev]->min_rate = + (opts & ADEV_FIXEDRATE) ? 48000 : 5000; + audio_engines[my_dev]->max_rate = 48000; + audio_engines[my_dev]->caps |= PCM_CAP_FREERATE; + /*audio_engines[my_dev]->min_block = 4096; */ + /*audio_engines[my_dev]->max_block = 4096; */ + audio_engines[my_dev]->min_channels = 2; + audio_engines[my_dev]->max_channels = 6; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = my_dev; + portc->port_type = port_fmt; + if (audio_engines[my_dev]->flags & ADEV_FIXEDRATE) + audio_engines[my_dev]->fixed_rate = 48000; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, my_dev, -1, 0); +#endif + } + } + return 1; +} + + +int +oss_ali5455_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr0; + ALI_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered ALI AC97 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if ((vendor != ALI_VENDOR_ID) || (device != ALI_DEVICE_5455)) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr0); + + if (pci_ioaddr0 == 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; + + /* Remove I/O space marker in bit 0. */ + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr0); + devc->base &= ~0xF; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->chip_name = "ALI M5455"; + devc->irq = pci_irq_line; + + 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 (oss_register_interrupts (devc->osdev, 0, ALIintr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to install interrupt handler\n"); + return 0; + } + + return init_ALI (devc); /* Detected */ +} + + +int +oss_ali5455_detach (oss_device_t * osdev) +{ + ALI_devc *devc = (ALI_devc *) osdev->devc; + + + if (oss_disable_device (osdev) < 0) + return 0; + + /* disable S/PDIF */ + if (devc->mixer_dev) + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0); + /* disable interrupts */ + OUTL (devc->osdev, 0x00, devc->base + 0x14); + OUTL (devc->osdev, 0x00, devc->base + 0x18); + + oss_unregister_interrupts (devc->osdev); + + if (devc->bdlBuffer) + { + CONTIG_FREE (devc->osdev, devc->bdlBuffer, 4 * 32 * 32, devc->bdl_dma_handle); + devc->bdlBuffer = NULL; + } + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_ali5455/oss_ali5455.man b/kernel/drv/oss_ali5455/oss_ali5455.man new file mode 100644 index 0000000..bab3621 --- /dev/null +++ b/kernel/drv/oss_ali5455/oss_ali5455.man @@ -0,0 +1,20 @@ +NAME +oss_ali5455 - ALIM5455 audio driver. + +DESCRIPTION +Open Sound System driver for onboard audio on ALI M5455 motherboards. This +driver is very similar to the Intel ICH driver. + +ALI 5455 device characteristics: + o 8/16 bit playback/record + o mono/stereo/4/5.1 channel playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_ali5455.conf Device configuration file + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_atiaudio/.config b/kernel/drv/oss_atiaudio/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_atiaudio/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_atiaudio/.devices b/kernel/drv/oss_atiaudio/.devices new file mode 100644 index 0000000..703bd00 --- /dev/null +++ b/kernel/drv/oss_atiaudio/.devices @@ -0,0 +1,3 @@ +oss_atiaudio pci1002,4341 ATI IXP200 +oss_atiaudio pci1002,4361 ATI IXP300 +oss_atiaudio pci1002,4370 ATI IXP400 diff --git a/kernel/drv/oss_atiaudio/.name b/kernel/drv/oss_atiaudio/.name new file mode 100644 index 0000000..7d242bd --- /dev/null +++ b/kernel/drv/oss_atiaudio/.name @@ -0,0 +1 @@ +ATI IXP motherboard audio diff --git a/kernel/drv/oss_atiaudio/oss_atiaudio.c b/kernel/drv/oss_atiaudio/oss_atiaudio.c new file mode 100644 index 0000000..6727894 --- /dev/null +++ b/kernel/drv/oss_atiaudio/oss_atiaudio.c @@ -0,0 +1,1147 @@ +/* + * Purpose: Driver for the ATI IXP (AC97) 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_atiaudio_cfg.h" +#include "oss_pci.h" +#include "ac97.h" + +#define ATI_VENDOR_ID 0x1002 +#define ATI_DEVICE_IXP 0x4341 +#define ATI_DEVICE_IXP300 0x4361 +#define ATI_DEVICE_IXP400 0x4370 + +#define MAX_PORTC 3 +#define BDL_SIZE 64 + +typedef struct +{ + int open_mode; + int speed, bits, channels; + int audio_enabled; + int trigger_bits; + int audiodev; + int port_type; +#define DF_ANALOG 0 +#define DF_SPDIF 1 +} +ATI_portc; + +typedef struct +{ + unsigned int addr; + unsigned short status; + unsigned short size; + unsigned int next; +} +bdl_t; + +typedef struct +{ + oss_device_t *osdev; + oss_native_word membar_addr; + char *membar_virt; + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* Mixer */ + ac97_devc ac97devc; + int mixer_dev; + int inverted; + + /* Audio parameters */ + int open_mode; + + /* Buffer Descriptor List */ + char *bdlBuffer; + bdl_t *playBDL, *recBDL, *spdifBDL; + oss_native_word playBDL_phys, recBDL_phys, spdifBDL_phys; + oss_dma_handle_t bldbuf_dma_handle; + + int play_currbuf, play_currfrag; + int rec_currbuf, rec_currfrag; + char *chip_name; + ATI_portc portc[MAX_PORTC]; + int play_frag_index[BDL_SIZE]; + int rec_frag_index[BDL_SIZE]; +} +ATI_devc; + + +/* Mem mapped I/O registers */ +#define READL(o,a) *(volatile unsigned int*)(devc->membar_virt+(a)) +#define READW(o,a) *(volatile unsigned short*)(devc->membar_virt+(a)) +#define READB(o,a) *(volatile unsigned char*)(devc->membar_virt+(a)) +#define WRITEL(o,d,a) *(volatile unsigned int*)(devc->membar_virt+(a))=d +#define WRITEW(o,d,a) *(volatile unsigned short*)(devc->membar_virt+(a))=d +#define WRITEB(o,d,a) *(volatile unsigned char*)(devc->membar_virt+(a))=d + + +static int +ac97_ready (void *devc_) +{ + ATI_devc *devc = devc_; + int timeout = 10000; + + while (READL (devc->osdev, 0x0c) & 0x100) + { + if (!timeout--) + { + cmn_err (CE_WARN, "codec ready timed out\n"); + return OSS_EIO; + } + oss_udelay (10); + } + return 0; +} + +static int +ac97_read (void *devc_, int reg) +{ + ATI_devc *devc = devc_; + unsigned int data = 0; + unsigned int addr = 0; + int timeout; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + +again: + if (ac97_ready (devc) < 0) + { + cmn_err (CE_WARN, "ac97 not ready\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + + addr = (unsigned int) (reg << 9) | (1 << 8) | (1 << 2); + WRITEL (devc->osdev, addr, 0x0c); /* Set read commmand */ + + if (ac97_ready (devc) < 0) + { + cmn_err (CE_WARN, "ac97 not ready\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + + timeout = 1000; + + for (;;) + { + data = READL (devc->osdev, 0x10); /* ac97 data port */ + if (data & 0x100) + { + /* if the register returned isn't the reg sent then resend command */ + if ((data & 0xFE00) != (reg << 9)) + goto again; + else + break; + } + + if (!--timeout) + { + cmn_err (CE_WARN, "AC97 read timed out\n"); + break; + } + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (data >> 16); +} + + +static int +ac97_write (void *devc_, int reg, int data) +{ + ATI_devc *devc = devc_; + oss_native_word flags; + unsigned int val; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (ac97_ready (devc) < 0) + { + cmn_err (CE_WARN, "AC97 not ready\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + val = (data << 16) | (reg << 9) | 0x100; + WRITEL (devc->osdev, val, 0x0c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +ATIIXPintr (oss_device_t * osdev) +{ + int status, i; + int serviced = 0; + ATI_devc *devc = (ATI_devc *) osdev->devc; + ATI_portc *portc; + /* oss_native_word flags; */ + +/* + * TODO: Enable the mutexes and move inputintr/outputintr calls outside the + * mutex region. + */ + + /* MUTEX_ENTER (devc->mutex, flags); */ + /* Handle Global Interrupts */ + status = READL (devc->osdev, 0x00); + + /* handle PCM output */ + if (status & 0x08) + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) + && (portc->port_type == DF_ANALOG)) + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + int ptr=0, n = 0; + int timeout = 1000; + serviced = 1; + while (timeout--) + { + ptr = READL (devc->osdev, 0x44); + + if (ptr < dmap->dmabuf_phys) + continue; + + ptr -= dmap->dmabuf_phys; + + if (ptr >= dmap->bytes_in_use) + continue; + + break; + } + + if (dmap->fragment_size == 0) + { + cmn_err (CE_WARN, "dmap->fragment_size == 0\n"); + continue; + } + + ptr /= dmap->fragment_size; + + if ((ptr < 0) || (ptr > dmap->nfrags)) + ptr = 0; + + n = 0; + while ((dmap_get_qhead (dmap) != ptr) && (n++ < dmap->nfrags)) + oss_audio_outputintr (portc->audiodev, 1); + } + } + + /* handle PCM input */ + if (status & 0x02) + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + if ((portc->trigger_bits & PCM_ENABLE_INPUT) + && (portc->port_type == DF_ANALOG)) + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in; + int ptr=0, n = 0; + int timeout = 1000; + serviced = 1; + + while (timeout--) + { + ptr = READL (devc->osdev, 0x2c); + + if (ptr < dmap->dmabuf_phys) + continue; + + ptr -= dmap->dmabuf_phys; + + if (ptr >= dmap->bytes_in_use) + continue; + + break; + } + + if (dmap->fragment_size == 0) + { + cmn_err (CE_WARN, "dmap->fragment_size == 0\n"); + continue; + } + + ptr /= dmap->fragment_size; + + if ((ptr < 0) || (ptr > dmap->nfrags)) + ptr = 0; + + n = 0; + while ((dmap_get_qtail (dmap) != ptr) && (n++ < dmap->nfrags)) + oss_audio_inputintr (portc->audiodev, 0); + } + } + + /* handle SPDIF output */ + if (status & 0x20) + { + portc = &devc->portc[2]; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) + && (portc->port_type == DF_SPDIF)) + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + int ptr=0, n = 0; + int timeout = 1000; + serviced = 1; + + while (timeout--) + { + ptr = READL (devc->osdev, 0x5c); + if (ptr < dmap->dmabuf_phys) + continue; + ptr -= dmap->dmabuf_phys; + if (ptr >= dmap->bytes_in_use) + continue; + break; + } + + if (dmap->fragment_size == 0) + cmn_err (CE_WARN, "dmap->fragment_size == 0\n"); + else + { + ptr /= dmap->fragment_size; + + if ((ptr < 0) || (ptr > dmap->nfrags)) + ptr = 0; + + n = 0; + while ((dmap_get_qhead (dmap) != ptr) && (n++ < dmap->nfrags)) + oss_audio_outputintr (portc->audiodev, 1); + } + } + } + + /* Acknowledge Interrupts */ + WRITEL (devc->osdev, status, 0x00); + /* MUTEX_EXIT (devc->mutex, flags); */ + return serviced; +} + +/* + * Audio routines + */ + +static int +ATI_audio_set_rate (int dev, int arg) +{ + ATI_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 +ATI_audio_set_channels (int dev, short arg) +{ + ATI_portc *portc = audio_engines[dev]->portc; + + if ((arg == 1) || (arg == 2)) + { + audio_engines[dev]->flags |= ADEV_STEREOONLY; + arg = 2; + } + else + audio_engines[dev]->flags &= ~ADEV_STEREOONLY; + + if (arg>6) + arg=6; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +ATI_audio_set_format (int dev, unsigned int arg) +{ + ATI_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +ATI_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void ATI_audio_trigger (int dev, int state); + +static void +ATI_audio_reset (int dev) +{ + ATI_audio_trigger (dev, 0); +} + +static void +ATI_audio_reset_input (int dev) +{ + ATI_portc *portc = audio_engines[dev]->portc; + ATI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +ATI_audio_reset_output (int dev) +{ + ATI_portc *portc = audio_engines[dev]->portc; + ATI_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +ATI_audio_open (int dev, int mode, int openflags) +{ + ATI_portc *portc = audio_engines[dev]->portc; + ATI_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode || (devc->open_mode & mode)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + portc->audio_enabled &= ~mode; + devc->open_mode |= mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +ATI_audio_close (int dev, int mode) +{ + ATI_portc *portc = audio_engines[dev]->portc; + ATI_devc *devc = audio_engines[dev]->devc; + + ATI_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +ATI_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ATI_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +ATI_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ATI_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +ATI_enable_dma (int dev, int direction, int enable) +{ + ATI_devc *devc = audio_engines[dev]->devc; + ATI_portc *portc = audio_engines[dev]->portc; + + if (enable) + { + if (direction) + { + /* flush fifo and enable analog or spdif DMA */ + WRITEL (devc->osdev, READL (devc->osdev, 0x88) | 1, 0x88); + + if (portc->port_type == DF_ANALOG) + WRITEL (devc->osp, READL (devc->osp, 0x08) | 1 << 9, 0x08); + else + WRITEL (devc->osp, READL (devc->osp, 0x08) | 1 << 10, 0x08); + + } + else + { + /* flush fifo */ + WRITEL (devc->osdev, READL (devc->osdev, 0x88) | 2, 0x88); + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | 1 << 8, 0x08); + } + } + else + { + if (direction) + { + if (portc->port_type == DF_ANALOG) + WRITEL (devc->osp, READL (devc->osp, 0x08) & ~(1 << 9), 0x08); + else + WRITEL (devc->osp, READL (devc->osp, 0x08) & ~(1 << 10), 0x08); + } + else + WRITEL (devc->osdev, READL (devc->osdev, 0x08) & ~(1 << 8), 0x08); + } +} + +static void +ATI_audio_trigger (int dev, int state) +{ + ATI_devc *devc = audio_engines[dev]->devc; + ATI_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + 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)) + { + ATI_enable_dma (dev, 1, 1); + + /* set BDL & enable analog or SPDIF DMA */ + if (portc->port_type == DF_ANALOG) + { + WRITEL (devc->osp, devc->playBDL_phys | 1, 0x38); + WRITEL (devc->osp, READL (devc->osp, 0x08) | 0x04, 0x08); + } + else /* SPDIF */ + { + WRITEL (devc->osp, devc->spdifBDL_phys | 1, 0x50); + WRITEL (devc->osp, READL (devc->osp, 0x08) | 0x10, 0x08); + } + + /* set bus busy */ + WRITEL (devc->osdev, READL (devc->osdev, 0x04) | 1 << 14, 0x04); + + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + ATI_enable_dma (dev, 1, 0); + + /* Stop Anlog or SPDIF DMA */ + if (portc->port_type == DF_ANALOG) + WRITEL (devc->osp, READL (devc->osp, 0x08) & ~0x04, 0x08); + else + WRITEL (devc->osp, READL (devc->osp, 0x08) & ~0x10, 0x08); + + /* set bus clear */ + WRITEL (devc->osdev, READL (devc->osdev, 0x04) & ~(1 << 14), + 0x04); + + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->trigger_bits |= PCM_ENABLE_INPUT; + ATI_enable_dma (dev, 0, 1); + WRITEL (devc->osdev, devc->recBDL_phys | 1, 0x20); + + /* enable audio intput and enable input DMA */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | 0x02, 0x08); + /* set bus busy */ + WRITEL (devc->osdev, READL (devc->osdev, 0x04) | (1 << 14), + 0x04); + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + ATI_enable_dma (dev, 0, 0); + /* stop audio input */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) & ~0x02, 0x08); + /* clear bus busy */ + WRITEL (devc->osdev, READL (devc->osdev, 0x04) & ~(1 << 14), + 0x04); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +ATI_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + ATI_devc *devc = audio_engines[dev]->devc; + ATI_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int i, n; + unsigned int data; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + /* set the bits */ + data = READL (devc->osdev, 0x08) & ~(1 << 21); + if (portc->bits == 16) + data |= (1 << 21); + WRITEL (devc->osdev, data, 0x08); /*set 8/16 bits */ + + n = dmap->nfrags; + if (n > BDL_SIZE) + { + cmn_err (CE_WARN, "Internal error - BDL too small\n"); + return OSS_EIO; + } + + for (i = 0; i < n; i++) + { + int next = i + 1; + if (i == n - 1) + next = 0; + + devc->recBDL[i].addr = dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->recBDL[i].status = 0; + devc->recBDL[i].size = dmap->fragment_size >> 2; + devc->recBDL[i].next = devc->recBDL_phys + next * sizeof (bdl_t); + } + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +ATI_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + ATI_devc *devc = audio_engines[dev]->devc; + ATI_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int i, n; + unsigned int data; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + + if (portc->port_type == DF_SPDIF) + { + ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits); + + if (portc->bits == AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + } + + n = dmap->nfrags; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + int next = i + 1; + if (i == n - 1) + next = 0; + + devc->spdifBDL[i].addr = + dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->spdifBDL[i].status = 0; + devc->spdifBDL[i].size = dmap->fragment_size >> 2; + devc->spdifBDL[i].next = + devc->spdifBDL_phys + next * sizeof (bdl_t); + } + + } + else + { + data = READL (devc->osdev, 0x34) & ~0x3ff; + switch (portc->channels) + { + case 6: + data |= 0x30; /* slots 7, 8 */ + break; + case 4: + data |= 0x48; /* slts 6, 9 */ + break; + default: + data |= 0x03; /* slots 3, 4 */ + break; + } + data |= 4 << 11; + WRITEL (devc->osdev, data, 0x34); + + /* set the bits */ + data = READL (devc->osdev, 0x08) & ~(1 << 22); + if (portc->bits == 16) + data |= (1 << 22); + WRITEL (devc->osdev, data, 0x08); /*set 8/16 bits */ +#if 0 + /* set 6 channel reorder */ + if (portc->channels >= 6) + WRITEL (devc->osdev, 0x1, 0x84); + else + WRITEL (devc->osdev, 0x00, 0x84); +#endif + n = dmap->nfrags; + if (n > BDL_SIZE) + { + cmn_err (CE_WARN, "Internal error - BDL too small\n"); + return OSS_EIO; + } + + for (i = 0; i < n; i++) + { + int next = i + 1; + if (i == n - 1) + next = 0; + + devc->playBDL[i].addr = + dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->playBDL[i].status = 0; + devc->playBDL[i].size = dmap->fragment_size >> 2; + devc->playBDL[i].next = devc->playBDL_phys + next * sizeof (bdl_t); + } + } + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +ATI_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + ATI_devc *devc = audio_engines[dev]->devc; + ATI_portc *portc = audio_engines[dev]->portc; + unsigned int f = 0; + oss_native_word flags; + int loop = 100; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* we need to read the regs a couple of times because of possible h/w bugs */ + while (loop--) + { + if (direction == PCM_ENABLE_OUTPUT) + { + if (portc->port_type == DF_ANALOG) + f = READL (devc->osdev, 0x44); + else + f = READL (devc->osdev, 0x5c); + } + + if (direction == PCM_ENABLE_INPUT) + { + f = READL (devc->osdev, 0x2c); + } + + if (f < dmap->dmabuf_phys) + continue; + + f -= dmap->dmabuf_phys; + + if (f >= dmap->bytes_in_use) + continue; + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return f; + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static const audiodrv_t ATI_audio_driver = { + ATI_audio_open, + ATI_audio_close, + ATI_audio_output_block, + ATI_audio_start_input, + ATI_audio_ioctl, + ATI_audio_prepare_for_input, + ATI_audio_prepare_for_output, + ATI_audio_reset, + NULL, + NULL, + ATI_audio_reset_input, + ATI_audio_reset_output, + ATI_audio_trigger, + ATI_audio_set_rate, + ATI_audio_set_format, + ATI_audio_set_channels, + NULL, + NULL, + NULL, /* ATI_check_input, */ + NULL, /* ATI_check_output, */ + NULL, /* ATI_alloc_buffer, */ + NULL, /* ATI_free_buffer, */ + NULL, + NULL, + ATI_get_buffer_pointer +}; + +static int +init_ATI (ATI_devc * devc) +{ + int my_mixer, my_dev, opts; + int i, timeout; + oss_native_word phaddr; + + /* Power up */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) & ~1, 0x08); + oss_udelay (20); + /* check if the ACLink is Active */ + timeout = 10; + while (!(READL (devc->osdev, 0x08) & (1 << 28))) + { + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (1 << 30), 0x08); /* assert sync */ + oss_udelay (10); + if (READL (devc->osdev, 0x08) & (1 << 28)) + break; + + /* set AC97 reset field to 0 */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) & ~(0x80000000), 0x08); + oss_udelay (10); + + /* set AC97 reset field to 1 */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (0x80000000), 0x08); + oss_udelay (10); + + if (READL (devc->osdev, 0x08) & (1 << 28)) + break; + if (!--timeout) + { + cmn_err (CE_WARN, "Timed out waiting for AC97 Link ready\n"); + break; + } + } + + /* set ac97 reset field to 1: deassert */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (0x80000000), 0x08); + + /* do a soft reset */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (1 << 29), 0x08); + oss_udelay (10); + + /* deassert softreset */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) & ~(1 << 29), 0x08); + oss_udelay (10); + + /* do a sync */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (1 << 30), 0x08); + oss_udelay (10); + + /* now continue with initializing the rest of the chip */ + WRITEL (devc->osdev, READL (devc->osdev, 0x08) | (1 << 25), 0x08); /*enable burst */ + + WRITEL (devc->osdev, 0x22, 0x04); /* enable audio+spdif interrupts */ + devc->bdlBuffer = + CONTIG_MALLOC (devc->osdev, MAX_PORTC * BDL_SIZE * sizeof (bdl_t), + MEMLIMIT_32BITS, &phaddr, devc->bldbuf_dma_handle); + if (devc->bdlBuffer == NULL) + { + cmn_err (CE_WARN, "OSS Failed to allocate BDL\n"); + return 0; + } + + devc->playBDL = (bdl_t *) devc->bdlBuffer; + devc->playBDL_phys = phaddr; + devc->recBDL = + (bdl_t *) (devc->bdlBuffer + (1 * BDL_SIZE * sizeof (bdl_t))); + devc->recBDL_phys = phaddr + (1 * BDL_SIZE * sizeof (bdl_t)); + devc->spdifBDL = + (bdl_t *) (devc->bdlBuffer + (2 * BDL_SIZE * sizeof (bdl_t))); + devc->spdifBDL_phys = phaddr + (2 * BDL_SIZE * sizeof (bdl_t)); + +/* + * Init mixer + */ + my_mixer = + ac97_install_full (&devc->ac97devc, "AC97 Mixer", ac97_read, ac97_write, + devc, devc->osdev, devc->inverted); + + if (my_mixer == -1) + return 0; /* No mixer */ + + devc->mixer_dev = my_mixer; + + + /* enable S/PDIF */ + devc->ac97devc.spdif_slot = SPDIF_SLOT1011; + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1); + + for (i = 0; i < MAX_PORTC; i++) + { + ATI_portc *portc = &devc->portc[i]; + char tmp_name[100]; + int formats = AFMT_S16_LE | AFMT_AC3; + char *devfile_name = ""; + strcpy (tmp_name, devc->chip_name); + opts = ADEV_AUTOMODE | ADEV_STEREOONLY | ADEV_FIXEDRATE; + portc->port_type = DF_ANALOG; + + if (i == 0) + { + opts |= ADEV_DUPLEX; + strcpy (tmp_name, devc->chip_name); + } + if (i == 1) + { + strcpy (tmp_name, devc->chip_name); + opts |= ADEV_DUPLEX | ADEV_SHADOW; + } + if (i == 2) + { + sprintf (tmp_name, "%s (SPDIF out)", devc->chip_name); + opts |= ADEV_NOINPUT | ADEV_SPECIAL; + portc->port_type = DF_SPDIF; + devfile_name = "spdout"; + } + + if ((my_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &ATI_audio_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + my_dev = -1; + return 0; + } + else + { + audio_engines[my_dev]->portc = portc; + audio_engines[my_dev]->mixer_dev = my_mixer; + audio_engines[my_dev]->min_rate = + (opts & ADEV_FIXEDRATE) ? 48000 : 5000; + audio_engines[my_dev]->max_rate = 48000; + audio_engines[my_dev]->caps |= PCM_CAP_FREERATE; + audio_engines[my_dev]->min_channels = 2; + audio_engines[my_dev]->max_channels = 6; + + /* + * We can have at most BDL_SIZE fragments and they can + * be at most 128k each. + */ + audio_engines[my_dev]->max_block = 128 * 1024; + audio_engines[my_dev]->max_fragments = BDL_SIZE; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = my_dev; + if (audio_engines[my_dev]->flags & ADEV_FIXEDRATE) + audio_engines[my_dev]->fixed_rate = 48000; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, my_dev, -1, 0); +#endif + } + } + return 1; +} + + +int +oss_atiaudio_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device, sub_vendor, sub_id; + unsigned int pci_ioaddr; + ATI_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered ATI AC97 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if ((vendor != ATI_VENDOR_ID) || (device != ATI_DEVICE_IXP && + device != ATI_DEVICE_IXP300 + && device != ATI_DEVICE_IXP400)) + return 0; + + oss_pci_byteswap (osdev, 1); + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &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; + + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &sub_vendor); + pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &sub_id); + switch ((sub_id << 16) | sub_vendor) + { + case 0x11831043: /* ASUS A6R */ + case 0x2043161f: /* Maxselect x710s */ + case 0x0506107b: /* Gateway 7510GX */ + devc->inverted = AC97_INVERTED; + cmn_err (CE_CONT, "An inverted amplifier has been autodetected\n"); + break; + default: + devc->inverted = 0; + break; + } + + devc->membar_addr = pci_ioaddr; + devc->membar_virt = + (char *) MAP_PCI_MEM (devc->osdev, 0, devc->membar_addr, 256); + + if (devc->membar_virt == NULL) + { + cmn_err (CE_WARN, "ATIIXP: Cannot map pci mem\n"); + return 0; + } + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + +#if 0 + latency = pci_read_config_dword (osdev, 0x50, &latency); + pci_write_config_dword (osdev, 0x50, latency | 1); +#endif + + switch (device) + { + case ATI_DEVICE_IXP: + devc->chip_name = "ATI IXP200"; + break; + + case ATI_DEVICE_IXP300: + devc->chip_name = "ATI IXP300"; + break; + + case ATI_DEVICE_IXP400: + devc->chip_name = "ATI IXP400"; + break; + + default: + devc->chip_name = "ATI IXP"; + break; + } + + devc->irq = pci_irq_line; + devc->open_mode = 0; + + 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 (oss_register_interrupts (devc->osdev, 0, ATIIXPintr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to register interrupts\n"); + return 0; + } + + return init_ATI (devc); /* Detected */ +} + + +int +oss_atiaudio_detach (oss_device_t * osdev) +{ + ATI_devc *devc = (ATI_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + WRITEL (devc->osdev, 0x3f, 0x00); /* ack all interrupts */ + WRITEL (devc->osdev, 0, 0x04); /* disable interrupts */ + + /* disable S/PDIF */ + if (devc->mixer_dev) + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0); + + oss_unregister_interrupts (devc->osdev); + + if (devc->bdlBuffer) + CONTIG_FREE (devc->osdev, devc->bdlBuffer, + MAX_PORTC * BDL_SIZE * sizeof (bdl_t), devc->bldbuf_dma_handle); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + if (devc->membar_addr != 0) + { + UNMAP_PCI_MEM (devc->osdev, 0, devc->membar_addr, devc->membar_virt, + 256); + devc->membar_addr = 0; + } + + oss_unregister_device (devc->osdev); + return 1; + +} diff --git a/kernel/drv/oss_atiaudio/oss_atiaudio.man b/kernel/drv/oss_atiaudio/oss_atiaudio.man new file mode 100644 index 0000000..9818517 --- /dev/null +++ b/kernel/drv/oss_atiaudio/oss_atiaudio.man @@ -0,0 +1,19 @@ +NAME +oss_atiaudio - ATI IXP southbridge audio driver. + +DESCRIPTION +Open Sound System driver for ATI IXP 150/200/250 audio controller +ATI IXP device characteristics: + o 8/16 bit playback/record + o mono/stereo/4ch/5.1ch playback + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_atiaudio.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_audigyls/.devices b/kernel/drv/oss_audigyls/.devices new file mode 100644 index 0000000..fee016d --- /dev/null +++ b/kernel/drv/oss_audigyls/.devices @@ -0,0 +1 @@ +oss_audigyls pci1102,7 Sound Blaster Audigy LS / Live7.1 diff --git a/kernel/drv/oss_audigyls/.name b/kernel/drv/oss_audigyls/.name new file mode 100644 index 0000000..c68179e --- /dev/null +++ b/kernel/drv/oss_audigyls/.name @@ -0,0 +1 @@ +Sound Blaster Audigy LS / Live7.1 diff --git a/kernel/drv/oss_audigyls/.params b/kernel/drv/oss_audigyls/.params new file mode 100644 index 0000000..7714edd --- /dev/null +++ b/kernel/drv/oss_audigyls/.params @@ -0,0 +1,6 @@ +int audigyls_spdif_enable=0; +/* + * Set the Orange Jack to SPDIF or Analog output + * Values 1=SPDIF 0=Analog (side-surround) Default=0 + */ + diff --git a/kernel/drv/oss_audigyls/oss_audigyls.c b/kernel/drv/oss_audigyls/oss_audigyls.c new file mode 100644 index 0000000..1639e6c --- /dev/null +++ b/kernel/drv/oss_audigyls/oss_audigyls.c @@ -0,0 +1,1860 @@ +/* + * Purpose: Driver for Creative Audigy LS audio controller + * + * This sound card has been sold under many different names. + */ +/* + * + * 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_audigyls_cfg.h" +#include "oss_pci.h" +#include "ac97.h" +#include "midi_core.h" +#include "remux.h" + +#define DEFAULT_RATE 48000 + +#undef USE_ITIMER + +#define PCI_VENDOR_ID_CREATIVE 0x1102 +#define PCI_DEVICE_ID_CREATIVE_AUDIGYLS 0x0007 + +/* + * Indirect registers + */ + +#define PTBA 0x000 +#define PTBS 0x001 +#define PTCA 0x002 +#define PFBA 0x004 +#define PFBS 0x005 +#define CPFA 0x006 +#define PFEA 0x007 +#define CPCAV 0x008 +#define RFBA 0x010 +#define RFBS 0x011 +#define CRFA 0x012 +#define CRCAV 0x013 +#define CDL 0x020 +#define SA 0x040 +#define SCS3 0x041 +#define SCS0 0x042 +#define SCS1 0x043 +#define SCS2 0x044 +#define SPC 0x045 +#define WMARK 0x046 +#define SPSC 0x049 +#define RCD 0x050 /* 0x50-0z5f */ +#define P17RECSEL 0x060 +#define P17RECVOLL 0x061 +#define P17RECVOLH 0x062 + +#define HMIXMAP_SPDIF 0x63 +#define SMIXMAP_SPDIF 0x64 +#define MIXCTL_SPDIF 0x65 +#define MIXVOL_SPDIF 0x66 +#define HMIXMAP_I2S 0x67 +#define SMIXMAP_I2S 0x68 +#define MIXCTL_I2S 0x69 +#define MIXVOL_I2S 0x6a + +/* MIDI UART */ +#define MUDATA 0x06c +#define MUCMDA 0x06d +#define MUDATB 0x06e +#define MUCMDB 0x06f + +#define SRT 0x070 +#define SRCTL 0x071 +#define AUDCTL 0x072 +#define CHIP_ID 0x074 +#define AINT_ENABLE 0x075 +#define AINT_STATUS 0x076 +#define Wall192 0x077 +#define Wall441 0x078 +#define IT 0x079 +#define SPI 0x07a +#define I2C_A 0x07b +#define I2C_0 0x07c +#define I2C_1 0x07d + +/* + * Global Interrupt bits + */ + +#define IE 0x0c +#define INTR_PCI (1<< 0) +#define INTR_TXA (1<< 1) +#define INTR_RXA (1<< 2) +#define INTR_IT1 (1<< 3) +#define INTR_IT2 (1<< 4) +#define INTR_SS_ (1<< 5) +#define INTR_SRT (1<< 6) +#define INTR_GP (1<< 7) +#define INTR_AI (1<< 8) +#define INTR_I2Cdac (1<< 9) +#define INTR_I2CEE (1<< 10) +#define INTR_SPI (1<< 11) +#define INTR_SPF (1<< 12) +#define INTR_SUO (1<< 13) +#define INTR_SUI (1<< 14) +#define INTR_TXB (1<< 16) +#define INTR_RXB (1<< 17) + +/* + * Audio interrupt bits + */ + +#define AI_PFH (1<< 0) +#define AI_PFF (1<< 4) +#define AI_TFH (1<< 8) +#define AI_TFF (1<< 12) +#define AI_RFH (1<< 16) +#define AI_RFF (1<< 20) +#define AI_EAI (1<< 24) + + +#define MAX_PORTC 3 + +extern int audigyls_spdif_enable; + +typedef struct +{ + int audio_dev; + int play_port; + int rec_port; + int open_mode; + int trigger_bits; + int audio_enabled; + int channels; + int bits; + int speed; +#ifdef USE_ITIMER + int frag_192khz; +#endif + int port_type; + int play_ptr, rec_ptr; +} +audigyls_portc; + +typedef struct +{ + oss_device_t *osdev; + oss_native_word base; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + char *card_name; + unsigned int subvendor; + int rec_src; /* record channel src spdif/i2s/ac97/src */ +#define RECSEL_SPDIFOUT 0 +#define RECSEL_I2SOUT 1 +#define RECSEL_SPDIFIN 2 +#define RECSEL_I2SIN 3 +#define RECSEL_AC97 4 +#define RECSEL_SRC 5 + + int mixer_dev; + ac97_devc ac97devc; + int has_ac97; + int spread; /* copy front to surr/center channels */ + int loopback; /* record channel input from /dev/dspXX */ + int input_source; /* input from mic/line/aux/etc */ + int captmon; /* hear what you record*/ + int fbvol; /* recording monitor volume */ +/* + * UART + */ + oss_midi_inputbyte_t midi_input_intr; + int midi_opened, midi_disabled; + volatile unsigned char input_byte; + int midi_dev; + int mpu_attached; + int playvol[4]; + int recvol; + audigyls_portc portc[MAX_PORTC]; + +} +audigyls_devc; + + +static void audigylsuartintr (audigyls_devc * devc); + +static unsigned int +read_reg (audigyls_devc * devc, int reg, int chn) +{ + oss_native_word flags; + unsigned int val; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTL (devc->osdev, (reg << 16) | (chn & 0xffff), devc->base + 0x00); /* Pointer */ + val = INL (devc->osdev, devc->base + 0x04); /* Data */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + +/*printk("Read reg %03x (ch %d) = %08x\n", reg, chn, val);*/ + return val; +} + +static void +write_reg (audigyls_devc * devc, int reg, int chn, unsigned int value) +{ + oss_native_word flags; + + /*printk("Write reg %03x (ch %d) = %08x\n", reg, chn, value); */ + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTL (devc->osdev, (reg << 16) | (chn & 0xffff), devc->base + 0x00); /* Pointer */ + OUTL (devc->osdev, value, devc->base + 0x04); /* Data */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +#if 0 + { + char tmp[100]; + int ok = 1; + sprintf (tmp, "@w%d %04x/%s %x", chn, reg, emu_regname (reg, &ok), value); + if (ok) + oss_do_timing (tmp); + } +#endif +} + + +static int +audigyls_ac97_read (void *devc_, int wAddr) +{ + audigyls_devc *devc = devc_; + int dtemp = 0, i; + + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + if (i == 10000) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + dtemp = INW (devc->osdev, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dtemp & 0xffff; +} + +static int +audigyls_ac97_write (void *devc_, int wAddr, int wData) +{ + audigyls_devc *devc = devc_; + oss_native_word flags; + int i; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + if (i == 10000) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + OUTW (devc->osdev, wData, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + +static void +check_recording_intr (audigyls_devc * devc, audigyls_portc * portc) +{ +#if 1 + int pos, n = 0; + dmap_p dmap; + + dmap = audio_engines[portc->audio_dev]->dmap_in; + + pos = read_reg (devc, CRFA, portc->rec_port); + pos /= dmap->fragment_size; + while (dmap_get_qtail (dmap) != pos && n++ < dmap->nfrags) +#endif + oss_audio_inputintr (portc->audio_dev, 0); +} + +static void +check_playback_intr (audigyls_devc * devc, audigyls_portc * portc) +{ +#if 1 + int pos, n = 0; + dmap_p dmap; + + dmap = audio_engines[portc->audio_dev]->dmap_out; + + pos = read_reg (devc, CPFA, portc->play_port); + pos /= dmap->fragment_size; + while (dmap_get_qhead (dmap) != pos && n++ < dmap->nfrags) +#endif + oss_audio_outputintr (portc->audio_dev, 0); +} + +static int +audigylsintr (oss_device_t * osdev) +{ + int serviced = 0; + unsigned int status; + unsigned int astatus = 0; + int i; + audigyls_devc *devc = osdev->devc; + audigyls_portc *portc; + oss_native_word flags; + + flags = 0; /* To fix compiler warnings about unused variable */ + MUTEX_ENTER (devc->mutex, flags); + + status = INL (devc->osdev, devc->base + 0x08); + + if (status & INTR_RXA) /* MIDI RX interrupt */ + { + audigylsuartintr (devc); + } + + if (status & INTR_AI) + { + astatus = read_reg (devc, AINT_STATUS, 0); + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && + (astatus & ((AI_PFF | AI_PFH) << portc->play_port))) + { + dmap_t *dmap = audio_engines[portc->audio_dev]->dmap_out; + + if (astatus & (AI_PFF << portc->play_port)) + portc->play_ptr = 0; + if (astatus & (AI_PFH << portc->play_port)) + portc->play_ptr = dmap->bytes_in_use / 2; + + oss_audio_outputintr (portc->audio_dev, 0); + } + if ((portc->trigger_bits & PCM_ENABLE_INPUT) && + (astatus & ((AI_RFF | AI_RFH) << portc->rec_port))) + { + dmap_t *dmap = audio_engines[portc->audio_dev]->dmap_in; + + if (astatus & (AI_RFF << portc->rec_port)) + portc->rec_ptr = 0; + if (astatus & (AI_RFH << portc->rec_port)) + portc->rec_ptr = dmap->bytes_in_use / 2; + + oss_audio_inputintr (portc->audio_dev, 0); + } + } + write_reg (devc, AINT_STATUS, 0, astatus); + } + + if (status & INTR_IT1) + { + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) + check_playback_intr (devc, portc); + + if ((portc->trigger_bits & PCM_ENABLE_INPUT)) + check_recording_intr (devc, portc); + } + } + + serviced = 1; + OUTL (devc->osdev, status, devc->base + 0x08); /* Acknowledge */ + MUTEX_EXIT (devc->mutex, flags); + return serviced; +} + +static int +audigyls_set_rate (int dev, int arg) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (audio_engines[dev]->flags & ADEV_FIXEDRATE) + arg = DEFAULT_RATE; + + if (arg != 44100 && arg != 48000 && arg != 96000 && arg != 192000) + arg = 48000; + + portc->speed = arg; + return portc->speed; +} + +static short +audigyls_set_channels (int dev, short arg) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->channels; + + if ((arg == 1)) + arg = 2; + + if (portc->open_mode & OPEN_READ) + return portc->channels = 2; + + if (arg != 1 && arg != 2) + return portc->channels = 2; + return portc->channels = arg; +} + +static unsigned int +audigyls_set_format (int dev, unsigned int arg) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (arg != AFMT_AC3 && arg != AFMT_S16_LE) + return portc->bits = AFMT_S16_LE; + + return portc->bits = arg; +} + +/*ARGSUSED*/ +static int +audigyls_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void audigyls_trigger (int dev, int state); + +static void +audigyls_reset (int dev) +{ + audigyls_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +audigyls_open (int dev, int mode, int open_flags) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + audigyls_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; + } + portc->open_mode = mode; + portc->audio_enabled = ~mode; + portc->play_ptr = portc->rec_ptr = 0; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +audigyls_close (int dev, int mode) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + + audigyls_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +audigyls_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +audigyls_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + audigyls_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +#ifdef USE_ITIMER +static void +check_itimer (audigyls_devc * devc) +{ + int i; + unsigned int t = 0x1fffffff; + audigyls_portc *portc; + int tmp; + + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + if (portc->frag_192khz != 0 && portc->frag_192khz < t) + t = portc->frag_192khz; + } + if (t == 0x1fffffff) /* No audio devices active */ + { + tmp = INL (devc->osdev, devc->base + IE); + tmp &= ~INTR_IT1; + OUTL (devc->osdev, tmp, devc->base + IE); + } + else + { + t /= 16; + if (t < 1) + t = 1; + write_reg (devc, IT, 0, t); + tmp = INL (devc->osdev, devc->base + IE); + tmp |= INTR_IT1; + OUTL (devc->osdev, tmp, devc->base + IE); + } +} + +static void +adjust_itimer (audigyls_devc * devc, audigyls_portc * portc, dmap_p dmap) +{ + unsigned int t; + + /* Compute byte rate */ + + t = portc->speed * portc->channels; + + switch (portc->bits) + { + case AFMT_S16_LE: + case AFMT_S16_BE: + case AFMT_AC3: + t *= 2; + break; + + case AFMT_S32_LE: + case AFMT_S32_BE: + case AFMT_S24_LE: + case AFMT_S24_BE: + t *= 4; + break; + } + +/* Compute the number of 192kHz ticks per fragment */ + + t = (dmap->fragment_size * 192000) / t; /* msecs / fragment */ + if (t < 1) + t = 1; + + portc->frag_192khz = t; + check_itimer (devc); +} +#endif + +static void +audigyls_trigger (int dev, int state) +{ + audigyls_devc *devc = audio_engines[dev]->devc; + audigyls_portc *portc = audio_engines[dev]->portc; + int tmp; + oss_native_word flags; + + 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)) + { + tmp = read_reg (devc, SA, 0); + tmp |= 1 << portc->play_port; + write_reg (devc, SA, 0, tmp); +#ifdef USE_ITIMER + check_itimer (devc); +#else + tmp = read_reg (devc, AINT_ENABLE, 0); + tmp |= ((AI_PFH | AI_PFF) << portc->play_port); + write_reg (devc, AINT_ENABLE, 0, tmp); +#endif + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +#ifdef USE_ITIMER + portc->frag_192khz = 0; + check_itimer (devc); +#endif + /* Disable Play channel */ + tmp = read_reg (devc, SA, 0); + tmp &= ~(1 << portc->play_port); + write_reg (devc, SA, 0, tmp); +#ifndef USE_ITIMER + tmp = read_reg (devc, AINT_ENABLE, 0); + tmp &= ~((AI_PFH | AI_PFF) << portc->play_port); + write_reg (devc, AINT_ENABLE, 0, tmp); +#endif + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Enable Rec Channel */ + tmp = read_reg (devc, SA, 0); + tmp |= 0x100 << portc->rec_port; /* enable record */ + write_reg (devc, SA, 0, tmp); +#ifdef USE_ITIMER + check_itimer (devc); +#else + tmp = read_reg (devc, AINT_ENABLE, 0); + tmp |= ((AI_RFF | AI_RFH) << portc->rec_port); + write_reg (devc, AINT_ENABLE, 0, tmp); +#endif + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +#ifdef USE_ITIMER + portc->frag_192khz = 0; + check_itimer (devc); +#endif + /* disable channel */ + tmp = read_reg (devc, SA, 0); + tmp &= ~(0x100 << portc->rec_port); + write_reg (devc, SA, 0, tmp); +#ifndef USE_ITIMER + tmp = read_reg (devc, AINT_ENABLE, 0); + tmp &= ~((AI_RFF | AI_RFH) << portc->rec_port); + write_reg (devc, AINT_ENABLE, 0, tmp); +#endif + } + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +audigyls_prepare_for_input (int dev, int bsize, int bcount) +{ + unsigned int tmp, recmap, reg; + /*LINTED*/ unsigned int oversample; + audigyls_devc *devc = audio_engines[dev]->devc; + audigyls_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + write_reg (devc, CRFA, portc->rec_port, 0); + write_reg (devc, CRCAV, portc->rec_port, 0); + + write_reg (devc, RFBA, portc->rec_port, dmap->dmabuf_phys); + write_reg (devc, RFBS, portc->rec_port, (dmap->bytes_in_use) << 16); + + /* set 16/24 bits */ + tmp = INL (devc->osdev, devc->base + 0x14); + if (portc->bits == AFMT_S16_LE) + tmp &= ~0x400; /*16 bit */ + else + tmp |= 0x400; /*24 bit */ + OUTL (devc->osdev, tmp, devc->base + 0x14); + + /* set recording speed */ + reg = read_reg (devc, SRCTL, 0) & ~0xc000; + + switch (portc->speed) + { + case 48000: + reg |= 0x0; + oversample = 0x2; + break; + + case 96000: + reg |= 0x8000; + oversample = 0xa; + break; + + case 192000: + reg |= 0xc000; + oversample = 0xa; + break; + + default: + reg |= 0; + oversample = 0x2; + break; + } + + write_reg (devc, SRCTL, 0, reg); +/* audigyls_i2c_write(devc, 0xc, oversample);*/ + +/* setup record input */ + if (devc->loopback) + { + devc->rec_src = RECSEL_I2SOUT; + recmap = 0; + } + else + { + if (devc->has_ac97) + { + devc->rec_src = RECSEL_AC97; /* audigy LS */ + } + else + { + devc->rec_src = RECSEL_I2SIN; /* sb 7.1 value */ + } + recmap = 0x00; + } + tmp = recmap; /* default record input map */ + tmp |= devc->rec_src << 28 | devc->rec_src << 24 | devc->rec_src << 20 | devc->rec_src << 16; +//write_reg (devc, SMIXMAP_SPDIF, 0, 0x76767676); + write_reg (devc, P17RECSEL, 0, tmp); + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + +#ifdef USE_ITIMER + adjust_itimer (devc, portc, dmap); +#endif + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +audigyls_prepare_for_output (int dev, int bsize, int bcount) +{ + audigyls_devc *devc = audio_engines[dev]->devc; + audigyls_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + unsigned int tmp, reg; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->bits == AFMT_AC3) + portc->channels = 2; + + write_reg (devc, PTBA, portc->play_port, 0); + write_reg (devc, PTBS, portc->play_port, 0); + write_reg (devc, PTCA, portc->play_port, 0); + + write_reg (devc, CPFA, portc->play_port, 0); + write_reg (devc, PFEA, portc->play_port, 0); + write_reg (devc, CPCAV, portc->play_port, 0); + + + /* set 16/24 bits */ + tmp = INL (devc->osdev, devc->base + 0x14); + if (portc->bits == AFMT_S16_LE) + tmp &= ~0x800; /*16 bit */ + else + tmp |= 0x800; /*24 bit */ + OUTL (devc->osdev, tmp, devc->base + 0x14); + + /* set playback rate */ + tmp = read_reg (devc, SA, 0) & ~0xff0000; + reg = read_reg (devc, SRCTL, 0) & ~0x0303000f; +#if 0 + switch (portc->speed) + { + case 48000: + tmp |= 0; + reg |= 0; + break; + + case 44100: + tmp |= 0x10000; + reg |= 0x01010005; + break; + + case 96000: + tmp |= 0x20000; + reg |= 0x0202000a; + break; + + case 192000: + tmp |= 0x30000; + reg |= 0x0303000f; + break; + + default: + tmp |= 0; /* default is 48000 */ + reg |= 0; + break; + } +#endif + write_reg (devc, SA, 0, tmp << (portc->play_port * 2)); + write_reg (devc, SRCTL, 0, reg); + + /* Single buffering mode */ + write_reg (devc, PFBA, portc->play_port, dmap->dmabuf_phys); + write_reg (devc, PFBS, portc->play_port, (dmap->bytes_in_use) << 16); + + if (audigyls_spdif_enable) + { + if (portc->bits == AFMT_AC3) + { + audigyls_ac97_write (devc, 0x1c, 0x8000); + write_reg (devc, SCS3, 0, 0x02108006); /* Non Audio */ +#if 0 + write_reg (devc, SCS0, 0, 0x02108006); /* Non Audio */ + write_reg (devc, SCS1, 0, 0x02108006); /* Non Audio */ + write_reg (devc, SCS2, 0, 0x02108006); /* Non Audio */ +#endif + } + else + { + write_reg (devc, SCS3, 0, 0x02108004); /* Audio */ +#if 0 + write_reg (devc, SCS0, 0, 0x02108004); /* Audio */ + write_reg (devc, SCS1, 0, 0x02108004); /* Audio */ + write_reg (devc, SCS2, 0, 0x02108004); /* Audio */ +#endif + } + } + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + +#ifdef USE_ITIMER + adjust_itimer (devc, portc, dmap); +#endif + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +audigyls_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + unsigned int p = 0; + audigyls_portc *portc = audio_engines[dev]->portc; + +#if 1 + audigyls_devc *devc = audio_engines[dev]->devc; + + if (direction == PCM_ENABLE_OUTPUT) + { + p = read_reg (devc, CPFA, portc->play_port); + } + + if (direction == PCM_ENABLE_INPUT) + { + p = read_reg (devc, CRFA, portc->rec_port); + } + + /* + * Round to the nearest fragment boundary. + */ + p = (p + dmap->fragment_size / 2); + p = (p / dmap->fragment_size) * dmap->fragment_size; +#else + if (direction == PCM_ENABLE_OUTPUT) + { + return portc->play_ptr; + } + + if (direction == PCM_ENABLE_INPUT) + { + return portc->rec_ptr; + } +#endif + + return p % dmap->bytes_in_use; +} + +static audiodrv_t audigyls_audio_driver = { + audigyls_open, + audigyls_close, + audigyls_output_block, + audigyls_start_input, + audigyls_ioctl, + audigyls_prepare_for_input, + audigyls_prepare_for_output, + audigyls_reset, + NULL, + NULL, + NULL, + NULL, + audigyls_trigger, + audigyls_set_rate, + audigyls_set_format, + audigyls_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* audigyls_alloc_buffer, */ + NULL, /* audigyls_free_buffer */ + NULL, + NULL, + audigyls_get_buffer_pointer +}; + + +static __inline__ int +audigylsuart_status (audigyls_devc * devc) +{ + return read_reg (devc, MUCMDA, 0); +} + +#define input_avail(devc) (!(audigylsuart_status(devc)&INPUT_AVAIL)) +#define output_ready(devc) (!(audigylsuart_status(devc)&OUTPUT_READY)) +static void +audigylsuart_cmd (audigyls_devc * devc, unsigned char cmd) +{ + write_reg (devc, MUCMDA, 0, cmd); +} + +static __inline__ int +audigylsuart_read (audigyls_devc * devc) +{ + return read_reg (devc, MUDATA, 0); +} + +static __inline__ void +audigylsuart_write (audigyls_devc * devc, unsigned char byte) +{ + write_reg (devc, MUDATA, 0, byte); +} + +#define OUTPUT_READY 0x40 +#define INPUT_AVAIL 0x80 +#define MPU_ACK 0xFE +#define MPU_RESET 0xFF +#define UART_MODE_ON 0x3F + +static int reset_audigylsuart (audigyls_devc * devc); +static void enter_uart_mode (audigyls_devc * devc); + +static void +audigylsuart_input_loop (audigyls_devc * devc) +{ + while (input_avail (devc)) + { + unsigned char c = audigylsuart_read (devc); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, c); + } +} + +static void +audigylsuartintr (audigyls_devc * devc) +{ + audigylsuart_input_loop (devc); +} + +/*ARGSUSED*/ +static int +audigylsuart_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + audigyls_devc *devc = (audigyls_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + while (input_avail (devc)) + audigylsuart_read (devc); + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + enter_uart_mode (devc); + devc->midi_disabled = 0; + + return 0; +} + +/*ARGSUSED*/ +static void +audigylsuart_close (int dev, int mode) +{ + audigyls_devc *devc = (audigyls_devc *) midi_devs[dev]->devc; + reset_audigylsuart (devc); + oss_udelay (10); + enter_uart_mode (devc); + reset_audigylsuart (devc); + devc->midi_opened = 0; +} + + +static int +audigylsuart_out (int dev, unsigned char midi_byte) +{ + int timeout; + audigyls_devc *devc = (audigyls_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + /* + * Test for input since pending input seems to block the output. + */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (input_avail (devc)) + audigylsuart_input_loop (devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + /* + * Sometimes it takes about 130000 loops before the output becomes ready + * (After reset). Normally it takes just about 10 loops. + */ + + for (timeout = 130000; timeout > 0 && !output_ready (devc); timeout--); + + if (!output_ready (devc)) + { + cmn_err (CE_WARN, "UART timeout - Device not responding\n"); + devc->midi_disabled = 1; + reset_audigylsuart (devc); + enter_uart_mode (devc); + return 1; + } + + audigylsuart_write (devc, midi_byte); + return 1; +} + +/*ARGSUSED*/ +static int +audigylsuart_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t audigyls_midi_driver = { + audigylsuart_open, + audigylsuart_close, + audigylsuart_ioctl, + audigylsuart_out, +}; + +static void +enter_uart_mode (audigyls_devc * devc) +{ + int ok, timeout; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + audigylsuart_cmd (devc, UART_MODE_ON); + + ok = 0; + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) + ok = 1; + else if (input_avail (devc)) + if (audigylsuart_read (devc) == MPU_ACK) + ok = 1; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + +void +attach_audigylsuart (audigyls_devc * devc) +{ + enter_uart_mode (devc); + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "AUDIGYLS", "AudigyLS UART", &audigyls_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev); + devc->midi_opened = 0; +} + +static int +reset_audigylsuart (audigyls_devc * devc) +{ + int ok, timeout, n; + + /* + * Send the RESET command. Try again if no success at the first time. + */ + + ok = 0; + + for (n = 0; n < 2 && !ok; n++) + { + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + audigylsuart_cmd (devc, MPU_RESET); + + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail (devc)) + if (audigylsuart_read (devc) == MPU_ACK) + ok = 1; + + } + + + + if (ok) + audigylsuart_input_loop (devc); /* + * Flush input before enabling interrupts + */ + + return ok; +} + + +int +probe_audigylsuart (audigyls_devc * devc) +{ + int ok = 0; + oss_native_word flags; + + DDB (cmn_err (CE_CONT, "Entered probe_audigylsuart\n")); + + devc->midi_input_intr = NULL; + devc->midi_opened = 0; + devc->input_byte = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ok = reset_audigylsuart (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (ok) + { + DDB (cmn_err (CE_CONT, "Reset UART401 OK\n")); + } + else + { + DDB (cmn_err + (CE_CONT, "Reset UART401 failed (no hardware present?).\n")); + DDB (cmn_err + (CE_CONT, "mpu401 status %02x\n", audigylsuart_status (devc))); + } + + DDB (cmn_err (CE_CONT, "audigylsuart detected OK\n")); + return ok; +} + +void +unload_audigylsuart (audigyls_devc * devc) +{ + reset_audigylsuart (devc); +} + + +static void +attach_mpu (audigyls_devc * devc) +{ + devc->mpu_attached = 1; + attach_audigylsuart (devc); +} + +/* only for SBLive 7.1 */ +int +audigyls_i2c_write (audigyls_devc * devc, int reg, int data) +{ + int i, timeout, tmp; + + + tmp = (reg << 9 | data) << 16; /* set the upper 16 bits */ + /* first write the command to the data reg */ + write_reg (devc, I2C_1, 0, tmp); + for (i = 0; i < 20; i++) + { + tmp = read_reg (devc, I2C_A, 0) & ~0x6fe; + /* see audigyls.pdf for bits */ + tmp |= 0x400 | 0x100 | 0x34; + write_reg (devc, I2C_A, 0, tmp); + /* now wait till controller sets valid bit (0x100) to 0 */ + timeout = 0; + /*LINTED*/ while (1) + { + tmp = read_reg (devc, I2C_A, 0); + if ((tmp & 0x100) == 0) + break; + + if (timeout > 100) + break; + + timeout++; + } + + /* transaction aborted */ + if (tmp & 0x200) + return 0; + } + return 1; +} + +int +audigyls_spi_write (audigyls_devc * devc, int data) +{ + unsigned int orig; + unsigned int tmp; + int i, valid; + + tmp = read_reg (devc, SPI, 0); + orig = (tmp & ~0x3ffff) | 0x30000; + write_reg (devc, SPI, 0, orig | data); + valid = 0; + /* Wait for status bit to return to 0 */ + for (i = 0; i < 1000; i++) + { + oss_udelay (100); + tmp = read_reg (devc, SPI, 0); + if (!(tmp & 0x10000)) + { + valid = 1; + break; + } + } + if (!valid) /* Timed out */ + return 0; + + return 1; +} + +static unsigned int +mix_scale (int left, int right, int bits) +{ + left = mix_cvt[left]; + right = mix_cvt[right]; + + return ((left * ((1 << bits) - 1) / 100) << 8) | (right * + ((1 << bits) - 1) / 100); +} + +static int +audigyls_set_volume (audigyls_devc * devc, int codecid, int value) +{ + audigyls_portc *portc = NULL; + int left, right, i2s_vol; + + portc = &devc->portc[codecid]; + + left = value & 0xff; + right = (value >> 8) & 0xff; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + devc->playvol[codecid] = left | (right << 8); + + i2s_vol = 65535 - mix_scale (left, right, 8); + write_reg (devc, MIXVOL_I2S, portc->play_port, (i2s_vol << 16)); + return devc->playvol[codecid]; +} + +int +audigyls_mix_control (int dev, int ctrl, unsigned int cmd, int value) +{ + audigyls_devc *devc = mixer_devs[dev]->hw_devc; + int val; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case 1: /* spread */ + value = devc->spread; + break; + + case 2: /* record what you hear */ + value = devc->loopback; + break; + + case 3: + { + value = devc->recvol; + } + break; + + case 4: + value = devc->input_source; + break; + case 5: + value = devc->captmon; + break; + case 7: + value = devc->fbvol; + break; + } + } + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: /* recording source */ + devc->spread = value; + if (value) + write_reg (devc, HMIXMAP_I2S, 0, 0x10101010); + else + write_reg (devc, HMIXMAP_I2S, 0, 0x76543210); + break; + + case 2: /* record what you hear */ + devc->loopback = value; + break; + + case 3: + { + val = (255 - value) & 0xff; + write_reg (devc, P17RECVOLL, 0, + val << 24 | val << 16 | val << 8 | val); + write_reg (devc, P17RECVOLH, 0, + val << 24 | val << 16 | val << 8 | val); + /* write_reg (devc, SRCTL, 1, + 0xff << 24 | 0xff << 16 | val << 8 | val); */ + devc->recvol = value & 0xff; + } + break; + + case 4: + { + switch (value) + { + case 0: /* for mic input remove GPIO */ + { + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x18) | 0x400, + devc->base + 0x18); + audigyls_i2c_write (devc, 0x15, 0x2); /* Mic */ + } + break; + case 1: + { + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 0x18) & ~0x400, + devc->base + 0x18); + audigyls_i2c_write (devc, 0x15, 0x4); /* Line */ + } + break; + case 2: + { + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 0x18) & ~0x400, + devc->base + 0x18); + audigyls_i2c_write (devc, 0x15, 0x8); /* Aux */ + } + break; + } + devc->input_source = value; + } + break; + case 5: + { + devc->captmon = value; + /* Send analog capture to front speakers */ + if (value) + write_reg (devc, SMIXMAP_I2S, 0, 0x76767676); + else + write_reg (devc, SMIXMAP_I2S, 0, 0x10101010); + } + break; + case 7: + { + /*Set recording monitor volume */ + val = (255 - value) & 0xff; + write_reg (devc, SRCTL, 1, val << 8 | val); + devc->fbvol = value & 0xff; + } + break; + } + } + return value; +} + +static int +audigyls_mix_init (int dev) +{ + int group, err; + audigyls_devc *devc = mixer_devs[dev]->hw_devc; + + if ((group = mixer_ext_create_group (dev, 0, "EXT")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 1, audigyls_mix_control, + MIXT_ONOFF, "Spread", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 2, audigyls_mix_control, + MIXT_ONOFF, "LOOPBACK", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + + if ((err = mixer_ext_create_control (dev, group, 3, audigyls_mix_control, + MIXT_MONOSLIDER, "RECORDVOL", 255, + MIXF_READABLE | MIXF_WRITEABLE | + MIXF_RECVOL)) < 0) + return err; + + if (!devc->has_ac97) + { + if ((err = + mixer_ext_create_control (dev, group, 4, audigyls_mix_control, + MIXT_ENUM, "RECORDSRC", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + mixer_ext_set_strings (dev, err, "MIC LINE AUX", 0); + } + if ((err = mixer_ext_create_control (dev, group, 7, audigyls_mix_control, + MIXT_MONOSLIDER, "monitorvol", 255, + MIXF_READABLE | MIXF_WRITEABLE | + MIXF_RECVOL)) < 0) + return err; + if ((err = mixer_ext_create_control (dev, group, 5, audigyls_mix_control, + MIXT_ONOFF, "RecMon", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + return 0; +} + +static const int bindings[MAX_PORTC] = { + DSP_BIND_FRONT, + DSP_BIND_CENTER_LFE, + DSP_BIND_SURR +}; + +static int +install_audio_devices (audigyls_devc * devc) +{ + int i; + int frontdev = -1; + int adev, flags; + int fmts = AFMT_S16_LE | AFMT_AC3; + static char *names[] = { + "AudigyLS front", + "AudigyLS center/lfe", + "AudigyLS surround" + }; + +#if 0 + if (audigyls_spdif_enable == 1) + n = 2; +#endif + + for (i = 0; i < MAX_PORTC; i++) + { + audigyls_portc *portc = &devc->portc[i]; + + flags = + ADEV_AUTOMODE | ADEV_16BITONLY | ADEV_STEREOONLY | ADEV_FIXEDRATE; + + switch (i) + { + case 0: + portc->play_port = 0; + portc->rec_port = 2; + flags |= ADEV_DUPLEX; + break; + case 1: + portc->play_port = 1; + portc->rec_port = 2; + flags |= ADEV_NOINPUT; + break; + case 2: + portc->play_port = 3; + portc->rec_port = 2; + flags |= ADEV_NOINPUT; + break; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + names[i], + &audigyls_audio_driver, + sizeof (audiodrv_t), + flags, fmts, devc, -1)) < 0) + { + return 0; + } + + if (i == 0) + frontdev = adev; + + audio_engines[adev]->portc = portc; + audio_engines[adev]->max_fragments = 2; + audio_engines[adev]->dmabuf_alloc_flags |= DMABUF_SIZE_16BITS; + audio_engines[adev]->rate_source = frontdev; + audio_engines[adev]->mixer_dev = devc->mixer_dev; + audio_engines[adev]->binding = bindings[i]; + if (audio_engines[adev]->flags & ADEV_FIXEDRATE) + { + audio_engines[adev]->fixed_rate = DEFAULT_RATE; + audio_engines[adev]->min_rate = DEFAULT_RATE; + audio_engines[adev]->max_rate = DEFAULT_RATE; + } + else + { + audio_engines[adev]->min_rate = 44100; + audio_engines[adev]->max_rate = 192000; + } + portc->audio_dev = adev; + portc->open_mode = 0; + devc->playvol[i] = 0x3030; + devc->recvol = 128; + portc->bits = AFMT_S16_LE; + } + +#ifdef USE_REMUX + if (frontdev >= 0) + { + if (audigyls_spdif_enable && devc->has_ac97) + remux_install ("AudigyLS 4.0 output", devc->osdev, frontdev, + frontdev + 2, -1, -1); + else + remux_install ("AudigyLS 5.1 output", devc->osdev, frontdev, + frontdev + 2, frontdev + 1, -1); + } +#endif + +#ifdef CONFIG_OSS_VMIX + if (frontdev >= 0) + vmix_attach_audiodev(devc->osdev, frontdev, -1, 0); +#endif + return 1; +} + +static void +select_out3_mode (audigyls_devc * devc, int mode) +{ + /* + * Set the out3/spdif combo jack format. + * mode0=analog rear/center, 1=spdif + */ + + if (mode == 0) + { + write_reg (devc, SPC, 0, 0x00000f00); + } + else + { + write_reg (devc, SPC, 0, 0x0000000f); + } +} + +/*ARGSUSED*/ +static int +audigyls_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + audigyls_devc *devc = mixer_devs[dev]->devc; + + if (((cmd >> 8) & 0xff) == 'M') + { + int val; + + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + return *arg = 0; + break; + + case SOUND_MIXER_PCM: + val = *arg; + return *arg = audigyls_set_volume (devc, 0, val); + + case SOUND_MIXER_CENTERVOL: + val = *arg; + return *arg = audigyls_set_volume (devc, 1, val); + + case SOUND_MIXER_REARVOL: + val = *arg; + return *arg = audigyls_set_volume (devc, 2, val); + } + else + switch (cmd & 0xff) /* Return Parameter */ + { + case SOUND_MIXER_RECSRC: + case SOUND_MIXER_RECMASK: + return *arg = 0; + break; + + case SOUND_MIXER_DEVMASK: + return *arg = + SOUND_MASK_PCM | SOUND_MASK_REARVOL | SOUND_MASK_CENTERVOL; + break; + + case SOUND_MIXER_STEREODEVS: + return *arg = + SOUND_MASK_PCM | SOUND_MASK_REARVOL | SOUND_MASK_CENTERVOL; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + case SOUND_MIXER_PCM: + return *arg = devc->playvol[0]; + break; + + case SOUND_MIXER_CENTERVOL: + return *arg = devc->playvol[2]; + break; + + case SOUND_MIXER_REARVOL: + return *arg = devc->playvol[3]; + break; + } + } + else + return *arg = 0; + + return OSS_EINVAL; +} + +static mixer_driver_t audigyls_mixer_driver = { + audigyls_mixer_ioctl +}; + +int +oss_audigyls_attach (oss_device_t * osdev) +{ + int tmp, err, i; + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + unsigned int subvendor; + audigyls_devc *devc; + + static unsigned int spi_dac[] = { + 0x00ff, 0x02ff, 0x0400, 0x530, 0x0622, 0x08ff, 0x0aff, 0x0cff, + 0x0eff, 0x10ff, 0x1200, 0x1400, 0x1800, 0x1aff, 0x1cff, + 0x1e00, + }; + + DDB (cmn_err (CE_WARN, "Entered AUDIGYLS probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != PCI_VENDOR_ID_CREATIVE || + device != PCI_DEVICE_ID_CREATIVE_AUDIGYLS) + return 0; + + pci_read_config_dword (osdev, 0x2c, &subvendor); + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &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.\n"); + 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->card_name = "AudigyLS"; + devc->subvendor = subvendor; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + devc->base &= ~0x3; + + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + MUTEX_INIT (osdev, devc->low_mutex, MH_DRV + 1); + + oss_register_device (osdev, devc->card_name); + + if ((err = + oss_register_interrupts (devc->osdev, 0, audigylsintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + +/* + * Init mixer + */ + if (subvendor == 0x10021102) /* original audigyls */ + { + devc->mixer_dev = ac97_install (&devc->ac97devc, devc->card_name, + audigyls_ac97_read, audigyls_ac97_write, + devc, devc->osdev); + devc->has_ac97 = 1; + audigyls_ac97_write (devc, 0x1c, 0x8000); + } + else + { + devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "AudigyLS Mixer", + &audigyls_mixer_driver, + sizeof (mixer_driver_t), devc); + devc->has_ac97 = 0; /* no ac97 */ + mixer_devs[devc->mixer_dev]->hw_devc = devc; + mixer_devs[devc->mixer_dev]->priority = 1; /* Possible default mixer candidate */ + } + + mixer_ext_set_init_fn (devc->mixer_dev, audigyls_mix_init, 10); + +#if 0 + write_reg (devc, SCS0, 0, 0x02108504); + write_reg (devc, SCS1, 0, 0x02108504); + write_reg (devc, SCS2, 0, 0x02108504); +#endif + write_reg (devc, SCS3, 0, 0x02108504); + + write_reg (devc, AUDCTL, 0, 0x0f0f003f); /* enable all outputs */ + + select_out3_mode (devc, audigyls_spdif_enable); + +/********************************************************************** + * In P17, there's 8 GPIO pins. + * GPIO register: 0x00XXYYZZ + * XX: Configure GPIO to be either GPI (0) or GPO (1). + * YY: GPO values, applicable if the pin is configure to be GPO. + * ZZ: GPI values, applicable if the pin is configure to be GPI. + * + * in SB570, pin 0-4 and 6 is used as GPO and pin 5 and 7 is used as GPI. + * + * GPO0: + * 1 ==> Analog output + * 0 ==> Digital output + * GPO1: + * 1 ==> Enable output on card + * 0 ==> Diable output on card + * GPO2: + * 1 ==> Enable Mic Bias and Mic Path + * 0 ==> Disable Mic Bias and Mic Path + * GPO3: + * 1 ==> Disable SPDIF-IO output + * 0 ==> Enable SPDIF-IO output + * GPO4 and GPO6: + * DAC sampling rate selection: + * Not applicable to SB570 since DAC is controlled through SPI + * GPI5: + * 1 ==> Front Panel is not connected + * 0 ==> Front Panel is connected + * GPI7: + * 1 ==> Front Panel Headphone is not connected + * 0 ==> Front Panel Headphone is connected + ***********************************************************/ + + OUTL (devc->osdev, 0, devc->base + 0x18); /* GPIO */ + if (devc->has_ac97) + OUTL (devc->osdev, 0x005f03a3, devc->base + 0x18); + else + { + /* for SBLive 7.1 */ + OUTL (devc->osdev, 0x005f4301, devc->base + 0x18); + audigyls_i2c_write (devc, 0x15, 0x4); + for (i = 0; i < (sizeof (spi_dac)/sizeof (spi_dac[0])); i++) + { + audigyls_spi_write (devc, spi_dac[i]); + } + } + + OUTL (devc->osdev, INTR_PCI | INTR_RXA | INTR_AI, devc->base + IE); + OUTL (devc->osdev, 0x00000009, devc->base + 0x14); /* Enable audio */ + + tmp = read_reg (devc, SRCTL, 0); + if (devc->has_ac97) + tmp |= 0xf0c81000; /* record src0/src1 from ac97 */ + else + tmp |= 0x50c81000; /* record src0/src1 from I2SIN */ + write_reg (devc, SRCTL, 0, tmp); + write_reg (devc, HMIXMAP_I2S, 0, 0x76543210); /* default out route */ + install_audio_devices (devc); + + if (devc->has_ac97) /* only attach midi for AudigyLS */ + attach_mpu (devc); + + return 1; +} + +int +oss_audigyls_detach (oss_device_t * osdev) +{ + unsigned int status; + audigyls_devc *devc = (audigyls_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + + write_reg (devc, SA, 0, 0); + OUTL (devc->osdev, 0x00000000, devc->base + IE); /* Interrupt disable */ + write_reg (devc, AINT_ENABLE, 0, 0); /* Disable audio interrupts */ + status = INL (devc->osdev, devc->base + 0x08); + OUTL (devc->osdev, status, devc->base + 0x08); /* Acknowledge */ + oss_udelay (1000); + if (devc->mpu_attached) + unload_audigylsuart (devc); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_audigyls/oss_audigyls.man b/kernel/drv/oss_audigyls/oss_audigyls.man new file mode 100644 index 0000000..b490a32 --- /dev/null +++ b/kernel/drv/oss_audigyls/oss_audigyls.man @@ -0,0 +1,45 @@ +NAME +oss_audigyls - Creative Labs CA106 (AudigyLS/SBLive 24bit) driver. + +DESCRIPTION +Open Sound System driver for Creative Labs Audigy2-LS and SBLive 24bit 7.1 +soundcards. + +Audigy-LS device characteristics: + o 8/16/24 bit playback/record + o mono/stereo/4/5.1 playback + o 8KHz to 192Khz sample rate. + + AUDIGYLS MODELS + +There are 2 models of the AudigyLS device: one with an AC97 codec called the +AudigyLS and the one without called the SBLive 7.1. Essentially they are +the same chip but behave a bit differently. + +When playing AC3 on the AudigyLS (the one with the AC97 mixer) - you +need to ensure that the igain slider is set to 0. + + AUDIGYLS MIXER + +o The AudigyLS has 4 mixer controls for each channel. +o The "spread" button will simply duplicate the front audio on the other 3 + channels so that every speaker is playing what the front L/R is playing. +o LoopBack recording allows you to capture any channel that's playing audio. +o Record Volume slider just adjusts the input gain. +o Record Source selector selects the input. +o The "recmon" button enables a passthrough of the analog input signal. +o Monitor Volume slider sets the passthrough gain if recmon is enabled. + +OPTIONS +o audigyls_spdif_enable=0|1 +The Audigy LS has a versa-jack (orange) that can be set as SPDIF output +or the Side-Surround left/right speakers in a 7.1 setup. +When set as SPDIF, you can get play PCM/AC3 audio to a Dolby(R) capable +receiver. + +FILES +CONFIGFILEPATH/oss_audigyls.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_audiocs/.config b/kernel/drv/oss_audiocs/.config new file mode 100644 index 0000000..a08633b --- /dev/null +++ b/kernel/drv/oss_audiocs/.config @@ -0,0 +1 @@ +platform=sparc diff --git a/kernel/drv/oss_audiocs/.devices b/kernel/drv/oss_audiocs/.devices new file mode 100644 index 0000000..75dcebb --- /dev/null +++ b/kernel/drv/oss_audiocs/.devices @@ -0,0 +1 @@ +oss_audiocs SUNW,CS4231 Sun UltraSparc workstation audio (CS4231) diff --git a/kernel/drv/oss_audiocs/.name b/kernel/drv/oss_audiocs/.name new file mode 100644 index 0000000..561dbe3 --- /dev/null +++ b/kernel/drv/oss_audiocs/.name @@ -0,0 +1 @@ +Driver for older Sun UltraSparc workstations based on CS4231 codec diff --git a/kernel/drv/oss_audiocs/cs4231_mixer.h b/kernel/drv/oss_audiocs/cs4231_mixer.h new file mode 100644 index 0000000..253ea01 --- /dev/null +++ b/kernel/drv/oss_audiocs/cs4231_mixer.h @@ -0,0 +1,101 @@ +/* + * Purpose: Definitions for the mixer of cs4231. + */ + +/* + * + * 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 MODE2_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \ + SOUND_MASK_MIC | \ + SOUND_MASK_LINE | SOUND_MASK_SPEAKER | \ + SOUND_MASK_IGAIN | \ + SOUND_MASK_PCM | SOUND_MASK_IMIX) + +#define MODE2_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \ + SOUND_MASK_LINE1|SOUND_MASK_IMIX) + +struct mixer_def +{ + unsigned int regno; + unsigned int polarity; /* 0=normal, 1=reversed */ + unsigned int bitpos; + unsigned int nbits; + unsigned int mutepos; +}; + +typedef struct mixer_def mixer_ent; +typedef mixer_ent mixer_ents[2]; + +/* + * Most of the mixer entries work in backwards. Setting the polarity field + * makes them to work correctly. + * + * The channel numbering used by individual soundcards is not fixed. Some + * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs. + * The current version doesn't try to compensate this. + */ + +#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \ + {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r, mute_bit}} + +static mixer_ents cs4231_mix_devices[32] = { + MIX_ENT (SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 7), + MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), + MIX_ENT (SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8), + MIX_ENT (SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), + MIX_ENT (SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), + MIX_ENT (SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7) +}; + +static int default_mixer_levels[32] = { + 0x3232, /* Master Volume */ + 0x3232, /* Bass */ + 0x3232, /* Treble */ + 0x4b4b, /* FM */ + 0x3232, /* PCM */ + 0x1515, /* PC Speaker */ + 0x2020, /* Line in */ + 0x2020, /* Mic */ + 0x4b4b, /* CD */ + 0x0000, /* Recording monitor */ + 0x4b4b, /* Second PCM */ + 0x4b4b, /* Recording level */ + 0x0000, /* Input gain */ + 0x4b4b, /* Output gain */ + 0x2020, /* Line1 */ + 0x2020, /* Line2 */ + 0x1515 /* Line3 (usually line in) */ +}; + +#define LEFT_CHN 0 +#define RIGHT_CHN 1 + +/* + * Channel enable bits for ioctl(SOUND_MIXER_PRIVATE1) + */ + +#ifndef AUDIO_SPEAKER +#define AUDIO_SPEAKER 0x01 /* Enable mono output */ +#define AUDIO_HEADPHONE 0x02 /* Sparc only */ +#define AUDIO_LINE_OUT 0x04 /* Sparc only */ +#endif diff --git a/kernel/drv/oss_audiocs/oss_audiocs.c b/kernel/drv/oss_audiocs/oss_audiocs.c new file mode 100644 index 0000000..774a410 --- /dev/null +++ b/kernel/drv/oss_audiocs/oss_audiocs.c @@ -0,0 +1,1808 @@ +/* + * Purpose: Driver for the UltraSparc workstations using CS4231 codec for audio + * + * This driver is for Solaris/Sparc only. It uses Solaris specific kernel + * services which are not portable to other operating systems. + * + * Originally this driver supported various AD1848 based ISA codecs. For + * this reason devc->model is used to find out which features the codec + * supports. The latest version of the driver supports only models 2 (CS4231) + * and 3 (CS4231A). + */ + +/* + * + * 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_audiocs_cfg.h" +#include <oss_pci.h> + +#include "cs4231_mixer.h" + +struct cs4231_pioregs +{ + uint8_t iar; /* index address register */ + uint8_t pad1[3]; /* pad */ + uint8_t idr; /* indexed data register */ + uint8_t pad2[3]; /* pad */ + uint8_t statr; /* status register */ + uint8_t pad3[3]; /* pad */ + uint8_t piodr; /* PIO data regsiter */ + uint8_t pad4[3]; +}; + +/* + * These are the registers for the EBUS2 DMA channel interface to the + * 4231. One struct per channel for playback and record, therefore there + * individual handles for the CODEC and the two DMA engines. + */ + +struct cs4231_eb2regs { + uint32_t eb2csr; /* Ebus 2 csr */ + uint32_t eb2acr; /* ebus 2 Addrs */ + uint32_t eb2bcr; /* ebus 2 counts */ +}; +typedef struct cs4231_eb2regs cs4231_eb2regs_t; + +#define PLAY_CSR devc->play_regs->eb2csr +#define PLAY_ACR devc->play_regs->eb2acr +#define PLAY_BCR devc->play_regs->eb2bcr +#define REC_CSR devc->rec_regs->eb2csr +#define REC_ACR devc->rec_regs->eb2acr +#define REC_BCR devc->rec_regs->eb2bcr + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + struct cs4231_pioregs *codec_base; + uint_t *auxio_base; + + cs4231_eb2regs_t *play_regs; + cs4231_eb2regs_t *rec_regs; + + ddi_acc_handle_t codec_acc_handle; + ddi_acc_handle_t auxio_acc_handle; + ddi_acc_handle_t play_acc_handle; + ddi_acc_handle_t rec_acc_handle; +#define CODEC_HNDL devc->codec_acc_handle +#define PLAY_HNDL devc->play_acc_handle +#define REC_HNDL devc->rec_acc_handle +#define AUXIO_HNDL devc->auxio_acc_handle + + unsigned char MCE_bit; + unsigned char saved_regs[32]; + + int audio_flags; + int record_dev, playback_dev; + int speed; + unsigned char speed_bits; + int channels; + int audio_format; + unsigned char format_bits; + + int xfer_count; + int audio_mode; + int open_mode; + char *chip_name; + int model; +#define MD_1848 1 +#define MD_4231 2 +#define MD_4231A 3 + + /* Mixer parameters */ + int is_muted; + int recmask; + int supported_devices, orig_devices; + int supported_rec_devices, orig_rec_devices; + int *levels; + short mixer_reroute[32]; + int dev_no; + volatile unsigned long timer_ticks; + int timer_running; + int irq_ok; + mixer_ents *mix_devices; + int mixer_output_port; +} +cs4231_devc_t; + +typedef struct cs4231_portc_t +{ + int open_mode; +} +cs4231_portc_t; + +static int ad_format_mask[9 /*devc->model */ ] = +{ + 0, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, /* AD1845 */ + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE, + AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE, + AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE, + AFMT_U8 | AFMT_S16_LE /* CMI8330 */ +}; + +#define CODEC_INB(devc, addr) ddi_get8(CODEC_HNDL, addr) +#define CODEC_OUTB(devc, data, addr) ddi_put8(CODEC_HNDL, addr, data) + +/* + * CS4231 codec I/O registers + */ +#define io_Index_Addr(d) &d->codec_base->iar +#define io_Indexed_Data(d) &d->codec_base->idr +#define io_Status(d) &d->codec_base->statr +#define io_Polled_IO(d) &d->codec_base->piodr +#define CS4231_IO_RETRIES 10 + +/* + * EB2 audio registers + */ +#define EB2_AUXIO_COD_PDWN 0x00000001u /* power down Codec */ + +static int cs4231_open (int dev, int mode, int open_flags); +static void cs4231_close (int dev, int mode); +static int cs4231_ioctl (int dev, unsigned int cmd, ioctl_arg arg); +static void cs4231_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag); +static void cs4231_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag); +static int cs4231_prepare_for_output (int dev, int bsize, int bcount); +static int cs4231_prepare_for_input (int dev, int bsize, int bcount); +static void cs4231_halt (int dev); +static void cs4231_halt_input (int dev); +static void cs4231_halt_output (int dev); +static void cs4231_trigger (int dev, int bits); + +static void +eb2_power(cs4231_devc_t * devc, int level) +{ + unsigned int tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + tmp = ddi_get32(AUXIO_HNDL, devc->auxio_base); + + tmp &= ~EB2_AUXIO_COD_PDWN; + + if (!level) + tmp |= EB2_AUXIO_COD_PDWN; + ddi_put32(AUXIO_HNDL, devc->auxio_base, tmp); + + oss_udelay(10000); + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +static int +ad_read (cs4231_devc_t * devc, int reg) +{ + oss_native_word flags; + int x; + + reg = reg & 0xff; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + for (x=0;x<CS4231_IO_RETRIES;x++) + { + CODEC_OUTB (devc, (unsigned char) reg | devc->MCE_bit, + io_Index_Addr (devc)); + oss_udelay(1000); + + if (CODEC_INB (devc, io_Index_Addr (devc)) == (reg | devc->MCE_bit)) + break; + } + + if (x==CS4231_IO_RETRIES) + { + cmn_err(CE_NOTE, "Indirect register selection failed (read %d)\n", reg); + cmn_err(CE_CONT, "Reg=%02x (%02x)\n", CODEC_INB (devc, io_Index_Addr (devc)), reg | devc->MCE_bit); + } + + x = CODEC_INB (devc, io_Indexed_Data (devc)); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return x; +} + +static void +ad_write (cs4231_devc_t * devc, int reg, int data) +{ + oss_native_word flags; + int x; + + reg &= 0xff; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + for (x=0;x<CS4231_IO_RETRIES;x++) + { + CODEC_OUTB (devc, (unsigned char) reg | devc->MCE_bit, + io_Index_Addr (devc)); + + oss_udelay(1000); + + if (CODEC_INB (devc, io_Index_Addr (devc)) == (reg | devc->MCE_bit)) + break; + } + + if (x==CS4231_IO_RETRIES) + { + cmn_err(CE_NOTE, "Indirect register selection failed (write %d)\n", reg); + cmn_err(CE_CONT, "Reg=%02x (%02x)\n", CODEC_INB (devc, io_Index_Addr (devc)), reg | devc->MCE_bit); + } + + CODEC_OUTB (devc, (unsigned char) (data & 0xff), io_Indexed_Data (devc)); + oss_udelay(1000); + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +static void +ad_mute (cs4231_devc_t * devc) +{ + int i; + unsigned char prev; + + /* + * Save old register settings and mute output channels + */ + for (i = 6; i < 8; i++) + { + prev = devc->saved_regs[i] = ad_read (devc, i); + + devc->is_muted = 1; + ad_write (devc, i, prev | 0x80); + } +} + +static void +ad_unmute (cs4231_devc_t * devc) +{ + int i, dummy; + + /* + * Restore back old volume registers (unmute) + */ + for (i = 6; i < 8; i++) + { + ad_write (devc, i, devc->saved_regs[i] & ~0x80); + } + devc->is_muted = 0; +} + +static void +ad_enter_MCE (cs4231_devc_t * devc) +{ + unsigned short prev; + + int timeout = 1000; + while (timeout > 0 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) /*Are we initializing */ + timeout--; + + devc->MCE_bit = 0x40; + prev = CODEC_INB (devc, io_Index_Addr (devc)); + if (prev & 0x40) + { + return; + } + + CODEC_OUTB (devc, devc->MCE_bit, io_Index_Addr (devc)); +} + +static void +ad_leave_MCE (cs4231_devc_t * devc) +{ + unsigned char prev; + int timeout = 1000; + + while (timeout > 0 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) /*Are we initializing */ + timeout--; + + devc->MCE_bit = 0x00; + prev = CODEC_INB (devc, io_Index_Addr (devc)); + CODEC_OUTB (devc, 0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ + + if ((prev & 0x40) == 0) /* Not in MCE mode */ + { + return; + } + + CODEC_OUTB (devc, 0x00, io_Index_Addr (devc)); /* Clear the MCE bit */ +} + +static int +cs4231_set_recmask (cs4231_devc_t * devc, int mask) +{ + unsigned char recdev; + int i, n; + + mask &= devc->supported_rec_devices; + + /* Rename the mixer bits if necessary */ + for (i = 0; i < 32; i++) + if (devc->mixer_reroute[i] != i) + if (mask & (1 << i)) + { + mask &= ~(1 << i); + mask |= (1 << devc->mixer_reroute[i]); + } + + n = 0; + for (i = 0; i < 32; i++) /* Count selected device bits */ + if (mask & (1 << i)) + n++; + + if (n == 0) + mask = SOUND_MASK_MIC; + else if (n != 1) /* Too many devices selected */ + { + mask &= ~devc->recmask; /* Filter out active settings */ + + n = 0; + for (i = 0; i < 32; i++) /* Count selected device bits */ + if (mask & (1 << i)) + n++; + + if (n != 1) + mask = SOUND_MASK_MIC; + } + + switch (mask) + { + case SOUND_MASK_MIC: + recdev = 2; + break; + + case SOUND_MASK_LINE: + recdev = 0; + break; + + case SOUND_MASK_CD: + case SOUND_MASK_LINE1: + recdev = 1; + break; + + case SOUND_MASK_IMIX: + recdev = 3; + break; + + default: + mask = SOUND_MASK_MIC; + recdev = 2; + } + + recdev <<= 6; + ad_write (devc, 0, (ad_read (devc, 0) & 0x3f) | recdev); + ad_write (devc, 1, (ad_read (devc, 1) & 0x3f) | recdev); + + /* Rename the mixer bits back if necessary */ + for (i = 0; i < 32; i++) + if (devc->mixer_reroute[i] != i) + if (mask & (1 << devc->mixer_reroute[i])) + { + mask &= ~(1 << devc->mixer_reroute[i]); + mask |= (1 << i); + } + + devc->recmask = mask; + return mask; +} + +static void +change_bits (cs4231_devc_t * devc, unsigned char *regval, int dev, int chn, + int newval, int regoffs) +{ + unsigned char mask; + int shift; + int mute; + int mutemask; + int set_mute_bit; + + set_mute_bit = (newval == 0) || (devc->is_muted && dev == SOUND_MIXER_PCM); + + if (devc->mix_devices[dev][chn].polarity == 1) /* Reverse */ + { + newval = 100 - newval; + } + + mask = (1 << devc->mix_devices[dev][chn].nbits) - 1; + shift = devc->mix_devices[dev][chn].bitpos; + +#if 0 + newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ + *regval &= ~(mask << shift); /* Clear bits */ + *regval |= (newval & mask) << shift; /* Set new value */ +#else + if (devc->mix_devices[dev][RIGHT_CHN].mutepos == 8) + { /* if there is no mute bit */ + mute = 0; /* No mute bit; do nothing special */ + mutemask = ~0; /* No mute bit; do nothing special */ + } + else + { + mute = (set_mute_bit << devc->mix_devices[dev][RIGHT_CHN].mutepos); + mutemask = ~(1 << devc->mix_devices[dev][RIGHT_CHN].mutepos); + } + + newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ + *regval &= (~(mask << shift)) & (mutemask); /* Clear bits */ + *regval |= ((newval & mask) << shift) | mute; /* Set new value */ +#endif +} + +static int +cs4231_mixer_get (cs4231_devc_t * devc, int dev) +{ + if (!((1 << dev) & devc->supported_devices)) + return OSS_EINVAL; + + dev = devc->mixer_reroute[dev]; + + return devc->levels[dev]; +} + +static int +cs4231_mixer_set (cs4231_devc_t * devc, int dev, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int retvol; + + int regoffs, regoffs1; + unsigned char val; + + if (dev > 31) + return OSS_EINVAL; + + if (!(devc->supported_devices & (1 << dev))) + return OSS_EINVAL; + + dev = devc->mixer_reroute[dev]; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0) /* Mono control */ + right = left; + + retvol = left | (right << 8); + +#if 1 + /* Scale volumes */ + left = mix_cvt[left]; + right = mix_cvt[right]; + + /* Scale it again */ + left = mix_cvt[left]; + right = mix_cvt[right]; +#endif + + if (devc->mix_devices[dev][LEFT_CHN].nbits == 0) + return OSS_EINVAL; + + devc->levels[dev] = retvol; + + /* + * Set the left channel + */ + + regoffs1 = regoffs = devc->mix_devices[dev][LEFT_CHN].regno; + val = ad_read (devc, regoffs); + change_bits (devc, &val, dev, LEFT_CHN, left, regoffs); + devc->saved_regs[regoffs] = val; + + /* + * Set the right channel + */ + + if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0) + { + ad_write (devc, regoffs, val); + return retvol; /* Was just a mono channel */ + } + + regoffs = devc->mix_devices[dev][RIGHT_CHN].regno; + if (regoffs != regoffs1) + { + ad_write (devc, regoffs1, val); + val = ad_read (devc, regoffs); + } + + change_bits (devc, &val, dev, RIGHT_CHN, right, regoffs); + ad_write (devc, regoffs, val); + devc->saved_regs[regoffs] = val; + + return retvol; +} + +static void +cs4231_mixer_reset (cs4231_devc_t * devc) +{ + int i; + + devc->mix_devices = &(cs4231_mix_devices[0]); + devc->supported_devices = MODE2_MIXER_DEVICES; + devc->supported_rec_devices = MODE2_REC_DEVICES; + + for (i = 0; i < 32; i++) + devc->mixer_reroute[i] = i; + + devc->orig_devices = devc->supported_devices; + devc->orig_rec_devices = devc->supported_rec_devices; + + devc->levels = default_mixer_levels; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (devc->supported_devices & (1 << i)) + cs4231_mixer_set (devc, i, devc->levels[i]); + cs4231_set_recmask (devc, SOUND_MASK_MIC); +} + +static int +cs4231_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + cs4231_devc_t *devc = mixer_devs[dev]->devc; + + if (cmd == SOUND_MIXER_PRIVATE1) /* SADA compatible play target selection */ + { + int val; + + val = *arg; + + if (val == 0xffff) + return *arg = devc->mixer_output_port; + + val &= (AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT); + + devc->mixer_output_port = val; + + if (val & AUDIO_SPEAKER) + ad_write (devc, 26, ad_read (devc, 26) & ~0x40); /* Unmute mono out */ + else + ad_write (devc, 26, ad_read (devc, 26) | 0x40); /* Mute mono out */ + + return *arg = devc->mixer_output_port; + } + + if (((cmd >> 8) & 0xff) == 'M') + { + int val; + + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + val = *arg; + return *arg = cs4231_set_recmask (devc, val); + break; + + default: + val = *arg; + return *arg = cs4231_mixer_set (devc, cmd & 0xff, val); + } + else + switch (cmd & 0xff) /* + * Return parameters + */ + { + + case SOUND_MIXER_RECSRC: + return *arg = devc->recmask; + break; + + case SOUND_MIXER_DEVMASK: + return *arg = devc->supported_devices; + break; + + case SOUND_MIXER_STEREODEVS: + return *arg = devc->supported_devices & + ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); + break; + + case SOUND_MIXER_RECMASK: + return *arg = devc->supported_rec_devices; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + default: + return *arg = cs4231_mixer_get (devc, cmd & 0xff); + } + } + else + return OSS_EINVAL; +} + +static int +cs4231_set_rate (int dev, int arg) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + /* + * The sampling speed is encoded in the least significant nibble of I8. The + * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other + * three bits select the divisor (indirectly): + * + * The available speeds are in the following table. Keep the speeds in + * the increasing order. + */ + typedef struct + { + int speed; + unsigned char bits; + } + speed_struct; + + static speed_struct speed_table[] = { + {5510, (0 << 1) | 1}, + {5510, (0 << 1) | 1}, + {6620, (7 << 1) | 1}, + {8000, (0 << 1) | 0}, + {9600, (7 << 1) | 0}, + {11025, (1 << 1) | 1}, + {16000, (1 << 1) | 0}, + {18900, (2 << 1) | 1}, + {22050, (3 << 1) | 1}, + {27420, (2 << 1) | 0}, + {32000, (3 << 1) | 0}, + {33075, (6 << 1) | 1}, + {37800, (4 << 1) | 1}, + {44100, (5 << 1) | 1}, + {48000, (6 << 1) | 0} + }; + + int i, n, selected = -1; + + n = sizeof (speed_table) / sizeof (speed_struct); + + if (arg <= 0) + return devc->speed; + +#if 1 + if (ad_read (devc, 9) & 0x03) + return devc->speed; +#endif + + if (arg < speed_table[0].speed) + selected = 0; + if (arg > speed_table[n - 1].speed) + selected = n - 1; + + for (i = 1 /*really */ ; selected == -1 && i < n; i++) + if (speed_table[i].speed == arg) + selected = i; + else if (speed_table[i].speed > arg) + { + int diff1, diff2; + + diff1 = arg - speed_table[i - 1].speed; + diff2 = speed_table[i].speed - arg; + + if (diff1 < diff2) + selected = i - 1; + else + selected = i; + } + + if (selected == -1) + { + cmn_err (CE_WARN, "Can't find supported sample rate?\n"); + selected = 3; + } + + devc->speed = speed_table[selected].speed; + devc->speed_bits = speed_table[selected].bits; + return devc->speed; +} + +static short +cs4231_set_channels (int dev, short arg) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + if (arg != 1 && arg != 2) + { + return devc->channels; + } + +#if 1 + if (ad_read (devc, 9) & 0x03) + { + return devc->channels; + } +#endif + + devc->channels = arg; + return arg; +} + +static unsigned int +cs4231_set_bits (int dev, unsigned int arg) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + static struct format_tbl + { + int format; + unsigned char bits; + } + format2bits[] = + { + {0, 0}, + {AFMT_MU_LAW, 1}, + {AFMT_A_LAW, 3}, + {AFMT_U8, 0}, + {AFMT_S16_LE, 2}, + {AFMT_S16_BE, 6}, + {AFMT_S8, 0}, + {AFMT_U16_LE, 0}, + {AFMT_U16_BE, 0} + }; + int i, n = sizeof (format2bits) / sizeof (struct format_tbl); + + if (arg == 0) + return devc->audio_format; + +#if 1 + if (ad_read (devc, 9) & 0x03) + return devc->audio_format; +#endif + + if (!(arg & ad_format_mask[devc->model])) + arg = AFMT_U8; + + devc->audio_format = arg; + + for (i = 0; i < n; i++) + if (format2bits[i].format == arg) + { + if ((devc->format_bits = format2bits[i].bits) == 0) + return devc->audio_format = AFMT_U8; /* Was not supported */ + + return arg; + } + + /* Still hanging here. Something must be terribly wrong */ + devc->format_bits = 0; + return devc->audio_format = AFMT_U8; +} + +static const audiodrv_t cs4231_audio_driver = { + cs4231_open, + cs4231_close, + cs4231_output_block, + cs4231_start_input, + cs4231_ioctl, + cs4231_prepare_for_input, + cs4231_prepare_for_output, + cs4231_halt, + NULL, + NULL, + cs4231_halt_input, + cs4231_halt_output, + cs4231_trigger, + cs4231_set_rate, + cs4231_set_bits, + cs4231_set_channels +}; + +static mixer_driver_t cs4231_mixer_driver = { + cs4231_mixer_ioctl +}; + +static int +cs4231_open (int dev, int mode, int open_flags) +{ + cs4231_devc_t *devc = NULL; + cs4231_portc_t *portc; + oss_native_word flags; + + if (dev < 0 || dev >= num_audio_engines) + return OSS_ENXIO; + + devc = (cs4231_devc_t *) audio_engines[dev]->devc; + portc = (cs4231_portc_t *) audio_engines[dev]->portc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode || (devc->open_mode & mode)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + devc->open_mode |= mode; + portc->open_mode = mode; + devc->audio_mode &= ~mode; + + if (mode & OPEN_READ) + devc->record_dev = dev; + if (mode & OPEN_WRITE) + devc->playback_dev = dev; +/* + * Mute output until the playback really starts. This decreases clicking (hope so). + */ + ad_mute (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +cs4231_close (int dev, int mode) +{ + oss_native_word flags; + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + cs4231_portc_t *portc = (cs4231_portc_t *) audio_engines[dev]->portc; + + DDB (cmn_err (CE_CONT, "cs4231_close(void)\n")); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + cs4231_halt (dev); + + devc->open_mode &= ~portc->open_mode; + devc->audio_mode &= ~portc->open_mode; + portc->open_mode = 0; + + ad_mute (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +cs4231_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void +cs4231_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + oss_native_word flags; + unsigned int cnt; + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + cnt = fragsize; + /* cnt = count; */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ + cnt >>= 1; + if (devc->channels > 1) + cnt >>= 1; + cnt--; + + if (devc->audio_mode & PCM_ENABLE_OUTPUT + && audio_engines[dev]->flags & ADEV_AUTOMODE && intrflag + && cnt == devc->xfer_count) + { + devc->audio_mode |= PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return; + } + + ad_write (devc, 15, (unsigned char) (cnt & 0xff)); + ad_write (devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); + + devc->xfer_count = cnt; + devc->audio_mode |= PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +cs4231_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + oss_native_word flags; + unsigned int cnt; + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + cnt = fragsize; + /* cnt = count; */ + + if (devc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ + cnt >>= 1; + + if (devc->channels > 1) + cnt >>= 1; + cnt--; + + if (devc->audio_mode & PCM_ENABLE_INPUT + && audio_engines[dev]->flags & ADEV_AUTOMODE && intrflag + && cnt == devc->xfer_count) + { + devc->audio_mode |= PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return; /* + * Auto DMA mode on. No need to react + */ + } + + ad_write (devc, 31, (unsigned char) (cnt & 0xff)); + ad_write (devc, 30, (unsigned char) ((cnt >> 8) & 0xff)); + + ad_unmute (devc); + + devc->xfer_count = cnt; + devc->audio_mode |= PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +set_output_format (int dev) +{ + int timeout; + unsigned char fs, old_fs, tmp = 0; + oss_native_word flags; + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + if (ad_read (devc, 9) & 0x03) + return; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + fs = devc->speed_bits | (devc->format_bits << 5); + + if (devc->channels > 1) + fs |= 0x10; + + ad_enter_MCE (devc); /* Enables changes to the format select reg */ + + old_fs = ad_read (devc, 8); + + ad_write (devc, 8, fs); + /* + * Write to I8 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && CODEC_INB (devc, io_Index_Addr(devc)) != 0x80) + timeout++; + timeout = 0; + while (timeout < 10000 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) + timeout++; + + ad_leave_MCE (devc); + + devc->xfer_count = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +set_input_format (int dev) +{ + int timeout; + unsigned char fs, old_fs, tmp = 0; + oss_native_word flags; + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + fs = devc->speed_bits | (devc->format_bits << 5); + + if (devc->channels > 1) + fs |= 0x10; + + ad_enter_MCE (devc); /* Enables changes to the format select reg */ + + /* + * If mode >= 2 (CS4231), set I28. It's the capture format register. + */ + if (devc->model != MD_1848) + { + old_fs = ad_read (devc, 28); + ad_write (devc, 28, fs); + + /* + * Write to I28 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && CODEC_INB (devc, io_Index_Addr(devc)) != 0x80) + timeout++; + + timeout = 0; + while (timeout < 10000 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) + timeout++; + + if (devc->model != MD_1848) + { + /* + * CS4231 compatible devices don't have separate sampling rate selection + * register for recording an playback. The I8 register is shared so we have to + * set the speed encoding bits of it too. + */ + unsigned char tmp = devc->speed_bits | (ad_read (devc, 8) & 0xf0); + ad_write (devc, 8, tmp); + /* + * Write to I8 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && CODEC_INB (devc, io_Index_Addr(devc)) != 0x80) + timeout++; + + timeout = 0; + while (timeout < 10000 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) + timeout++; + } + } + else + { /* For CS4231 set I8. */ + + old_fs = ad_read (devc, 8); + ad_write (devc, 8, fs); + /* + * Write to I8 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && CODEC_INB (devc, io_Index_Addr(devc)) != 0x80) + timeout++; + timeout = 0; + while (timeout < 10000 && CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) + timeout++; + } + + ad_leave_MCE (devc); + devc->xfer_count = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + +} + +static void +set_sample_format (int dev) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + if (ad_read (devc, 9) & 0x03) /* Playback or recording active */ + return; + + set_input_format (dev); + set_output_format (dev); +} + +static int +cs4231_prepare_for_output (int dev, int bsize, int bcount) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + ad_mute (devc); + + cs4231_halt_output (dev); + set_sample_format (dev); + +/* + * Setup the EB2 DMA engine + */ + + return 0; +} + +static int +cs4231_prepare_for_input (int dev, int bsize, int bcount) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + + if (devc->audio_mode) + return 0; + + cs4231_halt_input (dev); + set_sample_format (dev); + //TODO: Prepare the DMA engine + return 0; +} + +static void +cs4231_halt (int dev) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + cs4231_portc_t *portc = (cs4231_portc_t *) audio_engines[dev]->portc; + + unsigned char bits = ad_read (devc, 9); + + if (bits & 0x01 && portc->open_mode & OPEN_WRITE) + cs4231_halt_output (dev); + + if (bits & 0x02 && portc->open_mode & OPEN_READ) + cs4231_halt_input (dev); +} + +static void +cs4231_halt_input (int dev) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + cs4231_portc_t *portc = (cs4231_portc_t *) audio_engines[dev]->portc; + oss_native_word flags; + + if (!(portc->open_mode & OPEN_READ)) + return; + if (!(ad_read (devc, 9) & 0x02)) + return; /* Capture not enabled */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + ad_write (devc, 9, ad_read (devc, 9) & ~0x02); /* Stop capture */ + // TODO: Stop DMA + + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear interrupt status */ + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear interrupt status */ + + devc->audio_mode &= ~PCM_ENABLE_INPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +cs4231_halt_output (int dev) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + cs4231_portc_t *portc = (cs4231_portc_t *) audio_engines[dev]->portc; + oss_native_word flags; + + if (!(portc->open_mode & OPEN_WRITE)) + return; + if (!(ad_read (devc, 9) & 0x01)) + return; /* Playback not enabled */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + ad_mute (devc); + oss_udelay (10); + + ad_write (devc, 9, ad_read (devc, 9) & ~0x01); /* Stop playback */ + //TODO: Disable DMA + + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear interrupt status */ + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear interrupt status */ + + devc->audio_mode &= ~PCM_ENABLE_OUTPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +cs4231_trigger (int dev, int state) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) audio_engines[dev]->devc; + cs4231_portc_t *portc = (cs4231_portc_t *) audio_engines[dev]->portc; + oss_native_word flags; + unsigned char tmp, old, oldstate; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + oldstate = state; + state &= devc->audio_mode; + + tmp = old = ad_read (devc, 9); + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + tmp |= 0x02; + else + tmp &= ~0x02; + } + + if (portc->open_mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + tmp |= 0x01; + else + tmp &= ~0x01; + } + + /* ad_mute(devc); */ + if (tmp != old) + { + ad_write (devc, 9, tmp); + if (state & PCM_ENABLE_OUTPUT) + { + oss_udelay (10); + oss_udelay (10); + oss_udelay (10); + ad_unmute (devc); + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +cs4231_init_hw (cs4231_devc_t * devc) +{ + int i; + oss_native_word flags; + /* + * Initial values for the indirect registers of CS4248/CS4231. + */ + static int init_values[] = { + 0xa8, 0xa8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00, + + /* Positions 16 to 31 just for CS4231/2 and ad1845 */ + 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + for (i = 0; i < 16; i++) + ad_write (devc, i, init_values[i]); + +/* + * The XCTL0 (0x40) and XCTL1 (0x80) bits of I10 are used in Sparcs to + * control codec's output pins which mute the line out and speaker out + * connectors (respectively). + * + * Set them both to 0 (not muted). Better control is required in future. + */ + + ad_write (devc, 10, ad_read (devc, 10) & ~0xc0); + + ad_mute (devc); /* Mute PCM until next use and initialize some variables */ + + if (devc->model > MD_1848) + { + ad_write (devc, 12, ad_read (devc, 12) | 0x40); /* Mode2 = enabled */ + + for (i = 16; i < 32; i++) + ad_write (devc, i, init_values[i]); + + } + + if (devc->model > MD_1848) + { + if (devc->audio_flags & ADEV_DUPLEX) + ad_write (devc, 9, ad_read (devc, 9) & ~0x04); /* Dual DMA mode */ + else + ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */ + + } + else + { + devc->audio_flags &= ~ADEV_DUPLEX; + ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */ + } + + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear pending interrupts */ + + /* + * Toggle the MCE bit. It completes the initialization phase. + */ + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ad_enter_MCE (devc); /* In case the bit was off */ + ad_leave_MCE (devc); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + +/* + * Perform full calibration + */ + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ad_enter_MCE (devc); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + ad_write (devc, 9, ad_read (devc, 9) | 0x18); /* Enable autocalibration */ + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ad_leave_MCE (devc); /* This will trigger autocalibration */ + ad_enter_MCE (devc); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + ad_write (devc, 9, ad_read (devc, 9) & ~0x18); /* Disable autocalibration */ + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ad_leave_MCE (devc); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +int +cs4231_detect (cs4231_devc_t * devc) +{ + + unsigned char tmp; + unsigned char tmp1 = 0xff, tmp2 = 0xff; + oss_native_word flags; + + int i; + + devc->MCE_bit = 0x40; + devc->chip_name = "CS4231"; + devc->model = MD_4231; /* CS4231 or CS4248 */ + devc->levels = NULL; + + /* + * Check that the I/O address is in use. + * + * The bit 0x80 of the base I/O port is known to be 0 after the + * chip has performed its power on initialization. Just assume + * this has happened before the OS is starting. + * + * If the I/O address is unused, it typically returns 0xff. + */ + + if (CODEC_INB (devc, io_Index_Addr(devc)) == 0xff) + { + DDB (cmn_err + (CE_CONT, + "cs4231_detect: The base I/O address appears to be dead\n")); + } + +#if 1 +/* + * Wait for the device to stop initialization + */ + DDB (cmn_err (CE_CONT, "cs4231_detect() - step 0\n")); + + for (i = 0; i < 10000000; i++) + { + unsigned char x = CODEC_INB (devc, io_Index_Addr(devc)); + if (x == 0xff || !(x & 0x80)) + break; + } + +#endif + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step A\n")); + + if (CODEC_INB (devc, io_Index_Addr(devc)) == 0x80) /* Not ready. Let's wait */ + { + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ad_leave_MCE (devc); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + } + + if ((CODEC_INB (devc, io_Index_Addr(devc)) & 0x80) != 0x00) /* Not a CS4231 */ + { + DDB (cmn_err (CE_WARN, "cs4231 detect error - step A (%02x)\n", + (int) CODEC_INB (devc, io_Index_Addr(devc)))); + return 0; + } + + /* + * Test if it's possible to change contents of the indirect registers. + * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only + * so try to avoid using it. + */ + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step B\n")); + ad_write (devc, 0, 0xaa); + ad_write (devc, 1, 0x45); /* 0x55 with bit 0x10 clear */ + oss_udelay (10); + + if ((tmp1 = ad_read (devc, 0)) != 0xaa || + (tmp2 = ad_read (devc, 1)) != 0x45) + { + DDB (cmn_err + (CE_WARN, "cs4231 detect error - step B (%x/%x)\n", tmp1, tmp2)); +#if 1 + if (tmp1 == 0x8a && tmp2 == 0xff) /* AZT2320 ????? */ + { + DDB (cmn_err (CE_CONT, "Ignoring error\n")); + } + else +#endif + return 0; + } + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step C\n")); + ad_write (devc, 0, 0x45); + ad_write (devc, 1, 0xaa); + oss_udelay (10); + + if ((tmp1 = ad_read (devc, 0)) != 0x45 + || (tmp2 = ad_read (devc, 1)) != 0xaa) + { + DDB (cmn_err + (CE_WARN, "cs4231 detect error - step C (%x/%x)\n", tmp1, tmp2)); +#if 1 + if (tmp1 == 0x65 && tmp2 == 0xff) /* AZT2320 ????? */ + { + DDB (cmn_err (CE_CONT, "Ignoring error\n")); + } + else +#endif + return 0; + } + + /* + * The indirect register I12 has some read only bits. Lets + * try to change them. + */ + DDB (cmn_err (CE_CONT, "cs4231_detect() - step D\n")); + tmp = ad_read (devc, 12); + ad_write (devc, 12, (~tmp) & 0x0f); + + if ((tmp & 0x0f) != ((tmp1 = ad_read (devc, 12)) & 0x0f)) + { + DDB (cmn_err (CE_WARN, "cs4231 detect error - step D (%x)\n", tmp1)); + return 0; + } + + /* + * NOTE! Last 4 bits of the reg I12 tell the chip revision. + * 0x01=RevB and 0x0A=RevC. + */ + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step G\n")); + + ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */ + + tmp1 = ad_read (devc, 12); + if (tmp1 & 0x80) + { + devc->chip_name = "CS4248"; /* Our best knowledge just now */ + } + + if ((tmp1 & 0xc0) == (0x80 | 0x40)) + { + /* + * CS4231 detected - is it? + * + * Verify that setting I0 doesn't change I16. + */ + DDB (cmn_err (CE_CONT, "cs4231_detect() - step H\n")); + ad_write (devc, 16, 0); /* Set I16 to known value */ + + ad_write (devc, 0, 0x45); + if ((tmp1 = ad_read (devc, 16)) != 0x45) /* No change -> CS4231? */ + { + + ad_write (devc, 0, 0xaa); + if ((tmp1 = ad_read (devc, 16)) == 0xaa) /* Rotten bits? */ + { + DDB (cmn_err + (CE_WARN, "cs4231 detect error - step H(%x)\n", tmp1)); + return 0; + } + + /* + * Verify that some bits of I25 are read only. + */ + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step I\n")); + tmp1 = ad_read (devc, 25); /* Original bits */ + ad_write (devc, 25, ~tmp1); /* Invert all bits */ + if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7)) + { + int id, full_id; + + /* + * It's at least CS4231 + */ + devc->chip_name = "CS4231"; + + devc->model = MD_4231; + + /* + * It could be an AD1845 or CS4231A as well. + * CS4231 and AD1845 report the same revision info in I25 + * while the CS4231A reports different. + */ + + id = ad_read (devc, 25) & 0xe7; + full_id = ad_read (devc, 25); + if (id == 0x80) /* Device busy??? */ + id = ad_read (devc, 25) & 0xe7; + if (id == 0x80) /* Device still busy??? */ + id = ad_read (devc, 25) & 0xe7; + DDB (cmn_err + (CE_CONT, "cs4231_detect() - step J (%02x/%02x)\n", id, + ad_read (devc, 25))); + + switch (id) + { + + case 0xa0: + devc->chip_name = "CS4231A"; + devc->model = MD_4231A; + break; + + default: /* Assume CS4231 or OPTi 82C930 */ + DDB (cmn_err (CE_CONT, "I25 = %02x/%02x\n", + ad_read (devc, 25), + ad_read (devc, 25) & 0xe7)); + devc->model = MD_4231; + + } + } + ad_write (devc, 25, tmp1); /* Restore bits */ + + DDB (cmn_err (CE_CONT, "cs4231_detect() - step K\n")); + } + } + + DDB (cmn_err (CE_CONT, "cs4231_detect() - Detected OK\n")); + + return 1; +} + +void +cs4231_init (cs4231_devc_t * devc) +{ + int i, my_dev, my_mixer; + char dev_name[100]; + + cs4231_portc_t *portc = NULL; + + devc->open_mode = 0; + devc->timer_ticks = 0; + devc->audio_flags = ADEV_AUTOMODE; + devc->playback_dev = devc->record_dev = 0; + + sprintf (dev_name, "Sparc builtin audio (%s)", devc->chip_name); + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + dev_name, + &cs4231_mixer_driver, + sizeof (mixer_driver_t), devc)) >= 0) + { + cs4231_mixer_reset (devc); + } + + if (devc->model > MD_1848) + { + devc->audio_flags |= ADEV_DUPLEX; + } + + if ((my_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + dev_name, + &cs4231_audio_driver, + sizeof (audiodrv_t), + devc->audio_flags, + ad_format_mask[devc->model], + devc, -1)) < 0) + { + return; + } + + portc = PMALLOC (devc->osdev, sizeof (*portc)); + memset ((char *) portc, 0, sizeof (*portc)); + + audio_engines[my_dev]->portc = portc; + audio_engines[my_dev]->min_block = 512; + audio_engines[my_dev]->mixer_dev = my_mixer; + + cs4231_init_hw (devc); + +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, my_dev, -1, 0); +#endif +#if 0 + test_it (devc); +#endif +} + +void +cs4231_unload (cs4231_devc_t * devc) +{ +#if 0 + int i, dev = 0; + + for (i = 0; devc == NULL && i < nr_cs4231_devs; i++) + if (adev_info[i].base == io_base) + { + devc = &adev_info[i]; + dev = devc->dev_no; + } + + if (devc != NULL) + { + + if (!share_dma) + { + if (irq > 0) + snd_release_irq (devc->irq, NULL); + + FREE_DMA_CHN (audio_engines[dev]->dmap_out->dma); + + if (audio_engines[dev]->dmap_in->dma != + audio_engines[dev]->dmap_out->dma) + FREE_DMA_CHN (audio_engines[dev]->dmap_in->dma); + } + } + else + cmn_err (CE_WARN, "Can't find device to be unloaded. Base=%x\n", io_base); +#endif +} + +int +cs4231intr (oss_device_t * osdev) +{ + unsigned char status; + cs4231_devc_t *devc = osdev->devc; + int alt_stat = 0xff; + unsigned char c930_stat = 0; + int cnt = 0; + int serviced = 0; + + devc->irq_ok = 1; + +interrupt_again: /* Jump back here if int status doesn't reset */ + + status = CODEC_INB (devc, io_Status (devc)); + + if (status == 0x80) + cmn_err (CE_CONT, "cs4231intr: Why?\n"); + else + serviced = 1; + if (devc->model == MD_1848) + CODEC_OUTB (devc, 0, io_Status (devc)); /* Clear interrupt status */ + + if (status & 0x01) + { + if (devc->model != MD_1848) + { + alt_stat = ad_read (devc, 24); + } + + /* Acknowledge the intr before proceeding */ + if (devc->model != MD_1848) + ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat); /* Selective ack */ + + if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT + && alt_stat & 0x20) + { + oss_audio_inputintr (devc->record_dev, 0); + } + + if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT + && alt_stat & 0x10) + { + oss_audio_outputintr (devc->playback_dev, 1); + } + + if (devc->model != MD_1848 && alt_stat & 0x40) /* Timer interrupt */ + { + devc->timer_ticks++; + } + } + +#if 1 +/* + * Sometimes playback or capture interrupts occur while a timer interrupt + * is being handled. The interrupt will not be retriggered if we don't + * handle it now. Check if an interrupt is still pending and restart + * the handler in this case. + */ + if (CODEC_INB (devc, io_Status (devc)) & 0x01 && cnt++ < 4) + { + goto interrupt_again; + } +#endif + return serviced; +} + +int +oss_audiocs_attach (oss_device_t * osdev) +{ + unsigned int dw; + int err; + +static ddi_device_acc_attr_t acc_attr = { + DDI_DEVICE_ATTR_V0, + DDI_STRUCTURE_LE_ACC, + DDI_STRICTORDER_ACC +}; + caddr_t addr; + + cs4231_devc_t *devc = osdev->devc; + + DDB(cmn_err(CE_CONT, "Entered oss_audiocs_attach()\n")); + + 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->chip_name = "Generic CS4231"; + +/* + * Map I/O registers. This is done in Solaris specific way so the code + * is not portable. + */ + + // Codec registers + if ((err = ddi_regs_map_setup + (osdev->dip, 0, &addr, 0, 16, &acc_attr, + &CODEC_HNDL)) != DDI_SUCCESS) + { + cmn_err(CE_WARN, "Cannot map codec registers, error=%d\n", err); + return 0; + } + devc->codec_base = (struct cs4231_pioregs*)addr; + + // Play registers + if ((err = ddi_regs_map_setup + (osdev->dip, 1, (caddr_t *)&devc->play_regs, 0, sizeof(cs4231_eb2regs_t), &acc_attr, + &PLAY_HNDL)) != DDI_SUCCESS) + { + cmn_err(CE_WARN, "Cannot map codec registers, error=%d\n", err); + return 0; + } + + // Capture registers + if ((err = ddi_regs_map_setup + (osdev->dip, 2, (caddr_t *)&devc->rec_regs, 0, sizeof(cs4231_eb2regs_t), &acc_attr, + &REC_HNDL)) != DDI_SUCCESS) + { + cmn_err(CE_WARN, "Cannot map codec registers, error=%d\n", err); + return 0; + } + + // Auxio register + if ((err = ddi_regs_map_setup + (osdev->dip, 3, &addr, 0, 4, &acc_attr, + &AUXIO_HNDL)) != DDI_SUCCESS) + { + cmn_err(CE_WARN, "Cannot map aixio register, error=%d\n", err); + return 0; + } + devc->auxio_base = (uint_t *)addr; + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + + eb2_power(devc, 1); + + if (oss_register_interrupts (devc->osdev, 0, cs4231intr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to install interrupt handler\n"); + return 0; + } + + if (!cs4231_detect(devc)) + return 0; + + oss_register_device (osdev, devc->chip_name); + + cs4231_init (devc); + + return 1; +} + +int +oss_audiocs_detach (oss_device_t * osdev) +{ + cs4231_devc_t *devc = (cs4231_devc_t *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + oss_unregister_interrupts (devc->osdev); + + eb2_power(devc, 0); + + ddi_regs_map_free(&CODEC_HNDL); + ddi_regs_map_free(&PLAY_HNDL); + ddi_regs_map_free(&REC_HNDL); + ddi_regs_map_free(&AUXIO_HNDL); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_audiocs/oss_audiocs.man b/kernel/drv/oss_audiocs/oss_audiocs.man new file mode 100644 index 0000000..66f2b21 --- /dev/null +++ b/kernel/drv/oss_audiocs/oss_audiocs.man @@ -0,0 +1,21 @@ +NAME +oss_audiocs - Cirrus Logic CS4231 driver for Sun Sparc Workstations + +DESCRIPTION +Open Sound System driver for Cirrus Logic (Crystal Semicoductor) CS4231 audio +controller onboard the Sun Sparc workstatiosn + +CS4231 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_audiocs.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_audioloop/.config b/kernel/drv/oss_audioloop/.config new file mode 100644 index 0000000..828bd4f --- /dev/null +++ b/kernel/drv/oss_audioloop/.config @@ -0,0 +1,2 @@ +bus=VIRTUAL +targetcpu=any diff --git a/kernel/drv/oss_audioloop/.devices b/kernel/drv/oss_audioloop/.devices new file mode 100644 index 0000000..fd543fb --- /dev/null +++ b/kernel/drv/oss_audioloop/.devices @@ -0,0 +1 @@ +oss_audioloop AUDIOLOOP OSS loopback audio driver diff --git a/kernel/drv/oss_audioloop/.name b/kernel/drv/oss_audioloop/.name new file mode 100644 index 0000000..4d501dc --- /dev/null +++ b/kernel/drv/oss_audioloop/.name @@ -0,0 +1 @@ +OSS loopback audio driver diff --git a/kernel/drv/oss_audioloop/.params b/kernel/drv/oss_audioloop/.params new file mode 100644 index 0000000..b8c8f7b --- /dev/null +++ b/kernel/drv/oss_audioloop/.params @@ -0,0 +1,4 @@ +int audioloop_instances=1; +/* + * audioloop_instances: Number of instances (client/server pairs) to create. + */ diff --git a/kernel/drv/oss_audioloop/oss_audioloop.c b/kernel/drv/oss_audioloop/oss_audioloop.c new file mode 100644 index 0000000..c51cc48 --- /dev/null +++ b/kernel/drv/oss_audioloop/oss_audioloop.c @@ -0,0 +1,919 @@ +/* + * Purpose: OSS audio loopback (virtual) driver + * + * Description: + * OSS audio loopback driver is a virtual/pseudo driver that can be used + * for example to user land based virtual audio devices. + * + * Each audioloop instance has two sides or endpoints. The server side is + * typically used by the application that implements the virtual audio device. + * Client side in turn is used by any audio application that wants to record or + * play audio. Server side device must be open before the client side can be + * opened. + * + * + * + * CAUTION! Certain portc fields (mutex, rate/format) are only available + * on the server side portc structure. Care must be taken. + * + * + * + */ +/* + * + * 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_audioloop_cfg.h" + +#define MAX_RATE 192000 +#define MAX_CHANNELS 64 +#define SUPPORTED_FORMATS (AFMT_S16_NE|AFMT_S32_NE) + +extern int audioloop_instances; /* Config option */ + +#define MAX_INSTANCES 16 + +typedef struct _audioloop_devc_t audioloop_devc_t; +typedef struct _audioloop_portc_t audioloop_portc_t; + +struct _audioloop_portc_t +{ + audioloop_devc_t *devc; + audioloop_portc_t *peer; + int audio_dev; + int open_mode; + int port_type; +#define PT_CLIENT 1 +#define PT_SERVER 2 + int instance; + + /* State variables */ + int input_triggered, output_triggered; + oss_wait_queue_t *wq; + + /* Server side (only) fields */ + int rate; + int channels; + unsigned int fmt, fmt_bytes; + oss_mutex_t mutex; + timeout_id_t timeout_id; +}; + +struct _audioloop_devc_t +{ + oss_device_t *osdev; + oss_mutex_t mutex; + + int num_instances; + + audioloop_portc_t *client_portc[MAX_INSTANCES]; + audioloop_portc_t *server_portc[MAX_INSTANCES]; +}; + +#define MAX_ATTACH_COUNT 1 +static audioloop_devc_t audioloop_devices[MAX_ATTACH_COUNT]; +static int attach_count; + +static void +transfer_audio (audioloop_portc_t * server_portc, dmap_t * dmap_from, + dmap_t * dmap_to) +{ + int l = dmap_from->fragment_size; + unsigned char *fromp, *top; + + if (dmap_to->fragment_size != l) + { + cmn_err (CE_WARN, "Fragment size mismatch (%d != %d)\n", + dmap_to->fragment_size, l); + + /* Perform emergency stop */ + server_portc->input_triggered = 0; + server_portc->output_triggered = 0; + server_portc->peer->input_triggered = 0; + server_portc->peer->output_triggered = 0; + return; + } + + fromp = + dmap_from->dmabuf + (dmap_from->byte_counter % dmap_from->bytes_in_use); + top = dmap_to->dmabuf + (dmap_to->byte_counter % dmap_to->bytes_in_use); + + memcpy (top, fromp, l); + +} + +static void +handle_input (audioloop_portc_t * server_portc) +{ + audioloop_portc_t *client_portc = server_portc->peer; + + if (client_portc->output_triggered) + { + transfer_audio (server_portc, + audio_engines[client_portc->audio_dev]->dmap_out, + audio_engines[server_portc->audio_dev]->dmap_in); + oss_audio_outputintr (client_portc->audio_dev, 0); + } + + oss_audio_inputintr (server_portc->audio_dev, 0); +} + +static void +handle_output (audioloop_portc_t * server_portc) +{ + audioloop_portc_t *client_portc = server_portc->peer; + + if (client_portc->input_triggered) + { + transfer_audio (server_portc, + audio_engines[server_portc->audio_dev]->dmap_out, + audio_engines[client_portc->audio_dev]->dmap_in); + oss_audio_inputintr (client_portc->audio_dev, 0); + } + + oss_audio_outputintr (server_portc->audio_dev, 0); +} + +static void +audioloop_cb (void *pc) +{ +/* + * This timer callback routine will get called 100 times/second. It handles + * movement of audio data between the client and server sides. + */ + audioloop_portc_t *server_portc = pc; + int tmout = OSS_HZ / 100; + + if (tmout < 1) + tmout = 1; + + server_portc->timeout_id = 0; /* No longer valid */ + + if (server_portc->input_triggered) + handle_input (server_portc); + + if (server_portc->output_triggered) + handle_output (server_portc); + + /* Retrigger timer callback */ + if (server_portc->input_triggered || server_portc->output_triggered) + server_portc->timeout_id = timeout (audioloop_cb, server_portc, tmout); +} + +static int +audioloop_check_input (int dev) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + if (!portc->peer->output_triggered) + { + return OSS_ECONNRESET; + } + return 0; +} + +static int +audioloop_check_output (int dev) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + if (!portc->peer->input_triggered) + { + return OSS_ECONNRESET; + } + + if (portc->peer->open_mode == 0) + return OSS_EIO; + return 0; +} + +static void +setup_sample_format (audioloop_portc_t * portc) +{ + adev_t *adev; + int fragsize, frame_size; + + frame_size = portc->channels * portc->fmt_bytes; + if (frame_size == 0) + frame_size = 4; + + fragsize = (portc->rate * frame_size) / 100; /* Number of bytes/fragment (100Hz) */ + portc->rate = fragsize * 100 / frame_size; + +/* Setup the server side */ + adev = audio_engines[portc->audio_dev]; + adev->min_block = adev->max_block = fragsize; + +/* Setup the client side */ + adev = audio_engines[portc->peer->audio_dev]; + adev->min_block = adev->max_block = fragsize; + + adev->max_rate = adev->min_rate = portc->rate; + adev->iformat_mask = portc->fmt; + adev->oformat_mask = portc->fmt; + adev->xformat_mask = portc->fmt; + adev->min_channels = adev->max_channels = portc->channels; +} + +static int +audioloop_server_set_rate (int dev, int arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->rate; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return portc->rate; + + if (arg < 5000) + arg = 5000; + if (arg > MAX_RATE) + arg = MAX_RATE; + + /* Force the sample rate to be multiple of 100 */ + arg = (arg / 100) * 100; + + portc->rate = arg; + + setup_sample_format (portc); + + return portc->rate = arg; +} + +/*ARGSUSED*/ +static int +audioloop_client_set_rate (int dev, int arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + return portc->peer->rate; +} + +static short +audioloop_server_set_channels (int dev, short arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->channels; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return portc->channels; + + if (arg < 1) + arg = 1; + if (arg > MAX_CHANNELS) + arg = MAX_CHANNELS; + + portc->channels = arg; + + setup_sample_format (portc); + + return portc->channels; +} + +/*ARGSUSED*/ +static short +audioloop_client_set_channels (int dev, short arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + return portc->peer->channels; /* Server side channels */ +} + +static unsigned int +audioloop_server_set_format (int dev, unsigned int arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->fmt; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return portc->fmt; + + switch (arg) + { + case AFMT_S16_NE: + portc->fmt_bytes = 2; + break; + + case AFMT_S32_NE: + portc->fmt_bytes = 4; + break; + + default: /* Unsupported format */ + arg = AFMT_S16_NE; + portc->fmt_bytes = 2; + + } + + portc->fmt = arg; + + setup_sample_format (portc); + + return portc->fmt; +} + +/*ARGSUSED*/ +static unsigned int +audioloop_client_set_format (int dev, unsigned int arg) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + return portc->peer->fmt; /* Server side sample format */ +} + +static void audioloop_trigger (int dev, int state); + +static void +audioloop_reset (int dev) +{ + audioloop_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +audioloop_server_open (int dev, int mode, int open_flags) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + audioloop_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + adev_t *adev; + + if ((mode & OPEN_READ) && (mode & OPEN_WRITE)) + return OSS_EACCES; + + if (portc == NULL || portc->peer == NULL) + return OSS_ENXIO; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + +/* + * Update client device flags + */ + adev = audio_engines[portc->peer->audio_dev]; + adev->flags &= ~(ADEV_NOINPUT | ADEV_NOOUTPUT); + if (!(mode & OPEN_READ)) + adev->flags |= ADEV_NOOUTPUT; + if (!(mode & OPEN_WRITE)) + adev->flags |= ADEV_NOINPUT; + adev->enabled = 1; /* Enable client side */ + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_client_open (int dev, int mode, int open_flags) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + audioloop_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + if (portc == NULL || portc->peer == NULL) + return OSS_ENXIO; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static void +audioloop_server_close (int dev, int mode) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + audioloop_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + audio_engines[portc->peer->audio_dev]->enabled = 0; /* Disable client side */ + portc->open_mode = 0; + + /* Stop the client side */ + portc->peer->input_triggered = 0; + portc->peer->output_triggered = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +audioloop_client_close (int dev, int mode) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + audioloop_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + + /* Stop the server side */ + portc->peer->input_triggered = 0; + portc->peer->output_triggered = 0; + + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +audioloop_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + switch (cmd) + { + case SNDCTL_GETLABEL: + { + /* + * Return an empty string so that this feature can be tested. + * Complete functionality is to be implemented later. + */ + oss_label_t *s = (oss_label_t *) arg; + memset (s, 0, sizeof (oss_label_t)); + return 0; + } + break; + + case SNDCTL_GETSONG: + { + /* + * Return an empty string so that this feature can be tested. + * Complete functionality is to be implemented later. + */ + oss_longname_t *s = (oss_longname_t *) arg; + memset (s, 0, sizeof (oss_longname_t)); + return 0; + } + break; + } + + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static void +audioloop_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +audioloop_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +static void +audioloop_trigger (int dev, int state) +{ + audioloop_portc_t *portc = audio_engines[dev]->portc; + + if (portc->open_mode & OPEN_READ) /* Handle input */ + { + portc->input_triggered = !!(state & OPEN_READ); + if (!portc->input_triggered) + portc->peer->output_triggered = 0; + } + + if (portc->open_mode & OPEN_WRITE) /* Handle output */ + { + portc->output_triggered = !!(state & OPEN_WRITE); + if (!portc->output_triggered) + portc->peer->input_triggered = 0; + } + + if (portc->output_triggered || portc->input_triggered) /* Something is going on */ + { + int tmout = OSS_HZ / 100; + + if (tmout < 1) + tmout = 1; + + if (portc->port_type != PT_SERVER) + portc = portc->peer; /* Switch to the server side */ + + if (portc->output_triggered || portc->input_triggered) /* Something is going on */ + if (portc->timeout_id == 0) + portc->timeout_id = timeout (audioloop_cb, portc, tmout); + } + else + { + if (portc->port_type == PT_SERVER) + if (portc->timeout_id != 0) + { + untimeout (portc->timeout_id); + portc->timeout_id = 0; + } + } +} + +/*ARGSUSED*/ +static int +audioloop_server_prepare_for_input (int dev, int bsize, int bcount) +{ + oss_native_word flags; + unsigned int status; + + audioloop_portc_t *portc = audio_engines[dev]->portc; + + MUTEX_ENTER_IRQDISABLE (portc->mutex, flags); + portc->input_triggered = 0; + + /* + * Wake the client which may be in waiting in close() + */ + oss_wakeup (portc->peer->wq, &portc->mutex, &flags, POLLOUT | POLLWRNORM); + + if (!(portc->peer->open_mode & OPEN_WRITE)) + { + /* Sleep until the client side becomes ready */ + oss_sleep (portc->wq, &portc->mutex, 0, &flags, &status); + if (status & WK_SIGNAL) + { + MUTEX_EXIT_IRQRESTORE (portc->mutex, flags); + return OSS_EINTR; + } + } + MUTEX_EXIT_IRQRESTORE (portc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_server_prepare_for_output (int dev, int bsize, int bcount) +{ + oss_native_word flags; + unsigned int status; + + audioloop_portc_t *portc = audio_engines[dev]->portc; + + MUTEX_ENTER_IRQDISABLE (portc->mutex, flags); + portc->output_triggered = 0; + + /* + * Wake the client which may be in waiting in close() + */ + oss_wakeup (portc->peer->wq, &portc->mutex, &flags, POLLIN | POLLRDNORM); + + if (!(portc->peer->open_mode & OPEN_READ)) + { + /* Sleep until the client side becomes ready */ + oss_sleep (portc->wq, &portc->mutex, 0, &flags, &status); + if (status & WK_SIGNAL) + { + MUTEX_EXIT_IRQRESTORE (portc->mutex, flags); + return OSS_EINTR; + } + } + MUTEX_EXIT_IRQRESTORE (portc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_client_prepare_for_input (int dev, int bsize, int bcount) +{ + oss_native_word flags; + audioloop_portc_t *portc = audio_engines[dev]->portc; + unsigned int status; + + MUTEX_ENTER_IRQDISABLE (portc->peer->mutex, flags); + portc->input_triggered = 0; + /* Wake the server side */ + oss_wakeup (portc->peer->wq, &portc->peer->mutex, &flags, + POLLIN | POLLRDNORM); + + /* + * Delay a moment so that the server side gets chance to reinit itself + * for next file/stream. + */ + oss_sleep (portc->wq, &portc->peer->mutex, OSS_HZ, &flags, &status); + MUTEX_EXIT_IRQRESTORE (portc->peer->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_client_prepare_for_output (int dev, int bsize, int bcount) +{ + oss_native_word flags; + audioloop_portc_t *portc = audio_engines[dev]->portc; + unsigned int status; + + MUTEX_ENTER_IRQDISABLE (portc->peer->mutex, flags); + portc->output_triggered = 0; + /* Wake the server side */ + oss_wakeup (portc->peer->wq, &portc->peer->mutex, &flags, + POLLIN | POLLRDNORM); + + /* + * Delay a moment so that the server side gets chance to reinit itself + * for next file/stream. + */ + oss_sleep (portc->wq, &portc->peer->mutex, OSS_HZ, &flags, &status); + MUTEX_EXIT_IRQRESTORE (portc->peer->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ +#define MY_BUFFSIZE (64*1024) + if (dmap->dmabuf != NULL) + return 0; + dmap->dmabuf_phys = 0; /* Not mmap() capable */ + dmap->dmabuf = KERNEL_MALLOC (MY_BUFFSIZE); + if (dmap->dmabuf == NULL) + return OSS_ENOSPC; + dmap->buffsize = MY_BUFFSIZE; + + return 0; +} + +/*ARGSUSED*/ +static int +audioloop_free_buffer (int dev, dmap_t * dmap, int direction) +{ + if (dmap->dmabuf == NULL) + return 0; + KERNEL_FREE (dmap->dmabuf); + + dmap->dmabuf = NULL; + return 0; +} + +#if 0 +static int +audioloop_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ +} +#endif + +static audiodrv_t audioloop_server_driver = { + audioloop_server_open, + audioloop_server_close, + audioloop_output_block, + audioloop_start_input, + audioloop_ioctl, + audioloop_server_prepare_for_input, + audioloop_server_prepare_for_output, + audioloop_reset, + NULL, + NULL, + NULL, + NULL, + audioloop_trigger, + audioloop_server_set_rate, + audioloop_server_set_format, + audioloop_server_set_channels, + NULL, + NULL, + audioloop_check_input, + audioloop_check_output, + audioloop_alloc_buffer, + audioloop_free_buffer, + NULL, + NULL, + NULL /* audioloop_get_buffer_pointer */ +}; + +static audiodrv_t audioloop_client_driver = { + audioloop_client_open, + audioloop_client_close, + audioloop_output_block, + audioloop_start_input, + audioloop_ioctl, + audioloop_client_prepare_for_input, + audioloop_client_prepare_for_output, + audioloop_reset, + NULL, + NULL, + NULL, + NULL, + audioloop_trigger, + audioloop_client_set_rate, + audioloop_client_set_format, + audioloop_client_set_channels, + NULL, + NULL, + audioloop_check_input, + audioloop_check_output, + audioloop_alloc_buffer, + audioloop_free_buffer, + NULL, + NULL, + NULL /* audioloop_get_buffer_pointer */ +}; + + +static int +install_server (audioloop_devc_t * devc, int num) +{ + audioloop_portc_t *portc; + char tmp[64], devname[16]; + int adev; + + int opts = + ADEV_STEREOONLY | ADEV_16BITONLY | ADEV_VIRTUAL | + ADEV_FIXEDRATE | ADEV_SPECIAL; + + if ((portc = PMALLOC (devc->osdev, sizeof (*portc))) == NULL) + return OSS_ENOMEM; + memset (portc, 0, sizeof (*portc)); + + portc->devc = devc; + MUTEX_INIT (devc->osdev, portc->mutex, MH_DRV + 1); + if ((portc->wq = oss_create_wait_queue (devc->osdev, "audioloop")) == NULL) + { + cmn_err (CE_WARN, "Cannot create audioloop wait queue\n"); + return OSS_EIO; + } + + portc->instance = num; + portc->port_type = PT_SERVER; + + devc->server_portc[num] = portc; + + sprintf (devname, "server%d", num); + + sprintf (tmp, "Audio loopback %d server side", num); + + if ((adev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &audioloop_server_driver, + sizeof (audiodrv_t), + opts, SUPPORTED_FORMATS, devc, -1, + devname)) < 0) + { + return adev; + } + + audio_engines[adev]->portc = portc; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = MAX_RATE; + audio_engines[adev]->min_channels = 1; + audio_engines[adev]->caps |= PCM_CAP_HIDDEN; + audio_engines[adev]->max_channels = MAX_CHANNELS; + + portc->audio_dev = adev; + portc->rate = 48000; + portc->fmt = AFMT_S16_NE; + portc->fmt_bytes = 2; + portc->channels = 2; + + return 0; +} + + +static int +install_client (audioloop_devc_t * devc, int num) +{ + audioloop_portc_t *portc; + char tmp[64]; + int adev; + + int opts = + ADEV_STEREOONLY | ADEV_16BITONLY | ADEV_VIRTUAL | + ADEV_FIXEDRATE | ADEV_SPECIAL | ADEV_LOOP; + + if ((portc = PMALLOC (devc->osdev, sizeof (*portc))) == NULL) + return OSS_ENOMEM; + memset (portc, 0, sizeof (*portc)); + + portc->devc = devc; + if ((portc->wq = oss_create_wait_queue (devc->osdev, "audioloop")) == NULL) + { + cmn_err (CE_WARN, "Cannot create audioloop wait queue\n"); + return OSS_EIO; + } + + portc->instance = num; + portc->port_type = PT_CLIENT; + + devc->client_portc[num] = portc; + + sprintf (tmp, "Audio loopback %d", num); + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &audioloop_client_driver, + sizeof (audiodrv_t), + opts, SUPPORTED_FORMATS, devc, -1)) < 0) + { + return adev; + } + + audio_engines[adev]->portc = portc; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = MAX_RATE; + audio_engines[adev]->min_channels = 1; + audio_engines[adev]->max_channels = MAX_CHANNELS;; + audio_engines[adev]->enabled = 0; /* Not enabled until server side is opened */ + + portc->audio_dev = adev; + + + return 0; +} + +int +oss_audioloop_attach (oss_device_t * osdev) +{ + audioloop_devc_t *devc; + int i; + + if (attach_count >= MAX_ATTACH_COUNT) + { + cmn_err (CE_WARN, "Attach limit reached (%d)\n", MAX_ATTACH_COUNT); + return 0; + } + + if (audioloop_instances < 1) + audioloop_instances = 1; + if (audioloop_instances > MAX_INSTANCES) + audioloop_instances = MAX_INSTANCES; + + DDB (cmn_err + (CE_CONT, "Initailzing audioloop %d instances\n", + audioloop_instances)); + devc = &audioloop_devices[0]; + + osdev->devc = devc; + devc->osdev = osdev; + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + + oss_register_device (osdev, "audioloop"); + + for (i = 0; i < audioloop_instances; i++) + { + if (install_server (devc, i) < 0) + break; + + if (install_client (devc, i) < 0) + break; + + devc->client_portc[i]->peer = devc->server_portc[i]; + devc->server_portc[i]->peer = devc->client_portc[i]; + devc->num_instances = i + 1; + } + + return 1; +} + +int +oss_audioloop_detach (oss_device_t * osdev) +{ + audioloop_devc_t *devc = osdev->devc; + int i; + + if (oss_disable_device (osdev) < 0) + return 0; + + MUTEX_CLEANUP (devc->mutex); + + for (i = 0; i < devc->num_instances; i++) + { + MUTEX_CLEANUP (devc->server_portc[i]->mutex); + } + + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_audioloop/oss_audioloop.man b/kernel/drv/oss_audioloop/oss_audioloop.man new file mode 100644 index 0000000..46932cb --- /dev/null +++ b/kernel/drv/oss_audioloop/oss_audioloop.man @@ -0,0 +1,80 @@ +NAME +oss_audioloop - Loopback audio driver. + +DESCRIPTION +The loopback audio driver makes it possible to create special purpose +virtual audio devices based on user land server processes. + +Loopback devices are driven by a timer interrupt and no real audio +hardware is required. + + INTRODUCTION +Audio loopback devices are like named pipes or pseudo terminals. They are +grouped in client and server device pairs. The server side device must be open +before the client side device can be opened. + +Loopback devices are typically used to implement server based special purpose +audio devices. This kind of server can for example transfer the audio data +played by the client application to some remote system using some VoIP +protocol. However the server application doesn't need to be any dedicated +server. Practically any audio application can be used as the server. + + SERVER SIDE DEVICE +The server side applications sets up the native sampling rate and sample format +(number of bits and channels). The server side device can be opened for input +(O_RDONLY) pr output (O_WRONLY). Opening for simultaneous input and output +(O_RDWR) is not permitted. + +The server application will automatically be paused at the moment it tries to +read or write audio data for the first time. It will be kept in sleep until the +client side application starts writing or reading data. This sleep period may +last forever and in some cases the first write/read call never returns. For +this reason it's not recommended to use GUI based audio applications as the +server. Note that this wait will occur even in the non-blocking +(O_NONBLOCK) mode (this is intentional feature and not a bug). + + CLIENT SIDE DEVICE +The client side device is typically used by any ordinary audio application. +There is nothing special in loopback devices. + +Since the loop is unidirectional the client side will be forced to be write +only if the server side device is open for recording and vice versa. + +The loop will use the sample rate and sample format (number of bits and +channels) set by the server side application. If the client uses different +settings then OSS will perform the required sampling rate and format conversions +automatically. + +COMPATIBILITY ISSUES +Audio loopback devices differ from "normal" audio devices because an +application is needed at the both ends of the loop. The loop device +will return a "Connection reset by peer" error (ECONNRESET) error. Applications +designed to be used as loopback based server applications can/should use this +error (returned by read or write) as an end-of-stream indication. + +OPTIONS + +o audioloop_instances: Specifies how many loopback client/server audio device + pairs to be created. + Values: 1-16 Default: 1 + +KNOWN PROBLEMS +o There is no mixer (volume control) related with loopback audio devices. This +may prevent poorly designed audio applications (that expect/require a mixer) +from working. There is no workaround available. + +o The server side application will wait until the client side application +starts using it. This wait may last forever which in turn may cause +unrecoverable (network) problems with some applications. + +o Loopback devices may return "Connection reset by peer" error when the +reote side of the loop disconnects the device. Some recording applications +may fail to save the recorded data properly because of this. Use some +other application (such as ossrecord) if this happens. + +FILES +CONFIGFILEPATH/oss_audioloop.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_audiopci/.devices b/kernel/drv/oss_audiopci/.devices new file mode 100644 index 0000000..431c66e --- /dev/null +++ b/kernel/drv/oss_audiopci/.devices @@ -0,0 +1 @@ +oss_audiopci pci1274,5000 Creative AudioPCI (ES1370) diff --git a/kernel/drv/oss_audiopci/.name b/kernel/drv/oss_audiopci/.name new file mode 100644 index 0000000..6bea261 --- /dev/null +++ b/kernel/drv/oss_audiopci/.name @@ -0,0 +1 @@ +Ensoniq/Creative AudioPCI (ES1370) diff --git a/kernel/drv/oss_audiopci/audiopci.h b/kernel/drv/oss_audiopci/audiopci.h new file mode 100644 index 0000000..cacf0bb --- /dev/null +++ b/kernel/drv/oss_audiopci/audiopci.h @@ -0,0 +1,299 @@ +/* + * Purpose: Definitions for the Creative/Ensoniq AudioPCI 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. + * + */ + +/* CONCERT PCI-SIG defines */ +#define CONC_PCI_VENDID 0x1274U +#define CONC_PCI_DEVID 0x5000U + +/* used for the development board only!!*/ +#define CONC_DEV_PCI_VENDID 0x1274U +#define CONC_DEV_PCI_DEVID 0x5000U + + +/* +** CONCERT Registers +** +** +*/ + +#define DAC_CLOCK_DIVIDE 22579200UL /* DAC2 (CODEC) clock divide */ +/* Concert direct register offset defines */ + +#define CONC_bDEVCTL_OFF 0x00 /* Device control/enable */ +/* Device Control defines */ +#define CONC_DEVCTL_SERR_DISABLE 0x01 /* internal PCI serr bus enable */ +#define CONC_DEVCTL_CODEC_EN 0x02 /* CoDec Enable */ +#define CONC_DEVCTL_JSTICK_EN 0x04 /* Joystick Enable */ +#define CONC_DEVCTL_UART_EN 0x08 /* UART Enable */ +#define CONC_DEVCTL_ADC_EN 0x10 /* ADC Enable (record) */ +#define CONC_DEVCTL_DAC2_EN 0x20 /* DAC2 Enable (playback) */ +#define CONC_DEVCTL_DAC1_EN 0x40 /* DAC1 Enabale (synth) */ +#define CONC_DEVCTL_MICBIAS 0x4000L /* mic bias switch */ + +#define CONC_bMISCCTL_OFF 0x01 /* Miscellaneous control */ +/* Misc Control defines */ +#define CONC_MISCTL_MUTE 0x01 /* XTL0 wired to mute */ +#define CONC_MISCTL_CCB_INTRM 0x04 /* CCB interrupt mask */ +#define CONC_MISCTL_DAC1FREQ_2205 0x20 /* synth frequency */ + +#define CONC_wDACRATE_OFF 0x02 /* CODEC clock divider for PLL */ +#define CONC_dSTATUS_OFF 0x04 /* long status register */ + +#define CONC_bINTSTAT_OFF 0x04 /* Device interrupt status */ +/* Interrupt Status defines */ +#define CONC_INTSTAT_ADCINT 0x01 /* A/D interrupt pending bit */ +#define CONC_INTSTAT_DAC2INT 0x02 /* DAC2 interrupt pending bit */ +#define CONC_INTSTAT_DAC1INT 0x04 /* DAC1 interrupt pending bit */ +#define CONC_INTSTAT_UARTINT 0x08 /* UART interrupt pending bit */ + +#define CONC_bCODECSTAT_OFF 0x05 /* CODEC interface status */ +#define CONC_bINTSUMM_OFF 0x07 /* Interrupt summary status */ +#define CONC_bUARTDATA_OFF 0x08 /* UART data R/W - read clears RX int */ +#define CONC_bUARTCSTAT_OFF 0x09 /* UART control and status */ +#define CONC_bMEMPAGE_OFF 0x0c /* Memory page select */ +#define CONC_wCODECCTL_OFF 0x10 /* CODEC control - word-write-only */ +#define CONC_wNMISTAT_OFF 0x18 /* Legacy NMI status */ +#define CONC_bNMIENA_OFF 0x1a /* Legacy NMI enable */ +#define CONC_bNMICTL_OFF 0x1b /* Legacy control */ + +#define CONC_bSERFMT_OFF 0x20 /* Serial device control */ +/* SERFMT PCM format defines */ +#define CONC_PCM_DAC1_STEREO 0x01 +#define CONC_PCM_DAC1_16BIT 0x02 +#define CONC_PCM_DAC1_MASK 0xfc +#define CONC_PCM_DAC2_STEREO 0x04 +#define CONC_PCM_DAC2_16BIT 0x08 +#define CONC_PCM_DAC2_MASK 0xf3 +#define CONC_PCM_ADC_STEREO 0x10 +#define CONC_PCM_ADC_16BIT 0x20 +#define CONC_PCM_ADC_MASK 0xcf + +#define CONC_bSERCTL_OFF 0x21 /* Serial device format */ +/* Serial Control defines */ +#define CONC_SERCTL_SYNIE 0x01 /* synth (DAC1) int enable */ +#define CONC_SERCTL_SYNIE_MASK 0x0e /* synth interrupt mask */ +#define CONC_SERCTL_DACIE 0x02 /* playback interrupt enable */ +#define CONC_SERCTL_DACIE_MASK 0x0d /* playback interrupt mask */ +#define CONC_SERCTL_ADCIE 0x04 /* record interrupt enable */ +#define CONC_SERCTL_ADCIE_MASK 0x0b /* record interrupt mask */ +#define CONC_SERCTL_DACPAUSE 0x10 /* playback pause */ + +#define CONC_bSKIPC_OFF 0x22 /* Start/end skip counts for DAC2 (wave) */ +#define CONC_wSYNIC_OFF 0x24 /* Synth int count in sample frames */ +#define CONC_wSYNCIC_OFF 0x26 /* Synth current int count */ +#define CONC_wDACIC_OFF 0x28 /* DAC int count in sample frames */ +#define CONC_wDACCIC_OFF 0x2a /* DAC current int count */ +#define CONC_wADCIC_OFF 0x2c /* ADC int count in sample frames */ +#define CONC_wADCCIC_OFF 0x2e /* ADC current int count */ +#define CONC_MEMBASE_OFF 0x30 /* Memory window base - 16 bytes */ + +/* Concert memory page-banked register offset defines */ +#define CONC_dSYNPADDR_OFF 0x30 /* Synth host frame PCI phys addr */ +#define CONC_wSYNFC_OFF 0x34 /* Synth host frame count in DWORDS */ +#define CONC_wSYNCFC_OFF 0x36 /* Synth host current frame count */ +#define CONC_dDACPADDR_OFF 0x38 /* DAC host frame PCI phys addr */ +#define CONC_wDACFC_OFF 0x3c /* DAC host frame count in DWORDS */ +#define CONC_wDACCFC_OFF 0x3e /* DAC host current frame count */ +#define CONC_dADCPADDR_OFF 0x30 /* ADC host frame PCI phys addr */ +#define CONC_wADCFC_OFF 0x34 /* ADC host frame count in DWORDS */ +#define CONC_wADCCFC_OFF 0x36 /* ADC host current frame count */ + +/* Concert memory page number defines */ +#define CONC_SYNRAM_PAGE 0x00 /* Synth host/serial I/F RAM */ +#define CONC_DACRAM_PAGE 0x04 /* DAC host/serial I/F RAM */ +#define CONC_ADCRAM_PAGE 0x08 /* ADC host/serial I/F RAM */ +#define CONC_SYNCTL_PAGE 0x0c /* Page bank for synth host control */ +#define CONC_DACCTL_PAGE 0x0c /* Page bank for DAC host control */ +#define CONC_ADCCTL_PAGE 0x0d /* Page bank for ADC host control */ +#define CONC_FIFO0_PAGE 0x0e /* page 0 of UART "FIFO" (rx stash) */ +#define CONC_FIFO1_PAGE 0x0f /* page 1 of UART "FIFO" (rx stash) */ + +/* UARTCSTAT register masks */ +#define CONC_UART_RXRDY 0x01 +#define CONC_UART_TXRDY 0x02 +#define CONC_UART_TXINT 0x04 +#define CONC_UART_RXINT 0x80 + +#define CONC_UART_CTL 0x03 +#define CONC_UART_TXINTEN 0x20 +#define CONC_UART_RXINTEN 0x80 + +/* +** CODEC register map +** +*/ +#define NUMREGS 32 /* total number of registers */ +#define NUMVOLS 16 /* number of vol regs */ + +/* Source and output volume control defines */ +#define CODEC_VOL_MASTER_L 0x00U /* Master out, left */ +#define CODEC_VOL_MASTER_R 0x01U /* Master out, right */ +#define CODEC_VOL_WAVE_L 0x02U /* Wave DAC, left */ +#define CODEC_VOL_WAVE_R 0x03U /* Wave DAC, right */ +#define CODEC_VOL_SYNTH_L 0x04U /* Synth DAC, left */ +#define CODEC_VOL_SYNTH_R 0x05U /* Synth DAC, right */ +#define CODEC_VOL_CD_L 0x06U /* CD audio, left */ +#define CODEC_VOL_CD_R 0x07U /* CD audio, right */ +#define CODEC_VOL_AUX_L 0x08U /* Aux line source, left */ +#define CODEC_VOL_AUX_R 0x09U /* Aux line source, right */ +#define CODEC_VOL_TV_L 0x0aU /* TV Tuner, left */ +#define CODEC_VOL_TV_R 0x0bU /* TV Tuner, right */ +#define CODEC_VOL_TAD 0x0cU /* TAD monitor, mono */ +#define CODEC_VOL_MONO2 0x0dU /* Unused MONO2 */ +#define CODEC_VOL_MIC 0x0eU /* Mic, mono */ +#define CODEC_VOL_MONO 0x0fU /* Mono out volume */ + +/* Input bus enable defines -SW1 */ +#define CODEC_IN_ENABLE_MIC 0x01U /* Mic enable, mono */ +#define CODEC_IN_ENABLE_CD_R 0x02U /* CD audio enable, right */ +#define CODEC_IN_ENABLE_CD_L 0x04U /* CD audio enable, left */ +#define CODEC_IN_ENABLE_AUX_R 0x08U /* Aux line source enable, right */ +#define CODEC_IN_ENABLE_AUX_L 0x10U /* Aux line source enable, left */ +#define CODEC_IN_ENABLE_SYNTH_R 0x20U /* Synth DAC enable, right */ +#define CODEC_IN_ENABLE_SYNTH_L 0x40U /* Synth DAC enable, left */ + +/* Input bus enable defines - SW2 */ +#define CODEC_IN_ENABLE_TAD 0x01U /* TAD monitor enable, mono */ +#define CODEC_IN_ENABLE_MONO2 0x02U /* Unused MONO2 enable, mono */ +#define CODEC_IN_ENABLE_WAVE 0x04U /* Wave DAC enable */ +#define CODEC_IN_ENABLE_TV_R 0x08U /* TV Tuner enable, right */ +#define CODEC_IN_ENABLE_TV_L 0x10U /* TV Tuner enable, left */ +#define CODEC_IN_ENABLE_TMONO2 0x20U /* unboosted MONO2 */ +#define CODEC_IN_ENABLE_TMONO1 0x40U /* unboosted MONO1 */ +#define CODEC_IN_ENABLE_TMIC 0x80U /* unboosted MONO3 (mic) */ + +/* Output bus enable defines */ +#define CODEC_OUT_ENABLE_MIC 0x0001U /* Mic enable, mono */ +#define CODEC_OUT_ENABLE_CD 0x0006U /* CD audio enable, stereo */ +#define CODEC_OUT_ENABLE_AUX 0x0018U /* Aux line source enable, stereo */ +#define CODEC_OUT_ENABLE_SYNTH 0x0060U /* Synth DAC enable, stereo */ +#define CODEC_OUT_ENABLE_TAD 0x0100U /* TAD monitor enable, mono */ +#define CODEC_OUT_ENABLE_MONO2 0x0200U /* Unused MONO2 enable, mono */ +#define CODEC_OUT_ENABLE_WAVE 0x0c00U /* Wave DAC enable, stereo */ +#define CODEC_OUT_ENABLE_TV 0x3000U /* TV Tuner enable, stereo */ + +/* Volume setting constants */ +#define CODEC_VOL_MUTE 0x80U +#define CODEC_VOL_MAX 0x00U +#define CODEC_VOL_MIN 0x1fU + +/* Control function defines */ +#define CODEC_CTL_4SPKR 0x00U /* 4-spkr output mode enable */ +#define CODEC_CTL_MICBOOST 0x01U /* Mic boost (+30 dB) enable */ + +/* Miscellaneous CODEC defines for internal use */ +#define CODEC_OUT_SW1 0x10U +#define CODEC_OUT_SW2 0x11U +#define CODEC_LIN_SW1 0x12U +#define CODEC_RIN_SW1 0x13U +#define CODEC_LIN_SW2 0x14U +#define CODEC_RIN_SW2 0x15U +#define CODEC_RESET_PWRD 0x16U +#define CODEC_CLKSELECT 0x17U +#define CODEC_ADSELECT 0x18U +#define CODEC_MICBOOST 0x19U + +/* PCM format defines */ +#define CONC_PCM_DAC_STEREO 0x04 +#define CONC_PCM_DAC_16BIT 0x08 +#define CONC_PCM_DAC_MASK 0xf3 +#define CONC_PCM_ADC_STEREO 0x10 +#define CONC_PCM_ADC_16BIT 0x20 +#define CONC_PCM_ADC_MASK 0xcf + +/* Logical index for each DMA controller on chip - used for */ +/* generic routines that access all DMA controllers */ +#define CONC_SYNTH_DAC 0 +#define CONC_WAVE_DAC 1 +#define CONC_WAVE_ADC 2 + +/************************ + * Mixer definitions + */ + +struct mixer_def +{ + unsigned int regno; + unsigned int polarity; /* 0=normal, 1=reversed */ + unsigned int bitpos; + unsigned int nbits; + unsigned int mutepos; +}; + +typedef struct mixer_def mixer_ent; +typedef mixer_ent mixer_ents[2]; + +#define MIXER_DEVS (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \ + SOUND_MASK_MIC | SOUND_MASK_VOLUME | \ + SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \ + SOUND_MASK_CD | SOUND_MASK_LINE | \ + SOUND_MASK_PCM | SOUND_MASK_ALTPCM) + +#define REC_DEVS (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \ + SOUND_MASK_MIC | \ + SOUND_MASK_LINE3 | \ + SOUND_MASK_CD | SOUND_MASK_LINE) + +#define STEREO_DEVS (SOUND_MASK_LINE1 | \ + SOUND_MASK_VOLUME | \ + SOUND_MASK_CD | SOUND_MASK_LINE | \ + SOUND_MASK_PCM | SOUND_MASK_ALTPCM) + +#define LEFT_CHN 0 +#define RIGHT_CHN 1 + +#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \ + {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r, mute_bit}} + +static mixer_ents ak_mix_devices[32] = { +/* Name Reg p b l Reg p b l M */ + MIX_ENT (SOUND_MIXER_VOLUME, 0x00, 1, 0, 5, 0x01, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_BASS, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_TREBLE, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_SYNTH, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_PCM, 0x02, 1, 0, 5, 0x03, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_SPEAKER, 0x0f, 1, 0, 3, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE, 0x08, 1, 0, 5, 0x09, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_MIC, 0x0e, 1, 0, 5, 0xff, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_CD, 0x06, 1, 0, 5, 0x07, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_IMIX, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_ALTPCM, 0x04, 1, 0, 5, 0x05, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_RECLEV, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_IGAIN, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_OGAIN, 0xff, 0, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE1, 0x0a, 1, 0, 5, 0x0b, 1, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE2, 0x0c, 1, 0, 5, 0xff, 0, 0, 5, 7), + MIX_ENT (SOUND_MIXER_LINE3, 0x0d, 1, 0, 5, 0xff, 0, 0, 5, 7) +}; + +static int default_mixer_levels[32] = { + 0x3232, /* Master Volume */ + 0x3232, /* Bass */ + 0x3232, /* Treble */ + 0x4b4b, /* FM */ + 0x3232, /* PCM */ + 0x1515, /* PC Speaker */ + 0x2020, /* Ext Line */ + 0x2020, /* Mic */ + 0x4b4b, /* CD */ + 0x0000, /* Recording monitor */ + 0x4b4b, /* Second PCM */ + 0x4b4b, /* Recording level */ + 0x4b4b, /* Input gain */ + 0x4b4b, /* Output gain */ + 0x2020, /* Line1 */ + 0x2020, /* Line2 */ + 0x1515 /* Line3 (usually line in) */ +}; diff --git a/kernel/drv/oss_audiopci/oss_audiopci.c b/kernel/drv/oss_audiopci/oss_audiopci.c new file mode 100644 index 0000000..f608cf8 --- /dev/null +++ b/kernel/drv/oss_audiopci/oss_audiopci.c @@ -0,0 +1,1536 @@ +/* + * Purpose: Creative/Ensoniq AudioPCI driver (ES1370 "CONCERT" ASIC and AKM4531 codec/mixer) + */ +/* + * + * 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_audiopci_cfg.h" +#include "audiopci.h" +#include "midi_core.h" +#include "oss_pci.h" + +#define ENSONIQ_VENDOR_ID 0x1274 +#define ENSONIQ_VENDOR_ID2 0x1275 +#define ENSONIQ_AUDIOPCI 0x5000 + +#define MAX_PORTC 2 + +typedef struct apci_portc +{ + + /* Audio parameters */ + int audiodev; + int open_mode; + int trigger_bits; + int audio_enabled; + int speed, bits, channels; + int atype; /* 0=DAC/ADC, 1=Synth */ + int speedsel; +} apci_portc; + +typedef struct apci_devc +{ + oss_device_t *osdev; + oss_mutex_t mutex, low_mutex; + oss_native_word base; + int irq; + char *chip_name; + + /* Mixer parameters */ + int *levels; + unsigned char ak_regs[0x20]; /* Current mixer register values */ + int recdevs; + int micbias, micboost; + unsigned char outsw1, outsw2; + + /* Audio parameters */ + int irq_allocated; + apci_portc portc[MAX_PORTC]; + +/* + * MIDI + */ + int midi_opened; + int midi_dev; + oss_midi_inputbyte_t midi_input_intr; +} apci_devc; + + +/* + * Initial values to be written into the mixer registers of AK4531 codec. + */ +static const unsigned char ak_reg_init[0x20] = { + /* Mute all inputs/outputs initially */ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 00 to 07 */ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 08 to 0f */ + 0x7f, 0x3d, 0x55, 0x26, 0xf7, 0xef, 0x03, 0x00, /* 10 to 17 */ + 0x00, 0x01 /* 18 to 19 */ +}; + +static void +ak_write (apci_devc * devc, int reg, int value) +{ + int i; + + if (reg < 0 || reg > 0x19) + return; + + value &= 0xff; + devc->ak_regs[reg] = (unsigned char) value; + + /* Wait until the codec is ready */ + for (i = 0; i < 0x40000; i++) + if (!(INB (devc->osdev, devc->base + CONC_bCODECSTAT_OFF) & 0x01)) + break; + oss_udelay (10); + OUTW (devc->osdev, (reg << 8) | value, devc->base + CONC_wCODECCTL_OFF); + oss_udelay (10); +} + +static void +apci_writemem (apci_devc * devc, int page, int offs, int data) +{ + int tmp; + + tmp = INL (devc->osdev, devc->base + 0xc); + OUTL (devc->osdev, page, devc->base + 0xc); /* Select memory page */ + OUTL (devc->osdev, data, devc->base + offs); + OUTL (devc->osdev, tmp, devc->base + 0xc); /* Select the original memory page */ +} + +static unsigned int +apci_readmem (apci_devc * devc, int page, int offs) +{ + unsigned int val; + + OUTL (devc->osdev, page, devc->base + 0xc); /* Select memory page */ + val = INL (devc->osdev, devc->base + offs); + return val; +} + +#define bmast_off(x) +#define bmast_on(x) + +static int +apci_set_recmask (apci_devc * devc, int mask) +{ + unsigned char tmp; + + mask &= REC_DEVS; + +/* + * Set lch input mixer SW 1 register + */ + tmp = 0; + if (mask & SOUND_MASK_ALTPCM) + tmp |= 0x40; + if (mask & SOUND_MASK_LINE) + tmp |= 0x10; + if (mask & SOUND_MASK_CD) + tmp |= 0x04; + if (mask & SOUND_MASK_MIC) + tmp |= 0x01; + ak_write (devc, 0x12, tmp); + +/* + * Set rch input mixer SW 1 register + */ + tmp = 0; + if (mask & SOUND_MASK_ALTPCM) + tmp |= 0x20; + if (mask & SOUND_MASK_LINE) + tmp |= 0x08; + if (mask & SOUND_MASK_CD) + tmp |= 0x02; + if (mask & SOUND_MASK_MIC) + tmp |= 0x01; + ak_write (devc, 0x13, tmp); + +/* + * Set lch input mixer SW 2 register + */ + tmp = 0; + if (mask & SOUND_MASK_LINE2) + tmp |= 0x40; + if (mask & SOUND_MASK_LINE3) + tmp |= 0x20; + if (mask & SOUND_MASK_LINE1) + tmp |= 0x10; + if (mask & SOUND_MASK_MIC) + tmp |= 0x80; + ak_write (devc, 0x14, tmp); + +/* + * Set rch input mixer SW 2 register + */ + tmp = 0; + if (mask & SOUND_MASK_LINE2) + tmp |= 0x40; + if (mask & SOUND_MASK_LINE3) + tmp |= 0x20; + if (mask & SOUND_MASK_LINE1) + tmp |= 0x08; + if (mask & SOUND_MASK_MIC) + tmp |= 0x80; + ak_write (devc, 0x15, tmp); + + return devc->recdevs = mask; +} + +/*ARGSUSED*/ +static void +change_bits (apci_devc * devc, unsigned char *regval, int dev, int chn, + int newval) +{ + unsigned char mask; + int shift; + int mute; + int mutemask; + int set_mute_bit; + + set_mute_bit = (newval == 0); + + if (ak_mix_devices[dev][chn].polarity == 1) /* Reverse */ + newval = 100 - newval; + + mask = (1 << ak_mix_devices[dev][chn].nbits) - 1; + shift = ak_mix_devices[dev][chn].bitpos; + +#if 0 + newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ + *regval &= ~(mask << shift); /* Clear bits */ + *regval |= (newval & mask) << shift; /* Set new value */ +#else + if (ak_mix_devices[dev][chn].mutepos == 8) + { /* if there is no mute bit */ + mute = 0; /* No mute bit; do nothing special */ + mutemask = ~0; /* No mute bit; do nothing special */ + } + else + { + mute = (set_mute_bit << ak_mix_devices[dev][chn].mutepos); + mutemask = ~(1 << ak_mix_devices[dev][chn].mutepos); + } + + newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ + *regval &= (~(mask << shift)) & (mutemask); /* Clear bits */ + *regval |= ((newval & mask) << shift) | mute; /* Set new value */ +#endif +} + +static int +apci_mixer_get (apci_devc * devc, int dev) +{ + if (!((1 << dev) & MIXER_DEVS)) + return OSS_EINVAL; + + return devc->levels[dev]; +} + +static int +apci_mixer_set (apci_devc * devc, int dev, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int retvol; + + int regoffs; + unsigned char val; + + if (dev > 31) + return OSS_EINVAL; + + if (!(MIXER_DEVS & (1 << dev))) + return OSS_EINVAL; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + if (ak_mix_devices[dev][RIGHT_CHN].regno == 0xff) /* Mono control */ + right = left; + + retvol = left | (right << 8); + +#if 1 + /* Scale volumes */ + left = mix_cvt[left]; + right = mix_cvt[right]; + + /* Scale it again */ + left = mix_cvt[left]; + right = mix_cvt[right]; +#endif + + if (ak_mix_devices[dev][LEFT_CHN].regno == 0xff) + return OSS_EINVAL; + + devc->levels[dev] = retvol; + + /* + * Set the left channel + */ + + regoffs = ak_mix_devices[dev][LEFT_CHN].regno; + val = 0; + change_bits (devc, &val, dev, LEFT_CHN, left); + ak_write (devc, regoffs, val); + + /* + * Set the right channel + */ + + if (ak_mix_devices[dev][RIGHT_CHN].regno == 0xff) + return retvol; /* Was just a mono channel */ + + regoffs = ak_mix_devices[dev][RIGHT_CHN].regno; + val = 0; + change_bits (devc, &val, dev, RIGHT_CHN, right); + ak_write (devc, regoffs, val); + + return retvol; +} + +static void +apci_mixer_reset (apci_devc * devc) +{ + int i; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (MIXER_DEVS & (1 << i)) + apci_mixer_set (devc, i, devc->levels[i]); + apci_set_recmask (devc, SOUND_MASK_MIC); + devc->outsw1 = ak_reg_init[0x10]; + devc->outsw2 = ak_reg_init[0x11]; +} + +/*ARGSUSED*/ +static int +apci_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + apci_devc *devc = mixer_devs[dev]->devc; + + if (((cmd >> 8) & 0xff) == 'M') + { + int val; + + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + val = *arg; + return *arg = apci_set_recmask (devc, val); + break; + + default: + val = *arg; + return *arg = apci_mixer_set (devc, cmd & 0xff, val); + } + else + switch (cmd & 0xff) /* + * Return parameters + */ + { + + case SOUND_MIXER_RECSRC: + return *arg = devc->recdevs; + break; + + case SOUND_MIXER_DEVMASK: + return *arg = MIXER_DEVS; + break; + + case SOUND_MIXER_STEREODEVS: + return *arg = STEREO_DEVS; + break; + + case SOUND_MIXER_RECMASK: + return *arg = REC_DEVS; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + default: + return *arg = apci_mixer_get (devc, cmd & 0xff); + } + } + else + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +getmute (apci_devc * devc, int offs, unsigned char bits, int value) +{ + unsigned char tmp; + + tmp = (offs == 0x10) ? devc->outsw1 : devc->outsw2; + + tmp &= bits; + return (tmp == 0); /* Note! inverted polarity */ +} + +static int +setmute (apci_devc * devc, int offs, unsigned char bits, int value) +{ + unsigned char tmp; + + value = !value; /* Inverted polarity (now 0=mute) */ + + tmp = (offs == 0x10) ? devc->outsw1 : devc->outsw2; + + tmp &= ~bits; /* Mask old bits */ + if (value) + tmp |= bits; + + ak_write (devc, offs, tmp); + if (offs == 0x10) + devc->outsw1 = tmp; + else + devc->outsw2 = tmp; + + return !value; +} + +static int +apci_outsw (int dev, int ctrl, unsigned int cmd, int value) +{ +/* + * Access function for AudioPCI mixer extension bits + */ + apci_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case 1: /* 20 dB microphone boost */ + value = devc->micboost; + break; + + case 2: /* Microphone phantom power */ + value = devc->micbias; + break; + + case 10: /* Pcm mute */ + value = getmute (devc, 0x11, 0x0c, value); + break; + + case 11: /* Pcm2 mute */ + value = getmute (devc, 0x10, 0x60, value); + break; + + case 12: /* Mic mute */ + value = getmute (devc, 0x10, 0x01, value); + break; + + case 13: /* CD mute */ + value = getmute (devc, 0x10, 0x06, value); + break; + + case 14: /* Line mute */ + value = getmute (devc, 0x10, 0x18, value); + break; + + case 15: /* Line1 mute */ + value = getmute (devc, 0x11, 0x30, value); + break; + + case 16: /* Line2 mute */ + value = getmute (devc, 0x11, 0x01, value); + break; + + case 17: /* Line3 mute */ + value = getmute (devc, 0x11, 0x02, value); + break; + + case 18: /*Separate output enable for the synth device (XCTL0) */ + value = + ((INB (devc->osdev, devc->base + CONC_bMISCCTL_OFF) & 0x01) != 0); + break; + + default: + return OSS_EINVAL; + } + + return value; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int tmp; + + if (value) + value = 1; + + switch (ctrl) + { + case 1: /* 20 dB microphone boost */ + devc->micboost = value; + ak_write (devc, 0x19, value); + break; + + case 2: /* Microphone phantom power */ + devc->micbias = value; + /* Delay the actual change until next recording */ + break; + + case 10: /* Pcm mute */ + value = setmute (devc, 0x11, 0x0c, value); + break; + + case 11: /* Pcm2 mute */ + value = setmute (devc, 0x10, 0x60, value); + break; + + case 12: /* Mic mute */ + value = setmute (devc, 0x10, 0x01, value); + break; + + case 13: /* CD mute */ + value = setmute (devc, 0x10, 0x06, value); + break; + + case 14: /* Line mute */ + value = setmute (devc, 0x10, 0x18, value); + break; + + case 15: /* Line1 mute */ + value = setmute (devc, 0x11, 0x30, value); + break; + + case 16: /* Line2 mute */ + value = setmute (devc, 0x11, 0x01, value); + break; + + case 17: /* Line3 mute */ + value = setmute (devc, 0x11, 0x02, value); + break; + + case 18: /*Separate output enable for the synth device (XCTL0) */ + tmp = INB (devc->osdev, devc->base + CONC_bMISCCTL_OFF); + if (value) + { + OUTB (devc->osdev, tmp | 0x01, devc->base + CONC_bMISCCTL_OFF); + } + else + { + OUTB (devc->osdev, tmp & ~0x01, devc->base + CONC_bMISCCTL_OFF); + } + break; + + default: + return OSS_EINVAL; + } + + return value; + } + + return OSS_EINVAL; +} + +static int +apci_mix_init (int dev) +{ + int group, err; + + if ((group = mixer_ext_create_group (dev, 0, "APCI_EXTMIC")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 1, apci_outsw, MIXT_ONOFF, + "APCI_MICBOOST", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 2, apci_outsw, MIXT_ONOFF, + "APCI_MICBIAS", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((group = mixer_ext_create_group (dev, 0, "APCI_MUTE")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 10, apci_outsw, + MIXT_ONOFF, + "APCI_PCMMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 11, apci_outsw, + MIXT_ONOFF, + "APCI_PCM2MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 12, apci_outsw, + MIXT_ONOFF, + "APCI_MICMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 13, apci_outsw, + MIXT_ONOFF, + "APCI_CDMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 14, apci_outsw, + MIXT_ONOFF, + "APCI_LINEMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 15, apci_outsw, + MIXT_ONOFF, + "APCI_LINE1MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 16, apci_outsw, + MIXT_ONOFF, + "APCI_LINE2MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 17, apci_outsw, + MIXT_ONOFF, + "APCI_LINE3MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((group = mixer_ext_create_group (dev, 0, "APCI_4CHAN")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 18, apci_outsw, + MIXT_ONOFF, + "APCI4CH_ENABLE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +static mixer_driver_t apci_mixer_driver = { + apci_mixer_ioctl +}; + +static int +apciintr (oss_device_t * osdev) +{ + int stats, i; + unsigned char ackbits = 0, tmp; + unsigned char uart_stat; + apci_devc *devc = (apci_devc *) osdev->devc; + apci_portc *portc; + int serviced = 0; + + stats = INL (devc->osdev, devc->base + 0x04); + + if (!(stats & 0x80000000)) /* No interrupt pending */ + return 0; + + serviced = 1; + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if (stats & 0x00000010) /* CCB interrupt */ + { + cmn_err (CE_WARN, "CCB interrupt\n"); + } + + if ((stats & 0x00000004) && (portc->atype)) /* DAC1 (synth) interrupt */ + { + ackbits |= CONC_SERCTL_SYNIE; + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + oss_audio_outputintr (portc->audiodev, 0); + + } + + if ((stats & 0x00000002) && (!portc->atype)) /* DAC2 interrupt */ + { + ackbits |= CONC_SERCTL_DACIE; + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + oss_audio_outputintr (portc->audiodev, 0); + } + + if ((stats & 0x00000001) && (!portc->atype)) /* ADC interrupt */ + { + ackbits |= CONC_SERCTL_ADCIE; + if (portc->trigger_bits & PCM_ENABLE_INPUT) + oss_audio_inputintr (portc->audiodev, 0); + } + + if (stats & 0x00000008) /* UART interrupt */ + { + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + + while (uart_stat & CONC_UART_RXRDY) + { + unsigned char d; + + d = INB (devc->osdev, devc->base + CONC_bUARTDATA_OFF); + + if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, d); + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + } + } + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + OUTB (devc->osdev, (tmp & ~ackbits), devc->base + CONC_bSERCTL_OFF); /* Clear bits */ + OUTB (devc->osdev, tmp | ackbits, devc->base + CONC_bSERCTL_OFF); /* Return them back on */ + + } + return serviced; +} + +/* + * Audio routines + */ + +static unsigned short +compute_dac2_rate (int samPerSec) +{ + + unsigned short usTemp; + + /* samPerSec /= 2; */ + + usTemp = (unsigned short) ((DAC_CLOCK_DIVIDE / 8) / samPerSec); + + if (usTemp & 0x00000001) + { + usTemp >>= 1; + usTemp -= 1; + } + else + { + usTemp >>= 1; + usTemp -= 2; + } + + return usTemp; + +} + +static int +apci_audio_set_rate (int dev, int arg) +{ + apci_portc *portc = audio_engines[dev]->portc; + + int speeds[] = { 5512, 11025, 22050, 44100 }; + int i, n = 0, best = 1000000; + + + if (arg == 0) + return portc->speed; + + if (portc->atype) + { + if (arg > 44100) + arg = 44100; + if (arg < 5512) + arg = 5512; + + for (i = 0; i < 4; i++) + { + int diff = arg - speeds[i]; + + if (diff < 0) + diff *= -1; + + if (diff < best) + { + n = i; + best = diff; + } + } + portc->speed = speeds[n]; + portc->speedsel = n; + } + else + { + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + } + return portc->speed; +} + +static short +apci_audio_set_channels (int dev, short arg) +{ + apci_portc *portc = audio_engines[dev]->portc; + + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +apci_audio_set_format (int dev, unsigned int arg) +{ + apci_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +apci_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void apci_audio_trigger (int dev, int state); + +static void +apci_audio_reset (int dev) +{ + apci_audio_trigger (dev, 0); +} + +static void +apci_audio_reset_input (int dev) +{ + apci_portc *portc = audio_engines[dev]->portc; + apci_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +apci_audio_reset_output (int dev) +{ + apci_portc *portc = audio_engines[dev]->portc; + apci_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +apci_audio_open (int dev, int mode, int open_flags) +{ + apci_portc *portc = audio_engines[dev]->portc; + apci_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; + } + + portc->open_mode = mode; + portc->audio_enabled = ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +apci_audio_close (int dev, int mode) +{ + apci_portc *portc = audio_engines[dev]->portc; + + apci_audio_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +apci_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + apci_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + +} + +/*ARGSUSED*/ +static void +apci_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + apci_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + +} + +static void +apci_audio_trigger (int dev, int state) +{ + apci_devc *devc = audio_engines[dev]->devc; + apci_portc *portc = audio_engines[dev]->portc; + int tmp; + oss_native_word flags; + + 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->atype) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_DAC1_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + } + else + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_DAC2_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + } + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + oss_udelay (50); + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + if (portc->atype) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_DAC1_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_SYNIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + else + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_DAC2_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_DACIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + } + } + } + + if ((portc->open_mode & OPEN_READ) + && !(audio_engines[dev]->flags & ADEV_NOINPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_ADC_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + portc->trigger_bits |= PCM_ENABLE_INPUT; + oss_udelay (50); + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_ADC_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +apci_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + dmap_t *dmap = audio_engines[dev]->dmap_in; + apci_devc *devc = audio_engines[dev]->devc; + apci_portc *portc = audio_engines[dev]->portc; + unsigned short tmp = 0x00; + oss_native_word flags; + + /* Set physical address of the DMA buffer */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + apci_writemem (devc, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF, + dmap->dmabuf_phys); + + /* Set DAC (ADC) rate */ + OUTW (devc->osdev, compute_dac2_rate (portc->speed), + devc->base + CONC_wDACRATE_OFF); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~(CONC_PCM_ADC_STEREO | CONC_PCM_ADC_16BIT); + if (portc->channels == 2) + tmp |= CONC_PCM_ADC_STEREO; + if (portc->bits == 16) + { + tmp |= CONC_PCM_ADC_16BIT; + OUTB (devc->osdev, 0x10, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + else + { + OUTB (devc->osdev, 0x08, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + /* Set the frame count */ + apci_writemem (devc, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wADCIC_OFF); + + /* Enable the wave interrupt */ + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + + /* Enable microphone phantom power */ + tmp = INW (devc->osdev, devc->base + 2) & ~CONC_DEVCTL_MICBIAS; + if (devc->micbias) + tmp |= CONC_DEVCTL_MICBIAS; + OUTW (devc->osdev, tmp, devc->base + 2); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +apci_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + dmap_t *dmap = audio_engines[dev]->dmap_out; + unsigned char tmp = 0x00; + apci_devc *devc = audio_engines[dev]->devc; + apci_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->atype) + { + /* Set physical address of the DMA buffer */ + apci_writemem (devc, CONC_SYNCTL_PAGE, CONC_dSYNPADDR_OFF, + dmap->dmabuf_phys); + + /* Set DAC1 rate */ + tmp = INB (devc->osdev, devc->base + CONC_bMISCCTL_OFF) & ~0x30; + tmp |= portc->speedsel << 4; + OUTB (devc->osdev, tmp, devc->base + CONC_bMISCCTL_OFF); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~(CONC_PCM_DAC1_STEREO | CONC_PCM_DAC1_16BIT); + if (portc->channels == 2) + tmp |= CONC_PCM_DAC1_STEREO; + if (portc->bits == 16) + { + tmp |= CONC_PCM_DAC1_16BIT; + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + /* Set the frame count */ + apci_writemem (devc, CONC_SYNCTL_PAGE, CONC_wSYNFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wSYNIC_OFF); + + /* Enable the wave interrupt */ + tmp = + INB (devc->osdev, devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_SYNIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_SYNIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + else + { + /* Set physical address of the DMA buffer */ + apci_writemem (devc, CONC_DACCTL_PAGE, CONC_dDACPADDR_OFF, + dmap->dmabuf_phys); + + /* Set DAC rate */ + OUTW (devc->osdev, compute_dac2_rate (portc->speed), + devc->base + CONC_wDACRATE_OFF); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~(CONC_PCM_DAC2_STEREO | CONC_PCM_DAC2_16BIT); + if (portc->channels == 2) + tmp |= CONC_PCM_DAC2_STEREO; + if (portc->bits == 16) + { + tmp |= CONC_PCM_DAC2_16BIT; + OUTB (devc->osdev, 0x10, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + else + { + OUTB (devc->osdev, 0x08, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + /* Set the frame count */ + apci_writemem (devc, CONC_DACCTL_PAGE, CONC_wDACFC_OFF, + (dmap->bytes_in_use / 4) - 1); + apci_writemem (devc, CONC_DACCTL_PAGE, CONC_wDACFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wDACIC_OFF); + + /* Enable the wave interrupt */ + tmp = + INB (devc->osdev, devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_DACIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_DACIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +apci_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + apci_devc *devc = audio_engines[dev]->devc; + apci_portc *portc = audio_engines[dev]->portc; + int ptr = 0, port = 0, page = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + if (portc->atype) + { + port = CONC_wSYNFC_OFF; + page = CONC_SYNCTL_PAGE; + } + else + { + port = CONC_wDACFC_OFF; + page = CONC_DACCTL_PAGE; + } + } + + if (direction == PCM_ENABLE_INPUT) + { + port = CONC_wADCFC_OFF; + page = CONC_ADCCTL_PAGE; + } + + ptr = apci_readmem (devc, page, port); + ptr >>= 16; + ptr <<= 2; /* count is in dwords */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + + +static const audiodrv_t apci_audio_driver = { + apci_audio_open, + apci_audio_close, + apci_audio_output_block, + apci_audio_start_input, + apci_audio_ioctl, + apci_audio_prepare_for_input, + apci_audio_prepare_for_output, + apci_audio_reset, + NULL, + NULL, + apci_audio_reset_input, + apci_audio_reset_output, + apci_audio_trigger, + apci_audio_set_rate, + apci_audio_set_format, + apci_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* apci_alloc_buffer */ + NULL, /* apci_free_buffer */ + NULL, + NULL, + apci_get_buffer_pointer +}; + +/*ARGSUSED*/ +static int +apci_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + apci_devc *devc = (apci_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + + if (mode & OPEN_READ) + { + OUTB (devc->osdev, CONC_UART_RXINTEN, devc->base + CONC_bUARTCSTAT_OFF); + } + + return 0; +} + +/*ARGSUSED*/ +static void +apci_midi_close (int dev, int mode) +{ + apci_devc *devc = (apci_devc *) midi_devs[dev]->devc; + + OUTB (devc->osdev, 0x00, devc->base + CONC_bUARTCSTAT_OFF); + devc->midi_opened = 0; +} + +static int +apci_midi_out (int dev, unsigned char midi_byte) +{ + apci_devc *devc = (apci_devc *) midi_devs[dev]->devc; + int i; + + unsigned char uart_stat = + INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + + bmast_off (devc); + for (i = 0; i < 30000; i++) + { + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + if (uart_stat & CONC_UART_TXRDY) + break; + } + + if (!(uart_stat & CONC_UART_TXRDY)) + { + bmast_on (devc); + return 0; + } + + + OUTB (devc->osdev, midi_byte, devc->base + CONC_bUARTDATA_OFF); + bmast_on (devc); + + return 1; +} + +/*ARGSUSED*/ +static int +apci_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t apci_midi_driver = { + apci_midi_open, + apci_midi_close, + apci_midi_ioctl, + apci_midi_out, +}; + +static int +init_apci (apci_devc * devc) +{ + int i, my_mixer, tmp; + + devc->micbias = 1; + devc->micboost = 1; + + OUTW (devc->osdev, compute_dac2_rate (8000), + devc->base + CONC_wDACRATE_OFF); + + tmp = + INB (devc->osdev, + devc->base + CONC_bMISCCTL_OFF) & ~CONC_MISCTL_CCB_INTRM; + tmp |= CONC_MISCTL_MUTE | CONC_MISCTL_DAC1FREQ_2205; + OUTB (devc->osdev, tmp, devc->base + CONC_bMISCCTL_OFF); + + /* Turn on UART, CODEC and joystick. Disable SERR. */ + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF) & ~CONC_DEVCTL_SERR_DISABLE; /* Yes */ + tmp |= CONC_DEVCTL_UART_EN | CONC_DEVCTL_CODEC_EN | CONC_DEVCTL_JSTICK_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + /* Disable NMI */ + OUTB (devc->osdev, 0x00, devc->base + CONC_bNMIENA_OFF); + OUTW (devc->osdev, 0x0000, devc->base + CONC_wNMISTAT_OFF); + + /* Init serial interface */ + OUTB (devc->osdev, 0x00, devc->base + CONC_bSERCTL_OFF); + OUTB (devc->osdev, CONC_PCM_DAC1_STEREO | CONC_PCM_DAC1_16BIT, + devc->base + CONC_bSERFMT_OFF); + + /* Unmute the codec */ + tmp = INB (devc->osdev, devc->base + CONC_bMISCCTL_OFF) & ~CONC_MISCTL_MUTE; + OUTB (devc->osdev, tmp, devc->base + CONC_bMISCCTL_OFF); + + /* Reset the UART */ + OUTB (devc->osdev, 0x03, devc->base + CONC_bUARTCSTAT_OFF); + OUTB (devc->osdev, 0x00, devc->base + CONC_bUARTCSTAT_OFF); + + /* + ******** Mixer initialization ********* + */ + oss_udelay (30); + ak_write (devc, 0x16, 0x03); /* Release reset */ + oss_udelay (50); + ak_write (devc, 0x18, 0x00); /* Select ADC from input mixer */ + + for (i = 0; i <= 0x19; i++) + ak_write (devc, i, ak_reg_init[i]); + + /* Enable microphone phantom power */ + tmp = INW (devc->osdev, devc->base + 2) & ~CONC_DEVCTL_MICBIAS; + if (devc->micbias) + tmp |= CONC_DEVCTL_MICBIAS; + OUTW (devc->osdev, tmp, devc->base + 2); + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "Creative AudioPCI", + &apci_mixer_driver, + sizeof (mixer_driver_t), devc)) >= 0) + { + char mxname[20]; + + sprintf (mxname, "AudioPCI"); + devc->recdevs = 0; + apci_set_recmask (devc, SOUND_MASK_MIC); + devc->levels = load_mixer_volumes (mxname, default_mixer_levels, 1); + mixer_ext_set_init_fn (my_mixer, apci_mix_init, 30); + apci_mixer_reset (devc); + } + + for (i = 0; i < MAX_PORTC; i++) + { + + int adev; + char tmp_name[100]; + apci_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX; + } + else + { + sprintf (tmp_name, "%s (playback only)", devc->chip_name); + caps |= ADEV_NOINPUT; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &apci_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0) + { + adev = -1; + return 0; + } + else + { + audio_engines[adev]->portc = portc; + if (i == 0) + { + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + } + else + { + audio_engines[adev]->min_rate = 5012; + audio_engines[adev]->max_rate = 44100; + } +/* audio_engines[adev]->min_block = 1024; */ + portc->open_mode = 0; + portc->audiodev = adev; + portc->atype = i; + audio_engines[adev]->mixer_dev = my_mixer; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + } + + if ((devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "AUDIOPCI", "AudioPCI UART", &apci_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev)) < 0) + { + cmn_err (CE_WARN, "Couldn't install MIDI device\n"); + return 0; + } + + devc->midi_opened = 0; + return 1; +} + +int +oss_audiopci_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int err; + apci_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered AudioPCI probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if ((vendor != ENSONIQ_VENDOR_ID && vendor != ENSONIQ_VENDOR_ID2) || + device != ENSONIQ_AUDIOPCI) + + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d). Can't continue\n", + pci_irq_line); + return 0; + } + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n"); + 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->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + /* Remove I/O space marker in bit 0. */ + devc->base &= ~3; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->chip_name = "Creative AudioPCI (ES1370)"; + + oss_register_device (osdev, devc->chip_name); + + + if ((err = oss_register_interrupts (osdev, 0, apciintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err); + return 0; + } + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + + return init_apci (devc); /* Detected */ +} + + +int +oss_audiopci_detach (oss_device_t * osdev) +{ + apci_devc *devc = (apci_devc *) osdev->devc; + int tmp; + + if (oss_disable_device (osdev) < 0) + return 0; + + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF) & + ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + 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/kernel/drv/oss_audiopci/oss_audiopci.man b/kernel/drv/oss_audiopci/oss_audiopci.man new file mode 100644 index 0000000..d173821 --- /dev/null +++ b/kernel/drv/oss_audiopci/oss_audiopci.man @@ -0,0 +1,20 @@ +NAME +oss_audiopci - Creative/Ensoniq Audiopci - ES1370 audio driver. + +DESCRIPTION +Open Sound System driver for Creative AudioPCI ES1370 (also sold as SBPCI128) +audio controllers + +ES1370 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_audiopci.conf Device configuration file + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_cmi878x/.devices b/kernel/drv/oss_cmi878x/.devices new file mode 100644 index 0000000..c53ff1f --- /dev/null +++ b/kernel/drv/oss_cmi878x/.devices @@ -0,0 +1,8 @@ +oss_cmi878x pci13f6,8788 CMedia CMI8788 +oss_cmi878x pci1043,8269 Asus Xonar D2 +oss_cmi878x pci1043,834f Asus Xonar D1 +oss_cmi878x pci1043,8275 Asus Xonar DX +oss_cmi878x pci1043,82b7 Asus Xonar D2X +oss_cmi878x pci1043,838e Asus Xonar DS +oss_cmi878x pci1043,835c Asus Xonar Essence STX + diff --git a/kernel/drv/oss_cmi878x/.name b/kernel/drv/oss_cmi878x/.name new file mode 100644 index 0000000..162dfb0 --- /dev/null +++ b/kernel/drv/oss_cmi878x/.name @@ -0,0 +1 @@ +CMedia CMI8788 diff --git a/kernel/drv/oss_cmi878x/oss_cmi878x.c b/kernel/drv/oss_cmi878x/oss_cmi878x.c new file mode 100644 index 0000000..e19229c --- /dev/null +++ b/kernel/drv/oss_cmi878x/oss_cmi878x.c @@ -0,0 +1,3104 @@ +/* + * Purpose: Driver for C-Media CMI8788 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_cmi878x_cfg.h" +#include <oss_pci.h> +#include <uart401.h> +#include <ac97.h> + +#define CMEDIA_VENDOR_ID 0x13F6 +#define CMEDIA_CMI8788 0x8788 + +/* + * CM8338 registers definition + */ + +#define RECA_ADDR (devc->base+0x00) +#define RECA_SIZE (devc->base+0x04) +#define RECA_FRAG (devc->base+0x06) +#define RECB_ADDR (devc->base+0x08) +#define RECB_SIZE (devc->base+0x0C) +#define RECB_FRAG (devc->base+0x0E) +#define RECC_ADDR (devc->base+0x10) +#define RECC_SIZE (devc->base+0x14) +#define RECC_FRAG (devc->base+0x16) +#define SPDIF_ADDR (devc->base+0x18) +#define SPDIF_SIZE (devc->base+0x1C) +#define SPDIF_FRAG (devc->base+0x1E) +#define MULTICH_ADDR (devc->base+0x20) +#define MULTICH_SIZE (devc->base+0x24) +#define MULTICH_FRAG (devc->base+0x28) +#define FPOUT_ADDR (devc->base+0x30) +#define FPOUT_SIZE (devc->base+0x34) +#define FPOUT_FRAG (devc->base+0x36) + +#define DMA_START (devc->base+0x40) +#define CHAN_RESET (devc->base+0x42) +#define MULTICH_MODE (devc->base+0x43) +#define IRQ_MASK (devc->base+0x44) +#define IRQ_STAT (devc->base+0x46) +#define MISC_REG (devc->base+0x48) +#define REC_FORMAT (devc->base+0x4A) +#define PLAY_FORMAT (devc->base+0x4B) +#define REC_MODE (devc->base+0x4C) +#define FUNCTION (devc->base+0x50) + +#define I2S_MULTICH_FORMAT (devc->base+0x60) +#define I2S_ADC1_FORMAT (devc->base+0x62) +#define I2S_ADC2_FORMAT (devc->base+0x64) +#define I2S_ADC3_FORMAT (devc->base+0x66) + +#define SPDIF_FUNC (devc->base+0x70) +#define SPDIFOUT_CHAN_STAT (devc->base+0x74) +#define SPDIFIN_CHAN_STAT (devc->base+0x78) + +#define I2C_ADDR (devc->base+0x90) +#define I2C_MAP (devc->base+0x91) +#define I2C_DATA (devc->base+0x92) +#define I2C_CTRL (devc->base+0x94) + +#define SPI_CONTROL (devc->base+0x98) +#define SPI_DATA (devc->base+0x99) + +#define MPU401_DATA (devc->base+0xA0) +#define MPU401_COMMAND (devc->base+0xA1) +#define MPU401_CONTROL (devc->base+0xA2) + +#define GPI_DATA (devc->base+0xA4) +#define GPI_IRQ_MASK (devc->base+0xA5) +#define GPIO_DATA (devc->base+0xA6) +#define GPIO_CONTROL (devc->base+0xA8) +#define GPIO_IRQ_MASK (devc->base+0xAA) +#define DEVICE_SENSE (devc->base+0xAC) + +#define PLAY_ROUTING (devc->base+0xC0) +#define REC_ROUTING (devc->base+0xC2) +#define REC_MONITOR (devc->base+0xC3) +#define MONITOR_ROUTING (devc->base+0xC4) + +#define AC97_CTRL (devc->base+0xD0) +#define AC97_INTR_MASK (devc->base+0xD2) +#define AC97_INTR_STAT (devc->base+0xD3) +#define AC97_OUT_CHAN_CONFIG (devc->base+0xD4) +#define AC97_IN_CHAN_CONFIG (devc->base+0xD8) +#define AC97_CMD_DATA (devc->base+0xDC) + +#define CODEC_VERSION (devc->base+0xE4) +#define CTRL_VERSION (devc->base+0xE6) + +/* Device IDs */ +#define ASUS_VENDOR_ID 0x1043 +#define SUBID_XONAR_D2 0x8269 +#define SUBID_XONAR_D2X 0x82b7 +#define SUBID_XONAR_D1 0x834f +#define SUBID_XONAR_DX 0x8275 +#define SUBID_XONAR_STX 0x835c +#define SUBID_XONAR_DS 0x838e +#define SUBID_XONAR_ST 0x835d + +#define SUBID_GENERIC 0x0000 + +/* Xonar specific */ +#define XONAR_DX_FRONTDAC 0x9e +#define XONAR_DX_SURRDAC 0x30 +#define XONAR_STX_FRONTDAC 0x98 +#define XONAR_ST_FRONTDAC 0x98 +#define XONAR_ST_CLOCK 0x9c +#define XONAR_DS_FRONTDAC 0x1 +#define XONAR_DS_SURRDAC 0x0 +#define XONAR_MCLOCK_256 0x10 +#define XONAR_MCLOCK_512 0x20 + +/* defs for AKM 4396 DAC */ +#define AK4396_CTL1 0x00 +#define AK4396_CTL2 0x01 +#define AK4396_CTL3 0x02 +#define AK4396_LchATTCtl 0x03 +#define AK4396_RchATTCtl 0x04 + +/* defs for CS4398 DAC */ +#define CS4398_CHIP_ID 0x01 +#define CS4398_MODE_CTRL 0x02 +#define CS4398_MIXING 0x03 +#define CS4398_MUTE_CTRL 0x04 +#define CS4398_VOLA 0x05 +#define CS4398_VOLB 0x06 +#define CS4398_RAMP_CTRL 0x07 +#define CS4398_MISC_CTRL 0x08 +#define CS4398_MISC2_CTRL 0x09 + +#define CS4398_POWER_DOWN (1<<7) /* Obvious */ +#define CS4398_CPEN (1<<6) /* Control Port Enable */ +#define CS4398_FREEZE (1<<5) /* Freezes registers, unfreeze to + * accept changed registers */ +#define CS4398_MCLKDIV2 (1<<4) /* Divide MCLK by 2 */ +#define CS4398_MCLKDIV3 (1<<3) /* Divive MCLK by 3 */ +#define CS4398_I2S (1<<4) /* Set I2S mode */ + +/* defs for CS4362A DAC */ +#define CS4362A_MODE1_CTRL 0x01 +#define CS4362A_MODE2_CTRL 0x02 +#define CS4362A_MODE3_CTRL 0x03 +#define CS4362A_FILTER_CTRL 0x04 +#define CS4362A_INVERT_CTRL 0x05 +#define CS4362A_MIX1_CTRL 0x06 +#define CS4362A_VOLA_1 0x07 +#define CS4362A_VOLB_1 0x08 +#define CS4362A_MIX2_CTRL 0x09 +#define CS4362A_VOLA_2 0x0A +#define CS4362A_VOLB_2 0x0B +#define CS4362A_MIX3_CTRL 0x0C +#define CS4362A_VOLA_3 0x0D +#define CS4362A_VOLB_3 0x0E +#define CS4362A_CHIP_REV 0x12 + +/* CS4362A Reg 01h */ +#define CS4362A_CPEN (1<<7) +#define CS4362A_FREEZE (1<<6) +#define CS4362A_MCLKDIV (1<<5) +#define CS4362A_DAC3_ENABLE (1<<3) +#define CS4362A_DAC2_ENABLE (1<<2) +#define CS4362A_DAC1_ENABLE (1<<1) +#define CS4362A_POWER_DOWN (1) + +/* CS4362A Reg 02h */ +#define CS4362A_DIF_LJUST 0x00 +#define CS4362A_DIF_I2S 0x10 +#define CS4362A_DIF_RJUST16 0x20 +#define CS4362A_DIF_RJUST24 0x30 +#define CS4362A_DIF_RJUST20 0x40 +#define CS4362A_DIF_RJUST18 0x50 + +/* CS4362A Reg 03h */ +#define CS4362A_RAMP_IMMEDIATE 0x00 +#define CS4362A_RAMP_ZEROCROSS 0x40 +#define CS4362A_RAMP_SOFT 0x80 +#define CS4362A_RAMP_SOFTZERO 0xC0 +#define CS4362A_SINGLE_VOL 0x20 +#define CS4362A_RAMP_ERROR 0x10 +#define CS4362A_MUTEC_POL 0x08 +#define CS4362A_AUTOMUTE 0x04 +#define CS4362A_SIX_MUTE 0x00 +#define CS4362A_ONE_MUTE 0x01 +#define CS4362A_THREE_MUTE 0x03 + +/* CS4362A Reg 04h */ +#define CS4362A_FILT_SEL 0x10 +#define CS4362A_DEM_NONE 0x00 +#define CS4362A_DEM_44KHZ 0x02 +#define CS4362A_DEM_48KHZ 0x04 +#define CS4362A_DEM_32KHZ 0x06 +#define CS4362A_RAMPDOWN 0x01 + +/* CS4362A Reg 05h */ +#define CS4362A_INV_A3 (1<<4) +#define CS4362A_INV_B3 (1<<5) +#define CS4362A_INV_A2 (1<<2) +#define CS4362A_INV_B2 (1<<3) +#define CS4362A_INV_A1 (1) +#define CS4362A_INV_B1 (1<<1) + +/* CS4362A Reg 06h, 09h, 0Ch */ +/* ATAPI crap, does anyone still use analog CD playback? */ + +/* CS4362A Reg 07h, 08h, 0Ah, 0Bh, 0Dh, 0Eh */ +/* Volume registers */ +#define CS4362A_VOL_MUTE 0x80 + + +/* 0-100. Start at -96dB. */ +#define CS4398_VOL(x) \ + ((x) == 0 ? 0xFF : (0xC0 - ((x)*192/100))) +/* 0-100. Start at -96dB. Bit 7 is mute. */ +#define CS4362A_VOL(x) \ + (char)((x) == 0 ? 0xFF : (0x60 - ((x)*96/100))) + +#define UNUSED_CMI9780_CONTROLS ( \ + SOUND_MASK_VOLUME | \ + SOUND_MASK_PCM | \ + SOUND_MASK_REARVOL | \ + SOUND_MASK_CENTERVOL | \ + SOUND_MASK_SIDEVOL | \ + SOUND_MASK_SPEAKER | \ + SOUND_MASK_ALTPCM | \ + SOUND_MASK_VIDEO | \ + SOUND_MASK_DEPTH | \ + SOUND_MASK_MONO | \ + SOUND_MASK_PHONE \ + ) + +typedef struct cmi8788_portc +{ + int speed, bits, channels; + int open_mode; + int trigger_bits; + int audio_enabled; + int audiodev; + int dac_type; +#define ADEV_MULTICH 0 +#define ADEV_FRONTPANEL 2 +#define ADEV_SPDIF 3 + int adc_type; +#define ADEV_I2SADC1 0 +#define ADEV_I2SADC2 1 +#define ADEV_I2SADC3 2 + int play_dma_start, rec_dma_start; + int play_irq_mask, rec_irq_mask; + int play_chan_reset, rec_chan_reset; + int min_rate, max_rate, min_chan, max_chan; +} +cmi8788_portc; + +#define MAX_PORTC 4 + +typedef struct cmi8788_devc +{ + oss_device_t *osdev; + oss_native_word base; + int fm_attached; + int irq; + int dma_len; + volatile unsigned char intr_mask; + int model; +#define MDL_CMI8788 1 + char *chip_name; + + /* Audio parameters */ + oss_mutex_t mutex; + oss_mutex_t low_mutex; + oss_mutex_t dac_mutex; + int open_mode; + cmi8788_portc portc[MAX_PORTC]; + + /* Mixer */ + ac97_devc ac97devc, fp_ac97devc; + int ac97_mixer_dev, fp_mixer_dev, cmi_mixer_dev; + int playvol[4]; + int recvol; + int mute; + + /* uart401 */ + oss_midi_inputbyte_t midi_input_intr; + int midi_opened, midi_disabled; + volatile unsigned char input_byte; + int midi_dev; + int mpu_attached; +} +cmi8788_devc; + +static const char xd2_codec_map[4] = { + 0, 1, 2, 4 + }; + +static void cmi8788uartintr (cmi8788_devc * devc); +static int reset_cmi8788uart (cmi8788_devc * devc); +static void enter_uart_mode (cmi8788_devc * devc); + +static int +ac97_read (void *devc_, int reg) +{ + cmi8788_devc *devc = devc_; + oss_native_word flags; + int val, data; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + val = 0L; + val |= reg << 16; + val |= 1 << 23; /*ac97 read the reg address */ + val |= 0 << 24; /*codec 0 */ + OUTL (devc->osdev, val, AC97_CMD_DATA); + oss_udelay (200); + data = INL (devc->osdev, AC97_CMD_DATA) & 0xFFFF; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return data; +} + +static int +ac97_write (void *devc_, int reg, int data) +{ + cmi8788_devc *devc = devc_; + oss_native_word flags; + int val; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + val = 0L; + val |= data & 0xFFFF; + val |= reg << 16; + val |= 0 << 23; /*ac97 write operation */ + val |= 0 << 24; /*on board codec */ + OUTL (devc->osdev, val, AC97_CMD_DATA); + oss_udelay (200); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +fp_ac97_read (void *devc_, int reg) +{ + cmi8788_devc *devc = devc_; + oss_native_word flags; + int data, val; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + val = 0L; + val |= reg << 16; + val |= 1 << 23; /*ac97 read the reg address */ + val |= 1 << 24; /*fp codec1 */ + OUTL (devc->osdev, val, AC97_CMD_DATA); + oss_udelay (200); + data = INL (devc->osdev, AC97_CMD_DATA) & 0xFFFF; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return data; +} + +static int +fp_ac97_write (void *devc_, int reg, int data) +{ + cmi8788_devc *devc = devc_; + oss_native_word flags; + int val; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + val = 0L; + val |= data & 0xFFFF; + val |= reg << 16; + val |= 0 << 23; /*ac97 write operation */ + val |= 1 << 24; /*fp codec1 */ + OUTL (devc->osdev, val, AC97_CMD_DATA); + oss_udelay (200); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +spi_write (cmi8788_devc *devc, int codec_num, unsigned char reg, int val) +{ + oss_native_word flags; + unsigned int tmp; + int latch, shift, count; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + /* check if SPI is busy */ + count = 10; + while ((INB(devc->osdev, SPI_CONTROL) & 0x1) && count-- > 0) { + oss_udelay(10); + } + + if (devc->model == SUBID_XONAR_DS) { + shift = 9; + latch = 0; + } + else { + shift = 8; + latch = 0x80; + } + + /* 2 byte data/reg info to be written */ + tmp = val; + tmp |= (reg << shift); + + /* write 2-byte data values */ + OUTB (devc->osdev, tmp & 0xff, SPI_DATA + 0); + OUTB (devc->osdev, (tmp >> 8) & 0xff, SPI_DATA + 1); + + /* Latch high, clock=160, Len=2byte, mode=write */ + tmp = (INB (devc->osdev, SPI_CONTROL) & ~0x7E) | latch | 0x1; + + /* now address which codec you want to send the data to */ + tmp |= (codec_num << 4); + + /* send the command to write the data */ + OUTB (devc->osdev, tmp, SPI_CONTROL); + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +i2c_write (cmi8788_devc *devc, unsigned char codec_num, unsigned char reg, + unsigned char data) +{ + oss_native_word flags; + int count = 50; + + /* Wait for it to stop being busy */ + MUTEX_ENTER(devc->dac_mutex, flags); + while((INW(devc->osdev, I2C_CTRL) & 0x1) && (count > 0)) + { + oss_udelay(10); + count--; + } + if(count == 0) + { + cmn_err(CE_WARN, "Time out on Two-Wire interface (busy)."); + MUTEX_EXIT(devc->dac_mutex, flags); + return OSS_EIO; + } + MUTEX_EXIT(devc->dac_mutex, flags); + + MUTEX_ENTER_IRQDISABLE(devc->low_mutex, flags); + /* first write the Register Address into the MAP register */ + OUTB (devc->osdev, reg, I2C_MAP); + + /* now write the data */ + OUTB (devc->osdev, data, I2C_DATA); + + /* select the codec number to address */ + OUTB (devc->osdev, codec_num, I2C_ADDR); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + oss_udelay(100); + + return 1; + +} + +static void +cs4398_init (cmi8788_devc *devc, int codec_addr) +{ + + /* Fast Two-Wire. Reduces the wire ready time. */ + OUTW(devc->osdev, 0x0100, I2C_CTRL); + + /* Power down, enable control mode. + * i2c_write(devc, codec_addr, CS4398_MISC_CTRL, + * CS4398_CPEN | CS4398_POWER_DOWN); + * Left justified PCM (DAC and 8788 support I2S, but doesn't work. + * Setting it introduces clipping like hell). + */ + i2c_write(devc, codec_addr, CS4398_MODE_CTRL, 0); + /* That's the DAC default, set anyway. */ + i2c_write(devc, codec_addr, 3, 0x09); + /* PCM auto-mute. */ + i2c_write(devc, codec_addr, 4, 0x82); + /* Vol A+B to -64dB. */ + i2c_write(devc, codec_addr, 5, 0x80); + i2c_write(devc, codec_addr, 6, 0x80); + /* Soft-ramping. */ + i2c_write(devc, codec_addr, 7, 0xF0); + /* Remove power down flag. */ + i2c_write(devc, codec_addr, CS4398_MISC_CTRL, CS4398_CPEN); +} + +static void +cs4362a_init(cmi8788_devc *devc, int codec_addr) +{ + + /* Fast Two-Wire. Reduces the wire ready time. */ + OUTW(devc->osdev, 0x0100, I2C_CTRL); + + /* Power down and enable control port. */ + i2c_write(devc, codec_addr, CS4362A_MODE1_CTRL, CS4362A_CPEN | CS4362A_POWER_DOWN); + /* Left-justified PCM */ + i2c_write(devc, codec_addr, CS4362A_MODE2_CTRL, CS4362A_DIF_LJUST); + /* Ramp & Automute, re-set DAC defaults. */ + i2c_write(devc, codec_addr, CS4362A_MODE3_CTRL, 0x84); + /* Filter control, DAC defs. */ + i2c_write(devc, codec_addr, CS4362A_FILTER_CTRL, 0); + /* Invert control, DAC defs. */ + i2c_write(devc, codec_addr, CS4362A_INVERT_CTRL, 0); + /* Mixing control, DAC defs. */ + i2c_write(devc, codec_addr, CS4362A_MIX1_CTRL, 0x24); + i2c_write(devc, codec_addr, CS4362A_MIX2_CTRL, 0x24); + i2c_write(devc, codec_addr, CS4362A_MIX3_CTRL, 0x24); + /* Volume to -64dB. */ + i2c_write(devc, codec_addr, CS4362A_VOLA_1, 0x40); + i2c_write(devc, codec_addr, CS4362A_VOLB_1, 0x40); + i2c_write(devc, codec_addr, CS4362A_VOLA_2, 0x40); + i2c_write(devc, codec_addr, CS4362A_VOLB_2, 0x40); + i2c_write(devc, codec_addr, CS4362A_VOLA_3, 0x40); + i2c_write(devc, codec_addr, CS4362A_VOLB_3, 0x40); + /* Power up. */ + i2c_write(devc, codec_addr, CS4362A_MODE1_CTRL, CS4362A_CPEN); +} + + +static void +cs2000_init(cmi8788_devc *devc, int addr) +{ + + /* Fast Two-Wire. Reduces the wire ready time. */ + OUTW(devc->osdev, 0x0100, I2C_CTRL); + + /* first set global config reg to freeze */ + i2c_write (devc, addr, 0x5, 0x08); + + /* set dev ctrl reg to output enabled (0) */ + i2c_write (devc, addr, 0x2, 0); + + /* set dev cfg1 reg to defaults and enable */ + i2c_write (devc, addr, 0x3, 0x0 | (0 << 3) | 0x0 | 0x1); + + /* set dev cfg2 reg to defaults and enable */ + i2c_write (devc, addr, 0x4, (0 << 1) | 0x0); + + /* set ratio0 MSB to 0 */ + i2c_write (devc, addr, 0x06, 0x00); + /* set ratio0 MSB+8 to 0x10 */ + i2c_write (devc, addr, 0x07, 0x10); + /* set ratio0 LSB+15 to 0 */ + i2c_write (devc, addr, 0x08, 0x00); + /* set ratio0 LSB+7 to 0 */ + i2c_write (devc, addr, 0x09, 0x00); + + /* Func reg1 to ref clock div 1 */ + i2c_write (devc, addr, 0x16, 0x10); + + /* set func reg2 to 0 */ + i2c_write (devc, addr, 0x17, 0); + + /* set global cfg to run */ + i2c_write (devc, addr, 0x05, 0x1); +} + + +static unsigned int +mix_scale (int vol, int bits) +{ + vol = mix_cvt[vol]; + return (vol * ((1 << bits) - 1) / 100); +} + + +static void +cmi8788_generic_set_play_volume (cmi8788_devc *devc, int codec_id, int left, int right) + +{ + spi_write (devc, codec_id, AK4396_LchATTCtl | 0x20, mix_scale(left, 8)); + spi_write (devc, codec_id, AK4396_RchATTCtl | 0x20, mix_scale(right, 8)); +} + +static void +xonar_d1_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right) +{ + switch(codec_id) + { + case 0: + i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLA, CS4398_VOL(left)); + i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLB, CS4398_VOL(right)); + break; + case 1: + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_1, CS4362A_VOL(left)); + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_1, CS4362A_VOL(right)); + break; + case 2: + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_2, CS4362A_VOL(left)); + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_2, CS4362A_VOL(right)); + break; + case 3: + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_3, CS4362A_VOL(left)); + i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_3, CS4362A_VOL(right)); + break; + } +} + +static void +xonar_d2_set_play_volume(cmi8788_devc *devc, int codec_id, int left, int right) +{ + spi_write (devc, xd2_codec_map[codec_id], 16, mix_scale(left,8)); + spi_write (devc, xd2_codec_map[codec_id], 17, mix_scale(right,8)); +} + +static void +xonar_stx_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right) +{ + if (codec_id == 0) + { + i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(left,8)); + i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(right,8)); + } +} + +static void +xonar_st_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right) +{ + if (codec_id == 0) + { + i2c_write(devc, XONAR_ST_FRONTDAC, 16, mix_scale(left,8)); + i2c_write(devc, XONAR_ST_FRONTDAC, 17, mix_scale(right,8)); + } +} + +static void +xonar_ds_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right) +{ + switch (codec_id) + { + case 0: /* front */ + spi_write (devc, XONAR_DS_FRONTDAC, 0, mix_scale(left,7)|0x80); + spi_write (devc, XONAR_DS_FRONTDAC, 1, mix_scale(right,7)|0x180); + spi_write (devc, XONAR_DS_FRONTDAC, 3, mix_scale(left,7)|0x80); + spi_write (devc, XONAR_DS_FRONTDAC, 4, mix_scale(right,7)|0x180); + break; + + case 1: /* side */ + spi_write (devc, XONAR_DS_SURRDAC, 0, mix_scale(left,7)|0x80); + spi_write (devc, XONAR_DS_SURRDAC, 1, mix_scale(right,7)|0x180); + break; + case 2: /* rear */ + spi_write (devc, XONAR_DS_SURRDAC, 4, mix_scale(left,7)|0x80); + spi_write (devc, XONAR_DS_SURRDAC, 5, mix_scale(right,7)|0x180); + break; + case 3: /* center */ + spi_write (devc, XONAR_DS_SURRDAC, 6, mix_scale(left,7)|0x80); + spi_write (devc, XONAR_DS_SURRDAC, 7, mix_scale(right,7)|0x180); + break; + } +} + +static int +cmi8788_set_rec_volume (cmi8788_devc * devc, int value) +{ + unsigned char left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + devc->recvol = left | (right << 8); + + spi_write (devc, XONAR_DS_FRONTDAC, 0xe, mix_scale(left,8)); + spi_write (devc, XONAR_DS_FRONTDAC, 0xf, mix_scale(right,8)); + + return devc->recvol; +} + + + +static int +cmi8788_set_play_volume (cmi8788_devc * devc, int codec_id, int value) +{ + int left, right; + + left = (value & 0x00FF); + right = (value & 0xFF00) >> 8; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + devc->playvol[codec_id] = left | (right<<8); + + switch(devc->model) + { + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + xonar_d1_set_play_volume(devc, codec_id, left, right); + break; + case SUBID_XONAR_D2: + case SUBID_XONAR_D2X: + xonar_d2_set_play_volume(devc, codec_id, left, right); + break; + case SUBID_XONAR_STX: + xonar_stx_set_play_volume(devc, codec_id, left, right); + break; + case SUBID_XONAR_ST: + xonar_st_set_play_volume(devc, codec_id, left, right); + break; + case SUBID_XONAR_DS: + xonar_ds_set_play_volume(devc, codec_id, left, right); + break; + default: + cmi8788_generic_set_play_volume (devc, codec_id, left, right); + break; + } + return devc->playvol[codec_id]; +} + +static int +cmi8788intr (oss_device_t * osdev) +{ + cmi8788_devc *devc = (cmi8788_devc *) osdev->devc; + unsigned int intstat; + int i; + int serviced = 0; + + + intstat = INW (devc->osdev, IRQ_STAT); + if (intstat != 0) + serviced = 1; + else + return 0; + + for (i = 0; i < MAX_PORTC; i++) + { + cmi8788_portc *portc = &devc->portc[i]; + + /* Handle Playback Ints */ + if ((intstat & portc->play_irq_mask) + && (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + + /* Acknowledge the interrupt by disabling and enabling the irq */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) & ~portc->play_irq_mask, + IRQ_MASK); + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) | portc->play_irq_mask, IRQ_MASK); + + /* process buffer */ + oss_audio_outputintr (portc->audiodev, 0); + } + + /* Handle Record Ints */ + if ((intstat & portc->rec_irq_mask) + && (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* disable the interrupt first */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) & ~portc->rec_irq_mask, IRQ_MASK); + /* enable the interrupt mask */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) | portc->rec_irq_mask, IRQ_MASK); + oss_audio_inputintr (portc->audiodev, 0); + } + + } + + /* MPU interrupt */ + if (intstat & 0x1000) + { + cmi8788uartintr (devc); + } + + return serviced; +} + +static int +cmi8788_audio_set_rate (int dev, int arg) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (arg > portc->max_rate) + arg = portc->max_rate; + if (arg < portc->min_rate) + arg = portc->min_rate; + + portc->speed = arg; + return portc->speed; +} + +static short +cmi8788_audio_set_channels (int dev, short arg) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + + if (audio_engines[dev]->flags & ADEV_STEREOONLY) + arg = 2; + + if (arg == 1) + arg = 2; + + if (arg>8) + arg=8; + if ((arg != 2) && (arg != 4) && (arg != 6) && (arg != 8)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +cmi8788_audio_set_format (int dev, unsigned int arg) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (audio_engines[dev]->flags & ADEV_16BITONLY) + arg = AFMT_S16_LE; + + if (!(arg & (AFMT_S16_LE | AFMT_AC3 | AFMT_S32_LE))) + return portc->bits; + portc->bits = arg; + return portc->bits; +} + +/*ARGSUSED*/ +static int +cmi8788_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void cmi8788_audio_trigger (int dev, int state); + +static void +cmi8788_audio_reset (int dev) +{ + cmi8788_audio_trigger (dev, 0); +} + +static void +cmi8788_audio_reset_input (int dev) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + cmi8788_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +cmi8788_audio_reset_output (int dev) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + cmi8788_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +cmi8788_audio_open (int dev, int mode, int open_flags) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + cmi8788_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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +cmi8788_audio_close (int dev, int mode) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + cmi8788_devc *devc = audio_engines[dev]->devc; + + cmi8788_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +cmi8788_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +cmi8788_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +cmi8788_audio_trigger (int dev, int state) +{ + cmi8788_portc *portc = audio_engines[dev]->portc; + cmi8788_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + 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)) + { + /* Enable Interrupt */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) | portc->play_irq_mask, + IRQ_MASK); + /* enable the dma */ + OUTW (devc->osdev, + INW (devc->osdev, DMA_START) | portc->play_dma_start, + DMA_START); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + /* disable dma */ + OUTW (devc->osdev, + INW (devc->osdev, DMA_START) & ~portc->play_dma_start, + DMA_START); + /* Disable Interrupt */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) & ~portc->play_irq_mask, + IRQ_MASK); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Enable Interrupt */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) | portc->rec_irq_mask, + IRQ_MASK); + + /* enable the channel */ + OUTW (devc->osdev, + INW (devc->osdev, DMA_START) | portc->rec_dma_start, + DMA_START); + 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; + /* disable channel */ + OUTW (devc->osdev, + INW (devc->osdev, DMA_START) & ~portc->rec_dma_start, + DMA_START); + + /* Disable Interrupt */ + OUTW (devc->osdev, + INW (devc->osdev, IRQ_MASK) & ~portc->rec_irq_mask, + IRQ_MASK); + + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +cmi8788_reset_channel (cmi8788_devc * devc, cmi8788_portc * portc, + int direction) +{ + if (direction == PCM_ENABLE_OUTPUT) + { + /* reset the channel */ + OUTB (devc->osdev, + INB (devc->osdev, CHAN_RESET) | portc->play_chan_reset, + CHAN_RESET); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, CHAN_RESET) & ~portc->play_chan_reset, + CHAN_RESET); + } + + if (direction == PCM_ENABLE_INPUT) + { + /* reset the channel */ + OUTB (devc->osdev, + INB (devc->osdev, CHAN_RESET) | portc->rec_chan_reset, + CHAN_RESET); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, CHAN_RESET) & ~portc->rec_chan_reset, + CHAN_RESET); + } + +} + +static int +i2s_calc_rate (int rate) +{ + int i2s_rate; + + switch (rate) + { + case 32000: + i2s_rate = 0; + break; + case 44100: + i2s_rate = 1; + break; + case 48000: + i2s_rate = 2; + break; + case 64000: + i2s_rate = 3; + break; + case 88200: + i2s_rate = 4; + break; + case 96000: + i2s_rate = 5; + break; + case 176400: + i2s_rate = 6; + break; + case 192000: + i2s_rate = 7; + break; + default: + i2s_rate = 2; + break; + } + + return i2s_rate; +} + +int +i2s_calc_bits (int bits) +{ + int i2s_bits; + + switch (bits) + { +#if 0 + case AFMT_S24_LE: + i2s_bits = 0x80; + break; +#endif + case AFMT_S32_LE: + i2s_bits = 0xC0; + break; + default: /* AFMT_S16_LE */ + i2s_bits = 0x00; + break; + } + + return i2s_bits; +} + +/*ARGSUSED*/ +static int +cmi8788_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + cmi8788_devc *devc = audio_engines[dev]->devc; + cmi8788_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + int channels, bits, i2s_bits, i2s_rate; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + switch (portc->adc_type) + { + case ADEV_I2SADC1: + { + portc->rec_dma_start = 0x1; + portc->rec_irq_mask = 0x1; + portc->rec_chan_reset = 0x1; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_INPUT); + + OUTL (devc->osdev, dmap->dmabuf_phys, RECA_ADDR); + OUTW (devc->osdev, dmap->bytes_in_use / 4 - 1, RECA_SIZE); + OUTW (devc->osdev, dmap->fragment_size / 4 - 1, RECA_FRAG); + + switch (portc->channels) + { + case 4: + channels = 0x1; + break; + case 6: + channels = 0x2; + break; + case 8: + channels = 0x4; + break; + default: + channels = 0x0; /* Stereo */ + break; + } + + OUTB (devc->osdev, (INB (devc->osdev, REC_MODE) & ~0x3) | channels, + REC_MODE); + + switch (portc->bits) + { +#if 0 + /* The 24 bit format supported by cmi8788 is not AFMT_S24_LE */ + case AFMT_S24_LE: + bits = 0x1; + break; +#endif + case AFMT_S32_LE: + bits = 0x2; + break; + default: /* AFMT_S16_LE */ + bits = 0x0; + break; + } + OUTB (devc->osdev, (INB (devc->osdev, REC_FORMAT) & ~0x3) | bits, + REC_FORMAT); + + /* set up the i2s bits as well */ + i2s_bits = i2s_calc_bits (portc->bits); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC1_FORMAT) & ~0xC0) | i2s_bits, + I2S_ADC1_FORMAT); + + /* setup the i2s speed */ + i2s_rate = i2s_calc_rate (portc->speed); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC1_FORMAT) & ~0x7) | i2s_rate, + I2S_ADC1_FORMAT); + + break; + } + + case ADEV_I2SADC2: + { + portc->rec_dma_start = 0x2; + portc->rec_irq_mask = 0x2; + portc->rec_chan_reset = 0x2; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_INPUT); + + OUTL (devc->osdev, dmap->dmabuf_phys, RECB_ADDR); + OUTW (devc->osdev, dmap->bytes_in_use / 4 - 1, RECB_SIZE); + OUTW (devc->osdev, dmap->fragment_size / 4 - 1, RECB_FRAG); + + switch (portc->bits) + { +#if 0 + case AFMT_S24_LE: + bits = 0x04; + break; +#endif + case AFMT_S32_LE: + bits = 0x08; + break; + default: /* AFMT_S16_LE */ + bits = 0x0; + break; + } + + OUTB (devc->osdev, (INB (devc->osdev, REC_FORMAT) & ~0x0C) | bits, + REC_FORMAT); + + /* setup i2s bits */ + i2s_bits = i2s_calc_bits (portc->bits); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC2_FORMAT) & ~0xC0) | i2s_bits, + I2S_ADC2_FORMAT); + + /* setup speed */ + i2s_rate = i2s_calc_rate (portc->speed); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC2_FORMAT) & ~0x7) | i2s_rate, + I2S_ADC2_FORMAT); + + break; + } + + case ADEV_I2SADC3: + { + portc->rec_dma_start = 0x4; + portc->rec_irq_mask = 0x4; + portc->rec_chan_reset = 0x4; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_INPUT); + + OUTL (devc->osdev, dmap->dmabuf_phys, RECC_ADDR); + OUTW (devc->osdev, dmap->bytes_in_use / 4 - 1, RECC_SIZE); + OUTW (devc->osdev, dmap->fragment_size / 4 - 1, RECC_FRAG); + + switch (portc->bits) + { +#if 0 + case AFMT_S24_LE: + bits = 0x10; + break; +#endif + case AFMT_S32_LE: + bits = 0x20; + break; + default: /* AFMT_S16_LE */ + bits = 0x0; + break; + } + + OUTB (devc->osdev, (INB (devc->osdev, REC_FORMAT) & ~0x30) | bits, + REC_FORMAT); + + /* setup i2s bits */ + i2s_bits = i2s_calc_bits (portc->bits); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC3_FORMAT) & ~0xC0) | i2s_bits, + I2S_ADC3_FORMAT); + + /* setup speed */ + i2s_rate = i2s_calc_rate (portc->speed); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_ADC3_FORMAT) & ~0x7) | i2s_rate, + I2S_ADC3_FORMAT); + break; + } + } + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +cmi8788_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + cmi8788_devc *devc = audio_engines[dev]->devc; + cmi8788_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + oss_native_word flags; + int i2s_rate, rate, spdif_rate, bits = 0, i2s_bits, channels = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + switch (portc->dac_type) + { + case ADEV_MULTICH: + { + portc->play_dma_start = 0x10; + portc->play_irq_mask = 0x10; + portc->play_chan_reset = 0x10; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_OUTPUT); + + OUTL (devc->osdev, dmap->dmabuf_phys, MULTICH_ADDR); + OUTL (devc->osdev, dmap->bytes_in_use / 4 - 1, MULTICH_SIZE); + OUTL (devc->osdev, dmap->fragment_size / 4 - 1, MULTICH_FRAG); + + switch (portc->channels) + { + case 2: + channels = 0; + break; + case 4: + channels = 1; + break; + case 6: + channels = 2; + break; + case 8: + channels = 3; + break; + } + + OUTB (devc->osdev, + (INB (devc->osdev, MULTICH_MODE) & ~0x3) | channels, + MULTICH_MODE); + + /* setup bits per sample */ + switch (portc->bits) + { +#if 0 + case AFMT_S24_LE: + bits = 4; + break; +#endif + case AFMT_S32_LE: + bits = 8; + break; + + default: /* AFMT_S16_LE */ + bits = 0; + break; + } + + /* set the format bits in play format register */ + OUTB (devc->osdev, (INB (devc->osdev, PLAY_FORMAT) & ~0xC) | bits, + PLAY_FORMAT); + + /* setup the i2s bits in the i2s register */ + i2s_bits = i2s_calc_bits (portc->bits); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_MULTICH_FORMAT) & ~0xC0) | i2s_bits, + I2S_MULTICH_FORMAT); + + /* setup speed */ + i2s_rate = i2s_calc_rate (portc->speed); + OUTB (devc->osdev, + (INB (devc->osdev, I2S_MULTICH_FORMAT) & ~0x7) | i2s_rate, + I2S_MULTICH_FORMAT); + + break; + } + + case ADEV_FRONTPANEL: + { + portc->play_dma_start = 0x20; + portc->play_irq_mask = 0x20; + portc->play_chan_reset = 0x20; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_OUTPUT); + + OUTL (devc->osdev, dmap->dmabuf_phys, FPOUT_ADDR); + OUTW (devc->osdev, dmap->bytes_in_use / 4 - 1, FPOUT_SIZE); + OUTW (devc->osdev, dmap->fragment_size / 4 - 1, FPOUT_FRAG); + ac97_playrate (&devc->fp_ac97devc, portc->speed); + ac97_spdif_setup (devc->fp_mixer_dev, portc->speed, portc->bits); + + break; + } + + case ADEV_SPDIF: + { + portc->play_dma_start = 0x08; + portc->play_irq_mask = 0x08; + portc->play_chan_reset = 0x08; + cmi8788_reset_channel (devc, portc, PCM_ENABLE_OUTPUT); + + /* STOP SPDIF Out */ + OUTL (devc->osdev, (INL (devc->osdev, SPDIF_FUNC) & ~0x00000002), + SPDIF_FUNC); + + /* setup AC3 for 16bit 48Khz, Non-Audio */ + if (portc->bits == AFMT_AC3) + { + portc->bits = 16; + portc->channels = 2; + portc->speed = 48000; + + /* set the PCM/Data bit to Non-Audio */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x0002) | 0x0002, + SPDIFOUT_CHAN_STAT); + } + else + OUTL (devc->osdev, + INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x0002, + SPDIFOUT_CHAN_STAT); + + OUTL (devc->osdev, dmap->dmabuf_phys, SPDIF_ADDR); + OUTW (devc->osdev, dmap->bytes_in_use / 4 - 1, SPDIF_SIZE); + OUTW (devc->osdev, dmap->fragment_size / 4 - 1, SPDIF_FRAG); + + /* setup number of bits/sample */ + switch (portc->bits) + { + case 16: + bits = 0; + break; + case 24: + bits = 1; + break; + case 32: + bits = 2; + break; + } + + OUTB (devc->osdev, (INB (devc->osdev, PLAY_FORMAT) & ~0x3) | bits, + PLAY_FORMAT); + + /* setup sampling rate */ + switch (portc->speed) + { + case 32000: + rate = 0; + spdif_rate = 0x3; + break; + case 44100: + rate = 1; + spdif_rate = 0x0; + break; + case 48000: + rate = 2; + spdif_rate = 0x2; + break; + case 64000: + rate = 3; + spdif_rate = 0xb; + break; + case 88200: + rate = 4; + spdif_rate = 0x8; + break; + case 96000: + rate = 5; + spdif_rate = 0xa; + break; + case 176400: + rate = 6; + spdif_rate = 0xc; + break; + case 192000: + rate = 7; + spdif_rate = 0xe; + break; + default: + rate = 2; /* 48000 */ + spdif_rate = 0x2; + break; + } + + OUTL (devc->osdev, + (INL (devc->osdev, SPDIF_FUNC) & ~0x0f000000) | rate << 24, + SPDIF_FUNC); + + /* also program the Channel status */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF000) | spdif_rate + << 12, SPDIFOUT_CHAN_STAT); + + /* Enable SPDIF Out */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIF_FUNC) & ~0x00000002) | 0x2, + SPDIF_FUNC); + + break; + } + } + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +cmi8788_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + cmi8788_devc *devc = audio_engines[dev]->devc; + cmi8788_portc *portc = audio_engines[dev]->portc; + unsigned int ptr = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_INPUT) + { + switch (portc->adc_type) + { + case ADEV_I2SADC1: + ptr = INL (devc->osdev, RECA_ADDR); + break; + case ADEV_I2SADC2: + ptr = INL (devc->osdev, RECB_ADDR); + break; + case ADEV_I2SADC3: + ptr = INL (devc->osdev, RECC_ADDR); + break; + } + } + + if (direction == PCM_ENABLE_OUTPUT) + { + switch (portc->dac_type) + { + case ADEV_MULTICH: + ptr = INL (devc->osdev, MULTICH_ADDR); + break; + case ADEV_FRONTPANEL: + ptr = INL (devc->osdev, FPOUT_ADDR); + break; + case ADEV_SPDIF: + ptr = INL (devc->osdev, SPDIF_ADDR); + break; + } + } + + ptr -= dmap->dmabuf_phys; + ptr %= dmap->bytes_in_use; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + + +static audiodrv_t cmi8788_audio_driver = { + cmi8788_audio_open, + cmi8788_audio_close, + cmi8788_audio_output_block, + cmi8788_audio_start_input, + cmi8788_audio_ioctl, + cmi8788_audio_prepare_for_input, + cmi8788_audio_prepare_for_output, + cmi8788_audio_reset, + NULL, + NULL, + cmi8788_audio_reset_input, + cmi8788_audio_reset_output, + cmi8788_audio_trigger, + cmi8788_audio_set_rate, + cmi8788_audio_set_format, + cmi8788_audio_set_channels, + NULL, + NULL, + NULL, /* cmi8788_check_input, */ + NULL, /* cmi8788_check_output, */ + NULL, /* cmi8788_alloc_buffer */ + NULL, /* cmi8788_free_buffer */ + NULL, + NULL, + cmi8788_get_buffer_pointer +}; + +#define input_avail(devc) (!(cmi8788uart_status(devc)&INPUT_AVAIL)) +#define output_ready(devc) (!(cmi8788uart_status(devc)&OUTPUT_READY)) + +static __inline__ int +cmi8788uart_status (cmi8788_devc * devc) +{ + return INB (devc->osdev, MPU401_COMMAND); +} + +static void +cmi8788uart_cmd (cmi8788_devc * devc, unsigned char cmd) +{ + OUTB (devc->osdev, cmd, MPU401_COMMAND); +} + +static __inline__ int +cmi8788uart_read (cmi8788_devc * devc) +{ + return INB (devc->osdev, MPU401_DATA); +} + +static __inline__ void +cmi8788uart_write (cmi8788_devc * devc, unsigned char byte) +{ + OUTB (devc->osdev, byte, MPU401_DATA); +} + +#define OUTPUT_READY 0x40 +#define INPUT_AVAIL 0x80 +#define MPU_ACK 0xFE +#define MPU_RESET 0xFF +#define UART_MODE_ON 0x3F + + +static void +cmi8788uart_input_loop (cmi8788_devc * devc) +{ + while (input_avail (devc)) + { + unsigned char c = cmi8788uart_read (devc); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, c); + } +} + +static void +cmi8788uartintr (cmi8788_devc * devc) +{ + cmi8788uart_input_loop (devc); +} + +/*ARGSUSED*/ +static int +cmi8788uart_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + cmi8788_devc *devc = (cmi8788_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + while (input_avail (devc)) + cmi8788uart_read (devc); + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + enter_uart_mode (devc); + devc->midi_disabled = 0; + + return 0; +} + +/*ARGSUSED*/ +static void +cmi8788uart_close (int dev, int mode) +{ + cmi8788_devc *devc = (cmi8788_devc *) midi_devs[dev]->devc; + reset_cmi8788uart (devc); + oss_udelay (10); + enter_uart_mode (devc); + reset_cmi8788uart (devc); + devc->midi_opened = 0; +} + + +static int +cmi8788uart_out (int dev, unsigned char midi_byte) +{ + int timeout; + cmi8788_devc *devc = (cmi8788_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + /* + * Test for input since pending input seems to block the output. + */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (input_avail (devc)) + cmi8788uart_input_loop (devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + /* + * Sometimes it takes about 130000 loops before the output becomes ready + * (After reset). Normally it takes just about 10 loops. + */ + + for (timeout = 130000; timeout > 0 && !output_ready (devc); timeout--); + + if (!output_ready (devc)) + { + cmn_err (CE_WARN, "UART timeout - Device not responding\n"); + devc->midi_disabled = 1; + reset_cmi8788uart (devc); + enter_uart_mode (devc); + return 1; + } + + cmi8788uart_write (devc, midi_byte); + return 1; +} + +/*ARGSUSED*/ +static int +cmi8788uart_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t cmi8788_midi_driver = { + cmi8788uart_open, + cmi8788uart_close, + cmi8788uart_ioctl, + cmi8788uart_out, +}; + +static void +enter_uart_mode (cmi8788_devc * devc) +{ + int ok, timeout; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + cmi8788uart_cmd (devc, UART_MODE_ON); + + ok = 0; + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) + ok = 1; + else if (input_avail (devc)) + if (cmi8788uart_read (devc) == MPU_ACK) + ok = 1; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + +void +attach_cmi8788uart (cmi8788_devc * devc) +{ + enter_uart_mode (devc); + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "CMI8788", "CMI8788 UART", &cmi8788_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev); + devc->midi_opened = 0; +} + +static int +reset_cmi8788uart (cmi8788_devc * devc) +{ + int ok, timeout, n; + + /* + * Send the RESET command. Try again if no success at the first time. + */ + + ok = 0; + + for (n = 0; n < 2 && !ok; n++) + { + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + cmi8788uart_cmd (devc, MPU_RESET); + + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail (devc)) + if (cmi8788uart_read (devc) == MPU_ACK) + ok = 1; + + } + + + + if (ok) + cmi8788uart_input_loop (devc); /* + * Flush input before enabling interrupts + */ + + return ok; +} + + +int +probe_cmi8788uart (cmi8788_devc * devc) +{ + int ok = 0; + oss_native_word flags; + + DDB (cmn_err (CE_CONT, "Entered probe_cmi8788uart\n")); + + devc->midi_input_intr = NULL; + devc->midi_opened = 0; + devc->input_byte = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ok = reset_cmi8788uart (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (ok) + { + DDB (cmn_err (CE_CONT, "Reset UART401 OK\n")); + } + else + { + DDB (cmn_err + (CE_CONT, "Reset UART401 failed (no hardware present?).\n")); + DDB (cmn_err + (CE_CONT, "mpu401 status %02x\n", cmi8788uart_status (devc))); + } + + DDB (cmn_err (CE_CONT, "cmi8788uart detected OK\n")); + return ok; +} + +void +unload_cmi8788uart (cmi8788_devc * devc) +{ + reset_cmi8788uart (devc); +} + + +static void +attach_mpu (cmi8788_devc * devc) +{ + devc->mpu_attached = 1; + attach_cmi8788uart (devc); +} + +/*ARGSUSED*/ +static int +cmi8788_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + cmi8788_devc *devc = mixer_devs[dev]->devc; + + if (((cmd >> 8) & 0xff) == 'M') + { + int val; + + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + return *arg = 0; + break; + + case SOUND_MIXER_PCM: + val = *arg; + return *arg = cmi8788_set_play_volume (devc, 0, val); + break; + + case SOUND_MIXER_REARVOL: + val = *arg; + return *arg = cmi8788_set_play_volume (devc, 1, val); + break; + + case SOUND_MIXER_CENTERVOL: + val = *arg; + return *arg = cmi8788_set_play_volume (devc, 2, val); + break; + + case SOUND_MIXER_SIDEVOL: + val = *arg; + return *arg = cmi8788_set_play_volume (devc, 3, val); + break; + + case SOUND_MIXER_RECLEV: + val = *arg; + return *arg = cmi8788_set_rec_volume (devc, val); + break; + + default: + val = *arg; + return *arg = 0; + break; + } + else + switch (cmd & 0xff) /* Return Parameter */ + { + case SOUND_MIXER_RECSRC: + return *arg = 0; + break; + + case SOUND_MIXER_DEVMASK: + if ((devc->model == SUBID_XONAR_STX) || (devc->model == SUBID_XONAR_ST)) + *arg = SOUND_MASK_PCM; + else + *arg = SOUND_MASK_PCM | SOUND_MASK_REARVOL | + SOUND_MASK_CENTERVOL | SOUND_MASK_SIDEVOL; + + if (devc->model == SUBID_XONAR_DS) + *arg |= SOUND_MASK_RECLEV; + + return *arg; + break; + + case SOUND_MIXER_STEREODEVS: + if ((devc->model == SUBID_XONAR_STX) || (devc->model == SUBID_XONAR_ST)) + *arg = SOUND_MASK_PCM; + else + *arg = SOUND_MASK_PCM | SOUND_MASK_REARVOL | + SOUND_MASK_CENTERVOL | SOUND_MASK_SIDEVOL; + + if (devc->model == SUBID_XONAR_DS) + *arg |= SOUND_MASK_RECLEV; + + return *arg; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + case SOUND_MIXER_PCM: + return *arg = devc->playvol[0]; + break; + + case SOUND_MIXER_REARVOL: + return *arg = devc->playvol[1]; + break; + + case SOUND_MIXER_CENTERVOL: + return *arg = devc->playvol[2]; + break; + + case SOUND_MIXER_SIDEVOL: + return *arg = devc->playvol[3]; + break; + + case SOUND_MIXER_RECLEV: + return *arg = devc->recvol; + break; + + default: + return *arg = 0; + break; + } + } + else + return *arg = 0; + +} + +static mixer_driver_t cmi8788_mixer_driver = { + cmi8788_mixer_ioctl +}; + +/********************Record/Play ROUTING Control *************************/ + +static int +cmi8788_ext (int dev, int ctrl, unsigned int cmd, int value) +{ +/* + * Access function for CMPCI mixer extension bits + */ + cmi8788_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case 0: /* Record Monitor */ + value = (INB (devc->osdev, REC_MONITOR) & 0x1) ? 1 : 0; + break; + case 1: /* SPDIFIN Monitor */ + value = (INB (devc->osdev, REC_MONITOR) & 0x10) ? 1 : 0; + break; + case 2: /* Record source select */ + switch (devc->model) + { + case SUBID_XONAR_DS: + value = (INW (devc->osdev, GPIO_DATA) & 0x40) ? 1 : 0; + break; + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_STX: + case SUBID_XONAR_ST: + value = (INW (devc->osdev, GPIO_DATA) & 0x100) ? 1 : 0; + break; + default: + value = (ac97_read (devc, 0x72) & 0x1) ? 1 : 0; + break; + } + break; + case 3: /* Speaker Spread - check bit15 to see if it's set */ + value = (INW (devc->osdev, PLAY_ROUTING) & 0x8000) ? 0 : 1; + break; + case 4: /* SPDIF IN->OUT Loopback */ + value = (INW (devc->osdev, SPDIF_FUNC) & 0x4) ? 1 : 0; + break; + case 5: + value = (INW (devc->osdev, GPIO_DATA) & 0x80) ? 1 : 0; + break; + case 6: + if (!(INW (devc->osdev, GPIO_DATA) & 0x80)) + value = 0; + else if (INW (devc->osdev, GPIO_DATA) & 0x02) + value = 1; + else + value = 2; + break; + case 7: + value = devc->mute; + break; + + default: + return OSS_EINVAL; + break; + } + + return value; + } + + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 0: /* Record Monitor */ + if (value) + OUTB (devc->osdev, INB (devc->osdev, REC_MONITOR) | 0xF, + REC_MONITOR); + else + OUTB (devc->osdev, INB (devc->osdev, REC_MONITOR) & ~0xF, + REC_MONITOR); + break; + + case 1: /* SPDIFIN Monitor */ + if (value) + OUTB (devc->osdev, INB (devc->osdev, REC_MONITOR) | 0x10, + REC_MONITOR); + else + OUTB (devc->osdev, INB (devc->osdev, REC_MONITOR) & ~0x10, + REC_MONITOR); + break; + + case 2: + if (value) + { + switch (devc->model) + { + case SUBID_XONAR_DS: + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x40, GPIO_DATA); + break; + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_STX: + case SUBID_XONAR_ST: + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x100, GPIO_DATA); + break; + } + ac97_write(devc, 0x72, ac97_read(devc, 0x72) | 0x1); + } + else + { + switch (devc->model) + { + case SUBID_XONAR_DS: + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~0x40, GPIO_DATA); + break; + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_STX: + case SUBID_XONAR_ST: + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~0x100, GPIO_DATA); + break; + } + + ac97_write(devc, 0x72, ac97_read(devc, 0x72) & ~0x1); + } + break; + + case 3: /* Speaker Spread (clone front to all channels) */ + if (value) + OUTW (devc->osdev, INW (devc->osdev, PLAY_ROUTING) & 0x00FF, + PLAY_ROUTING); + else + OUTW (devc->osdev, + (INW (devc->osdev, PLAY_ROUTING) & 0x00FF) | 0xE400, + PLAY_ROUTING); + break; + + case 4: /* SPDIF IN->OUT Loopback */ + if (value) + OUTW (devc->osdev, INW (devc->osdev, SPDIF_FUNC) | 0x4, + SPDIF_FUNC); + else + OUTW (devc->osdev, INW (devc->osdev, SPDIF_FUNC) & ~0x4, + SPDIF_FUNC); + break; + + case 5: + if (value) + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x80, GPIO_DATA) ; + else + OUTW(devc->osdev, (INW(devc->osdev, GPIO_DATA) & ~0x80), GPIO_DATA); + break; + + case 6: + switch (value) + { + /* speaker (line) output */ + case 0: OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~(0x80|0x02), GPIO_DATA); + break; + /* rear headphone output */ + case 1: OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | (0x80|0x02), GPIO_DATA); + break; + case 2: OUTW (devc->osdev, (INW(devc->osdev, GPIO_DATA) | 0x80) & ~0x02, GPIO_DATA); + break; + + } + break; + + case 7: + /* muting for Xonar ST/STX on PCM1796 */ + if (value) + { + i2c_write (devc, XONAR_ST_FRONTDAC, 18, 0x01|0x30|0x80); + devc->mute=1; + } + else + { + i2c_write (devc, XONAR_ST_FRONTDAC, 18, 0x00|0x30|0x80); + devc->mute=0; + } + break; + + default: + return OSS_EINVAL; + break; + } + return (value); + } + return OSS_EINVAL; +} + + +/********************SPDIFOUT Control *************************/ +int +spdifout_ctl (int dev, int ctrl, unsigned int cmd, int value) +{ + int tmp = 0; + cmi8788_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case SPDIFOUT_ENABLE: /* SPDIF OUT */ + value = (INL (devc->osdev, SPDIF_FUNC) & 0x2) ? 1 : 0; + break; + + case SPDIFOUT_PRO: /* Consumer/PRO */ + value = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0x1) ? 1 : 0; + break; + + case SPDIFOUT_AUDIO: /* PCM/AC3 */ + value = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0x2) ? 1 : 0; + break; + + case SPDIFOUT_COPY: /* Copy Prot */ + value = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0x4) ? 1 : 0; + break; + + case SPDIFOUT_PREEMPH: /* Pre emphasis */ + value = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0x8) ? 1 : 0; + break; + + case SPDIFOUT_RATE: /* Sampling Rate */ + tmp = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0xf000); + switch (tmp) + { + case 0x0000: /* 44100 */ + value = 0; + break; + case 0x2000: /* 48000 */ + value = 1; + break; + case 0x3000: /* 32000 */ + value = 2; + break; + case 0x8000: /* 88200 */ + value = 3; + break; + case 0xA000: /* 96000 */ + value = 4; + break; + case 0xB000: /* 64000 */ + value = 5; + break; + case 0xC000: /* 176400 */ + value = 6; + break; + case 0xE000: /* 192000 */ + value = 7; + break; + default: + cmn_err (CE_WARN, "unsupported SPDIF F/S rate\n"); + break; + } + break; + + case SPDIFOUT_VBIT: /* V Bit */ + value = (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & 0x10000) ? 1 : 0; + break; + + case SPDIFOUT_ADC: /* Analog In to SPDIF Out */ + value = (INW (devc->osdev, PLAY_ROUTING) & 0x80) ? 1 : 0; + break; + + default: + break; + } + + return value; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case SPDIFOUT_ENABLE: /* Enable SPDIF OUT */ + if (value) + OUTL (devc->osdev, INL (devc->osdev, SPDIF_FUNC) | 0x2, + SPDIF_FUNC); + else + OUTL (devc->osdev, INL (devc->osdev, SPDIF_FUNC) & ~0x2, + SPDIF_FUNC); + break; + + case SPDIFOUT_PRO: /* consumer/pro audio */ + if (value) + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) | 0x1, + SPDIFOUT_CHAN_STAT); + else + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x1, + SPDIFOUT_CHAN_STAT); + break; + + case SPDIFOUT_AUDIO: /* PCM/AC3 */ + if (value) + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) | 0x2, + SPDIFOUT_CHAN_STAT); + else + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x2, + SPDIFOUT_CHAN_STAT); + break; + + case SPDIFOUT_COPY: /* copy prot */ + if (value) + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) | 0x4, + SPDIFOUT_CHAN_STAT); + else + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x4, + SPDIFOUT_CHAN_STAT); + break; + + case SPDIFOUT_PREEMPH: /* preemphasis */ + if (value) + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) | 0x8, + SPDIFOUT_CHAN_STAT); + else + OUTL (devc->osdev, INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x8, + SPDIFOUT_CHAN_STAT); + break; + + case SPDIFOUT_RATE: /* Frequency */ + switch (value) + { + case 0: /* 44100 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | 0x0, + SPDIFOUT_CHAN_STAT); + break; + case 1: /* 48000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0x2000, SPDIFOUT_CHAN_STAT); + break; + case 2: /* 32000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0x3000, SPDIFOUT_CHAN_STAT); + break; + case 3: /* 88000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0x8000, SPDIFOUT_CHAN_STAT); + break; + case 4: /* 96000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0xA000, SPDIFOUT_CHAN_STAT); + break; + case 5: /* 64000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0xB000, SPDIFOUT_CHAN_STAT); + break; + case 6: /* 176400 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0xC000, SPDIFOUT_CHAN_STAT); + break; + case 7: /* 192000 */ + OUTL (devc->osdev, + (INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0xF0000) | + 0xE000, SPDIFOUT_CHAN_STAT); + break; + + default: + break; + } + break; + + case SPDIFOUT_VBIT: /* V Bit */ + if (value) + OUTL (devc->osdev, + INL (devc->osdev, SPDIFOUT_CHAN_STAT) | 0x10000, + SPDIFOUT_CHAN_STAT); + else + OUTL (devc->osdev, + INL (devc->osdev, SPDIFOUT_CHAN_STAT) & ~0x10000, + SPDIFOUT_CHAN_STAT); + break; + + case SPDIFOUT_ADC: /* Analog In to SPDIF Out */ + if (value) + OUTW (devc->osdev, INW (devc->osdev, PLAY_ROUTING) | 0xA0, + PLAY_ROUTING); + else + OUTW (devc->osdev, INW (devc->osdev, PLAY_ROUTING) & ~0xE0, + PLAY_ROUTING); + break; + + default: + break; + } + + return (value); + } + + return OSS_EINVAL; +} + +static int +cmi8788_mix_init (int dev) +{ + int group, parent, ctl; + cmi8788_devc *devc = mixer_devs[dev]->hw_devc; + + if ((parent = mixer_ext_create_group (dev, 0, "EXT")) < 0) + return parent; + +/* CREATE MONITOR */ + if ((group = mixer_ext_create_group (dev, parent, "MONITOR")) < 0) + return group; + + if ((ctl = + mixer_ext_create_control (dev, group, 0, cmi8788_ext, + MIXT_ONOFF, "ANALOG", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, 1, cmi8788_ext, + MIXT_ONOFF, "SPDIF", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, 2, cmi8788_ext, MIXT_ENUM, + "INPUTSRC", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "Line Mic", 0); + +/* Create PLAYBACK ROUTING */ + if ((group = mixer_ext_create_group (dev, parent, "ROUTING")) < 0) + return group; + + if ((ctl = + mixer_ext_create_control (dev, group, 3, cmi8788_ext, + MIXT_ONOFF, "SPREAD", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, 4, cmi8788_ext, + MIXT_ONOFF, "SPDIF-LOOPBACK", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if (devc->model == SUBID_XONAR_D2 || devc->model == SUBID_XONAR_D2X) + if ((ctl = mixer_ext_create_control (dev, group, 5, cmi8788_ext, + MIXT_ONOFF, "PCM-LOOPBACK", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if (devc->model == SUBID_XONAR_STX || devc->model == SUBID_XONAR_ST) + + { + if ((ctl = + mixer_ext_create_control (dev, group, 6, cmi8788_ext, MIXT_ENUM, + "OUTPUTSRC", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "Speaker Headphone FrontHeadphone", 0); + + + if ((ctl = + mixer_ext_create_control (dev, group, 7, cmi8788_ext, + MIXT_ONOFF, "MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + } + +/* Create SPDIF OUTPUT */ + if ((group = mixer_ext_create_group (dev, 0, "SPDIF-OUT")) < 0) + return group; + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_ENABLE, + spdifout_ctl, MIXT_ONOFF, + "SPDOUT_ENABLE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_ADC, + spdifout_ctl, MIXT_ONOFF, + "SPDOUT_ADC/DAC", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_PRO, + spdifout_ctl, MIXT_ENUM, + "SPDOUT_Pro", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "Consumer Professional", 0); + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_AUDIO, + spdifout_ctl, MIXT_ENUM, + "SPDOUT_Audio", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "Audio Data", 0); + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_COPY, + spdifout_ctl, MIXT_ONOFF, + "SPDOUT_Copy", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_PREEMPH, + spdifout_ctl, MIXT_ONOFF, + "SPDOUT_Pre-emph", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_RATE, + spdifout_ctl, MIXT_ENUM, + "SPDOUT_Rate", 8, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + mixer_ext_set_strings (dev, ctl, + "44.1KHz 48KHz 32KHz 88.2KHz 96KHz 64KHz 176.4KHz 192KHz", + 0); + + if ((ctl = + mixer_ext_create_control (dev, group, SPDIFOUT_VBIT, + spdifout_ctl, MIXT_ONOFF, + "SPDOUT_VBit", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + return 0; +} + + +static void +ac97_hwinit(cmi8788_devc *devc) +{ + + /* Gpio #0 programmed as output, set CMI9780 Reg0x70 */ + ac97_write(devc, 0x70, 0x100); + + /* LI2LI,MIC2MIC; let them always on, FOE on, ROE/BKOE/CBOE off */ + ac97_write(devc, 0x62, 0x180F); + + /* change PCBeep path, set Mix2FR on, option for quality issue */ + ac97_write(devc, 0x64, 0x8043); +#if 0 + /* unmute Master Volume */ + ac97_write(devc, 0x02, 0x0); + + + /* mute PCBeep, option for quality issues */ + ac97_write(devc, 0x0A, 0x8000); + + /* Record Select Control Register (Index 1Ah) */ + ac97_write(devc, 0x1A, 0x0000); + + /* set Mic Volume Register 0x0Eh umute and enable micboost */ + ac97_write(devc, 0x0E, 0x0848); + + /* set Line in Volume Register 0x10h mute */ + ac97_write(devc, 0x10, 0x8808); + + /* set CD Volume Register 0x12h mute */ + ac97_write(devc, 0x12, 0x8808); + + /* set AUX Volume Register 0x16h max */ + ac97_write(devc, 0x16, 0x0808); + + /* set record gain Register 0x1Ch to max */ + ac97_write(devc, 0x1C, 0x0F0F); +#endif + ac97_write(devc, 0x71, 0x0001); +} + +static int +init_cmi8788 (cmi8788_devc * devc) +{ + unsigned short sVal; + unsigned short sDac; + unsigned char bVal; + int i, first_dev = -1, count; + int default_vol; +/* + * Init CMI Controller + */ + sVal = INW (devc->osdev, CTRL_VERSION); + if (!(sVal & 0x0008)) + { + bVal = INB (devc->osdev, MISC_REG); + bVal |= 0x20; + OUTB (devc->osdev, bVal, MISC_REG); + } + + bVal = INB (devc->osdev, FUNCTION); + bVal |= 0x02; /* Reset codec*/ + OUTB(devc->osdev, bVal, FUNCTION); + + + /* I2S to 16bit, see below. */ + sDac = 0x010A; + + /* Non-generic DAC initialization */ + switch(devc->model) + { + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_D2: + case SUBID_XONAR_D2X: + case SUBID_XONAR_STX: + case SUBID_XONAR_DS: + /* Must set master clock. */ + sDac |= XONAR_MCLOCK_256; + break; + case SUBID_XONAR_ST: + sDac |= XONAR_MCLOCK_512; + } + + /* Setup I2S to use 16bit instead of 24Bit */ + OUTW (devc->osdev, sDac, I2S_MULTICH_FORMAT); + OUTW (devc->osdev, sDac, I2S_ADC1_FORMAT); + OUTW (devc->osdev, sDac, I2S_ADC2_FORMAT); + OUTW (devc->osdev, sDac, I2S_ADC3_FORMAT); + + /* setup Routing regs (default vals) */ + OUTW (devc->osdev, 0xE400, PLAY_ROUTING); + OUTB (devc->osdev, 0x00, REC_ROUTING); + OUTB (devc->osdev, 0x00, REC_MONITOR); + OUTB (devc->osdev, 0xE4, MONITOR_ROUTING); + + + /* install the CMI8788 mixer */ + if ((devc->cmi_mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "CMedia CMI8788", + &cmi8788_mixer_driver, + sizeof (mixer_driver_t), + devc)) < 0) + { + return 0; + } + + mixer_devs[devc->cmi_mixer_dev]->hw_devc = devc; + mixer_devs[devc->cmi_mixer_dev]->priority = 10; /* Possible default mixer candidate */ + mixer_ext_set_init_fn (devc->cmi_mixer_dev, cmi8788_mix_init, 25); + + /* Cold reset onboard AC97 */ + OUTW (devc->osdev, 0x1, AC97_CTRL); + count = 100; + while ((INW (devc->osdev, AC97_CTRL) & 0x2) && (count--)) + { + OUTW (devc->osdev, (INW (devc->osdev, AC97_CTRL) & ~0x2) | 0x2, + AC97_CTRL); + oss_udelay (100); + } + if (!count) + cmn_err (CE_WARN, "CMI8788 AC97 not ready\n"); + + + sVal = INW (devc->osdev, AC97_CTRL); + + devc->ac97_mixer_dev = devc->fp_mixer_dev = -1; + + /* check if there's an onboard AC97 codec (CODEC 0) and install the mixer */ + if (sVal & 0x10) + { + /* disable CODEC0 OUTPUT */ + OUTW (devc->osdev, 0, /* INW (devc->osdev, AC97_OUT_CHAN_CONFIG) & ~0xFF00,*/ + AC97_OUT_CHAN_CONFIG); + + /* enable CODEC0 INPUT */ + OUTW (devc->osdev, 0, /* INW (devc->osdev, AC97_IN_CHAN_CONFIG) | 0x0300,*/ + AC97_IN_CHAN_CONFIG); + + devc->ac97_mixer_dev = + ac97_install (&devc->ac97devc, "AC97 Input Mixer", ac97_read, + ac97_write, devc, devc->osdev); + } + + /* check if there's an front panel AC97 codec (CODEC1) and install the mixer */ + if (sVal & 0x20) + { + /* enable CODEC1 OUTPUT */ + OUTW (devc->osdev, INW (devc->osdev, AC97_OUT_CHAN_CONFIG) | 0x0033, + AC97_OUT_CHAN_CONFIG); + /* enable CODEC1 INPUT */ + OUTW (devc->osdev, INW (devc->osdev, AC97_IN_CHAN_CONFIG) | 0x0033, + AC97_IN_CHAN_CONFIG); + + devc->fp_mixer_dev = + ac97_install (&devc->fp_ac97devc, "AC97 Mixer (Front Panel)", + fp_ac97_read, fp_ac97_write, devc, devc->osdev); + + if (devc->fp_mixer_dev >= 0) + { + /* enable S/PDIF */ + devc->fp_ac97devc.spdif_slot = SPDIF_SLOT34; + ac97_spdifout_ctl (devc->fp_mixer_dev, SPDIFOUT_ENABLE, + SNDCTL_MIX_WRITE, 1); + } + } + + + + switch(devc->model) { + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + /*GPIO8 = 0x100 controls mic/line-in */ + /*GPIO0 = 0x001controls output */ + /*GPIO2/3 = 0x00C codec output control*/ + + /* setup for i2c communication mode */ + OUTB(devc->osdev, INB (devc->osdev, FUNCTION) | 0x40, FUNCTION); + /* setup GPIO direction */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x010D, GPIO_CONTROL); + /* setup GPIO pins */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x0101, GPIO_DATA); + + /* init the front and rear dacs */ + cs4398_init(devc, XONAR_DX_FRONTDAC); + cs4362a_init(devc, XONAR_DX_SURRDAC); + /* initialize the codec 0 */ + ac97_hwinit(devc); + break; + + + case SUBID_XONAR_D2: + case SUBID_XONAR_D2X: + /*GPIO7 = 0x0080 controls mic/line-in */ + /*GPIO8 = 0x0100 controls output */ + /*GPIO2/3 = 0x000C codec output control*/ + + /* setup for spi communication mode */ + OUTB(devc->osdev, (INB (devc->osdev, FUNCTION) & ~0x40) | 0x80, FUNCTION); + /* setup the GPIO direction */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x018C, GPIO_CONTROL); + /* setup GPIO Pins */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x0100, GPIO_DATA); + + /* for all 4 codecs: unmute, set to 24Bit SPI */ + for (i = 0; i < 4; ++i) { + spi_write(devc, xd2_codec_map[i], 16, mix_scale(75,8)); /* left vol*/ + spi_write(devc, xd2_codec_map[i], 17, mix_scale(75,8)); /* right vol */ + spi_write(devc, xd2_codec_map[i], 18, 0x00| 0x30 | 0x80); /* unmute/24LSB/ATLD */ + } + /* initialize the codec 0 */ + ac97_hwinit(devc); + break; + + case SUBID_XONAR_STX: + /*GPIO0 = Antipop control */ + /*GPIO1 = frontpanel h/p control*/ + /*GPIO7 = 0x0080 controls analog out*/ + /*GPIO8 = 0x0100 controls mic/line in*/ + /*GPIO2/3 = 0x000C codec input control*/ + + /* setup for i2c communication mode */ + OUTB(devc->osdev, INB (devc->osdev, FUNCTION) | 0x40, FUNCTION); + + /* setup the GPIO direction control register */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x018F, GPIO_CONTROL); + /* setup GPIO pins mic/output */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x111, GPIO_DATA); + + OUTW(devc->osdev, INW(devc->osdev, I2C_CTRL)|0x0100, I2C_CTRL); + + /* initialize the PCM1796 DAC */ + i2c_write(devc, XONAR_STX_FRONTDAC, 20, 0x40); /*OS_64*/ + i2c_write(devc, XONAR_STX_FRONTDAC, 20, 0); /*OS_64*/ + i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(75,8)); + i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(75,8)); + i2c_write(devc, XONAR_STX_FRONTDAC, 18, 0x00|0x30|0x80); /*unmute, 24LSB, ATLD */ + i2c_write(devc, XONAR_STX_FRONTDAC, 19, 0); /*ATS1/FLT_SHARP*/ + + /* initialize the codec 0 */ + ac97_hwinit(devc); + break; + + case SUBID_XONAR_ST: + /*GPIO0 = enable output*/ + /*GPIO1 = frontpanel h/p control*/ + /*GPIO7 = 0x0080 controls analog out line/HP*/ + /*GPIO8 = 0x0100 controls mic/line in*/ + /*GPIO2/3 = 0x000C codec input control*/ + + /* setup for i2c communication mode */ + OUTB(devc->osdev, INB (devc->osdev, FUNCTION) | 0x40, FUNCTION); + + /* setup the GPIO direction control register */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x01FF, GPIO_CONTROL); + /* setup GPIO pins mic/output */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x101, GPIO_DATA); + OUTW(devc->osdev, INW(devc->osdev, I2C_CTRL)|0x0100, I2C_CTRL); + /* initialize the CS2000 clock chip */ + cs2000_init (devc, XONAR_ST_CLOCK); + + /* initialize the PCM1796 DAC */ + i2c_write(devc, XONAR_ST_FRONTDAC, 20, 0); /*normal*/ + i2c_write(devc, XONAR_ST_FRONTDAC, 18, 0x00|0x30|0x80); /*unmute, 24LSB, ATLD */ + i2c_write(devc, XONAR_ST_FRONTDAC, 16, mix_scale(75,8)); + i2c_write(devc, XONAR_ST_FRONTDAC, 17, mix_scale(75,8)); + i2c_write(devc, XONAR_ST_FRONTDAC, 19, 0); /*ATS1/FLT_SHARP*/ + + /* initialize the codec 0 */ + ac97_hwinit(devc); + + break; + + case SUBID_XONAR_DS: + /* GPIO 8 = 1 output enabled 0 mute */ + /* GPIO 7 = 1 lineout enabled 0 mute */ + /* GPIO 6 = 1 mic select 0 line-in select */ + /* GPIO 4 = 1 FP Headphone plugged in */ + /* GPIO 3 = 1 FP Mic plugged in */ + + /* setup for spi communication mode */ + OUTB(devc->osdev, (INB (devc->osdev, FUNCTION) & ~0x40)|0x32, FUNCTION); + /* setup the GPIO direction */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x1D0, GPIO_CONTROL); + /* setup GPIO Pins */ + OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x1D0, GPIO_DATA); + + spi_write(devc, XONAR_DS_FRONTDAC, 0x17, 0x1); /* reset */ + spi_write(devc, XONAR_DS_FRONTDAC, 0x7, 0x90); /* dac control */ + spi_write(devc, XONAR_DS_FRONTDAC, 0x8, 0); /* unmute */ + spi_write(devc, XONAR_DS_FRONTDAC, 0xC, 0x22 ); /* powerdown hp */ + spi_write(devc, XONAR_DS_FRONTDAC, 0xD, 0x8); /* powerdown hp */ + spi_write(devc, XONAR_DS_FRONTDAC, 0xA, 0x1); /* LJust/16bit*/ + spi_write(devc, XONAR_DS_FRONTDAC, 0xB, 0x1); /* LJust/16bit*/ + + spi_write(devc, XONAR_DS_SURRDAC, 0x1f, 1); /* reset */ + spi_write(devc, XONAR_DS_SURRDAC, 0x3, 0x1|0x20); /* LJust/24bit*/ + break; + + default: + /* SPI default for anything else, including the */ + OUTB(devc->osdev, (INB (devc->osdev, FUNCTION) & ~0x40) | 0x80, FUNCTION); + break; + } + + /* check if MPU401 is enabled in MISC register */ + if (INB (devc->osdev, MISC_REG) & 0x40) + attach_mpu (devc); + + for (i = 0; i < MAX_PORTC; i++) + { + char tmp_name[100]; + cmi8788_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + int fmt = AFMT_S16_LE; + + switch (i) + { + case 0: + sprintf (tmp_name, "%s (MultiChannel)", devc->chip_name); + caps |= ADEV_DUPLEX; + fmt |= AFMT_S32_LE; + portc->dac_type = ADEV_MULTICH; + switch(devc->model) + { + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_D2: + case SUBID_XONAR_D2X: + case SUBID_XONAR_STX: + case SUBID_XONAR_ST: + portc->adc_type = ADEV_I2SADC2; + break; + case SUBID_XONAR_DS: + portc->adc_type = ADEV_I2SADC1; + break; + default: + portc->adc_type = ADEV_I2SADC1; + OUTB (devc->osdev, INB (devc->osdev, REC_ROUTING) | 0x18, REC_ROUTING); + break; + } + + portc->min_rate = 32000; + portc->max_rate = 192000; + portc->min_chan = 2; + portc->max_chan = 8; + break; + + case 1: + sprintf (tmp_name, "%s (Multichannel)", devc->chip_name); + caps |= ADEV_DUPLEX | ADEV_SHADOW; + fmt |= AFMT_S32_LE; + portc->dac_type = ADEV_MULTICH; + switch(devc->model) + { + case SUBID_XONAR_D1: + case SUBID_XONAR_DX: + case SUBID_XONAR_D2: + case SUBID_XONAR_D2X: + case SUBID_XONAR_STX: + case SUBID_XONAR_ST: + portc->adc_type = ADEV_I2SADC2; + break; + case SUBID_XONAR_DS: + portc->adc_type = ADEV_I2SADC1; + break; + default: + portc->adc_type = ADEV_I2SADC1; + OUTB (devc->osdev, INB (devc->osdev, REC_ROUTING) | 0x18, REC_ROUTING); + break; + } + + portc->min_rate = 32000; + portc->max_rate = 192000; + portc->min_chan = 2; + portc->max_chan = 8; + break; + + case 2: + /* if there is no front panel AC97, then skip the device */ + if (devc->fp_mixer_dev == -1) + continue; + + sprintf (tmp_name, "%s (Front Panel)", devc->chip_name); + caps |= + ADEV_DUPLEX | ADEV_16BITONLY | ADEV_STEREOONLY | ADEV_SPECIAL; + fmt |= AFMT_AC3; + portc->dac_type = ADEV_FRONTPANEL; + portc->adc_type = ADEV_I2SADC2; + OUTB (devc->osdev, INB (devc->osdev, REC_ROUTING) | 0x18, REC_ROUTING); + portc->min_rate = 8000; + portc->max_rate = 48000; + portc->min_chan = 2; + portc->max_chan = 2; + break; + + case 3: + sprintf (tmp_name, "%s (SPDIF)", devc->chip_name); + caps |= ADEV_DUPLEX | ADEV_STEREOONLY | ADEV_SPECIAL; + fmt |= AFMT_AC3 | AFMT_S32_LE; + portc->dac_type = ADEV_SPDIF; + portc->adc_type = ADEV_I2SADC3; + portc->min_rate = 32000; + portc->max_rate = 192000; + portc->min_chan = 2; + portc->max_chan = 2; + break; + } + + if ((portc->audiodev = + oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, devc->osdev, + devc->osdev, tmp_name, + &cmi8788_audio_driver, + sizeof (audiodrv_t), caps, fmt, + devc, -1)) < 0) + { + return 0; + } + else + { + if (first_dev == -1) + first_dev = portc->audiodev; + audio_engines[portc->audiodev]->portc = portc; + audio_engines[portc->audiodev]->rate_source = first_dev; + if (caps & ADEV_FIXEDRATE) + { + audio_engines[portc->audiodev]->min_rate = 48000; + audio_engines[portc->audiodev]->max_rate = 48000; + audio_engines[portc->audiodev]->fixed_rate = 48000; + } + audio_engines[portc->audiodev]->min_rate = portc->min_rate; + audio_engines[portc->audiodev]->max_rate = portc->max_rate; + + audio_engines[portc->audiodev]->caps |= DSP_CAP_FREERATE; + audio_engines[portc->audiodev]->min_channels = portc->min_chan; + audio_engines[portc->audiodev]->max_channels = portc->max_chan; + portc->open_mode = 0; + portc->audio_enabled = 0; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, portc->audiodev, -1, 0); +#endif + } + } + + /* + * Setup the default volumes to 90% + */ + + devc->mute = 0; + + default_vol = mix_scale(90,8)<<8|mix_scale(90,8); + + devc->playvol[0] = + cmi8788_mixer_ioctl (devc->cmi_mixer_dev, first_dev, + MIXER_WRITE (SOUND_MIXER_PCM), &default_vol); + devc->playvol[1] = + cmi8788_mixer_ioctl (devc->cmi_mixer_dev, first_dev, + MIXER_WRITE (SOUND_MIXER_REARVOL), &default_vol); + devc->playvol[2] = + cmi8788_mixer_ioctl (devc->cmi_mixer_dev, first_dev, + MIXER_WRITE (SOUND_MIXER_CENTERVOL), &default_vol); + devc->playvol[3] = + cmi8788_mixer_ioctl (devc->cmi_mixer_dev, first_dev, + MIXER_WRITE (SOUND_MIXER_SIDEVOL), &default_vol); + + return 1; +} + +int +oss_cmi878x_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + unsigned short sub_vendor, sub_id; + int err; + cmi8788_devc *devc; + + DDB (cmn_err (CE_CONT, "Entered CMEDIA CMI8788 attach routine\n")); + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &sub_vendor); + pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &sub_id); + + if (vendor != CMEDIA_VENDOR_ID || device != CMEDIA_CMI8788) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + DDB (cmn_err (CE_WARN, "CMI8788 I/O base %04x\n", 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->irq = pci_irq_line; + + /* Map the IO Base address */ + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + + /* Remove I/O space marker in bit 0. */ + devc->base &= ~3; + + /* set the PCI_COMMAND register to master mode */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if (device == CMEDIA_CMI8788) + { + /* Detect Xonar device */ + if(sub_vendor == ASUS_VENDOR_ID) + { + switch(sub_id) + { + case SUBID_XONAR_D1: + devc->chip_name = "Asus Xonar D1 (AV100)"; + break; + case SUBID_XONAR_DX: + devc->chip_name = "Asus Xonar DX (AV100)"; + break; + case SUBID_XONAR_D2: + devc->chip_name = "Asus Xonar D2 (AV200)"; + break; + case SUBID_XONAR_D2X: + devc->chip_name = "Asus Xonar D2X (AV200)"; + break; + case SUBID_XONAR_STX: + devc->chip_name = "Asus Xonar Essence STX (AV100)"; + break; + case SUBID_XONAR_ST: + devc->chip_name = "Asus Xonar Essence ST (AV100)"; + break; + case SUBID_XONAR_DS: + devc->chip_name = "Asus Xonar DS (AV66)"; + break; + default: + devc->chip_name = "Asus Xonar (unknown)"; + sub_id = SUBID_GENERIC; + break; + } + devc->model = sub_id; + } + else + { + /* If not one of the above, regular. */ + devc->model = MDL_CMI8788; + devc->chip_name = "CMedia CMI8788"; + } + } + else + { + cmn_err (CE_WARN, "Unknown CMI8788 model\n"); + return 0; + } + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + MUTEX_INIT (devc->osdev, devc->dac_mutex, MH_DRV + 2); + + oss_register_device (osdev, devc->chip_name); + + if ((err = oss_register_interrupts (devc->osdev, 0, cmi8788intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err); + return 0; + } + + return init_cmi8788 (devc); /* Detected */ +} + +int +oss_cmi878x_detach (oss_device_t * osdev) +{ + cmi8788_devc *devc = (cmi8788_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + if (devc->mpu_attached) + unload_cmi8788uart (devc); + + oss_unregister_interrupts (devc->osdev); + + UNMAP_PCI_IOADDR (devc->osdev, 0); + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + MUTEX_CLEANUP (devc->dac_mutex); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_cmi878x/oss_cmi878x.man b/kernel/drv/oss_cmi878x/oss_cmi878x.man new file mode 100644 index 0000000..316d4c4 --- /dev/null +++ b/kernel/drv/oss_cmi878x/oss_cmi878x.man @@ -0,0 +1,54 @@ +NAME +oss_cmi878x - CMedia CMI8788 audio driver. + +DESCRIPTION +Open Sound System driver for CMedia Electronics CMI8788 audio + +CMI87xx device characteristics: + o 8/16/24/32 bit playback/record + o mono/stereo/4ch/5.1/7.1 playback + o 8KHz to 192Khz sample rate. + +The CMedia 8788 device provides 3 types of devices. The first devices is +a Multichannel full duplex device. The second device provides Front Panel +audio access and the SPDIF device provide SPDIF (Digital) audio I/O. + + MIXER PANEL +The CMedia chip provides some unique features that are set up +by the Mixer chip. There are 3 mixer devices presented to the user. + +Main Mixer Panel (/dev/mixer0) + +o Master Mixer panel is for controlling output volumes for each of the 8 +channels. + +o Monitor buttons will allow you to monitor the input from the Rear Panel +inputs, Front Panel Inputs and SPDIF IN. + +o Speaker-Spread function duplicates the front channel output on all 8 +speakers. + +o SPDIF Loopback simply takes SPDIF Input and Plays it out the SPDIF Output. +panel. + + +AC97 Input Mixer Panel (/dev/mixer1) +This mixer panel is used to switch between the various inputs like line-in, +mic, cd. When the Rear Panel Monitor button is check marked in the Main +mixer panel, the IGAIN slider in this panel controls the level of the input +that can be hear on the speakers. + + +AC97 Front Panel Mixer (/dev/mixer2) +This mixer controls the front panel ac97 device. It can be used to control +all the volumes and inputs as well as SPDIF output on the front panel device. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_cmi878x.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_cmpci/.devices b/kernel/drv/oss_cmpci/.devices new file mode 100644 index 0000000..9933503 --- /dev/null +++ b/kernel/drv/oss_cmpci/.devices @@ -0,0 +1,5 @@ +oss_cmpci pci13f6,100 C-Media CM8338A +oss_cmpci pci13f6,100 MIDIMan DiO 2448 +oss_cmpci pci13f6,101 CMedia CM8338B +oss_cmpci pci13f6,111 CMedia CM8738/CM8768 +oss_cmpci pci14af,20 Guillemot Maxi Sound MUSE diff --git a/kernel/drv/oss_cmpci/.name b/kernel/drv/oss_cmpci/.name new file mode 100644 index 0000000..0d987dc --- /dev/null +++ b/kernel/drv/oss_cmpci/.name @@ -0,0 +1 @@ +C-Media CM833x audio chipset diff --git a/kernel/drv/oss_cmpci/oss_cmpci.c b/kernel/drv/oss_cmpci/oss_cmpci.c new file mode 100644 index 0000000..50ccf84 --- /dev/null +++ b/kernel/drv/oss_cmpci/oss_cmpci.c @@ -0,0 +1,2379 @@ +/* + * Purpose: Driver for CMEDIA CM8738 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_cmpci_cfg.h" +#include "oss_pci.h" +#include "uart401.h" + +#define CMEDIA_VENDOR_ID 0x13F6 +#define CMEDIA_CM8738 0x0111 +#define CMEDIA_CM8338A 0x0100 +#define CMEDIA_CM8338B 0x0101 +/* + * CM8338 registers definition + */ + +#define FUNCTRL0 (devc->base+0x00) +#define FUNCTRL1 (devc->base+0x04) +#define CHFORMAT (devc->base+0x08) +#define INT_HLDCLR (devc->base+0x0C) +#define INT_STATUS (devc->base+0x10) +#define LEGACY_CTRL (devc->base+0x14) +#define MISC_CTRL (devc->base+0x18) +#define TDMA_POS (devc->base+0x1C) +#define MIXER (devc->base+0x20) +#define MIXER_DATA (devc->base+0x22) +#define MIXER_ADDR (devc->base+0x23) +#define MIXER1 (devc->base+0x24) +#define MIXER2 (devc->base+0x25) +#define AUX_VOL (devc->base+0x26) +#define MIXER3 (devc->base+0x27) +#define AC97 (devc->base+0x28) + +#define CH0_FRAME1 (devc->base+0x80) +#define CH0_FRAME2 (devc->base+0x84) +#define CH1_FRAME1 (devc->base+0x88) +#define CH1_FRAME2 (devc->base+0x8C) + +#define SPDIF_STAT (devc->base+0x90) +#define MISC2_CTRL (devc->base+0x92) + +#define MPU_MIRROR (devc->base+0x40) +#define FM_MIRROR (devc->base+0x50) +#define JOY_MIRROR (devc->base+0x60) + +#define DSP_MIX_DATARESETIDX (0x00) +#define DSP_MIX_OUTMIXIDX (0x3c) +#define CM_CH0_ENABLE 0x01 +#define CM_CH1_ENABLE 0x02 +#define CM_CH0_RESET 0x04 +#define CM_CH1_RESET 0x08 +#define CM_CH0_RECORD 0x01 +#define CM_CH1_RECORD 0x02 +#define CM_CH0_PLAY ~0x01 +#define CM_CH1_PLAY ~0x02 +#define CM_CH0_INT 1 +#define CM_CH1_INT 2 +#define CM_EXTENT_CODEC 0x100 +#define CM_EXTENT_MIDI 0x2 +#define CM_EXTENT_SYNTH 0x4 +#define CM_CFMT_STEREO 0x01 +#define CM_CFMT_16BIT 0x02 +#define CM_CFMT_MASK 0x03 +#define CM_CFMT_DACSHIFT 0 +#define CM_CFMT_ADCSHIFT 2 + +#define MUTE_LINE 1 +#define MUTE_CD 2 +#define MUTE_MIC 3 +#define MUTE_AUX 4 +#define REAR2LINE 5 +#define CEN2LINE 6 +#define BASS2LINE 7 +#define CEN2MIC 8 +#define MODE_4SPK 9 +#define DUALDAC 10 +#define MICBOOST 11 +#define SPDIF_PLAY 12 +#define SPDIF_LOOP 13 +#define SPDIF_REC 14 +#define SPDIF_IMON 15 +#define SPDIF_POL 16 +#define SPDIF_COPY 17 +#define SPDIF_OPT 18 +#define SPDIF_AC3 19 +#define AUX_REC 20 +#define AUX_LEVEL 21 + +#define CHAN0 0x1 +#define CHAN1 0x2 + +static struct +{ + unsigned int rate; + unsigned int lower; + unsigned int upper; + unsigned char freq; +} +rate_lookup[] = +{ + { + 5512, (0 + 5512) / 2, (5512 + 8000) / 2, 0} + , + { + 8000, (5512 + 8000) / 2, (8000 + 11025) / 2, 4} + , + { + 11025, (8000 + 11025) / 2, (11025 + 16000) / 2, 1} + , + { + 16000, (11025 + 16000) / 2, (16000 + 22050) / 2, 5} + , + { + 22050, (16000 + 22050) / 2, (22050 + 32000) / 2, 2} + , + { + 32000, (22050 + 32000) / 2, (32000 + 44100) / 2, 6} + , + { + 44100, (32000 + 44100) / 2, (44100 + 48000) / 2, 3} + , + { + 48000, (48000 + 44100) / 2, (48000 + 96000) / 2, 7} +}; + +static unsigned char cmpci_recmasks_L[SOUND_MIXER_NRDEVICES] = { + 0x00, /* SOUND_MIXER_VOLUME */ + 0x00, /* SOUND_MIXER_BASS */ + 0x00, /* SOUND_MIXER_TREBLE */ + 0x40, /* SOUND_MIXER_SYNTH */ + 0x00, /* SOUND_MIXER_PCM */ + 0x00, /* SOUND_MIXER_SPEAKER */ + 0x10, /* SOUND_MIXER_LINE */ + 0x01, /* SOUND_MIXER_MIC */ + 0x04, /* SOUND_MIXER_CD */ + 0x00, /* SOUND_MIXER_IMIX */ + 0x00, /* SOUND_MIXER_LINE1 */ + 0x00, /* SOUND_MIXER_RECLEV */ + 0x00, /* SOUND_MIXER_IGAIN */ + 0x00 /* SOUND_MIXER_OGAIN */ +}; + +static unsigned char cmpci_recmasks_R[SOUND_MIXER_NRDEVICES] = { + 0x00, /* SOUND_MIXER_VOLUME */ + 0x00, /* SOUND_MIXER_BASS */ + 0x00, /* SOUND_MIXER_TREBLE */ + 0x20, /* SOUND_MIXER_SYNTH */ + 0x00, /* SOUND_MIXER_PCM */ + 0x00, /* SOUND_MIXER_SPEAKER */ + 0x08, /* SOUND_MIXER_LINE */ + 0x01, /* SOUND_MIXER_MIC */ + 0x02, /* SOUND_MIXER_CD */ + 0x00, /* SOUND_MIXER_IMIX */ + 0x00, /* SOUND_MIXER_LINE1 */ + 0x00, /* SOUND_MIXER_RECLEV */ + 0x00, /* SOUND_MIXER_IGAIN */ + 0x00 /* SOUND_MIXER_OGAIN */ +}; + +#define CMEDIA_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \ + SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_LINE1) + +#define CMEDIA_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | \ + SOUND_MASK_LINE | SOUND_MASK_MIC | \ + SOUND_MASK_IGAIN | SOUND_MASK_CD | \ + SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER |\ + SOUND_MASK_LINE1|SOUND_MASK_RECLEV) + +#define LEFT_CHN 0 +#define RIGHT_CHN 1 +/* + * Mixer registers of CMPCI + */ +#define CMPCI_IMASK_L 0x3d +#define CMPCI_IMASK_R 0x3e + + +int default_levels[32] = { + 0x5a5a, /* Master Volume */ + 0x4b4b, /* Bass */ + 0x4b4b, /* Treble */ + 0x4b4b, /* FM */ + 0x4b4b, /* PCM */ + 0x4b4b, /* PC Speaker */ + 0x4b4b, /* Ext Line */ + 0x2020, /* Mic */ + 0x4b4b, /* CD */ + 0x0000, /* Recording monitor */ + 0x4b4b, /* SB PCM */ + 0x4b4b, /* Recording level */ + 0x4b4b, /* Input gain */ + 0x4b4b, /* Output gain */ + 0x4040, /* Line1 */ + 0x4040, /* Line2 */ + 0x1515 /* Line3 */ +}; + +typedef struct cmpci_portc +{ + int speed, bits, channels; + int open_mode; + int trigger_bits; + int audio_enabled; + int audiodev; + int dacfmt, adcfmt; + int chan0_play, chan0_rec; + int chan1_play, chan1_rec; +} +cmpci_portc; + +#define MAX_PORTC 2 + +typedef struct cmpci_devc +{ + oss_device_t *osdev; + oss_native_word base; + int fm_attached; + int irq; + int max_channels; + volatile unsigned char intr_mask; + int model; +#define MDL_CM8738 1 +#define MDL_CM8338A 2 +#define MDL_CM8338B 3 +#define MDL_CM8768 4 + char *chip_name; + int chiprev; + int mode_4spk; + int dev_mode; +#define DEFAULT_MODE 1 +#define DUALDAC_MODE 2 +#define SPDIFIN_MODE 4 + unsigned char spdif_control_bits[24]; + /* Audio parameters */ + oss_mutex_t mutex; + oss_mutex_t low_mutex; + int open_mode; + int audio_initialized; + cmpci_portc portc[MAX_PORTC]; + + /* spdif/ac3 stuff */ + int spdif_enabled; + int can_ac3; + + /* Mixer parameters */ + int mixer_dev; + int *levels; + int recmask; + + /* uart401 */ + int uart401_attached; + uart401_devc uart401devc; +} +cmpci_devc; + + +static void +set_spdif_rate (cmpci_devc * devc, cmpci_portc * portc) +{ + if (portc->speed == 48000) + { + /* setup MISC control reg */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 24) | (1 << 15), + MISC_CTRL); + } + else + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 15), + MISC_CTRL); + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 24), + MISC_CTRL); + } +} + +static void +setup_ac3 (cmpci_devc * devc, cmpci_portc * portc, int value) +{ + if (value && (portc->speed == 48000 || portc->speed == 44100)) + { + if (devc->chiprev == 37) + { + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) | (1 << 20), + CHFORMAT); + } + else + { + /* Enable AC3 */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 18), + MISC_CTRL); + } + } + else + { + if (devc->chiprev == 37) + { + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(1 << 20), + CHFORMAT); + } + else + { + /* Disable AC3 */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 18), + MISC_CTRL); + } + } +} + + +static void +cmpci_setmixer (cmpci_devc * devc, unsigned int port, unsigned int value) +{ + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR); + oss_udelay (20); + OUTB (devc->osdev, (unsigned char) (value & 0xff), MIXER_DATA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + oss_udelay (20); +} + +static unsigned int +cmpci_getmixer (cmpci_devc * devc, unsigned int port) +{ + unsigned int val; + + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR); + + + oss_udelay (20); + val = INB (devc->osdev, MIXER_DATA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + oss_udelay (20); + return val; +} + +struct mixer_def +{ + unsigned int regno:8; + unsigned int bitoffs:4; + unsigned int nbits:4; +}; + +typedef struct mixer_def mixer_tab[32][2]; +typedef struct mixer_def mixer_ent; + +#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \ + {{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}} + +static mixer_tab cmpci_mix = { + MIX_ENT (SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5), + MIX_ENT (SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4), + MIX_ENT (SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4), + MIX_ENT (SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5), + MIX_ENT (SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5), + MIX_ENT (SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5), + MIX_ENT (SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5), + MIX_ENT (SOUND_MIXER_IMIX, 0x3c, 0, 1, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_LINE1, 0, 0, 0, 0, 0, 0), + MIX_ENT (SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), + MIX_ENT (SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2), + MIX_ENT (SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2) +}; + +/*ARGSUSED*/ +static void +change_bits (cmpci_devc * devc, unsigned char *regval, int dev, int chn, + int newval) +{ + unsigned char mask; + int shift; + + mask = (1 << cmpci_mix[dev][chn].nbits) - 1; + newval = (int) ((newval * mask) + 50) / 100; /* Scale */ + + shift = cmpci_mix[dev][chn].bitoffs - cmpci_mix[dev][LEFT_CHN].nbits + 1; + + *regval &= ~(mask << shift); /* Mask out previous value */ + *regval |= (newval & mask) << shift; /* Set the new value */ +} + +static int set_recmask (int dev, int mask); + +static int +cmpci_mixer_set (cmpci_devc * devc, int chan, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + + int regoffs; + unsigned char val; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + if (chan > 31) + return OSS_EINVAL; + + if (!(CMEDIA_MIXER_DEVICES & (1 << chan))) /* + * Not supported + */ + return OSS_EINVAL; + + regoffs = cmpci_mix[chan][LEFT_CHN].regno; + + if (regoffs == 0) + return OSS_EINVAL; + + val = cmpci_getmixer (devc, regoffs); + change_bits (devc, &val, chan, LEFT_CHN, left); + + devc->levels[chan] = left | (left << 8); + + if (cmpci_mix[chan][RIGHT_CHN].regno != regoffs) /* + * Change register + */ + { + cmpci_setmixer (devc, regoffs, val); /* + * Save the old one + */ + regoffs = cmpci_mix[chan][RIGHT_CHN].regno; + + if (regoffs == 0) + return left | (left << 8); /* + * Just left channel present + */ + + val = cmpci_getmixer (devc, regoffs); /* + * Read the new one + */ + } + + change_bits (devc, &val, chan, RIGHT_CHN, right); + + cmpci_setmixer (devc, regoffs, val); + + devc->levels[chan] = left | (right << 8); + return left | (right << 8); +} + +static int cmpci_outsw (int dev, int ctrl, unsigned int cmd, int value); + +/*ARGSUSED*/ +static int +cmpci_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + cmpci_devc *devc = mixer_devs[dev]->devc; + int val; + + if (((cmd >> 8) & 0xff) == 'M') + { + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + val = *arg; + if (val == SOUND_MASK_LINE1) + *arg = cmpci_outsw (dev, AUX_REC, SNDCTL_MIX_WRITE, 1); + else + *arg = cmpci_outsw (dev, AUX_REC, SNDCTL_MIX_WRITE, 0); + return *arg = set_recmask (dev, val); + break; + + case SOUND_MIXER_LINE1: + val = *arg; + return *arg = cmpci_outsw (dev, AUX_LEVEL, SNDCTL_MIX_WRITE, val); + break; + + default: + val = *arg; + return *arg = cmpci_mixer_set (devc, cmd & 0xff, val); + } + else + switch (cmd & 0xff) + { + + case SOUND_MIXER_RECSRC: + return *arg = devc->recmask; + break; + + case SOUND_MIXER_DEVMASK: + return *arg = CMEDIA_MIXER_DEVICES; + break; + + case SOUND_MIXER_STEREODEVS: + return *arg = CMEDIA_MIXER_DEVICES & + ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); + break; + + case SOUND_MIXER_RECMASK: + return *arg = CMEDIA_RECORDING_DEVICES; + break; + + case SOUND_MIXER_LINE1: + val = cmpci_outsw (dev, AUX_LEVEL, SNDCTL_MIX_READ, 0); + return *arg = val; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + default: + return *arg = devc->levels[cmd & 0x1f]; + } + } + else + return OSS_EINVAL; +} + +static int +set_recmask (int dev, int mask) +{ + cmpci_devc *devc = mixer_devs[dev]->devc; + int devmask = mask & CMEDIA_RECORDING_DEVICES; + int i; + unsigned char regimageL, regimageR; + + if (!devmask) + devmask = SOUND_MASK_MIC; + + regimageL = regimageR = 0; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if ((1 << i) & devmask) + { + regimageL |= cmpci_recmasks_L[i]; + regimageR |= cmpci_recmasks_R[i]; + } + cmpci_setmixer (devc, CMPCI_IMASK_L, regimageL); + cmpci_setmixer (devc, CMPCI_IMASK_R, regimageR); + devc->recmask = devmask; + return devc->recmask; +} + +static int +cmpci_outsw (int dev, int ctrl, unsigned int cmd, int value) +{ +/* + * Access function for CMPCI mixer extension bits + */ + cmpci_devc *devc = mixer_devs[dev]->devc; + int left, right, tmp; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case MUTE_LINE: /* Left line in to output connection */ + value = (cmpci_getmixer (devc, 0x3c) & 0x18) ? 0 : 1; + break; + + case MUTE_CD: /* Cd in to output connection */ + value = (cmpci_getmixer (devc, 0x3c) & 0x06) ? 0 : 1; + break; + + case MUTE_MIC: /* Mic in to output connection */ + value = (cmpci_getmixer (devc, 0x3c) & 0x01) ? 0 : 1; + break; + + case MODE_4SPK: /* 4Speaker out */ + value = INL (devc->osdev, MISC_CTRL) & (1 << 26) ? 1 : 0; + break; + + case DUALDAC: /* dual dac */ + value = devc->dev_mode & DUALDAC_MODE ? 1 : 0; + break; + + case REAR2LINE: /* rear to line in */ + value = INB (devc->osdev, MIXER1) & (1 << 5) ? 1 : 0; + break; + + case CEN2LINE: /* center to line in */ + value = INL (devc->osdev, LEGACY_CTRL) & (1 << 14) ? 1 : 0; + break; + + case BASS2LINE: /* basss to line in */ + value = INL (devc->osdev, LEGACY_CTRL) & (1 << 13) ? 1 : 0; + break; + + case SPDIF_PLAY: /* spdif out */ + value = INL (devc->osdev, LEGACY_CTRL) & (1 << 23) ? 1 : 0; + break; + + case SPDIF_LOOP: /* S/PDIF I/O Loop */ + value = (INL (devc->osdev, FUNCTRL1) & (1 << 7)) ? 1 : 0; + break; + + case SPDIF_REC: /* spdif record mode */ + value = devc->dev_mode & SPDIFIN_MODE ? 1 : 0; + break; + + case SPDIF_IMON: /* spdif input monitor */ + value = INB (devc->osdev, MIXER1) & 0x1 ? 1 : 0; + break; + + case SPDIF_POL: /* spdif input reverse */ + if (devc->chiprev < 39) + value = INB (devc->osdev, MIXER3) & 0x06 ? 1 : 0; + else + value = INL (devc->osdev, CHFORMAT) & 0x80 ? 1 : 0; + break; + + case SPDIF_AC3: /* ac3 */ + value = INL (devc->osdev, MISC_CTRL) & (1 << 18) ? 1 : 0; + break; + + case SPDIF_COPY: /* copy protect (indirect) */ + value = INL (devc->osdev, LEGACY_CTRL) & (1 << 22) ? 1 : 0; + break; + + case SPDIF_OPT: /* Coax/Optical Select */ + value = INL (devc->osdev, MISC_CTRL) & (1 << 25) ? 1 : 0; + break; + + case CEN2MIC: /* Center2MIC */ + if (devc->chiprev >= 39) + value = INB (devc->osdev, MIXER3) & 0x4 ? 1 : 0; + break; + + case MICBOOST: /* MIC Boost */ + value = INB (devc->osdev, MIXER2) & 0x1 ? 0 : 1; + break; + + case AUX_LEVEL: + value = devc->levels[SOUND_MIXER_LINE1]; + break; + + case AUX_REC: /* set LINE1 as rec source - handled by set_recmask */ + break; + + case MUTE_AUX: /* AUX mute */ + value = INB (devc->osdev, MIXER2) & 0x30 ? 0 : 1; + break; + + default: + return OSS_EINVAL; + } + + return value; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case MUTE_LINE: /* L/R line in to output connection */ + if (!value) + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) | 0x18); + else + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) & ~0x18); + break; + + case MUTE_CD: /* Cd in to output connection */ + if (!value) + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) | 0x06); + else + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) & ~0x06); + break; + + case MUTE_MIC: /* Mic in to output connection */ + if (!value) + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) | 0x01); + else + cmpci_setmixer (devc, 0x3c, cmpci_getmixer (devc, 0x3c) & ~0x01); + break; + + case MODE_4SPK: /* 4Speaker out */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 26), + MISC_CTRL); + devc->mode_4spk = 1; + } + else + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + devc->mode_4spk = 0; + break; + + case DUALDAC: /* DUAL DAC mode */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 23), + MISC_CTRL); + /* Disable 4Speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + devc->dev_mode = DUALDAC_MODE; + } + else + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 23), + MISC_CTRL); + + /* enable back the 4Speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | 1 << 26, + MISC_CTRL); + + devc->dev_mode = DEFAULT_MODE; + } + break; + + case REAR2LINE: /* REAR TO LINEIN */ + if (value) + { + OUTB (devc->osdev, (INB (devc->osdev, MIXER1) | (1 << 5)), + MIXER1); + } + else + OUTB (devc->osdev, (INB (devc->osdev, MIXER1) & ~(1 << 5)), + MIXER1); + break; + + case CEN2LINE: /* CENTER TO LINEIN */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 14), + LEGACY_CTRL); + } + else + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 14), + LEGACY_CTRL); + break; + + case BASS2LINE: /* BASS TO LINEIN */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 13), + LEGACY_CTRL); + } + else + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 13), + LEGACY_CTRL); + break; + + case SPDIF_PLAY: /* SPDIF ENABLE */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 23), + LEGACY_CTRL); + + /* enable wave/fm/midi to spdif OUT DAC2SPDO on rev 33/37 */ + if (devc->chiprev < 39) + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 21), + LEGACY_CTRL); + devc->spdif_enabled = 1; + } + else + { + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 23), + LEGACY_CTRL); + /* Disable wave/fm/midi to spdif OUT (DAC2SPDO) */ + if (devc->chiprev < 39) + OUTL (devc->osdev, + INL (devc->osdev, LEGACY_CTRL) & ~(1 << 21), + LEGACY_CTRL); + devc->spdif_enabled = 0; + } + break; + + case SPDIF_LOOP: /* S/PDIF I/O Loop */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) | (1 << 7), + FUNCTRL1); + } + else + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) & ~(1 << 7), + FUNCTRL1); + break; + + case SPDIF_REC: /* SPDIF Record Mode */ + if (value) + { + devc->dev_mode = SPDIFIN_MODE; + } + else + devc->dev_mode = DEFAULT_MODE; + break; + + case SPDIF_IMON: /* spdif monitor */ + if (value) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER1) | 0x0D, MIXER1); + } + else + OUTB (devc->osdev, INB (devc->osdev, MIXER1) & ~0xD, MIXER1); + break; + + case SPDIF_POL: /* spdif reverse */ + if (value) + { + if (devc->chiprev < 39) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER3) | 0x06, + MIXER3); + } + else + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) | 0x80, + CHFORMAT); + } + else + { + if (devc->chiprev < 39) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER3) & ~0x06, + MIXER3); + } + else + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~0x80, + CHFORMAT); + } + break; + + case SPDIF_AC3: /* AC3 enabled on S/PDIF */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 18), + MISC_CTRL); + } + else + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 18), + MISC_CTRL); + break; + + case SPDIF_COPY: /* Copy protect */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 22), + LEGACY_CTRL); + } + else + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 22), + LEGACY_CTRL); + break; + + case SPDIF_OPT: /* Coax/Optical */ + if (value) + { + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 25), + MISC_CTRL); + } + else + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 25), + MISC_CTRL); + break; + + case CEN2MIC: /* Center -> Mic OUT */ + if (value) + { + if (devc->chiprev >= 39) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER3) | 0x4, MIXER3); + } + } + else if (devc->chiprev >= 39) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER3) & ~0x4, MIXER3); + } + break; + + case MICBOOST: /* Mic Boost */ + if (!value) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER2) | 0x1, MIXER2); + } + else + OUTB (devc->osdev, INB (devc->osdev, MIXER2) & ~0x1, MIXER2); + break; + + case AUX_LEVEL: /* Aux levels */ + left = value & 0xff; + right = (value >> 8) & 0xff; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + value = left | (right << 8); + left = mix_cvt[left]; + right = mix_cvt[right]; + + tmp = ((right * ((1 << 4) - 1) / 100) << 4) | + (left * ((1 << 4) - 1) / 100); + + OUTB (devc->osdev, tmp, AUX_VOL); + devc->levels[SOUND_MIXER_LINE1] = value; + break; + + case AUX_REC: /* line1 record select */ + if (value) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER2) | 0xc0, MIXER2); + } + else + OUTB (devc->osdev, INB (devc->osdev, MIXER2) & ~0xc0, MIXER2); + break; + + case MUTE_AUX: /* line1 mute control */ + if (!value) + { + OUTB (devc->osdev, INB (devc->osdev, MIXER2) | 0x30, MIXER2); + } + else + OUTB (devc->osdev, INB (devc->osdev, MIXER2) & ~0x30, MIXER2); + break; + + default: + return OSS_EINVAL; + } + + return (value); + } + return OSS_EINVAL; +} + +static int +cmpci_mix_init (int dev) +{ + int group, err; + + if ((group = mixer_ext_create_group (dev, 0, "CMPCI_MUTECTL")) < 0) + return group; + + if ((err = + mixer_ext_create_control (dev, group, MUTE_LINE, cmpci_outsw, + MIXT_ONOFF, "CMPCI_LINEMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, MUTE_CD, cmpci_outsw, MIXT_ONOFF, + "CMPCI_CDMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, MUTE_MIC, cmpci_outsw, + MIXT_ONOFF, "CMPCI_MICMUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, MUTE_AUX, cmpci_outsw, + MIXT_ONOFF, "CMPCI_LINE1MUTE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((group = mixer_ext_create_group (dev, 0, "CMPCI_JACKCTL")) < 0) + return group; + if ((err = + mixer_ext_create_control (dev, group, REAR2LINE, cmpci_outsw, + MIXT_ONOFF, "CMPCI_REAR2LINE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = + mixer_ext_create_control (dev, group, CEN2LINE, cmpci_outsw, + MIXT_ONOFF, "CMPCI_CEN2LINE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = + mixer_ext_create_control (dev, group, BASS2LINE, cmpci_outsw, + MIXT_ONOFF, "CMPCI_BASS2LINE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, CEN2MIC, cmpci_outsw, MIXT_ONOFF, + "CMPCI_CEN2MIC", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + + if ((group = mixer_ext_create_group (dev, 0, "CMPCI_MIXEXT")) < 0) + return group; + + if ((err = + mixer_ext_create_control (dev, group, MODE_4SPK, cmpci_outsw, + MIXT_ENUM, "CMPCI_SPKMODE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, DUALDAC, cmpci_outsw, MIXT_ONOFF, + "CMPCI_DUALDAC", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, MICBOOST, cmpci_outsw, + MIXT_ONOFF, "CMPCI_MICBOOST", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + /* Create a new SPDIF group */ + if ((group = mixer_ext_create_group (dev, 0, "CMPCI_SPDIF")) < 0) + return group; + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_PLAY, cmpci_outsw, + MIXT_ONOFF, "CMPCI_Play", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_LOOP, cmpci_outsw, + MIXT_ONOFF, "CMPCI_LOOP", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + /* Having this in mixer doesn't make any sense */ + if ((err = + mixer_ext_create_control (dev, group, SPDIF_REC, cmpci_outsw, + MIXT_ONOFF, "CMPCI_RECORD", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_IMON, cmpci_outsw, + MIXT_ONOFF, "CMPCI_IMON", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_POL, cmpci_outsw, + MIXT_ONOFF, "CMPCI_POLREV", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + +#if 0 + /* Having this in mixer doesn't make any sense */ + if ((err = + mixer_ext_create_control (dev, group, SPDIF_AC3, cmpci_outsw, + MIXT_ONOFF, "CMPCI_AC3", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; +#endif + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_COPY, cmpci_outsw, + MIXT_ONOFF, "CMPCI_COPYPROT", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = + mixer_ext_create_control (dev, group, SPDIF_OPT, cmpci_outsw, + MIXT_ONOFF, "CMPCI_OPTICAL", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +static void +cmpci_mixer_reset (int dev) +{ + int i; + cmpci_devc *devc = mixer_devs[dev]->devc; + + devc->levels = load_mixer_volumes ("CM8738_Mixer", default_levels, 1); + devc->recmask = 0; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + cmpci_mixer_set (devc, i, devc->levels[i]); + + set_recmask (dev, SOUND_MASK_MIC); +} + + +static mixer_driver_t cmpci_mixer_driver = { + cmpci_mixer_ioctl +}; + + +static int +cmpciintr (oss_device_t * osdev) +{ + cmpci_devc *devc = (cmpci_devc *) osdev->devc; + unsigned int intstat, intsrc; + int i; + int serviced = 0; + + /* see if this is our interrupt */ + intsrc = INL (devc->osdev, INT_STATUS); + if (intsrc & (CM_CH0_INT | CM_CH1_INT)) + { + /* Handle playback */ + serviced = 1; + + intstat = INB (devc->osdev, INT_HLDCLR + 2); + + for (i = 0; i < MAX_PORTC; i++) + { + cmpci_portc *portc = &devc->portc[i]; + + if (intstat & CM_CH1_INT) + { + /* do chan1 playback */ + if ((portc->chan1_play) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + OUTB (devc->osdev, intstat & ~CM_CH1_INT, INT_HLDCLR + 2); + OUTB (devc->osdev, intstat | CM_CH1_INT, INT_HLDCLR + 2); + oss_audio_outputintr (portc->audiodev, 0); + } + + /* do chan1 record */ + if ((portc->chan1_rec) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + OUTB (devc->osdev, intstat & ~CM_CH1_INT, INT_HLDCLR + 2); + OUTB (devc->osdev, intstat | CM_CH1_INT, INT_HLDCLR + 2); + oss_audio_inputintr (portc->audiodev, 0); + } + } + + if (intstat & CM_CH0_INT) + { + /* do chan0 playback */ + if ((portc->chan0_play) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + OUTB (devc->osdev, intstat & ~CM_CH0_INT, INT_HLDCLR + 2); + OUTB (devc->osdev, intstat | CM_CH0_INT, INT_HLDCLR + 2); + oss_audio_outputintr (portc->audiodev, 0); + } + + /* do chan0 record */ + if ((portc->chan0_rec) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + OUTB (devc->osdev, intstat & ~CM_CH0_INT, INT_HLDCLR + 2); + OUTB (devc->osdev, intstat | CM_CH0_INT, INT_HLDCLR + 2); + oss_audio_inputintr (portc->audiodev, 0); + } + } + } + } + + if (intsrc & 0x10000) + { + serviced = 1; + uart401_irq (&devc->uart401devc); + } + + return serviced; +} + +static int +cmpci_audio_set_rate (int dev, int arg) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +cmpci_audio_set_channels (int dev, short arg) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + + if (devc->model == MDL_CM8768) + { + if (arg>8) + arg=8; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6) && (arg != 8)) + return portc->channels; + } + else + { + if (arg>6) + arg=6; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + } + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +cmpci_audio_set_format (int dev, unsigned int arg) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +cmpci_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void cmpci_audio_trigger (int dev, int state); + +static void +cmpci_audio_reset (int dev) +{ + cmpci_audio_trigger (dev, 0); +} + +static void +cmpci_audio_reset_input (int dev) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + cmpci_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +cmpci_audio_reset_output (int dev) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + cmpci_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +cmpci_audio_open (int dev, int mode, int open_flags) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + cmpci_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->dev_mode & DUALDAC_MODE)) + { + 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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +cmpci_audio_close (int dev, int mode) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + cmpci_devc *devc = audio_engines[dev]->devc; + + cmpci_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; + + if ((devc->spdif_enabled) || (devc->dev_mode & SPDIFIN_MODE)) + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) & ~(1 << 9), FUNCTRL1); + + if (portc->chan0_play) + portc->chan0_play = 0; + + if (portc->chan1_play) + portc->chan1_play = 0; + + if (portc->chan0_rec) + portc->chan0_rec = 0; + + if (portc->chan1_rec) + portc->chan1_rec = 0; +} + +/*ARGSUSED*/ +static void +cmpci_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +cmpci_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +cmpci_audio_trigger (int dev, int state) +{ + cmpci_portc *portc = audio_engines[dev]->portc; + cmpci_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + 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->chan0_play) + { + /* enable the channel0 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH0_ENABLE, + FUNCTRL0 + 2); + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) | CM_CH0_INT, + INT_HLDCLR + 2); + } + + if (portc->chan1_play) + { + /* enable the channel1 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH1_ENABLE, + FUNCTRL0 + 2); + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) | CM_CH1_INT, + INT_HLDCLR + 2); + } + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + if (portc->chan0_play) + { + /* disable interrupt */ + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) & ~CM_CH0_INT, + INT_HLDCLR + 2); + + /* disable channel0 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH0_ENABLE, + FUNCTRL0 + 2); + } + if (portc->chan1_play) + { + /* disable interrupt */ + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) & ~CM_CH1_INT, + INT_HLDCLR + 2); + + /* disable channel */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH1_ENABLE, + FUNCTRL0 + 2); + } + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + if (portc->chan1_rec) + { + /* enable the channel1 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH1_ENABLE, + FUNCTRL0 + 2); + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) | CM_CH1_INT, + INT_HLDCLR + 2); + } + if (portc->chan0_rec) + { + /* enable the channel0 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH0_ENABLE, + FUNCTRL0 + 2); + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) | CM_CH0_INT, + INT_HLDCLR + 2); + } + 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; + if (portc->chan1_rec) + { + /* disable interrupt */ + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) & ~CM_CH1_INT, + INT_HLDCLR + 2); + + /* disable channel 1 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH1_ENABLE, + FUNCTRL0 + 2); + } + if (portc->chan0_rec) + { + /* disable interrupt */ + OUTB (devc->osdev, + INB (devc->osdev, INT_HLDCLR + 2) & ~CM_CH0_INT, + INT_HLDCLR + 2); + + /* disable channel 0 */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH0_ENABLE, + FUNCTRL0 + 2); + + } + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +set_dac_rate (int dev, int chan_type) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + unsigned char freq = 4, val; + int i; + int rate = portc->speed; + + if (rate > 48000) + rate = 48000; + if (rate < 5512) + rate = 5512; + + for (i = 0; i < sizeof (rate_lookup) / sizeof (rate_lookup[0]); i++) + { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) + { + rate = rate_lookup[i].rate; + freq = rate_lookup[i].freq; + break; + } + } + if (chan_type == CHAN0) + { + val = INB (devc->osdev, FUNCTRL1 + 1) & ~0x1c; + OUTB (devc->osdev, val | freq << 2, FUNCTRL1 + 1); + } + else + { + val = INB (devc->osdev, FUNCTRL1 + 1) & ~0xe0; + OUTB (devc->osdev, val | freq << 5, FUNCTRL1 + 1); + } + if (devc->spdif_enabled) + set_spdif_rate (devc, portc); +} + +static void +set_dac_fmt (int dev, int chan_type) +{ + unsigned char val; + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + int channels = portc->channels; + int bits = portc->bits; + + if (chan_type == CHAN0) + { + /* Set the format on Channl 0 */ + val = INB (devc->osdev, CHFORMAT) & ~0x3; + + if ((channels == 1) && (bits == 8)) + { + OUTB (devc->osdev, 0x00 | val, CHFORMAT); + portc->dacfmt = 0; + } + + if ((channels == 2) && (bits == 8)) + { + OUTB (devc->osdev, 0x01 | val, CHFORMAT); + portc->dacfmt = 1; + } + + if ((channels == 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x02 | val, CHFORMAT); + portc->dacfmt = 1; + } + + if ((channels > 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x03 | val, CHFORMAT); + portc->dacfmt = 2; + } + } + else + { + /* Set the format on Channel 1 */ + val = INB (devc->osdev, CHFORMAT) & ~0xC; + + if ((channels == 1) && (bits == 8)) + { + OUTB (devc->osdev, 0x00 | val, CHFORMAT); + portc->dacfmt = 0; + } + + if ((channels == 2) && (bits == 8)) + { + OUTB (devc->osdev, 0x04 | val, CHFORMAT); + portc->dacfmt = 1; + } + + if ((channels == 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x08 | val, CHFORMAT); + portc->dacfmt = 1; + } + + if ((channels > 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x0C | val, CHFORMAT); + portc->dacfmt = 2; + } + } +} + + +static void +set_adc_rate (int dev, int chan_type) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + unsigned char freq = 4, val; + int i; + int rate = portc->speed; + + if (rate > 48000) + rate = 48000; + if (rate < 5512) + rate = 5512; + for (i = 0; i < sizeof (rate_lookup) / sizeof (rate_lookup[0]); i++) + { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) + { + rate = rate_lookup[i].rate; + freq = rate_lookup[i].freq; + break; + } + } + if (chan_type == CHAN1) + { + val = INB (devc->osdev, FUNCTRL1 + 1) & ~0xe0; + OUTB (devc->osdev, val | freq << 5, FUNCTRL1 + 1); + } + else + { + val = INB (devc->osdev, FUNCTRL1 + 1) & ~0x1c; + OUTB (devc->osdev, val | freq << 2, FUNCTRL1 + 1); + } + + if (devc->dev_mode & SPDIFIN_MODE) + set_spdif_rate (devc, portc); +} + +static void +set_adc_fmt (int dev, int chan_type) +{ + unsigned char val; + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + int channels = portc->channels; + int bits = portc->bits; + + if (chan_type == CHAN1) + { + /* Set the format on Channel 1 */ + val = INB (devc->osdev, CHFORMAT) & ~0xC; + + if ((channels == 1) && (bits == 8)) + { + OUTB (devc->osdev, 0x00 | val, CHFORMAT); + portc->adcfmt = 0; + } + + if ((channels == 2) && (bits == 8)) + { + OUTB (devc->osdev, 0x04 | val, CHFORMAT); + portc->adcfmt = 1; + } + + if ((channels == 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x08 | val, CHFORMAT); + portc->adcfmt = 1; + } + + if ((channels > 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x0C | val, CHFORMAT); + portc->adcfmt = 2; + } + } + else + { + /* Set the format on Channl 0 */ + val = INB (devc->osdev, CHFORMAT) & ~0x3; + + if ((channels == 1) && (bits == 8)) + { + OUTB (devc->osdev, 0x00 | val, CHFORMAT); + portc->adcfmt = 0; + } + + if ((channels == 2) && (bits == 8)) + { + OUTB (devc->osdev, 0x01 | val, CHFORMAT); + portc->adcfmt = 1; + } + + if ((channels == 1) && (bits == 16)) + { + OUTB (devc->osdev, 0x02 | val, CHFORMAT); + portc->adcfmt = 1; + } + + if ((channels == 2) && (bits == 16)) + { + OUTB (devc->osdev, 0x03 | val, CHFORMAT); + portc->adcfmt = 2; + } + } +} + +static void +setup_record (int dev, int chan_type) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + + if (chan_type == CHAN1) /* SPDIF Record can only occur on CHAN1 */ + { + /* reset and disable channel */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH1_RESET, FUNCTRL0 + 2); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH1_RESET, FUNCTRL0 + 2); + + cmpci_outsw (devc->mixer_dev, SPDIF_PLAY, SNDCTL_MIX_WRITE, 0); + + OUTL (devc->osdev, dmap->dmabuf_phys, CH1_FRAME1); + OUTW (devc->osdev, (dmap->bytes_in_use >> portc->adcfmt) - 1, + CH1_FRAME2); + OUTW (devc->osdev, (dmap->fragment_size >> portc->adcfmt), + CH1_FRAME2 + 2); + + /* set channel 1 to record mode */ + OUTB (devc->osdev, INB (devc->osdev, FUNCTRL0) | CM_CH1_RECORD, + FUNCTRL0); + portc->chan1_rec = 1; + + /* setup SPDIF in on CHAN A */ + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) | (1 << 9), FUNCTRL1); + } + else /* Normal PCM record on Channel 0 */ + { + /* reset and disable channel */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH0_RESET, FUNCTRL0 + 2); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH0_RESET, FUNCTRL0 + 2); + + OUTL (devc->osdev, dmap->dmabuf_phys, CH0_FRAME1); + OUTW (devc->osdev, (dmap->bytes_in_use >> portc->adcfmt) - 1, + CH0_FRAME2); + OUTW (devc->osdev, (dmap->fragment_size >> portc->adcfmt), + CH0_FRAME2 + 2); + + /* set channel 0 to record mode */ + OUTB (devc->osdev, INB (devc->osdev, FUNCTRL0) | CM_CH0_RECORD, + FUNCTRL0); + portc->chan0_rec = 1; + } +} + +/*ARGSUSED*/ +static int +cmpci_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + switch (devc->dev_mode) + { + case DEFAULT_MODE: + set_adc_rate (dev, CHAN0); + set_adc_fmt (dev, CHAN0); + setup_record (dev, CHAN0); + break; + + case DUALDAC_MODE: + cmn_err (CE_WARN, "Cannot record because DUALDAC mode is ON.\n"); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EIO; + + case SPDIFIN_MODE: + if (portc->speed < 44100) + { + cmn_err (CE_WARN, + "Cannot record spdif at sampling rate less than 44.1Khz.\n"); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EIO; + } + set_adc_rate (dev, CHAN1); + set_adc_fmt (dev, CHAN1); + setup_record (dev, CHAN1); + break; + } + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +setup_play (int dev, int chan_type) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + + if (chan_type == CHAN0) + { + /* reset channel */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH0_RESET, FUNCTRL0 + 2); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH0_RESET, FUNCTRL0 + 2); + oss_udelay (10); + + /* Now set the buffer address/sizes */ + OUTL (devc->osdev, dmap->dmabuf_phys, CH0_FRAME1); + OUTW (devc->osdev, (dmap->bytes_in_use >> portc->dacfmt) - 1, + CH0_FRAME2); + OUTW (devc->osdev, (dmap->fragment_size >> portc->dacfmt), + CH0_FRAME2 + 2); + + /* set channel 0 to play mode */ + OUTB (devc->osdev, INB (devc->osdev, FUNCTRL0) & CM_CH0_PLAY, FUNCTRL0); + portc->chan0_play = 1; + + /* setup spdif output on CHAN A , disable CHAN B spdif */ + if (devc->spdif_enabled) + { + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) | (1 << 8), + FUNCTRL1); + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) & ~(1 << 9), + FUNCTRL1); + } + } + else + { + /* reset and disable channel */ + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) | CM_CH1_RESET, FUNCTRL0 + 2); + oss_udelay (10); + OUTB (devc->osdev, + INB (devc->osdev, FUNCTRL0 + 2) & ~CM_CH1_RESET, FUNCTRL0 + 2); + oss_udelay (10); + + /* Handle 4/5/6 channel mode */ + if (portc->channels < 4) + { + /* check if 4speaker mode is enabled from mixer or not */ + if (devc->mode_4spk) + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + + /* disable 4channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(1 << 29), + CHFORMAT); + /* disable 5 channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(0x80000000), + CHFORMAT); + /* disable 6channel mode out CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 15), + LEGACY_CTRL); + /* disable 8 channel decode on CHAN B - only for CMI8768 */ + if (devc->model == MDL_CM8768) + OUTB (devc->osdev, INB (devc->osdev, MISC2_CTRL) & ~0x20, + MISC2_CTRL); + /* Set NXCNG */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(0x80000000), + LEGACY_CTRL); + } + + if ((portc->channels == 4) && (devc->chiprev > 37)) + { + /* disable 4 speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + /* enable 4channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) | (1 << 29), + CHFORMAT); + + /* disable 5 channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(0x80000000), + CHFORMAT); + /* disable 6channel mode out CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 15), + LEGACY_CTRL); + /* disable center/bass channel */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 7), + MISC_CTRL); + /* disable bass */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 12), + LEGACY_CTRL); + + /* disable 8 channel decode on CHAN B - only for CMI8768 */ + if (devc->model == MDL_CM8768) + OUTB (devc->osdev, INB (devc->osdev, MISC2_CTRL) & ~0x20, + MISC2_CTRL); + /* Set NXCNG */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(0x80000000), + LEGACY_CTRL); + } + + if ((portc->channels == 6) && (devc->chiprev > 37)) + { + /* disable 4 speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + /* disable 4channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(1 << 29), + CHFORMAT); + + /* enable center channel */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 7), + MISC_CTRL); + /* enable bass */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 12), + LEGACY_CTRL); + /* enable 5 channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) | (0x80000000), + CHFORMAT); + /* enable 6 channel decode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 15), + LEGACY_CTRL); + + /* disable 8 channel decode on CHAN B - only for CMI8768 */ + if (devc->model == MDL_CM8768) + OUTB (devc->osdev, INB (devc->osdev, MISC2_CTRL) & ~0x20, + MISC2_CTRL); + + /* Set NXCNG */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (0x80000000), + LEGACY_CTRL); + } + + if ((portc->channels == 8) && (devc->model == MDL_CM8768)) + { + /* disable 4 speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) & ~(1 << 26), + MISC_CTRL); + /* disable 4channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(1 << 29), + CHFORMAT); + + /* enable center channel */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 7), + MISC_CTRL); + /* enable bass channel */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 12), + LEGACY_CTRL); + /* disable 5 channel mode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, CHFORMAT) & ~(0x80000000), + CHFORMAT); + /* disable 6 channel decode on CHAN B */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) & ~(1 << 15), + LEGACY_CTRL); + + /* enable 8 channel decode on CHAN B */ + OUTB (devc->osdev, INB (devc->osdev, MISC2_CTRL) | 0x20, + MISC2_CTRL); + /* Set NXCNG */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (0x80000000), + LEGACY_CTRL); + } + + /* Now set the buffer address/sizes */ + OUTL (devc->osdev, dmap->dmabuf_phys, CH1_FRAME1); + OUTW (devc->osdev, (dmap->bytes_in_use >> portc->dacfmt) - 1, + CH1_FRAME2); + OUTW (devc->osdev, (dmap->fragment_size >> portc->dacfmt), + CH1_FRAME2 + 2); + + + /* set channel 1 to play mode */ + OUTB (devc->osdev, INB (devc->osdev, FUNCTRL0) & CM_CH1_PLAY, FUNCTRL0); + portc->chan1_play = 1; + + /* setup spdif output on CHAN B , disable CHAN A spdif */ + if (devc->spdif_enabled) + { + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) | (1 << 9), + FUNCTRL1); + OUTL (devc->osdev, INL (devc->osdev, FUNCTRL1) & ~(1 << 8), + FUNCTRL1); + } + } +} + +/*ARGSUSED*/ +static int +cmpci_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if ((portc->bits == AFMT_AC3) && devc->can_ac3) + { + portc->bits = 16; + portc->channels = 2; + cmpci_outsw (devc->mixer_dev, SPDIF_PLAY, SNDCTL_MIX_WRITE, 1); + setup_ac3 (devc, portc, 1); + } + else + setup_ac3 (devc, portc, 0); + + switch (devc->dev_mode) + { + case DEFAULT_MODE: + /* set speed */ + set_dac_rate (dev, CHAN1); + /* set format */ + set_dac_fmt (dev, CHAN1); + /* set buffer address/size and other setups */ + setup_play (dev, CHAN1); + break; + + case DUALDAC_MODE: + if (dev == devc->portc[0].audiodev) + { + set_dac_rate (dev, CHAN1); + set_dac_fmt (dev, CHAN1); + setup_play (dev, CHAN1); + setup_ac3 (devc, portc, 0); + } + if (dev == devc->portc[1].audiodev) + { + set_dac_rate (dev, CHAN0); + set_dac_fmt (dev, CHAN0); + setup_play (dev, CHAN0); + setup_ac3 (devc, portc, 0); + } + break; + + case SPDIFIN_MODE: + set_dac_rate (dev, CHAN0); + set_dac_fmt (dev, CHAN0); + setup_play (dev, CHAN0); + setup_ac3 (devc, portc, 0); + break; + } + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +cmpci_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + cmpci_devc *devc = audio_engines[dev]->devc; + cmpci_portc *portc = audio_engines[dev]->portc; + unsigned int ptr = 0; + oss_native_word flags; + + if (!(portc->open_mode & direction)) + return 0; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_INPUT) + { + if (portc->chan0_rec) + ptr = INW (devc->osdev, CH0_FRAME1); + if (portc->chan1_rec) + ptr = INW (devc->osdev, CH1_FRAME1); + } + + if (direction == PCM_ENABLE_OUTPUT) + { + if (portc->chan0_play) + ptr = INW (devc->osdev, CH0_FRAME1); + if (portc->chan1_play) + ptr = INW (devc->osdev, CH1_FRAME1); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr % dmap->bytes_in_use; +} + +static audiodrv_t cmpci_audio_driver = { + cmpci_audio_open, + cmpci_audio_close, + cmpci_audio_output_block, + cmpci_audio_start_input, + cmpci_audio_ioctl, + cmpci_audio_prepare_for_input, + cmpci_audio_prepare_for_output, + cmpci_audio_reset, + NULL, + NULL, + cmpci_audio_reset_input, + cmpci_audio_reset_output, + cmpci_audio_trigger, + cmpci_audio_set_rate, + cmpci_audio_set_format, + cmpci_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* cmpci_alloc_buffer, */ + NULL, /* cmpci_free_buffer, */ + NULL, + NULL, + cmpci_get_buffer_pointer +}; + +#ifdef OBSOLETED_STUFF +static void +attach_mpu (cmpci_devc * devc) +{ + unsigned int base; + + if (devc->chiprev == 33) + base = 0x330; /* Chiprev033 doen't have bas+0x40 */ + else + base = MPU_MIRROR; /* base+0x40 is MPU PCI mirror */ + + uart401_init (&devc->uart401devc, devc->osdev, base, "Cmedia MIDI UART"); + devc->uart401_attached = 1; +} +#endif + +static int +init_cmpci (cmpci_devc * devc) +{ + oss_native_word val; + int first_dev = 0; + int i; + + devc->fm_attached = 0; + +/* + * Enable BusMasterMode and IOSpace Access + */ + /* Check the model number of the chip */ + val = INL (devc->osdev, INT_HLDCLR) & 0xff000000; + + if (!val) + { + val = INL (devc->osdev, CHFORMAT) & 0x1f000000; + if (!val) + { + devc->chiprev = 33; + devc->can_ac3 = 0; + devc->max_channels = 6; + } + else + { + devc->chiprev = 37; + devc->can_ac3 = 1; + devc->max_channels = 6; + } + } + else + { + if (val & 0x04000000) + { + devc->chiprev = 39; + devc->can_ac3 = 1; + devc->max_channels = 6; + } + if (val & 0x08000000) + { + devc->chiprev = 55; + devc->can_ac3 = 1; + devc->max_channels = 6; + } + if (val & 0x28000000) + { + devc->chiprev = 68; + devc->can_ac3 = 1; + devc->model = MDL_CM8768; + devc->max_channels = 8; + devc->chip_name = "CMedia CM8768"; + } + } + + /* enable uart, joystick in Function Control Reg1 */ + OUTB (devc->osdev, INB (devc->osdev, FUNCTRL1) | 0x06, FUNCTRL1); + /* enable FM */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 19), MISC_CTRL); + OUTB (devc->osdev, 0, INT_HLDCLR + 2); /* disable ints */ + OUTB (devc->osdev, 0, FUNCTRL0 + 2); /* reset channels */ + +#ifdef OBSOLETED_STUFF + attach_mpu (devc); +#endif + + /* install the CMPCI mixer */ + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "CMedia CMPCI", + &cmpci_mixer_driver, + sizeof (mixer_driver_t), + devc)) < 0) + { + return 0; + } + + mixer_devs[devc->mixer_dev]->hw_devc = devc; + mixer_devs[devc->mixer_dev]->priority = 1; /* Possible default mixer candidate */ + + cmpci_mixer_reset (devc->mixer_dev); + mixer_ext_set_init_fn (devc->mixer_dev, cmpci_mix_init, 25); + OUTB (devc->osdev, 0xF, MIXER2); + + /* setup 4speaker output */ + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 26), MISC_CTRL); + /* enable subwoofer/center channel */ + OUTL (devc->osdev, INL (devc->osdev, LEGACY_CTRL) | (1 << 12), LEGACY_CTRL); + OUTL (devc->osdev, INL (devc->osdev, MISC_CTRL) | (1 << 7), MISC_CTRL); + + for (i = 0; i < MAX_PORTC; i++) + { + char tmp_name[100]; + cmpci_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + + if (i == 0) + { + sprintf (tmp_name, "%s (rev %0d)", devc->chip_name, devc->chiprev); + caps |= ADEV_DUPLEX; + } + else + { + sprintf (tmp_name, "%s (playback only)", devc->chip_name); + caps |= ADEV_NOINPUT; + } + if ((portc->audiodev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &cmpci_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_U8 | AFMT_S16_LE | + AFMT_AC3, devc, -1)) < 0) + { + return 0; + } + else + { + if (i == 0) + first_dev = portc->audiodev; + audio_engines[portc->audiodev]->portc = portc; + audio_engines[portc->audiodev]->rate_source = first_dev; + audio_engines[portc->audiodev]->caps = + PCM_CAP_ANALOGOUT | PCM_CAP_ANALOGIN | PCM_CAP_DIGITALOUT | + PCM_CAP_DIGITALIN; + audio_engines[portc->audiodev]->min_rate = 5000; + audio_engines[portc->audiodev]->max_rate = 48000; + audio_engines[portc->audiodev]->caps |= PCM_CAP_FREERATE; + audio_engines[portc->audiodev]->min_channels = 2; + audio_engines[portc->audiodev]->max_channels = devc->max_channels; + audio_engines[portc->audiodev]->vmix_flags = VMIX_MULTIFRAG; + audio_engines[portc->audiodev]->dmabuf_alloc_flags |= + DMABUF_SIZE_16BITS; + portc->open_mode = 0; + portc->audio_enabled = 0; + audio_engines[portc->audiodev]->mixer_dev = devc->mixer_dev; + devc->dev_mode = DEFAULT_MODE; + devc->spdif_enabled = 0; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, portc->audiodev, -1, 0); +#endif + } + } + return 1; +} + +int +oss_cmpci_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int err; + cmpci_devc *devc; + + DDB (cmn_err (CE_CONT, "Entered CMEDIA CMPCI attach routine\n")); + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != CMEDIA_VENDOR_ID + || ((device != CMEDIA_CM8738) && (device != CMEDIA_CM8338A) + && (device != CMEDIA_CM8338B))) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + DDB (cmn_err (CE_WARN, "CMPCI I/O base %04x\n", 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->irq = pci_irq_line; + + /* Map the IO Base address */ + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + + /* Remove I/O space marker in bit 0. */ + devc->base &= ~3; + + /* set the PCI_COMMAND register to master mode */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + switch (device) + { + case CMEDIA_CM8738: + devc->model = MDL_CM8738; + devc->chip_name = "CMedia CM8738"; + devc->max_channels = 6; + break; + + case CMEDIA_CM8338A: + devc->model = MDL_CM8338A; + devc->chip_name = "CMedia CM8338A"; + devc->max_channels = 6; + break; + + case CMEDIA_CM8338B: + devc->model = MDL_CM8338B; + devc->chip_name = "CMedia CM8338B"; + devc->max_channels = 6; + 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, cmpciintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err); + return 0; + } + + return init_cmpci (devc); /* Detected */ +} + +int +oss_cmpci_detach (oss_device_t * osdev) +{ + cmpci_devc *devc = (cmpci_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + /* disable Interrupts */ + OUTB (devc->osdev, 0, INT_HLDCLR + 2); + + /* disable channels */ + OUTB (devc->osdev, 0, FUNCTRL0 + 2); + + /* uninstall UART401 */ + if (devc->uart401_attached) + uart401_disable (&devc->uart401devc); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_cmpci/oss_cmpci.man b/kernel/drv/oss_cmpci/oss_cmpci.man new file mode 100644 index 0000000..1d817b3 --- /dev/null +++ b/kernel/drv/oss_cmpci/oss_cmpci.man @@ -0,0 +1,56 @@ +NAME +oss_cmpci - CMedia CMI8738/8768 audio driver. + +DESCRIPTION +Open Sound System driver for CMedia Electronics CMI8738/8768 audio + +CMI87xx device characteristics: + o 8/16 bit playback/record + o mono/stereo/4ch/5.1ch playback + o 8KHz to 48Khz sample rate. + + MIXER PANEL +The CMedia chip provides some unique features that are set up +by the Mixer chip. Running ossxmix will display the CMI8738 mixer +panel. + +Most of the sliders and buttons are self evident. However there +are some options that need explaining: + +Dual Dac: Enabling this button sets the CMPCI device as two +separate output devices with /dev/dsp1 audio going to the front and +/dev/dsp0 going to the rear outputs. Separate audio streams can +be send to the device simultaneously. + +Speaker Mode: The audio can be sent just to the front speakers or +it can be sent simultaneously to all speakers in the "Spread" mode. + +AC3 passthrough only works on Models 037 and higher. This is because of +a hardware bug in the earlier models so check the model number +(ossinfo -a). + +SPDIF: + +o Enable will enable SPDIF output. + +o Rec will allow you to record from the SPDIF device. Note that when +you have SPDIF recording enabled, you cannot play 4/6 channel audio. + +o Polarity - certain models require you to flip the bit otherwise you + get distorted audio. + +o IMon - monitor input via SPDIF in. + +o Optical - sets the SPDIF to Optical (TOSLINK) or RCA Jacks interface. + + + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_cmpci.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_cs4281/.devices b/kernel/drv/oss_cs4281/.devices new file mode 100644 index 0000000..1c415d7 --- /dev/null +++ b/kernel/drv/oss_cs4281/.devices @@ -0,0 +1 @@ +oss_cs4281 pci1013,6005 Crystal CS4281 diff --git a/kernel/drv/oss_cs4281/.name b/kernel/drv/oss_cs4281/.name new file mode 100644 index 0000000..6464db1 --- /dev/null +++ b/kernel/drv/oss_cs4281/.name @@ -0,0 +1 @@ +Crystal CS4281 diff --git a/kernel/drv/oss_cs4281/cs4281.h b/kernel/drv/oss_cs4281/cs4281.h new file mode 100644 index 0000000..f82568f --- /dev/null +++ b/kernel/drv/oss_cs4281/cs4281.h @@ -0,0 +1,1108 @@ +/* + * Purpose: Definitions for the cs4281 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. + * + */ +/***************************************************************************** */ +/* */ +/* HWDEFS.H - Definitions of the registers and data structures used by the */ +/* CS4281 */ +/* */ +/***************************************************************************** */ + +#ifndef _H_HWDEFS +#define _H_HWDEFS + +/***************************************************************************** */ +/* */ +/* The following define the offsets of the registers accessed via base address */ +/* register zero on the CS4281 part. */ +/* */ +/***************************************************************************** */ +#define BA0_HISR 0x00000000L +#define BA0_HICR 0x00000008L +#define BA0_HIMR 0x0000000CL +#define BA0_IIER 0x00000010L +#define BA0_HDSR0 0x000000F0L +#define BA0_HDSR1 0x000000F4L +#define BA0_HDSR2 0x000000F8L +#define BA0_HDSR3 0x000000FCL +#define BA0_DCA0 0x00000110L +#define BA0_DCC0 0x00000114L +#define BA0_DBA0 0x00000118L +#define BA0_DBC0 0x0000011CL +#define BA0_DCA1 0x00000120L +#define BA0_DCC1 0x00000124L +#define BA0_DBA1 0x00000128L +#define BA0_DBC1 0x0000012CL +#define BA0_DCA2 0x00000130L +#define BA0_DCC2 0x00000134L +#define BA0_DBA2 0x00000138L +#define BA0_DBC2 0x0000013CL +#define BA0_DCA3 0x00000140L +#define BA0_DCC3 0x00000144L +#define BA0_DBA3 0x00000148L +#define BA0_DBC3 0x0000014CL +#define BA0_DMR0 0x00000150L +#define BA0_DCR0 0x00000154L +#define BA0_DMR1 0x00000158L +#define BA0_DCR1 0x0000015CL +#define BA0_DMR2 0x00000160L +#define BA0_DCR2 0x00000164L +#define BA0_DMR3 0x00000168L +#define BA0_DCR3 0x0000016CL +#define BA0_DLMR 0x00000170L +#define BA0_DLSR 0x00000174L +#define BA0_FCR0 0x00000180L +#define BA0_FCR1 0x00000184L +#define BA0_FCR2 0x00000188L +#define BA0_FCR3 0x0000018CL +#define BA0_FPDR0 0x00000190L +#define BA0_FPDR1 0x00000194L +#define BA0_FPDR2 0x00000198L +#define BA0_FPDR3 0x0000019CL +#define BA0_FCHS 0x0000020CL +#define BA0_FSIC0 0x00000210L +#define BA0_FSIC1 0x00000214L +#define BA0_FSIC2 0x00000218L +#define BA0_FSIC3 0x0000021CL +#define BA0_PCICFG00 0x00000300L +#define BA0_PCICFG04 0x00000304L +#define BA0_PCICFG08 0x00000308L +#define BA0_PCICFG0C 0x0000030CL +#define BA0_PCICFG10 0x00000310L +#define BA0_PCICFG14 0x00000314L +#define BA0_PCICFG18 0x00000318L +#define BA0_PCICFG1C 0x0000031CL +#define BA0_PCICFG20 0x00000320L +#define BA0_PCICFG24 0x00000324L +#define BA0_PCICFG28 0x00000328L +#define BA0_PCICFG2C 0x0000032CL +#define BA0_PCICFG30 0x00000330L +#define BA0_PCICFG34 0x00000334L +#define BA0_PCICFG38 0x00000338L +#define BA0_PCICFG3C 0x0000033CL +#define BA0_PCICFG40 0x00000340L +#define BA0_PMCS 0x00000344L +#define BA0_CWPR 0x000003E0L +#define BA0_EPPMC 0x000003E4L +#define BA0_GPIOR 0x000003E8L +#define BA0_SPMC 0x000003ECL +#define BA0_CFLR 0x000003F0L +#define BA0_IISR 0x000003F4L +#define BA0_TMS 0x000003F8L +#define BA0_SSVID 0x000003FCL +#define BA0_CLKCR1 0x00000400L +#define BA0_FRR 0x00000410L +#define BA0_SLT12O 0x0000041CL +#define BA0_SERMC 0x00000420L +#define BA0_SERC1 0x00000428L +#define BA0_SERC2 0x0000042CL +#define BA0_SLT12M 0x0000045CL +#define BA0_ACCTL 0x00000460L +#define BA0_ACSTS 0x00000464L +#define BA0_ACOSV 0x00000468L +#define BA0_ACCAD 0x0000046CL +#define BA0_ACCDA 0x00000470L +#define BA0_ACISV 0x00000474L +#define BA0_ACSAD 0x00000478L +#define BA0_ACSDA 0x0000047CL +#define BA0_JSPT 0x00000480L +#define BA0_JSCTL 0x00000484L +#define BA0_MIDCR 0x00000490L +#define BA0_MIDCMD 0x00000494L +#define BA0_MIDSR 0x00000494L +#define BA0_MIDWP 0x00000498L +#define BA0_MIDRP 0x0000049CL +#define BA0_AODSD1 0x000004A8L +#define BA0_AODSD2 0x000004ACL +#define BA0_CFGI 0x000004B0L +#define BA0_SLT12M2 0x000004DCL +#define BA0_ACSTS2 0x000004E4L +#define BA0_ACISV2 0x000004F4L +#define BA0_ACSAD2 0x000004F8L +#define BA0_ACSDA2 0x000004FCL +#define BA0_IOTGP 0x00000500L +#define BA0_IOTSB 0x00000504L +#define BA0_IOTFM 0x00000508L +#define BA0_IOTDMA 0x0000050CL +#define BA0_IOTAC0 0x00000500L +#define BA0_IOTAC1 0x00000504L +#define BA0_IOTAC2 0x00000508L +#define BA0_IOTAC3 0x0000050CL +#define BA0_IOTPCP 0x0000052CL +#define BA0_IOTCC 0x00000530L +#define BA0_IOTCR 0x0000058CL +#define BA0_PCPRR 0x00000600L +#define BA0_PCPGR 0x00000604L +#define BA0_PCPCR 0x00000608L +#define BA0_PCPCIEN 0x00000608L +#define BA0_SBMAR 0x00000700L +#define BA0_SBMDR 0x00000704L +#define BA0_SBRR 0x00000708L +#define BA0_SBRDP 0x0000070CL +#define BA0_SBWDP 0x00000710L +#define BA0_SBWBS 0x00000710L +#define BA0_SBRBS 0x00000714L +#define BA0_FMSR 0x00000730L +#define BA0_B0AP 0x00000730L +#define BA0_FMDP 0x00000734L +#define BA0_B1AP 0x00000738L +#define BA0_B1DP 0x0000073CL +#define BA0_SSPM 0x00000740L +#define BA0_DACSR 0x00000744L +#define BA0_ADCSR 0x00000748L +#define BA0_SSCR 0x0000074CL +#define BA0_FMLVC 0x00000754L +#define BA0_FMRVC 0x00000758L +#define BA0_SRCSA 0x0000075CL +#define BA0_PPLVC 0x00000760L +#define BA0_PPRVC 0x00000764L +#define BA0_PASR 0x00000768L +#define BA0_CASR 0x0000076CL + +/***************************************************************************** */ +/* */ +/* The following define the offsets of the AC97 shadow registers, which appear */ +/* as a virtual extension to the base address register zero memory range. */ +/* */ +/***************************************************************************** */ +#define AC97_REG_OFFSET_MASK 0x0000007EL +#define AC97_CODEC_NUMBER_MASK 0x00003000L + +#define BA0_AC97_RESET 0x00001000L +#define BA0_AC97_MASTER_VOLUME 0x00001002L +#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L +#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L +#define BA0_AC97_MASTER_TONE 0x00001008L +#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL +#define BA0_AC97_PHONE_VOLUME 0x0000100CL +#define BA0_AC97_MIC_VOLUME 0x0000100EL +#define BA0_AC97_LINE_IN_VOLUME 0x00001010L +#define BA0_AC97_CD_VOLUME 0x00001012L +#define BA0_AC97_VIDEO_VOLUME 0x00001014L +#define BA0_AC97_AUX_VOLUME 0x00001016L +#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L +#define BA0_AC97_RECORD_SELECT 0x0000101AL +#define BA0_AC97_RECORD_GAIN 0x0000101CL +#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL +#define BA0_AC97_GENERAL_PURPOSE 0x00001020L +#define BA0_AC97_3D_CONTROL 0x00001022L +#define BA0_AC97_MODEM_RATE 0x00001024L +#define BA0_AC97_POWERDOWN 0x00001026L +#define BA0_AC97_EXT_AUDIO_ID 0x00001028L +#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL +#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL +#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL +#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L +#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L +#define BA0_AC97_MIC_ADC_RATE 0x00001034L +#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L +#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L +#define BA0_AC97_RESERVED_3A 0x0000103AL +#define BA0_AC97_EXT_MODEM_ID 0x0000103CL +#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL +#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L +#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L +#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L +#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L +#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L +#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL +#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL +#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL +#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L +#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L +#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L +#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L +#define BA0_AC97_RESERVED_58 0x00001058L +#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL +#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL +#define BA0_AC97_AC_MODE 0x0000105EL +#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L +#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L +#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L +#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L +#define BA0_AC97_SPDIF_CONTROL 0x00001068L +#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL +#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL +#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL +#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L +#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L +#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L +#define BA0_AC97_CAL_ADDRESS 0x00001076L +#define BA0_AC97_CAL_DATA 0x00001078L +#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL +#define BA0_AC97_VENDOR_ID1 0x0000107CL +#define BA0_AC97_VENDOR_ID2 0x0000107EL + +/***************************************************************************** */ +/* */ +/* The following define the offsets of the registers and memories accessed via */ +/* base address register one on the CS4281 part. */ +/* */ +/***************************************************************************** */ + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the host interrupt status */ +/* register. */ +/* */ +/***************************************************************************** */ +#define HISR_HVOLMASK 0x00000003L +#define HISR_VDNI 0x00000001L +#define HISR_VUPI 0x00000002L +#define HISR_GP1I 0x00000004L +#define HISR_GP3I 0x00000008L +#define HISR_GPSI 0x00000010L +#define HISR_GPPI 0x00000020L +#define HISR_DMAI 0x00040000L +#define HISR_FIFOI 0x00100000L +#define HISR_HVOL 0x00200000L +#define HISR_MIDI 0x00400000L +#define HISR_SBINT 0x00800000L +#define HISR_INTENA 0x80000000UL +#define HISR_DMA_MASK 0x00000F00L +#define HISR_FIFO_MASK 0x0000F000L +#define HISR_DMA_SHIFT 8L +#define HISR_FIFO_SHIFT 12L +#define HISR_FIFO0 0x00001000L +#define HISR_FIFO1 0x00002000L +#define HISR_FIFO2 0x00004000L +#define HISR_FIFO3 0x00008000L +#define HISR_DMA0 0x00000100L +#define HISR_DMA1 0x00000200L +#define HISR_DMA2 0x00000400L +#define HISR_DMA3 0x00000800L +#define HISR_RESERVED 0x40000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the host interrupt control */ +/* register. */ +/* */ +/***************************************************************************** */ +#define HICR_IEV 0x00000001L +#define HICR_CHGM 0x00000002L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the DMA Mode Register n */ +/* (DMRn) */ +/* */ +/***************************************************************************** */ +#define DMRn_TR_MASK 0x0000000CL +#define DMRn_TR_SHIFT 2L +#define DMRn_AUTO 0x00000010L +#define DMRn_TR_READ 0x00000008L +#define DMRn_TR_WRITE 0x00000004L +#define DMRn_TYPE_MASK 0x000000C0L +#define DMRn_TYPE_SHIFT 6L +#define DMRn_SIZE8 0x00010000L +#define DMRn_MONO 0x00020000L +#define DMRn_BEND 0x00040000L +#define DMRn_USIGN 0x00080000L +#define DMRn_SIZE20 0x00100000L +#define DMRn_SWAPC 0x00400000L +#define DMRn_CBC 0x01000000L +#define DMRn_TBC 0x02000000L +#define DMRn_POLL 0x10000000L +#define DMRn_DMA 0x20000000L +#define DMRn_FSEL_MASK 0xC0000000L +#define DMRn_FSEL_SHIFT 30L +#define DMRn_FSEL0 0x00000000L +#define DMRn_FSEL1 0x40000000L +#define DMRn_FSEL2 0x80000000L +#define DMRn_FSEL3 0xC0000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the DMA Command Register n */ +/* (DCRn) */ +/* */ +/***************************************************************************** */ +#define DCRn_HTCIE 0x00020000L +#define DCRn_TCIE 0x00010000L +#define DCRn_MSK 0x00000001L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the FIFO Control */ +/* register n.(FCRn) */ +/* */ +/***************************************************************************** */ +#define FCRn_OF_MASK 0x0000007FL +#define FCRn_OF_SHIFT 0L +#define FCRn_SZ_MASK 0x00007F00L +#define FCRn_SZ_SHIFT 8L +#define FCRn_LS_MASK 0x001F0000L +#define FCRn_LS_SHIFT 16L +#define FCRn_RS_MASK 0x1F000000L +#define FCRn_RS_SHIFT 24L +#define FCRn_FEN 0x80000000UL +#define FCRn_PSH 0x20000000L +#define FCRn_DACZ 0x40000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the serial port Power Management */ +/* control register.(SPMC) */ +/* */ +/***************************************************************************** */ +#define SPMC_RSTN 0x00000001L +#define SPMC_ASYN 0x00000002L +#define SPMC_WUP1 0x00000004L +#define SPMC_WUP2 0x00000008L +#define SPMC_ASDI2E 0x00000100L +#define SPMC_ESSPD 0x00000200L +#define SPMC_GISPEN 0x00004000L +#define SPMC_GIPPEN 0x00008000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the Configuration Load register. */ +/* (CFLR) */ +/* */ +/***************************************************************************** */ +#define CFLR_CLOCK_SOURCE_MASK 0x00000003L +#define CFLR_CLOCK_SOURCE_AC97 0x00000001L + +#define CFLR_CB0_MASK 0x000000FFL +#define CFLR_CB1_MASK 0x0000FF00L +#define CFLR_CB2_MASK 0x00FF0000L +#define CFLR_CB3_MASK 0xFF000000L +#define CFLR_CB0_SHIFT 0L +#define CFLR_CB1_SHIFT 8L +#define CFLR_CB2_SHIFT 16L +#define CFLR_CB3_SHIFT 24L + +#define IOTCR_DMA0 0x00000000L +#define IOTCR_DMA1 0x00000400L +#define IOTCR_DMA2 0x00000800L +#define IOTCR_DMA3 0x00000C00L +#define IOTCR_CCLS 0x00000100L +#define IOTCR_PCPCI 0x00000200L +#define IOTCR_DDMA 0x00000300L + +#define SBWBS_WBB 0x00000080L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the SRC Slot Assignment Register */ +/* (SRCSA) */ +/* */ +/***************************************************************************** */ +#define SRCSA_PLSS_MASK 0x0000001FL +#define SRCSA_PLSS_SHIFT 0L +#define SRCSA_PRSS_MASK 0x00001F00L +#define SRCSA_PRSS_SHIFT 8L +#define SRCSA_CLSS_MASK 0x001F0000L +#define SRCSA_CLSS_SHIFT 16L +#define SRCSA_CRSS_MASK 0x1F000000L +#define SRCSA_CRSS_SHIFT 24L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the Sound System Power Management */ +/* register.(SSPM) */ +/* */ +/***************************************************************************** */ +#define SSPM_FPDN 0x00000080L +#define SSPM_MIXEN 0x00000040L +#define SSPM_CSRCEN 0x00000020L +#define SSPM_PSRCEN 0x00000010L +#define SSPM_JSEN 0x00000008L +#define SSPM_ACLEN 0x00000004L +#define SSPM_FMEN 0x00000002L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the Sound System Control */ +/* Register. (SSCR) */ +/* */ +/***************************************************************************** */ +#define SSCR_SB 0x00000004L +#define SSCR_HVC 0x00000008L +#define SSCR_LPFIFO 0x00000040L +#define SSCR_LPSRC 0x00000080L +#define SSCR_XLPSRC 0x00000100L +#define SSCR_MVMD 0x00010000L +#define SSCR_MVAD 0x00020000L +#define SSCR_MVLD 0x00040000L +#define SSCR_MVCS 0x00080000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the Clock Control Register 1. */ +/* (CLKCR1) */ +/* */ +/***************************************************************************** */ +#define CLKCR1_DLLSS_MASK 0x0000000CL +#define CLKCR1_DLLSS_SHIFT 2L +#define CLKCR1_DLLP 0x00000010L +#define CLKCR1_SWCE 0x00000020L +#define CLKCR1_DLLOS 0x00000040L +#define CLKCR1_CKRA 0x00010000L +#define CLKCR1_CKRN 0x00020000L +#define CLKCR1_DLLRDY 0x01000000L +#define CLKCR1_CLKON 0x02000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the Sound Blaster Read Buffer */ +/* Status.(SBRBS) */ +/* */ +/***************************************************************************** */ +#define SBRBS_RD_MASK 0x0000007FL +#define SBRBS_RD_SHIFT 0L +#define SBRBS_RBF 0x00000080L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the serial port master control */ +/* register.(SERMC) */ +/* */ +/***************************************************************************** */ +#define SERMC_MSPE 0x00000001L +#define SERMC_PTC_MASK 0x0000000EL +#define SERMC_PTC_SHIFT 1L +#define SERMC_PTC_AC97 0x00000002L +#define SERMC_PLB 0x00000010L +#define SERMC_PXLB 0x00000020L +#define SERMC_LOFV 0x00080000L +#define SERMC_SLB 0x00100000L +#define SERMC_SXLB 0x00200000L +#define SERMC_ODSEN1 0x01000000L +#define SERMC_ODSEN2 0x02000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the General Purpose I/O Register. */ +/* (GPIOR) */ +/* */ +/***************************************************************************** */ +#define GPIOR_VDNS 0x00000001L +#define GPIOR_VUPS 0x00000002L +#define GPIOR_GP1S 0x00000004L +#define GPIOR_GP3S 0x00000008L +#define GPIOR_GPSS 0x00000010L +#define GPIOR_GPPS 0x00000020L +#define GPIOR_GP1D 0x00000400L +#define GPIOR_GP3D 0x00000800L +#define GPIOR_VDNLT 0x00010000L +#define GPIOR_VDNPO 0x00020000L +#define GPIOR_VDNST 0x00040000L +#define GPIOR_VDNW 0x00080000L +#define GPIOR_VUPLT 0x00100000L +#define GPIOR_VUPPO 0x00200000L +#define GPIOR_VUPST 0x00400000L +#define GPIOR_VUPW 0x00800000L +#define GPIOR_GP1OE 0x01000000L +#define GPIOR_GP1PT 0x02000000L +#define GPIOR_GP1ST 0x04000000L +#define GPIOR_GP1W 0x08000000L +#define GPIOR_GP3OE 0x10000000L +#define GPIOR_GP3PT 0x20000000L +#define GPIOR_GP3ST 0x40000000L +#define GPIOR_GP3W 0x80000000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the clock control register 1. */ +/* */ +/***************************************************************************** */ +#define CLKCR1_OSCS 0x00000001L +#define CLKCR1_OSCP 0x00000002L +#define CLKCR1_PLLSS_MASK 0x0000000CL +#define CLKCR1_PLLSS_SERIAL 0x00000000L +#define CLKCR1_PLLSS_CRYSTAL 0x00000004L +#define CLKCR1_PLLSS_PCI 0x00000008L +#define CLKCR1_PLLSS_RESERVED 0x0000000CL +#define CLKCR1_PLLP 0x00000010L +#define CLKCR1_SWCE 0x00000020L +#define CLKCR1_PLLOS 0x00000040L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the feature reporting register. */ +/* */ +/***************************************************************************** */ +#define FRR_FAB_MASK 0x00000003L +#define FRR_MASK_MASK 0x0000001CL +#define FRR_ID_MASK 0x00003000L +#define FRR_FAB_SHIFT 0L +#define FRR_MASK_SHIFT 2L +#define FRR_ID_SHIFT 12L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the serial port 1 configuration */ +/* register. */ +/* */ +/***************************************************************************** */ +#define SERC1_VALUE 0x00000003L +#define SERC1_SO1EN 0x00000001L +#define SERC1_SO1F_MASK 0x0000000EL +#define SERC1_SO1F_CS423X 0x00000000L +#define SERC1_SO1F_AC97 0x00000002L +#define SERC1_SO1F_DAC 0x00000004L +#define SERC1_SO1F_SPDIF 0x00000006L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the serial port 2 configuration */ +/* register. */ +/* */ +/***************************************************************************** */ +#define SERC2_VALUE 0x00000003L +#define SERC2_SI1EN 0x00000001L +#define SERC2_SI1F_MASK 0x0000000EL +#define SERC2_SI1F_CS423X 0x00000000L +#define SERC2_SI1F_AC97 0x00000002L +#define SERC2_SI1F_ADC 0x00000004L +#define SERC2_SI1F_SPDIF 0x00000006L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 control register. */ +/* */ +/***************************************************************************** */ +#define ACCTL_ESYN 0x00000002L +#define ACCTL_VFRM 0x00000004L +#define ACCTL_DCV 0x00000008L +#define ACCTL_CRW 0x00000010L +#define ACCTL_TC 0x00000040L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status register. */ +/* */ +/***************************************************************************** */ +#define ACSTS_CRDY 0x00000001L +#define ACSTS_VSTS 0x00000002L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 output slot valid */ +/* register. */ +/* */ +/***************************************************************************** */ +#define ACOSV_SLV3 0x00000001L +#define ACOSV_SLV4 0x00000002L +#define ACOSV_SLV5 0x00000004L +#define ACOSV_SLV6 0x00000008L +#define ACOSV_SLV7 0x00000010L +#define ACOSV_SLV8 0x00000020L +#define ACOSV_SLV9 0x00000040L +#define ACOSV_SLV10 0x00000080L +#define ACOSV_SLV11 0x00000100L +#define ACOSV_SLV12 0x00000200L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 command address */ +/* register. */ +/* */ +/***************************************************************************** */ +#define ACCAD_CI_MASK 0x0000007FL +#define ACCAD_CI_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 command data register. */ +/* */ +/***************************************************************************** */ +#define ACCDA_CD_MASK 0x0000FFFFL +#define ACCDA_CD_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 input slot valid */ +/* register. */ +/* */ +/***************************************************************************** */ +#define ACISV_ISV3 0x00000001L +#define ACISV_ISV4 0x00000002L +#define ACISV_ISV5 0x00000004L +#define ACISV_ISV6 0x00000008L +#define ACISV_ISV7 0x00000010L +#define ACISV_ISV8 0x00000020L +#define ACISV_ISV9 0x00000040L +#define ACISV_ISV10 0x00000080L +#define ACISV_ISV11 0x00000100L +#define ACISV_ISV12 0x00000200L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status address */ +/* register. */ +/* */ +/***************************************************************************** */ +#define ACSAD_SI_MASK 0x0000007FL +#define ACSAD_SI_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status data register. */ +/* */ +/***************************************************************************** */ +#define ACSDA_SD_MASK 0x0000FFFFL +#define ACSDA_SD_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the I/O trap address and control */ +/* registers (all 12). */ +/* */ +/***************************************************************************** */ +#define IOTAC_SA_MASK 0x0000FFFFL +#define IOTAC_MSK_MASK 0x000F0000L +#define IOTAC_IODC_MASK 0x06000000L +#define IOTAC_IODC_16_BIT 0x00000000L +#define IOTAC_IODC_10_BIT 0x02000000L +#define IOTAC_IODC_12_BIT 0x04000000L +#define IOTAC_WSPI 0x08000000L +#define IOTAC_RSPI 0x10000000L +#define IOTAC_WSE 0x20000000L +#define IOTAC_WE 0x40000000L +#define IOTAC_RE 0x80000000L +#define IOTAC_SA_SHIFT 0L +#define IOTAC_MSK_SHIFT 16L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the PC/PCI master enable */ +/* register. */ +/* */ +/***************************************************************************** */ +#define PCPCIEN_EN 0x00000001L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the joystick poll/trigger */ +/* register. */ +/* */ +/***************************************************************************** */ +#define JSPT_CAX 0x00000001L +#define JSPT_CAY 0x00000002L +#define JSPT_CBX 0x00000004L +#define JSPT_CBY 0x00000008L +#define JSPT_BA1 0x00000010L +#define JSPT_BA2 0x00000020L +#define JSPT_BB1 0x00000040L +#define JSPT_BB2 0x00000080L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the joystick control register. */ +/* */ +/***************************************************************************** */ +#define JSCTL_SP_MASK 0x00000003L +#define JSCTL_SP_SLOW 0x00000000L +#define JSCTL_SP_MEDIUM_SLOW 0x00000001L +#define JSCTL_SP_MEDIUM_FAST 0x00000002L +#define JSCTL_SP_FAST 0x00000003L +#define JSCTL_ARE 0x00000004L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the MIDI control register. */ +/* */ +/***************************************************************************** */ +#define MIDCR_TXE 0x00000001L +#define MIDCR_RXE 0x00000002L +#define MIDCR_RIE 0x00000004L +#define MIDCR_TIE 0x00000008L +#define MIDCR_MLB 0x00000010L +#define MIDCR_MRST 0x00000020L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the MIDI status register. */ +/* */ +/***************************************************************************** */ +#define MIDSR_TBF 0x00000040L +#define MIDSR_RBE 0x00000080L +#define MIDSR_RDA 0x00008000L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the MIDI write port register. */ +/* */ +/***************************************************************************** */ +#define MIDWP_MWD_MASK 0x000000FFL +#define MIDWP_MWD_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the MIDI read port register. */ +/* */ +/***************************************************************************** */ +#define MIDRP_MRD_MASK 0x000000FFL +#define MIDRP_MRD_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the configuration interface */ +/* register. */ +/* */ +/***************************************************************************** */ +#define CFGI_CLK 0x00000001L +#define CFGI_DOUT 0x00000002L +#define CFGI_DIN_EEN 0x00000004L +#define CFGI_EELD 0x00000008L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the subsystem ID and vendor ID */ +/* register. */ +/* */ +/***************************************************************************** */ +#define SSVID_VID_MASK 0x0000FFFFL +#define SSVID_SID_MASK 0xFFFF0000L +#define SSVID_VID_SHIFT 0L +#define SSVID_SID_SHIFT 16L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the GPIO pin interface register. */ +/* */ +/***************************************************************************** */ +#define GPIOR_VOLDN 0x00000001L +#define GPIOR_VOLUP 0x00000002L +#define GPIOR_SI2D 0x00000004L +#define GPIOR_SI2OE 0x00000008L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status register 2. */ +/* */ +/***************************************************************************** */ +#define ACSTS2_CRDY 0x00000001L +#define ACSTS2_VSTS 0x00000002L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 input slot valid */ +/* register 2. */ +/* */ +/***************************************************************************** */ +#define ACISV2_ISV3 0x00000001L +#define ACISV2_ISV4 0x00000002L +#define ACISV2_ISV5 0x00000004L +#define ACISV2_ISV6 0x00000008L +#define ACISV2_ISV7 0x00000010L +#define ACISV2_ISV8 0x00000020L +#define ACISV2_ISV9 0x00000040L +#define ACISV2_ISV10 0x00000080L +#define ACISV2_ISV11 0x00000100L +#define ACISV2_ISV12 0x00000200L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status address */ +/* register 2. */ +/* */ +/***************************************************************************** */ +#define ACSAD2_SI_MASK 0x0000007FL +#define ACSAD2_SI_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the AC97 status data register 2. */ +/* */ +/***************************************************************************** */ +#define ACSDA2_SD_MASK 0x0000FFFFL +#define ACSDA2_SD_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the I/O trap control register. */ +/* */ +/***************************************************************************** */ +#define IOTCR_ITD 0x00000001L +#define IOTCR_HRV 0x00000002L +#define IOTCR_SRV 0x00000004L +#define IOTCR_DTI 0x00000008L +#define IOTCR_DFI 0x00000010L +#define IOTCR_DDP 0x00000020L +#define IOTCR_JTE 0x00000040L +#define IOTCR_PPE 0x00000080L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the I/O trap address and control */ +/* registers for Hardware Master Volume. */ +/* */ +/***************************************************************************** */ +#define IOTGP_SA_MASK 0x0000FFFFL +#define IOTGP_MSK_MASK 0x000F0000L +#define IOTGP_IODC_MASK 0x06000000L +#define IOTGP_IODC_16_BIT 0x00000000L +#define IOTGP_IODC_10_BIT 0x02000000L +#define IOTGP_IODC_12_BIT 0x04000000L +#define IOTGP_WSPI 0x08000000L +#define IOTGP_RSPI 0x10000000L +#define IOTGP_WSE 0x20000000L +#define IOTGP_WE 0x40000000L +#define IOTGP_RE 0x80000000L +#define IOTGP_SA_SHIFT 0L +#define IOTGP_MSK_SHIFT 16L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the I/O trap address and control */ +/* registers for Sound Blaster */ +/* */ +/***************************************************************************** */ +#define IOTSB_SA_MASK 0x0000FFFFL +#define IOTSB_MSK_MASK 0x000F0000L +#define IOTSB_IODC_MASK 0x06000000L +#define IOTSB_IODC_16_BIT 0x00000000L +#define IOTSB_IODC_10_BIT 0x02000000L +#define IOTSB_IODC_12_BIT 0x04000000L +#define IOTSB_WSPI 0x08000000L +#define IOTSB_RSPI 0x10000000L +#define IOTSB_WSE 0x20000000L +#define IOTSB_WE 0x40000000L +#define IOTSB_RE 0x80000000L +#define IOTSB_SA_SHIFT 0L +#define IOTSB_MSK_SHIFT 16L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the I/O trap address and control */ +/* registers for FM. */ +/* */ +/***************************************************************************** */ +#define IOTFM_SA_MASK 0x0000FFFFL +#define IOTFM_MSK_MASK 0x000F0000L +#define IOTFM_IODC_MASK 0x06000000L +#define IOTFM_IODC_16_BIT 0x00000000L +#define IOTFM_IODC_10_BIT 0x02000000L +#define IOTFM_IODC_12_BIT 0x04000000L +#define IOTFM_WSPI 0x08000000L +#define IOTFM_RSPI 0x10000000L +#define IOTFM_WSE 0x20000000L +#define IOTFM_WE 0x40000000L +#define IOTFM_RE 0x80000000L +#define IOTFM_SA_SHIFT 0L +#define IOTFM_MSK_SHIFT 16L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the PC/PCI request register. */ +/* */ +/***************************************************************************** */ +#define PCPRR_RDC_MASK 0x00000007L +#define PCPRR_REQ 0x00008000L +#define PCPRR_RDC_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the PC/PCI grant register. */ +/* */ +/***************************************************************************** */ +#define PCPGR_GDC_MASK 0x00000007L +#define PCPGR_VL 0x00008000L +#define PCPGR_GDC_SHIFT 0L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the PC/PCI Control Register. */ +/* */ +/***************************************************************************** */ +#define PCPCR_EN 0x00000001L + +/***************************************************************************** */ +/* */ +/* The following defines are for the flags in the debug index register. */ +/* */ +/***************************************************************************** */ +#define DREG_REGID_MASK 0x0000007FL +#define DREG_DEBUG 0x00000080L +#define DREG_RGBK_MASK 0x00000700L +#define DREG_TRAP 0x00000800L +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_TRAPX 0x00001000L +#endif +#endif +#define DREG_REGID_SHIFT 0L +#define DREG_RGBK_SHIFT 8L +#define DREG_RGBK_REGID_MASK 0x0000077FL +#define DREG_REGID_R0 0x00000010L +#define DREG_REGID_R1 0x00000011L +#define DREG_REGID_R2 0x00000012L +#define DREG_REGID_R3 0x00000013L +#define DREG_REGID_R4 0x00000014L +#define DREG_REGID_R5 0x00000015L +#define DREG_REGID_R6 0x00000016L +#define DREG_REGID_R7 0x00000017L +#define DREG_REGID_R8 0x00000018L +#define DREG_REGID_R9 0x00000019L +#define DREG_REGID_RA 0x0000001AL +#define DREG_REGID_RB 0x0000001BL +#define DREG_REGID_RC 0x0000001CL +#define DREG_REGID_RD 0x0000001DL +#define DREG_REGID_RE 0x0000001EL +#define DREG_REGID_RF 0x0000001FL +#define DREG_REGID_RA_BUS_LOW 0x00000020L +#define DREG_REGID_RA_BUS_HIGH 0x00000038L +#define DREG_REGID_YBUS_LOW 0x00000050L +#define DREG_REGID_YBUS_HIGH 0x00000058L +#define DREG_REGID_TRAP_0 0x00000100L +#define DREG_REGID_TRAP_1 0x00000101L +#define DREG_REGID_TRAP_2 0x00000102L +#define DREG_REGID_TRAP_3 0x00000103L +#define DREG_REGID_TRAP_4 0x00000104L +#define DREG_REGID_TRAP_5 0x00000105L +#define DREG_REGID_TRAP_6 0x00000106L +#define DREG_REGID_TRAP_7 0x00000107L +#define DREG_REGID_INDIRECT_ADDRESS 0x0000010EL +#define DREG_REGID_TOP_OF_STACK 0x0000010FL +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_8 0x00000110L +#define DREG_REGID_TRAP_9 0x00000111L +#define DREG_REGID_TRAP_10 0x00000112L +#define DREG_REGID_TRAP_11 0x00000113L +#define DREG_REGID_TRAP_12 0x00000114L +#define DREG_REGID_TRAP_13 0x00000115L +#define DREG_REGID_TRAP_14 0x00000116L +#define DREG_REGID_TRAP_15 0x00000117L +#define DREG_REGID_TRAP_16 0x00000118L +#define DREG_REGID_TRAP_17 0x00000119L +#define DREG_REGID_TRAP_18 0x0000011AL +#define DREG_REGID_TRAP_19 0x0000011BL +#define DREG_REGID_TRAP_20 0x0000011CL +#define DREG_REGID_TRAP_21 0x0000011DL +#define DREG_REGID_TRAP_22 0x0000011EL +#define DREG_REGID_TRAP_23 0x0000011FL +#endif +#endif +#define DREG_REGID_RSA0_LOW 0x00000200L +#define DREG_REGID_RSA0_HIGH 0x00000201L +#define DREG_REGID_RSA1_LOW 0x00000202L +#define DREG_REGID_RSA1_HIGH 0x00000203L +#define DREG_REGID_RSA2 0x00000204L +#define DREG_REGID_RSA3 0x00000205L +#define DREG_REGID_RSI0_LOW 0x00000206L +#define DREG_REGID_RSI0_HIGH 0x00000207L +#define DREG_REGID_RSI1 0x00000208L +#define DREG_REGID_RSI2 0x00000209L +#define DREG_REGID_SAGUSTATUS 0x0000020AL +#define DREG_REGID_RSCONFIG01_LOW 0x0000020BL +#define DREG_REGID_RSCONFIG01_HIGH 0x0000020CL +#define DREG_REGID_RSCONFIG23_LOW 0x0000020DL +#define DREG_REGID_RSCONFIG23_HIGH 0x0000020EL +#define DREG_REGID_RSDMA01E 0x0000020FL +#define DREG_REGID_RSDMA23E 0x00000210L +#define DREG_REGID_RSD0_LOW 0x00000211L +#define DREG_REGID_RSD0_HIGH 0x00000212L +#define DREG_REGID_RSD1_LOW 0x00000213L +#define DREG_REGID_RSD1_HIGH 0x00000214L +#define DREG_REGID_RSD2_LOW 0x00000215L +#define DREG_REGID_RSD2_HIGH 0x00000216L +#define DREG_REGID_RSD3_LOW 0x00000217L +#define DREG_REGID_RSD3_HIGH 0x00000218L +#define DREG_REGID_SRAR_HIGH 0x0000021AL +#define DREG_REGID_SRAR_LOW 0x0000021BL +#define DREG_REGID_DMA_STATE 0x0000021CL +#define DREG_REGID_CURRENT_DMA_STREAM 0x0000021DL +#define DREG_REGID_NEXT_DMA_STREAM 0x0000021EL +#define DREG_REGID_CPU_STATUS 0x00000300L +#define DREG_REGID_MAC_MODE 0x00000301L +#define DREG_REGID_STACK_AND_REPEAT 0x00000302L +#define DREG_REGID_INDEX0 0x00000304L +#define DREG_REGID_INDEX1 0x00000305L +#define DREG_REGID_DMA_STATE_0_3 0x00000400L +#define DREG_REGID_DMA_STATE_4_7 0x00000404L +#define DREG_REGID_DMA_STATE_8_11 0x00000408L +#define DREG_REGID_DMA_STATE_12_15 0x0000040CL +#define DREG_REGID_DMA_STATE_16_19 0x00000410L +#define DREG_REGID_DMA_STATE_20_23 0x00000414L +#define DREG_REGID_DMA_STATE_24_27 0x00000418L +#define DREG_REGID_DMA_STATE_28_31 0x0000041CL +#define DREG_REGID_DMA_STATE_32_35 0x00000420L +#define DREG_REGID_DMA_STATE_36_39 0x00000424L +#define DREG_REGID_DMA_STATE_40_43 0x00000428L +#define DREG_REGID_DMA_STATE_44_47 0x0000042CL +#define DREG_REGID_DMA_STATE_48_51 0x00000430L +#define DREG_REGID_DMA_STATE_52_55 0x00000434L +#define DREG_REGID_DMA_STATE_56_59 0x00000438L +#define DREG_REGID_DMA_STATE_60_63 0x0000043CL +#define DREG_REGID_DMA_STATE_64_67 0x00000440L +#define DREG_REGID_DMA_STATE_68_71 0x00000444L +#define DREG_REGID_DMA_STATE_72_75 0x00000448L +#define DREG_REGID_DMA_STATE_76_79 0x0000044CL +#define DREG_REGID_DMA_STATE_80_83 0x00000450L +#define DREG_REGID_DMA_STATE_84_87 0x00000454L +#define DREG_REGID_DMA_STATE_88_91 0x00000458L +#define DREG_REGID_DMA_STATE_92_95 0x0000045CL +#define DREG_REGID_TRAP_SELECT 0x00000500L +#define DREG_REGID_TRAP_WRITE_0 0x00000500L +#define DREG_REGID_TRAP_WRITE_1 0x00000501L +#define DREG_REGID_TRAP_WRITE_2 0x00000502L +#define DREG_REGID_TRAP_WRITE_3 0x00000503L +#define DREG_REGID_TRAP_WRITE_4 0x00000504L +#define DREG_REGID_TRAP_WRITE_5 0x00000505L +#define DREG_REGID_TRAP_WRITE_6 0x00000506L +#define DREG_REGID_TRAP_WRITE_7 0x00000507L +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_WRITE_8 0x00000510L +#define DREG_REGID_TRAP_WRITE_9 0x00000511L +#define DREG_REGID_TRAP_WRITE_10 0x00000512L +#define DREG_REGID_TRAP_WRITE_11 0x00000513L +#define DREG_REGID_TRAP_WRITE_12 0x00000514L +#define DREG_REGID_TRAP_WRITE_13 0x00000515L +#define DREG_REGID_TRAP_WRITE_14 0x00000516L +#define DREG_REGID_TRAP_WRITE_15 0x00000517L +#define DREG_REGID_TRAP_WRITE_16 0x00000518L +#define DREG_REGID_TRAP_WRITE_17 0x00000519L +#define DREG_REGID_TRAP_WRITE_18 0x0000051AL +#define DREG_REGID_TRAP_WRITE_19 0x0000051BL +#define DREG_REGID_TRAP_WRITE_20 0x0000051CL +#define DREG_REGID_TRAP_WRITE_21 0x0000051DL +#define DREG_REGID_TRAP_WRITE_22 0x0000051EL +#define DREG_REGID_TRAP_WRITE_23 0x0000051FL +#endif +#endif +#define DREG_REGID_MAC0_ACC0_LOW 0x00000600L +#define DREG_REGID_MAC0_ACC1_LOW 0x00000601L +#define DREG_REGID_MAC0_ACC2_LOW 0x00000602L +#define DREG_REGID_MAC0_ACC3_LOW 0x00000603L +#define DREG_REGID_MAC1_ACC0_LOW 0x00000604L +#define DREG_REGID_MAC1_ACC1_LOW 0x00000605L +#define DREG_REGID_MAC1_ACC2_LOW 0x00000606L +#define DREG_REGID_MAC1_ACC3_LOW 0x00000607L +#define DREG_REGID_MAC0_ACC0_MID 0x00000608L +#define DREG_REGID_MAC0_ACC1_MID 0x00000609L +#define DREG_REGID_MAC0_ACC2_MID 0x0000060AL +#define DREG_REGID_MAC0_ACC3_MID 0x0000060BL +#define DREG_REGID_MAC1_ACC0_MID 0x0000060CL +#define DREG_REGID_MAC1_ACC1_MID 0x0000060DL +#define DREG_REGID_MAC1_ACC2_MID 0x0000060EL +#define DREG_REGID_MAC1_ACC3_MID 0x0000060FL +#define DREG_REGID_MAC0_ACC0_HIGH 0x00000610L +#define DREG_REGID_MAC0_ACC1_HIGH 0x00000611L +#define DREG_REGID_MAC0_ACC2_HIGH 0x00000612L +#define DREG_REGID_MAC0_ACC3_HIGH 0x00000613L +#define DREG_REGID_MAC1_ACC0_HIGH 0x00000614L +#define DREG_REGID_MAC1_ACC1_HIGH 0x00000615L +#define DREG_REGID_MAC1_ACC2_HIGH 0x00000616L +#define DREG_REGID_MAC1_ACC3_HIGH 0x00000617L +#define DREG_REGID_RSHOUT_LOW 0x00000620L +#define DREG_REGID_RSHOUT_MID 0x00000628L +#define DREG_REGID_RSHOUT_HIGH 0x00000630L + +#endif /* _H_HWDEFS */ diff --git a/kernel/drv/oss_cs4281/oss_cs4281.c b/kernel/drv/oss_cs4281/oss_cs4281.c new file mode 100644 index 0000000..45ceaa7 --- /dev/null +++ b/kernel/drv/oss_cs4281/oss_cs4281.c @@ -0,0 +1,1061 @@ +/* + * Purpose: Driver for Crystal 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_cs4281_cfg.h" +#include "midi_core.h" +#include "ac97.h" +#include "oss_pci.h" +#include "cs4281.h" + +#define CRYSTAL_VENDOR_ID 0x1013 +#define CRYSTAL_CS4281_ID 0x6005 + +#if 1 +#define WRITEB(a,d) devc->bRegister0[a] = d +#define READB(a) devc->bRegister0[a] +#define WRITEW(a,d) devc->wRegister0[a>>1] = d +#define READW(a) devc->wRegister0[a>>1] +#define READL(a) (devc->dwRegister0[a>>2]) +#define WRITEL(a, d) devc->dwRegister0[a>>2] = d +#else +#define WRITEB(a,d) PCI_WRITEB(devc->osdev, d, devc->bRegister0[a]) +#define READB(a) PCI_READB(devc->osdev, devc->bRegister0[a]) +#define WRITEW(a,d) PCI_WRITEW(devc->osdev, d, devc->wRegister0[a>>1]) +#define READW(a) PCI_READW(devc->osdev, devc->wRegister0[a>>1]) +#define READL(a) PCI_READL(devc->osdev, devc->dwRegister0[a>>2]) +#define WRITEL(a, d) PCI_WRITEL(devc->osdev, d, devc->dwRegister0[a>>2]) +#endif + +#ifdef OSS_BIG_ENDIAN +static unsigned int +be_swap (unsigned int x) +{ + return ((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24); +} + +#define LSWAP(x) be_swap(x) +#else +#define LSWAP(x) x +#endif + +#define MAX_PORTC 2 + +typedef struct cs4281_portc +{ + int speed, bits, channels; + int open_mode; + int trigger_bits; + int audio_enabled; + int audiodev; +} +cs4281_portc; + +typedef struct cs4281_devc +{ + oss_device_t *osdev; + char *chip_name; + oss_native_word bar0addr, bar1addr; + unsigned int *bar0virt, *bar1virt; + volatile unsigned int *dwRegister0, *dwRegister1; + volatile unsigned short *wRegister0, *wRegister1; + volatile unsigned char *bRegister0, *bRegister1; + int irq; + volatile unsigned char intr_mask; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* MIDI */ + int midi_opened; + int midi_dev; + oss_midi_inputbyte_t midi_input_intr; + + /* Mixer parameters */ + ac97_devc ac97devc; + int mixer_dev; + + /* Audio parameters */ + cs4281_portc portc[MAX_PORTC]; + int open_mode; + int fm_attached, mpu_attached; +} +cs4281_devc; + + + +static int +ac97_read (void *devc_, int reg) +{ + cs4281_devc *devc = devc_; + int count; + oss_native_word status, value; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Make sure that there is not data sitting around from a previous + * uncompleted access. ACSDA = Status Data Register = 47Ch + */ + status = READL (BA0_ACSDA); + /* Get the actual AC97 register from the offset */ + WRITEL (BA0_ACCAD, reg); + WRITEL (BA0_ACCDA, 0); + WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN); + + /* Wait for the read to occur. */ + for (count = 0; count < 500; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (10); + /* + * Now, check to see if the read has completed. + * ACCTL = 460h, DCV should be reset by now and 460h = 17h + */ + status = READL (BA0_ACCTL); + if (!(status & ACCTL_DCV)) + { + break; + } + } + + /* Make sure the read completed. */ + if (status & ACCTL_DCV) + { + cmn_err (CE_WARN, "AC97 Read Timedout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* Wait for the valid status bit to go active. */ + + for (count = 0; count < 500; count++) + { + /* + * Read the AC97 status register. + * ACSTS = Status Register = 464h + */ + status = READL (BA0_ACSTS); + /* + * See if we have valid status. + * VSTS - Valid Status + */ + if (status & ACSTS_VSTS) + break; + + /* + * Wait for a short while. + */ + oss_udelay (10); + } + /* Make sure we got valid status. */ + if (!(status & ACSTS_VSTS)) + { + cmn_err (CE_WARN, "AC97 Read Timedout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* + * Read the data returned from the AC97 register. + * ACSDA = Status Data Register = 474h + */ + value = READL (BA0_ACSDA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (value); +} + +static int +ac97_write (void *devc_, int reg, int data) +{ + cs4281_devc *devc = devc_; + int count; + oss_native_word status, flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + WRITEL (BA0_ACCAD, reg); + WRITEL (BA0_ACCDA, data); + WRITEL (BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN); + for (count = 0; count < 500; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (10); + /* Now, check to see if the write has completed. */ + /* ACCTL = 460h, DCV should be reset by now and 460h = 07h */ + status = READL (BA0_ACCTL); + if (!(status & ACCTL_DCV)) + break; + } + + /* write didn't completed. */ + if (status & ACCTL_DCV) + { + cmn_err (CE_WARN, "AC97 Write timeout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + + +static int +cs4281intr (oss_device_t * osdev) +{ + cs4281_devc *devc = (cs4281_devc *) osdev->devc; + cs4281_portc *portc; + oss_native_word status, uart_stat; + int i; + int serviced = 0; + +/* Read the Interrupt Status Register */ + status = READL (BA0_HISR); + +/* + * This is the MIDI read interrupt service. First check to see + * if the MIDI interrupt flag is set in the HISR register. Next + * read the MIDI status register. See if Receive Buffer Empty + * is empty (0=FIFO Not empty, 1=FIFO is empty + */ + if ((devc->midi_opened & OPEN_READ) && (status & HISR_MIDI)) + { + serviced = 1; + uart_stat = READL (BA0_MIDSR); +/* + * read one byte of MIDI data and hand it off the the sequencer module + * to decode this. Keep checking to see if the data is available. Stop + * when no more data is there in the FIFO. + */ + while (!(uart_stat & MIDSR_RBE)) + { + unsigned char d; + d = READL (BA0_MIDRP); + + if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, d); + uart_stat = READL (BA0_MIDSR); + } + } +/* Audio interrupt handling */ + if (status & (HISR_INTENA | HISR_DMAI)) + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + if ((status & HISR_DMA0) && (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + dmap_t *dmapout = audio_engines[portc->audiodev]->dmap_out; + unsigned int currdac; + int n; + + serviced = 1; + READL (BA0_HDSR0); /* ack the DMA interrupt */ + currdac = READL (BA0_DCA0) - dmapout->dmabuf_phys; + currdac /= dmapout->fragment_size; + n = 0; + while (dmap_get_qhead (dmapout) != currdac + && n++ < dmapout->nfrags) + oss_audio_outputintr (portc->audiodev, 1); + } + + if ((status & HISR_DMA1) && (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + dmap_t *dmapin = audio_engines[portc->audiodev]->dmap_in; + unsigned int curradc; + int n; + + serviced = 1; + READL (BA0_HDSR1); /* ack the DMA interrupt */ + curradc = READL (BA0_DCA1) - dmapin->dmabuf_phys; + curradc /= dmapin->fragment_size; + n = 0; + while (dmap_get_qtail (dmapin) != curradc && n++ < dmapin->nfrags) + oss_audio_inputintr (portc->audiodev, 0); + } + WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM); + } + return serviced; +} + +static int +cs4281_audio_set_rate (int dev, int arg) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + if (arg == 0) + return portc->speed; + if (arg > 48000) + arg = 48000; + if (arg < 6023) + arg = 6023; + portc->speed = arg; + return portc->speed; +} + +static short +cs4281_audio_set_channels (int dev, short arg) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + return portc->channels; +} + +static unsigned int +cs4281_audio_set_format (int dev, unsigned int arg) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + if (arg == 0) + return portc->bits; + if (!(arg & (AFMT_U8 | AFMT_S16_LE))) + return portc->bits; + portc->bits = arg; + return portc->bits; +} + +/*ARGSUSED*/ +static int +cs4281_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void cs4281_audio_trigger (int dev, int state); +static void +cs4281_audio_reset (int dev) +{ + cs4281_audio_trigger (dev, 0); +} + +static void +cs4281_audio_reset_input (int dev) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +cs4281_audio_reset_output (int dev) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + cs4281_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +cs4281_audio_open (int dev, int mode, int open_flags) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + cs4281_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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +cs4281_audio_close (int dev, int mode) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + cs4281_devc *devc = audio_engines[dev]->devc; + cs4281_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +cs4281_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +cs4281_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cs4281_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +cs4281_audio_trigger (int dev, int state) +{ + cs4281_devc *devc = audio_engines[dev]->devc; + cs4281_portc *portc = audio_engines[dev]->portc; + oss_native_word tmp1; + oss_native_word flags; + 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)) + { + /* Clear DMA0 channel Mask bit. Start Playing. */ + tmp1 = READL (BA0_DCR0) & ~DCRn_MSK; /*enable DMA */ + WRITEL (BA0_DCR0, tmp1); /* (154h) */ + WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM); /*enable intr */ + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + tmp1 = READL (BA0_DCR0) & ~DCRn_MSK; + WRITEL (BA0_DCR0, tmp1 | DCRn_MSK); + } + } + } + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Clear DMA1 channel Mask bit. Start recording. */ + tmp1 = READL (BA0_DCR1) & ~DCRn_MSK; + WRITEL (BA0_DCR1, tmp1); /* (15ch) */ + WRITEL (BA0_HICR, HICR_IEV | HICR_CHGM); /*Set INTENA=1. */ + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + tmp1 = READL (BA0_DCR1) & ~DCRn_MSK; + WRITEL (BA0_DCR1, tmp1 | DCRn_MSK); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +cs4281_rate (oss_native_word rate) +{ + int val = 0; + + switch (rate) + { + case 8000: + val = 5; + break; + case 11025: + val = 4; + break; + case 16000: + val = 3; + break; + case 22050: + val = 2; + break; + case 44100: + val = 1; + break; + case 48000: + val = 0; + break; + default: + val = 1536000 / rate; + break; + } + return val; +} + +/*ARGSUSED*/ +static int +cs4281_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + cs4281_devc *devc = audio_engines[dev]->devc; + cs4281_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int count = dmap->bytes_in_use; + oss_native_word recordFormat; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* set the record rate */ + WRITEL (BA0_ADCSR, cs4281_rate (portc->speed)); /* (748h) */ + /* Start with defaults for the record format */ + /* reg & modify them for the current case. */ + recordFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE; + if (portc->channels == 1) /* If mono, */ + recordFormat |= DMRn_MONO; /* Turn on mono bit. */ + if (portc->bits == 8) /* If 8-bit, */ + recordFormat |= (DMRn_SIZE8 | DMRn_USIGN); /* turn on 8bit/unsigned. */ + WRITEL (BA0_DMR1, recordFormat); + /* set input gain to 0db */ + /* ac97_write(devc, BA0_AC97_RECORD_GAIN, 0x0808); */ + if (portc->channels == 2) /* If stereo, */ + count /= 2; /* halve DMA count(stereo); */ + if (portc->bits == 16) /* If 16-bit, */ + count /= 2; + /* Set the physical play buffer address DMA1 Base & Current. */ + WRITEL (BA0_DBA1, dmap->dmabuf_phys); /* (118h) */ + /* Set the sample count(-1) in DMA Base Count register 1. */ + WRITEL (BA0_DBC1, count - 1); + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +cs4281_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + cs4281_devc *devc = audio_engines[dev]->devc; + cs4281_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int count = dmap->bytes_in_use; + oss_native_word playFormat; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* Set the sample rate converter */ + WRITEL (BA0_DACSR, cs4281_rate (portc->speed)); + playFormat = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ | (1 << 6); + if (portc->channels == 1) /* If stereo, */ + playFormat |= DMRn_MONO; /* Turn on mono bit. */ + if (portc->bits == 8) /* If 16-bit, */ + playFormat |= (DMRn_SIZE8 | DMRn_USIGN); /* turn on 8-bit/unsigned. */ + WRITEL (BA0_DMR0, playFormat); /* (150h) */ + if (portc->channels == 2) /* If stereo, */ + count /= 2; /* halve DMA count(stereo); */ + if (portc->bits == 16) /* If 16-bit, */ + count /= 2; + /* Set the physical play buffer address DMA0 Base & Current. */ + WRITEL (BA0_DBA0, dmap->dmabuf_phys & ~0x3); /* (118h) */ + /* Set the sample count(-1) in DMA Base Count register 0. */ + WRITEL (BA0_DBC0, count - 1); + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +cs4281_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + cs4281_devc *devc = audio_engines[dev]->devc; + unsigned int ptr = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + if (direction == PCM_ENABLE_OUTPUT) + { + ptr = READL (BA0_DCA0); + } + if (direction == PCM_ENABLE_INPUT) + { + ptr = READL (BA0_DCA1); + } + ptr -= dmap->dmabuf_phys; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + +static audiodrv_t cs4281_audio_driver = { + cs4281_audio_open, + cs4281_audio_close, + cs4281_audio_output_block, + cs4281_audio_start_input, + cs4281_audio_ioctl, + cs4281_audio_prepare_for_input, + cs4281_audio_prepare_for_output, + cs4281_audio_reset, + NULL, + NULL, + cs4281_audio_reset_input, + cs4281_audio_reset_output, + cs4281_audio_trigger, + cs4281_audio_set_rate, + cs4281_audio_set_format, + cs4281_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* cs4281_alloc_buffer, */ + NULL, /* cs4281_free_buffer, */ + NULL, + NULL, + cs4281_get_buffer_pointer +}; + +/***********************MIDI PORT ROUTINES ****************/ +/*ARGSUSED*/ +static int +cs4281_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc; + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + /* first reset the MIDI port */ + WRITEL (BA0_MIDCR, 0x10); + WRITEL (BA0_MIDCR, 0x00); + /* Now check if we're in Read or Write mode */ + if (mode & OPEN_READ) + { + /* enable MIDI Input intr and receive enable */ + WRITEL (BA0_MIDCR, MIDCR_RXE | MIDCR_RIE); + } + + if (mode & OPEN_WRITE) + { + /* enable MIDI transmit enable */ + WRITEL (BA0_MIDCR, MIDCR_TXE); + } + return 0; +} + +/*ARGSUSED*/ +static void +cs4281_midi_close (int dev, int mode) +{ + cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc; +/* Reset the device*/ + WRITEL (BA0_MIDCR, 0x10); + WRITEL (BA0_MIDCR, 0x00); + devc->midi_opened = 0; +} + +static int +cs4281_midi_out (int dev, unsigned char midi_byte) +{ + cs4281_devc *devc = (cs4281_devc *) midi_devs[dev]->devc; + unsigned char uart_stat = READL (BA0_MIDSR); +/* Check if Transmit buffer full flag is set - if so return */ + if ((uart_stat & MIDSR_TBF)) + return 0; +/* Now put the MIDI databyte in the write port */ + WRITEL (BA0_MIDWP, midi_byte); + return 1; +} + +/*ARGSUSED*/ +static int +cs4281_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t cs4281_midi_driver = { + cs4281_midi_open, + cs4281_midi_close, + cs4281_midi_ioctl, + cs4281_midi_out +}; + +static int +init_cs4281 (cs4281_devc * devc) +{ + + int my_mixer, i; + oss_native_word dwAC97SlotID, tmp1; + int first_dev = 0; +/****************BEGIN HARDWARE INIT*****************/ + /* Setup CFLR */ + tmp1 = READL (BA0_CFLR); + if (tmp1 != 0x01) + { + WRITEL (BA0_CFLR, 0x01); /*set up AC97 mode */ + tmp1 = READL (BA0_CFLR); + if (tmp1 != 0x01) + { + tmp1 = READL (BA0_CWPR); + if (tmp1 != 0x4281) + WRITEL (BA0_CWPR, 0x4281); + tmp1 = READL (BA0_CWPR); + if (tmp1 != 0x4281) + { + cmn_err (CE_WARN, "Resetting AC97 failed\n"); + return OSS_EIO; + } + WRITEL (BA0_CFLR, 0x1); + tmp1 = READL (BA0_CFLR); + if (tmp1 != 0x1) + { + cmn_err (CE_WARN, "Resetting AC97 still fails\n"); + return OSS_EIO; + } + } + } + /* Setup the FM and Joystick trap address for Legacy emulation */ + WRITEL (BA0_IOTCR, 0x1); + WRITEL (BA0_IOTFM, 0xc0030388); + WRITEL (BA0_IOTGP, 0xc0070200); + /**************************************** */ + /* Set up the Sound System Configuration */ + /**************************************** */ + /* Set the 'Configuration Write Protect' register */ + /* to 4281h. Allows vendor-defined configuration */ + /* space between 0e4h and 0ffh to be written. */ + WRITEL (BA0_CWPR, 0x4281); /* (3e0h) */ + if ((tmp1 = READL (BA0_SERC1)) != (SERC1_SO1EN | SERC1_SO1F_AC97)) + { + cmn_err (CE_WARN, "SERC1: AC97 check failed\n"); + return OSS_EIO; + } + /* setup power management to full power */ + WRITEL (BA0_SSPM, 0x7E); + /* First, blast the clock control register to zero so that the */ + /* PLL starts out in a known state, and blast the master serial */ + /* port control register to zero so that the serial ports also */ + /* start out in a known state. */ + WRITEL (BA0_CLKCR1, 0); /* (400h) */ + WRITEL (BA0_SERMC, 0); /* (420h) */ + /* (1) Drive the ARST# pin low for a minimum of 1uS (as defined in */ + /* the AC97 spec) and then drive it high. This is done for non */ + /* AC97 modes since there might be logic external to the CS461x */ + /* that uses the ARST# line for a reset. */ + WRITEL (BA0_ACCTL, 0); + oss_udelay (50); + WRITEL (BA0_SPMC, 0); /* (3ech) */ + oss_udelay (50); + WRITEL (BA0_SPMC, SPMC_RSTN); + oss_udelay (50000); + WRITEL (BA0_SERMC, SERMC_PTC_AC97 | SERMC_MSPE | 0x10000); + /* (3) Turn on the Sound System Clocks. */ + WRITEL (BA0_CLKCR1, CLKCR1_DLLP); /* (400h) */ + /* Wait for the PLL to stabilize. */ + oss_udelay (50000); + /* Turn on clocking of the core (CLKCR1(400h) = 0x00000030) */ + WRITEL (BA0_CLKCR1, CLKCR1_DLLP | CLKCR1_SWCE); + /* (5) Wait for clock stabilization. */ + for (tmp1 = 0; tmp1 < 100; tmp1++) + { + if (READL (BA0_CLKCR1) & CLKCR1_DLLRDY) + break; + oss_udelay (50000); + } + if (!(READL (BA0_CLKCR1) & CLKCR1_DLLRDY)) + { + cmn_err (CE_WARN, "DLLRDY Clock not ready\n"); + return OSS_EIO; + } + /* (6) Enable ASYNC generation. */ + WRITEL (BA0_ACCTL, ACCTL_ESYN); /* (460h) */ + /* Now wait 'for a short while' to allow the AC97 */ + /* part to start generating bit clock. (so we don't */ + /* Try to start the PLL without an input clock.) */ + /* (7) Wait for the codec ready signal from the AC97 codec. */ + for (tmp1 = 0; tmp1 < 100; tmp1++) + { + /* Delay a mil to let things settle out and */ + /* to prevent retrying the read too quickly. */ + if (READL (BA0_ACSTS) & ACSTS_CRDY) /* If ready, (464h) */ + break; /* exit the 'for' loop. */ + oss_udelay (50000); + } + if (!(READL (BA0_ACSTS) & ACSTS_CRDY)) /* If never came ready, */ + { + cmn_err (CE_WARN, "AC97 not ready\n"); + return OSS_EIO; /* exit initialization. */ + } + /* (8) Assert the 'valid frame' signal so we can */ + /* begin sending commands to the AC97 codec. */ + WRITEL (BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN); /* (460h) */ + + /* (11) Wait until we've sampled input slots 3 & 4 as valid, meaning */ + /* that the codec is pumping ADC data across the AC link. */ + for (tmp1 = 0; tmp1 < 100; tmp1++) + { + /* Read the input slot valid register; See */ + /* if input slots 3 and 4 are valid yet. */ + if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == /* (474h) */ + (ACISV_ISV3 | ACISV_ISV4)) + break; /* Exit the 'for' if slots are valid. */ + oss_udelay (50000); + } + /* If we never got valid data, exit initialization. */ + if ((READL (BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) != + (ACISV_ISV3 | ACISV_ISV4)) + { + cmn_err (CE_WARN, "AC97 Slot not valid\n"); + return OSS_EIO; /* If no valid data, exit initialization. */ + } + /* (12) Start digital data transfer of audio data to the codec. */ + WRITEL (BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); /* (468h) */ + + /* For playback, we map AC97 slot 3 and 4(Left */ + /* & Right PCM playback) to DMA Channel 0. */ + /* Set the fifo to be 31 bytes at offset zero. */ + dwAC97SlotID = 0x01001F00; /* FCR0.RS[4:0]=1(=>slot4, right PCM playback). */ + /* FCR0.LS[4:0]=0(=>slot3, left PCM playback). */ + /* FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. */ + WRITEL (BA0_FCR0, dwAC97SlotID); /* (180h) */ + WRITEL (BA0_FCR0, dwAC97SlotID | FCRn_FEN); /* Turn on FIFO Enable. */ + /* For capture, we map AC97 slot 10 and 11(Left */ + /* and Right PCM Record) to DMA Channel 1. */ + /* Set the fifo to be 31 bytes at offset 32. */ + dwAC97SlotID = 0x0B0A1F20; /* FCR1.RS[4:0]=11(=>slot11, right PCM record). */ + /* FCR1.LS[4:0]=10(=>slot10, left PCM record). */ + /* FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. */ + WRITEL (BA0_FCR1, dwAC97SlotID); /* (184h) */ + WRITEL (BA0_FCR1, dwAC97SlotID | FCRn_FEN); /* Turn on FIFO Enable. */ + /* Map the Playback SRC to the same AC97 slots(3 & 4-- */ + /* --Playback left & right)as DMA channel 0. */ + /* Map the record SRC to the same AC97 slots(10 & 11-- */ + /* -- Record left & right) as DMA channel 1. */ + dwAC97SlotID = 0x0b0a0100; /*SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). */ + /*SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). */ + /*SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) */ + /*SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). */ + WRITEL (BA0_SRCSA, dwAC97SlotID); /* (75ch) */ + /* Set 'Half Terminal Count Interrupt Enable' and 'Terminal */ + /* Count Interrupt Enable' in DMA Control Registers 0 & 1. */ + /* Set 'MSK' flag to 1 to keep the DMA engines paused. */ + tmp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); /* (00030001h) */ + WRITEL (BA0_DCR0, tmp1); /* (154h) */ + WRITEL (BA0_DCR1, tmp1); /* (15ch) */ + /* Set 'Auto-Initialize Control' to 'enabled'; For playback, */ + /* set 'Transfer Type Control'(TR[1:0]) to 'read transfer', */ + /* for record, set Transfer Type Control to 'write transfer'. */ + /* All other bits set to zero; Some will be changed @ transfer start. */ + tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); /* (20000018h) */ + WRITEL (BA0_DMR0, tmp1); /* (150h) */ + tmp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); /* (20000014h) */ + WRITEL (BA0_DMR1, tmp1); /* (158h) */ + /* Enable DMA interrupts generally, and */ + /* DMA0 & DMA1 interrupts specifically. */ + tmp1 = READL (BA0_HIMR) & 0x7fbbfcff; + WRITEL (BA0_HIMR, tmp1); + /* set up some volume defaults */ + WRITEL (BA0_PPLVC, 0x0808); + WRITEL (BA0_PPRVC, 0x0808); + WRITEL (BA0_FMLVC, 0x0); + WRITEL (BA0_FMRVC, 0x0); +/****** END OF HARDWARE INIT *****/ + + + my_mixer = + ac97_install (&devc->ac97devc, "CS4281 AC97 Mixer", ac97_read, ac97_write, + devc, devc->osdev); + if (my_mixer < 0) + { + return 0; + } + + devc->mixer_dev = my_mixer; + + /* ac97_write(devc, 0x26, ac97_read(devc, 0x26) | 0x8000); */ + for (i = 0; i < MAX_PORTC; i++) + { + int adev; + int caps = 0; + cs4281_portc *portc = &devc->portc[i]; + char tmp_name[100]; + strcpy (tmp_name, devc->chip_name); + + if (i == 0) + { + caps = ADEV_AUTOMODE | ADEV_DUPLEX; + strcpy (tmp_name, devc->chip_name); + } + else + { + caps = ADEV_AUTOMODE | ADEV_DUPLEX | ADEV_SHADOW; + strcpy (tmp_name, devc->chip_name); + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &cs4281_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_S16_LE | AFMT_U8, devc, -1)) < 0) + { + adev = -1; + return 0; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 6023; + 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 + } + } + + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "CS4281", "CS4281 MIDI Port", &cs4281_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev); + devc->midi_opened = 0; + return 1; +} + +int +oss_cs4281_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision, pci_irq_inta; + unsigned short pci_command, vendor, device; + unsigned int ioaddr; + int err; + cs4281_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered CS4281 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != CRYSTAL_VENDOR_ID || device != CRYSTAL_CS4281_ID) + 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; + + oss_pci_byteswap (osdev, 1); + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_byte (osdev, PCI_INTERRUPT_LINE + 1, &pci_irq_inta); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &ioaddr); + devc->bar0addr = ioaddr; + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, &ioaddr); + devc->bar1addr = ioaddr; + + /* activate the device enable bus master/memory space */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if ((devc->bar0addr == 0) || (devc->bar1addr == 0)) + { + cmn_err (CE_WARN, "undefined MEMORY I/O address.\n"); + return 0; + } + + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS.\n"); + return 0; + } + + + /* Map the shared memory area */ + devc->bar0virt = + (unsigned int *) MAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, 4 * 1024); + devc->bar1virt = + (unsigned int *) MAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, + 1024 * 1024); + devc->dwRegister0 = devc->bar0virt; + devc->wRegister0 = (unsigned short *) devc->bar0virt; + devc->bRegister0 = (unsigned char *) devc->bar0virt; + devc->dwRegister1 = devc->bar1virt; + devc->wRegister1 = (unsigned short *) devc->bar1virt; + devc->bRegister1 = (unsigned char *) devc->bar1virt; + + devc->chip_name = "CS4281"; + devc->irq = pci_irq_line; + devc->open_mode = 0; + + 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, cs4281intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + return init_cs4281 (devc); /*Detected */ +} + + +int +oss_cs4281_detach (oss_device_t * osdev) +{ + cs4281_devc *devc = (cs4281_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + WRITEL (BA0_HICR, 0x02); /*enable intena */ + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + UNMAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, devc->bar0virt, 4 * 1024); + UNMAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, devc->bar1virt, 1024 * 1024); + + devc->bar0addr = 0; + devc->bar1addr = 0; + + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_cs4281/oss_cs4281.man b/kernel/drv/oss_cs4281/oss_cs4281.man new file mode 100644 index 0000000..7e19190 --- /dev/null +++ b/kernel/drv/oss_cs4281/oss_cs4281.man @@ -0,0 +1,21 @@ +NAME +oss_cs4281 - Cirrus Logic CS4281 driver + +DESCRIPTION +Open Sound System driver for Cirrus Logic (Crystal Semicoductor) CS4281 audio +controller. + +CS4281 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_cs4281.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_cs461x/.devices b/kernel/drv/oss_cs461x/.devices new file mode 100644 index 0000000..2ee1e6f --- /dev/null +++ b/kernel/drv/oss_cs461x/.devices @@ -0,0 +1,7 @@ +oss_cs461x pci1013,6001 Crystal CS4610 +oss_cs461x pci1013,6003 Crystal CS4280 +oss_cs461x pci1013,6004 Crystal CS4615 +oss_cs461x pcs153b,112e Terratec DMX Xfire 1024 +oss_cs461x pcs1681,50 Hercules Game Theater XP +oss_cs461x pcs1681,51 Hercules Game Theater XP+ +oss_cs461x pcs5053,3357 TurtleBeach SantaCruz / VideoLogic SonicFury diff --git a/kernel/drv/oss_cs461x/.name b/kernel/drv/oss_cs461x/.name new file mode 100644 index 0000000..3c0e69b --- /dev/null +++ b/kernel/drv/oss_cs461x/.name @@ -0,0 +1 @@ +Crystal CS461x/CS4280 diff --git a/kernel/drv/oss_cs461x/.params b/kernel/drv/oss_cs461x/.params new file mode 100644 index 0000000..18ed0a3 --- /dev/null +++ b/kernel/drv/oss_cs461x/.params @@ -0,0 +1,6 @@ +int cs461x_clkrun_fix=0; +/* + * Some IBM Thinkpads require a workaround for the CLKRUN protocol. + * Values: 1=Enable 0=Disable Default: 0 + */ + diff --git a/kernel/drv/oss_cs461x/cs461x.h b/kernel/drv/oss_cs461x/cs461x.h new file mode 100644 index 0000000..79ae7f5 --- /dev/null +++ b/kernel/drv/oss_cs461x/cs461x.h @@ -0,0 +1,1668 @@ +/* + * Purpose: Definitions for the cs461x 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. + * + */ + + +/* + * Direct registers + */ + +/* + * The following define the offsets of the registers accessed via base address + * register zero on the CS461x part. + */ +#define BA0_HISR 0x00000000 +#define BA0_HSR0 0x00000004 +#define BA0_HICR 0x00000008 +#define BA0_DMSR 0x00000100 +#define BA0_HSAR 0x00000110 +#define BA0_HDAR 0x00000114 +#define BA0_HDMR 0x00000118 +#define BA0_HDCR 0x0000011C +#define BA0_PFMC 0x00000200 +#define BA0_PFCV1 0x00000204 +#define BA0_PFCV2 0x00000208 +#define BA0_PCICFG00 0x00000300 +#define BA0_PCICFG04 0x00000304 +#define BA0_PCICFG08 0x00000308 +#define BA0_PCICFG0C 0x0000030C +#define BA0_PCICFG10 0x00000310 +#define BA0_PCICFG14 0x00000314 +#define BA0_PCICFG18 0x00000318 +#define BA0_PCICFG1C 0x0000031C +#define BA0_PCICFG20 0x00000320 +#define BA0_PCICFG24 0x00000324 +#define BA0_PCICFG28 0x00000328 +#define BA0_PCICFG2C 0x0000032C +#define BA0_PCICFG30 0x00000330 +#define BA0_PCICFG34 0x00000334 +#define BA0_PCICFG38 0x00000338 +#define BA0_PCICFG3C 0x0000033C +#define BA0_CLKCR1 0x00000400 +#define BA0_CLKCR2 0x00000404 +#define BA0_PLLM 0x00000408 +#define BA0_PLLCC 0x0000040C +#define BA0_FRR 0x00000410 +#define BA0_CFL1 0x00000414 +#define BA0_CFL2 0x00000418 +#define BA0_SERMC1 0x00000420 +#define BA0_SERMC2 0x00000424 +#define BA0_SERC1 0x00000428 +#define BA0_SERC2 0x0000042C +#define BA0_SERC3 0x00000430 +#define BA0_SERC4 0x00000434 +#define BA0_SERC5 0x00000438 +#define BA0_SERBSP 0x0000043C +#define BA0_SERBST 0x00000440 +#define BA0_SERBCM 0x00000444 +#define BA0_SERBAD 0x00000448 +#define BA0_SERBCF 0x0000044C +#define BA0_SERBWP 0x00000450 +#define BA0_SERBRP 0x00000454 +#ifndef NO_CS4612 +#define BA0_ASER_FADDR 0x00000458 +#endif +#define BA0_ACCTL 0x00000460 +#define BA0_ACSTS 0x00000464 +#define BA0_ACOSV 0x00000468 +#define BA0_ACCAD 0x0000046C +#define BA0_ACCDA 0x00000470 +#define BA0_ACISV 0x00000474 +#define BA0_ACSAD 0x00000478 +#define BA0_ACSDA 0x0000047C +#define BA0_JSPT 0x00000480 +#define BA0_JSCTL 0x00000484 +#define BA0_JSC1 0x00000488 +#define BA0_JSC2 0x0000048C +#define BA0_MIDCR 0x00000490 +#define BA0_MIDSR 0x00000494 +#define BA0_MIDWP 0x00000498 +#define BA0_MIDRP 0x0000049C +#define BA0_JSIO 0x000004A0 +#ifndef NO_CS4612 +#define BA0_ASER_MASTER 0x000004A4 +#endif +#define BA0_CFGI 0x000004B0 +#define BA0_SSVID 0x000004B4 +#define BA0_GPIOR 0x000004B8 +#ifndef NO_CS4612 +#define BA0_EGPIODR 0x000004BC +#define BA0_EGPIOPTR 0x000004C0 +#define BA0_EGPIOTR 0x000004C4 +#define BA0_EGPIOWR 0x000004C8 +#define BA0_EGPIOSR 0x000004CC +#define BA0_SERC6 0x000004D0 +#define BA0_SERC7 0x000004D4 +#define BA0_SERACC 0x000004D8 +#define BA0_ACCTL2 0x000004E0 +#define BA0_ACSTS2 0x000004E4 +#define BA0_ACOSV2 0x000004E8 +#define BA0_ACCAD2 0x000004EC +#define BA0_ACCDA2 0x000004F0 +#define BA0_ACISV2 0x000004F4 +#define BA0_ACSAD2 0x000004F8 +#define BA0_ACSDA2 0x000004FC +#define BA0_IOTAC0 0x00000500 +#define BA0_IOTAC1 0x00000504 +#define BA0_IOTAC2 0x00000508 +#define BA0_IOTAC3 0x0000050C +#define BA0_IOTAC4 0x00000510 +#define BA0_IOTAC5 0x00000514 +#define BA0_IOTAC6 0x00000518 +#define BA0_IOTAC7 0x0000051C +#define BA0_IOTAC8 0x00000520 +#define BA0_IOTAC9 0x00000524 +#define BA0_IOTAC10 0x00000528 +#define BA0_IOTAC11 0x0000052C +#define BA0_IOTFR0 0x00000540 +#define BA0_IOTFR1 0x00000544 +#define BA0_IOTFR2 0x00000548 +#define BA0_IOTFR3 0x0000054C +#define BA0_IOTFR4 0x00000550 +#define BA0_IOTFR5 0x00000554 +#define BA0_IOTFR6 0x00000558 +#define BA0_IOTFR7 0x0000055C +#define BA0_IOTFIFO 0x00000580 +#define BA0_IOTRRD 0x00000584 +#define BA0_IOTFP 0x00000588 +#define BA0_IOTCR 0x0000058C +#define BA0_DPCID 0x00000590 +#define BA0_DPCIA 0x00000594 +#define BA0_DPCIC 0x00000598 +#define BA0_PCPCIR 0x00000600 +#define BA0_PCPCIG 0x00000604 +#define BA0_PCPCIEN 0x00000608 +#define BA0_EPCIPMC 0x00000610 +#endif + +/* + * The following define the offsets of the registers and memories accessed via + * base address register one on the CS461x part. + */ +#define BA1_SP_DMEM0 0x00000000 +#define BA1_SP_DMEM1 0x00010000 +#define BA1_SP_PMEM 0x00020000 +#define BA1_SP_REG 0x00030000 +#define BA1_SPCR 0x00030000 +#define BA1_DREG 0x00030004 +#define BA1_DSRWP 0x00030008 +#define BA1_TWPR 0x0003000C +#define BA1_SPWR 0x00030010 +#define BA1_SPIR 0x00030014 +#define BA1_FGR1 0x00030020 +#define BA1_SPCS 0x00030028 +#define BA1_SDSR 0x0003002C +#define BA1_FRMT 0x00030030 +#define BA1_FRCC 0x00030034 +#define BA1_FRSC 0x00030038 +#define BA1_OMNI_MEM 0x000E0000 + +/* + * The following defines are for the flags in the host interrupt status + * register. + */ +#define HISR_VC_MASK 0x0000FFFF +#define HISR_VC0 0x00000001 +#define HISR_VC1 0x00000002 +#define HISR_VC2 0x00000004 +#define HISR_VC3 0x00000008 +#define HISR_VC4 0x00000010 +#define HISR_VC5 0x00000020 +#define HISR_VC6 0x00000040 +#define HISR_VC7 0x00000080 +#define HISR_VC8 0x00000100 +#define HISR_VC9 0x00000200 +#define HISR_VC10 0x00000400 +#define HISR_VC11 0x00000800 +#define HISR_VC12 0x00001000 +#define HISR_VC13 0x00002000 +#define HISR_VC14 0x00004000 +#define HISR_VC15 0x00008000 +#define HISR_INT0 0x00010000 +#define HISR_INT1 0x00020000 +#define HISR_DMAI 0x00040000 +#define HISR_FROVR 0x00080000 +#define HISR_MIDI 0x00100000 +#ifdef NO_CS4612 +#define HISR_RESERVED 0x0FE00000 +#else +#define HISR_SBINT 0x00200000 +#define HISR_RESERVED 0x0FC00000 +#endif +#define HISR_H0P 0x40000000 +#define HISR_INTENA 0x80000000 + +/* + * The following defines are for the flags in the host signal register 0. + */ +#define HSR0_VC_MASK 0xFFFFFFFF +#define HSR0_VC16 0x00000001 +#define HSR0_VC17 0x00000002 +#define HSR0_VC18 0x00000004 +#define HSR0_VC19 0x00000008 +#define HSR0_VC20 0x00000010 +#define HSR0_VC21 0x00000020 +#define HSR0_VC22 0x00000040 +#define HSR0_VC23 0x00000080 +#define HSR0_VC24 0x00000100 +#define HSR0_VC25 0x00000200 +#define HSR0_VC26 0x00000400 +#define HSR0_VC27 0x00000800 +#define HSR0_VC28 0x00001000 +#define HSR0_VC29 0x00002000 +#define HSR0_VC30 0x00004000 +#define HSR0_VC31 0x00008000 +#define HSR0_VC32 0x00010000 +#define HSR0_VC33 0x00020000 +#define HSR0_VC34 0x00040000 +#define HSR0_VC35 0x00080000 +#define HSR0_VC36 0x00100000 +#define HSR0_VC37 0x00200000 +#define HSR0_VC38 0x00400000 +#define HSR0_VC39 0x00800000 +#define HSR0_VC40 0x01000000 +#define HSR0_VC41 0x02000000 +#define HSR0_VC42 0x04000000 +#define HSR0_VC43 0x08000000 +#define HSR0_VC44 0x10000000 +#define HSR0_VC45 0x20000000 +#define HSR0_VC46 0x40000000 +#define HSR0_VC47 0x80000000 + +/* + * The following defines are for the flags in the host interrupt control + * register. + */ +#define HICR_IEV 0x00000001 +#define HICR_CHGM 0x00000002 + +/* + * The following defines are for the flags in the DMA status register. + */ +#define DMSR_HP 0x00000001 +#define DMSR_HR 0x00000002 +#define DMSR_SP 0x00000004 +#define DMSR_SR 0x00000008 + +/* + * The following defines are for the flags in the host DMA source address + * register. + */ +#define HSAR_HOST_ADDR_MASK 0xFFFFFFFF +#define HSAR_DSP_ADDR_MASK 0x0000FFFF +#define HSAR_MEMID_MASK 0x000F0000 +#define HSAR_MEMID_SP_DMEM0 0x00000000 +#define HSAR_MEMID_SP_DMEM1 0x00010000 +#define HSAR_MEMID_SP_PMEM 0x00020000 +#define HSAR_MEMID_SP_DEBUG 0x00030000 +#define HSAR_MEMID_OMNI_MEM 0x000E0000 +#define HSAR_END 0x40000000 +#define HSAR_ERR 0x80000000 + +/* + * The following defines are for the flags in the host DMA destination address + * register. + */ +#define HDAR_HOST_ADDR_MASK 0xFFFFFFFF +#define HDAR_DSP_ADDR_MASK 0x0000FFFF +#define HDAR_MEMID_MASK 0x000F0000 +#define HDAR_MEMID_SP_DMEM0 0x00000000 +#define HDAR_MEMID_SP_DMEM1 0x00010000 +#define HDAR_MEMID_SP_PMEM 0x00020000 +#define HDAR_MEMID_SP_DEBUG 0x00030000 +#define HDAR_MEMID_OMNI_MEM 0x000E0000 +#define HDAR_END 0x40000000 +#define HDAR_ERR 0x80000000 + +/* + * The following defines are for the flags in the host DMA control register. + */ +#define HDMR_AC_MASK 0x0000F000 +#define HDMR_AC_8_16 0x00001000 +#define HDMR_AC_M_S 0x00002000 +#define HDMR_AC_B_L 0x00004000 +#define HDMR_AC_S_U 0x00008000 + +/* + * The following defines are for the flags in the host DMA control register. + */ +#define HDCR_COUNT_MASK 0x000003FF +#define HDCR_DONE 0x00004000 +#define HDCR_OPT 0x00008000 +#define HDCR_WBD 0x00400000 +#define HDCR_WBS 0x00800000 +#define HDCR_DMS_MASK 0x07000000 +#define HDCR_DMS_LINEAR 0x00000000 +#define HDCR_DMS_16_DWORDS 0x01000000 +#define HDCR_DMS_32_DWORDS 0x02000000 +#define HDCR_DMS_64_DWORDS 0x03000000 +#define HDCR_DMS_128_DWORDS 0x04000000 +#define HDCR_DMS_256_DWORDS 0x05000000 +#define HDCR_DMS_512_DWORDS 0x06000000 +#define HDCR_DMS_1024_DWORDS 0x07000000 +#define HDCR_DH 0x08000000 +#define HDCR_SMS_MASK 0x70000000 +#define HDCR_SMS_LINEAR 0x00000000 +#define HDCR_SMS_16_DWORDS 0x10000000 +#define HDCR_SMS_32_DWORDS 0x20000000 +#define HDCR_SMS_64_DWORDS 0x30000000 +#define HDCR_SMS_128_DWORDS 0x40000000 +#define HDCR_SMS_256_DWORDS 0x50000000 +#define HDCR_SMS_512_DWORDS 0x60000000 +#define HDCR_SMS_1024_DWORDS 0x70000000 +#define HDCR_SH 0x80000000 +#define HDCR_COUNT_SHIFT 0 + +/* + * The following defines are for the flags in the performance monitor control + * register. + */ +#define PFMC_C1SS_MASK 0x0000001F +#define PFMC_C1EV 0x00000020 +#define PFMC_C1RS 0x00008000 +#define PFMC_C2SS_MASK 0x001F0000 +#define PFMC_C2EV 0x00200000 +#define PFMC_C2RS 0x80000000 +#define PFMC_C1SS_SHIFT 0 +#define PFMC_C2SS_SHIFT 16 +#define PFMC_BUS_GRANT 0 +#define PFMC_GRANT_AFTER_REQ 1 +#define PFMC_TRANSACTION 2 +#define PFMC_DWORD_TRANSFER 3 +#define PFMC_SLAVE_READ 4 +#define PFMC_SLAVE_WRITE 5 +#define PFMC_PREEMPTION 6 +#define PFMC_DISCONNECT_RETRY 7 +#define PFMC_INTERRUPT 8 +#define PFMC_BUS_OWNERSHIP 9 +#define PFMC_TRANSACTION_LAG 10 +#define PFMC_PCI_CLOCK 11 +#define PFMC_SERIAL_CLOCK 12 +#define PFMC_SP_CLOCK 13 + +/* + * The following defines are for the flags in the performance counter value 1 + * register. + */ +#define PFCV1_PC1V_MASK 0xFFFFFFFF +#define PFCV1_PC1V_SHIFT 0 + +/* + * The following defines are for the flags in the performance counter value 2 + * register. + */ +#define PFCV2_PC2V_MASK 0xFFFFFFFF +#define PFCV2_PC2V_SHIFT 0 + +/* + * The following defines are for the flags in the clock control register 1. + */ +#define CLKCR1_OSCS 0x00000001 +#define CLKCR1_OSCP 0x00000002 +#define CLKCR1_PLLSS_MASK 0x0000000C +#define CLKCR1_PLLSS_SERIAL 0x00000000 +#define CLKCR1_PLLSS_CRYSTAL 0x00000004 +#define CLKCR1_PLLSS_PCI 0x00000008 +#define CLKCR1_PLLSS_RESERVED 0x0000000C +#define CLKCR1_PLLP 0x00000010 +#define CLKCR1_SWCE 0x00000020 +#define CLKCR1_PLLOS 0x00000040 + +/* + * The following defines are for the flags in the clock control register 2. + */ +#define CLKCR2_PDIVS_MASK 0x0000000F +#define CLKCR2_PDIVS_1 0x00000001 +#define CLKCR2_PDIVS_2 0x00000002 +#define CLKCR2_PDIVS_4 0x00000004 +#define CLKCR2_PDIVS_7 0x00000007 +#define CLKCR2_PDIVS_8 0x00000008 +#define CLKCR2_PDIVS_16 0x00000000 + +/* + * The following defines are for the flags in the PLL multiplier register. + */ +#define PLLM_MASK 0x000000FF +#define PLLM_SHIFT 0 + +/* + * The following defines are for the flags in the PLL capacitor coefficient + * register. + */ +#define PLLCC_CDR_MASK 0x00000007 +#ifndef NO_CS4610 +#define PLLCC_CDR_240_350_MHZ 0x00000000 +#define PLLCC_CDR_184_265_MHZ 0x00000001 +#define PLLCC_CDR_144_205_MHZ 0x00000002 +#define PLLCC_CDR_111_160_MHZ 0x00000003 +#define PLLCC_CDR_87_123_MHZ 0x00000004 +#define PLLCC_CDR_67_96_MHZ 0x00000005 +#define PLLCC_CDR_52_74_MHZ 0x00000006 +#define PLLCC_CDR_45_58_MHZ 0x00000007 +#endif +#ifndef NO_CS4612 +#define PLLCC_CDR_271_398_MHZ 0x00000000 +#define PLLCC_CDR_227_330_MHZ 0x00000001 +#define PLLCC_CDR_167_239_MHZ 0x00000002 +#define PLLCC_CDR_150_215_MHZ 0x00000003 +#define PLLCC_CDR_107_154_MHZ 0x00000004 +#define PLLCC_CDR_98_140_MHZ 0x00000005 +#define PLLCC_CDR_73_104_MHZ 0x00000006 +#define PLLCC_CDR_63_90_MHZ 0x00000007 +#endif +#define PLLCC_LPF_MASK 0x000000F8 +#ifndef NO_CS4610 +#define PLLCC_LPF_23850_60000_KHZ 0x00000000 +#define PLLCC_LPF_7960_26290_KHZ 0x00000008 +#define PLLCC_LPF_4160_10980_KHZ 0x00000018 +#define PLLCC_LPF_1740_4580_KHZ 0x00000038 +#define PLLCC_LPF_724_1910_KHZ 0x00000078 +#define PLLCC_LPF_317_798_KHZ 0x000000F8 +#endif +#ifndef NO_CS4612 +#define PLLCC_LPF_25580_64530_KHZ 0x00000000 +#define PLLCC_LPF_14360_37270_KHZ 0x00000008 +#define PLLCC_LPF_6100_16020_KHZ 0x00000018 +#define PLLCC_LPF_2540_6690_KHZ 0x00000038 +#define PLLCC_LPF_1050_2780_KHZ 0x00000078 +#define PLLCC_LPF_450_1160_KHZ 0x000000F8 +#endif + +/* + * The following defines are for the flags in the feature reporting register. + */ +#define FRR_FAB_MASK 0x00000003 +#define FRR_MASK_MASK 0x0000001C +#ifdef NO_CS4612 +#define FRR_CFOP_MASK 0x000000E0 +#else +#define FRR_CFOP_MASK 0x00000FE0 +#endif +#define FRR_CFOP_NOT_DVD 0x00000020 +#define FRR_CFOP_A3D 0x00000040 +#define FRR_CFOP_128_PIN 0x00000080 +#ifndef NO_CS4612 +#define FRR_CFOP_CS4280 0x00000800 +#endif +#define FRR_FAB_SHIFT 0 +#define FRR_MASK_SHIFT 2 +#define FRR_CFOP_SHIFT 5 + +/* + * The following defines are for the flags in the configuration load 1 + * register. + */ +#define CFL1_CLOCK_SOURCE_MASK 0x00000003 +#define CFL1_CLOCK_SOURCE_CS423X 0x00000000 +#define CFL1_CLOCK_SOURCE_AC97 0x00000001 +#define CFL1_CLOCK_SOURCE_CRYSTAL 0x00000002 +#define CFL1_CLOCK_SOURCE_DUAL_AC97 0x00000003 +#define CFL1_VALID_DATA_MASK 0x000000FF + +/* + * The following defines are for the flags in the configuration load 2 + * register. + */ +#define CFL2_VALID_DATA_MASK 0x000000FF + +/* + * The following defines are for the flags in the serial port master control + * register 1. + */ +#define SERMC1_MSPE 0x00000001 +#define SERMC1_PTC_MASK 0x0000000E +#define SERMC1_PTC_CS423X 0x00000000 +#define SERMC1_PTC_AC97 0x00000002 +#define SERMC1_PTC_DAC 0x00000004 +#define SERMC1_PLB 0x00000010 +#define SERMC1_XLB 0x00000020 + +/* + * The following defines are for the flags in the serial port master control + * register 2. + */ +#define SERMC2_LROE 0x00000001 +#define SERMC2_MCOE 0x00000002 +#define SERMC2_MCDIV 0x00000004 + +/* + * The following defines are for the flags in the serial port 1 configuration + * register. + */ +#define SERC1_SO1EN 0x00000001 +#define SERC1_SO1F_MASK 0x0000000E +#define SERC1_SO1F_CS423X 0x00000000 +#define SERC1_SO1F_AC97 0x00000002 +#define SERC1_SO1F_DAC 0x00000004 +#define SERC1_SO1F_SPDIF 0x00000006 + +/* + * The following defines are for the flags in the serial port 2 configuration + * register. + */ +#define SERC2_SI1EN 0x00000001 +#define SERC2_SI1F_MASK 0x0000000E +#define SERC2_SI1F_CS423X 0x00000000 +#define SERC2_SI1F_AC97 0x00000002 +#define SERC2_SI1F_ADC 0x00000004 +#define SERC2_SI1F_SPDIF 0x00000006 + +/* + * The following defines are for the flags in the serial port 3 configuration + * register. + */ +#define SERC3_SO2EN 0x00000001 +#define SERC3_SO2F_MASK 0x00000006 +#define SERC3_SO2F_DAC 0x00000000 +#define SERC3_SO2F_SPDIF 0x00000002 + +/* + * The following defines are for the flags in the serial port 4 configuration + * register. + */ +#define SERC4_SO3EN 0x00000001 +#define SERC4_SO3F_MASK 0x00000006 +#define SERC4_SO3F_DAC 0x00000000 +#define SERC4_SO3F_SPDIF 0x00000002 + +/* + * The following defines are for the flags in the serial port 5 configuration + * register. + */ +#define SERC5_SI2EN 0x00000001 +#define SERC5_SI2F_MASK 0x00000006 +#define SERC5_SI2F_ADC 0x00000000 +#define SERC5_SI2F_SPDIF 0x00000002 + +/* + * The following defines are for the flags in the serial port backdoor sample + * pointer register. + */ +#define SERBSP_FSP_MASK 0x0000000F +#define SERBSP_FSP_SHIFT 0 + +/* + * The following defines are for the flags in the serial port backdoor status + * register. + */ +#define SERBST_RRDY 0x00000001 +#define SERBST_WBSY 0x00000002 + +/* + * The following defines are for the flags in the serial port backdoor command + * register. + */ +#define SERBCM_RDC 0x00000001 +#define SERBCM_WRC 0x00000002 + +/* + * The following defines are for the flags in the serial port backdoor address + * register. + */ +#ifdef NO_CS4612 +#define SERBAD_FAD_MASK 0x000000FF +#else +#define SERBAD_FAD_MASK 0x000001FF +#endif +#define SERBAD_FAD_SHIFT 0 + +/* + * The following defines are for the flags in the serial port backdoor + * configuration register. + */ +#define SERBCF_HBP 0x00000001 + +/* + * The following defines are for the flags in the serial port backdoor write + * port register. + */ +#define SERBWP_FWD_MASK 0x000FFFFF +#define SERBWP_FWD_SHIFT 0 + +/* + * The following defines are for the flags in the serial port backdoor read + * port register. + */ +#define SERBRP_FRD_MASK 0x000FFFFF +#define SERBRP_FRD_SHIFT 0 + +/* + * The following defines are for the flags in the async FIFO address register. + */ +#ifndef NO_CS4612 +#define ASER_FADDR_A1_MASK 0x000001FF +#define ASER_FADDR_EN1 0x00008000 +#define ASER_FADDR_A2_MASK 0x01FF0000 +#define ASER_FADDR_EN2 0x80000000 +#define ASER_FADDR_A1_SHIFT 0 +#define ASER_FADDR_A2_SHIFT 16 +#endif + +/* + * The following defines are for the flags in the AC97 control register. + */ +#define ACCTL_RSTN 0x00000001 +#define ACCTL_ESYN 0x00000002 +#define ACCTL_VFRM 0x00000004 +#define ACCTL_DCV 0x00000008 +#define ACCTL_CRW 0x00000010 +#define ACCTL_ASYN 0x00000020 +#ifndef NO_CS4612 +#define ACCTL_TC 0x00000040 +#endif + +/* + * The following defines are for the flags in the AC97 status register. + */ +#define ACSTS_CRDY 0x00000001 +#define ACSTS_VSTS 0x00000002 +#ifndef NO_CS4612 +#define ACSTS_WKUP 0x00000004 +#endif + +/* + * The following defines are for the flags in the AC97 output slot valid + * register. + */ +#define ACOSV_SLV3 0x00000001 +#define ACOSV_SLV4 0x00000002 +#define ACOSV_SLV5 0x00000004 +#define ACOSV_SLV6 0x00000008 +#define ACOSV_SLV7 0x00000010 +#define ACOSV_SLV8 0x00000020 +#define ACOSV_SLV9 0x00000040 +#define ACOSV_SLV10 0x00000080 +#define ACOSV_SLV11 0x00000100 +#define ACOSV_SLV12 0x00000200 + +/* + * The following defines are for the flags in the AC97 command address + * register. + */ +#define ACCAD_CI_MASK 0x0000007F +#define ACCAD_CI_SHIFT 0 + +/* + * The following defines are for the flags in the AC97 command data register. + */ +#define ACCDA_CD_MASK 0x0000FFFF +#define ACCDA_CD_SHIFT 0 + +/* + * The following defines are for the flags in the AC97 input slot valid + * register. + */ +#define ACISV_ISV3 0x00000001 +#define ACISV_ISV4 0x00000002 +#define ACISV_ISV5 0x00000004 +#define ACISV_ISV6 0x00000008 +#define ACISV_ISV7 0x00000010 +#define ACISV_ISV8 0x00000020 +#define ACISV_ISV9 0x00000040 +#define ACISV_ISV10 0x00000080 +#define ACISV_ISV11 0x00000100 +#define ACISV_ISV12 0x00000200 + +/* + * The following defines are for the flags in the AC97 status address + * register. + */ +#define ACSAD_SI_MASK 0x0000007F +#define ACSAD_SI_SHIFT 0 + +/* + * The following defines are for the flags in the AC97 status data register. + */ +#define ACSDA_SD_MASK 0x0000FFFF +#define ACSDA_SD_SHIFT 0 + +/* + * The following defines are for the flags in the joystick poll/trigger + * register. + */ +#define JSPT_CAX 0x00000001 +#define JSPT_CAY 0x00000002 +#define JSPT_CBX 0x00000004 +#define JSPT_CBY 0x00000008 +#define JSPT_BA1 0x00000010 +#define JSPT_BA2 0x00000020 +#define JSPT_BB1 0x00000040 +#define JSPT_BB2 0x00000080 + +/* + * The following defines are for the flags in the joystick control register. + */ +#define JSCTL_SP_MASK 0x00000003 +#define JSCTL_SP_SLOW 0x00000000 +#define JSCTL_SP_MEDIUM_SLOW 0x00000001 +#define JSCTL_SP_MEDIUM_FAST 0x00000002 +#define JSCTL_SP_FAST 0x00000003 +#define JSCTL_ARE 0x00000004 + +/* + * The following defines are for the flags in the joystick coordinate pair 1 + * readback register. + */ +#define JSC1_Y1V_MASK 0x0000FFFF +#define JSC1_X1V_MASK 0xFFFF0000 +#define JSC1_Y1V_SHIFT 0 +#define JSC1_X1V_SHIFT 16 + +/* + * The following defines are for the flags in the joystick coordinate pair 2 + * readback register. + */ +#define JSC2_Y2V_MASK 0x0000FFFF +#define JSC2_X2V_MASK 0xFFFF0000 +#define JSC2_Y2V_SHIFT 0 +#define JSC2_X2V_SHIFT 16 + +/* + * The following defines are for the flags in the MIDI control register. + */ +#define MIDCR_TXE 0x00000001 /* Enable transmitting. */ +#define MIDCR_RXE 0x00000002 /* Enable receiving. */ +#define MIDCR_RIE 0x00000004 /* Interrupt upon tx ready. */ +#define MIDCR_TIE 0x00000008 /* Interrupt upon rx ready. */ +#define MIDCR_MLB 0x00000010 /* Enable midi loopback. */ +#define MIDCR_MRST 0x00000020 /* Reset interface. */ + +/* + * The following defines are for the flags in the MIDI status register. + */ +#define MIDSR_TBF 0x00000001 /* Tx FIFO is full. */ +#define MIDSR_RBE 0x00000002 /* Rx FIFO is empty. */ + +/* + * The following defines are for the flags in the MIDI write port register. + */ +#define MIDWP_MWD_MASK 0x000000FF +#define MIDWP_MWD_SHIFT 0 + +/* + * The following defines are for the flags in the MIDI read port register. + */ +#define MIDRP_MRD_MASK 0x000000FF +#define MIDRP_MRD_SHIFT 0 + +/* + * The following defines are for the flags in the joystick GPIO register. + */ +#define JSIO_DAX 0x00000001 +#define JSIO_DAY 0x00000002 +#define JSIO_DBX 0x00000004 +#define JSIO_DBY 0x00000008 +#define JSIO_AXOE 0x00000010 +#define JSIO_AYOE 0x00000020 +#define JSIO_BXOE 0x00000040 +#define JSIO_BYOE 0x00000080 + +/* + * The following defines are for the flags in the master async/sync serial + * port enable register. + */ +#ifndef NO_CS4612 +#define ASER_MASTER_ME 0x00000001 +#endif + +/* + * The following defines are for the flags in the configuration interface + * register. + */ +#define CFGI_CLK 0x00000001 +#define CFGI_DOUT 0x00000002 +#define CFGI_DIN_EEN 0x00000004 +#define CFGI_EELD 0x00000008 + +/* + * The following defines are for the flags in the subsystem ID and vendor ID + * register. + */ +#define SSVID_VID_MASK 0x0000FFFF +#define SSVID_SID_MASK 0xFFFF0000 +#define SSVID_VID_SHIFT 0 +#define SSVID_SID_SHIFT 16 + +/* + * The following defines are for the flags in the GPIO pin interface register. + */ +#define GPIOR_VOLDN 0x00000001 +#define GPIOR_VOLUP 0x00000002 +#define GPIOR_SI2D 0x00000004 +#define GPIOR_SI2OE 0x00000008 + +/* + * The following defines are for the flags in the extended GPIO pin direction + * register. + */ +#ifndef NO_CS4612 +#define EGPIODR_GPOE0 0x00000001 +#define EGPIODR_GPOE1 0x00000002 +#define EGPIODR_GPOE2 0x00000004 +#define EGPIODR_GPOE3 0x00000008 +#define EGPIODR_GPOE4 0x00000010 +#define EGPIODR_GPOE5 0x00000020 +#define EGPIODR_GPOE6 0x00000040 +#define EGPIODR_GPOE7 0x00000080 +#define EGPIODR_GPOE8 0x00000100 +#endif + +/* + * The following defines are for the flags in the extended GPIO pin polarity/ + * type register. + */ +#ifndef NO_CS4612 +#define EGPIOPTR_GPPT0 0x00000001 +#define EGPIOPTR_GPPT1 0x00000002 +#define EGPIOPTR_GPPT2 0x00000004 +#define EGPIOPTR_GPPT3 0x00000008 +#define EGPIOPTR_GPPT4 0x00000010 +#define EGPIOPTR_GPPT5 0x00000020 +#define EGPIOPTR_GPPT6 0x00000040 +#define EGPIOPTR_GPPT7 0x00000080 +#define EGPIOPTR_GPPT8 0x00000100 +#endif + +/* + * The following defines are for the flags in the extended GPIO pin sticky + * register. + */ +#ifndef NO_CS4612 +#define EGPIOTR_GPS0 0x00000001 +#define EGPIOTR_GPS1 0x00000002 +#define EGPIOTR_GPS2 0x00000004 +#define EGPIOTR_GPS3 0x00000008 +#define EGPIOTR_GPS4 0x00000010 +#define EGPIOTR_GPS5 0x00000020 +#define EGPIOTR_GPS6 0x00000040 +#define EGPIOTR_GPS7 0x00000080 +#define EGPIOTR_GPS8 0x00000100 +#endif + +/* + * The following defines are for the flags in the extended GPIO ping wakeup + * register. + */ +#ifndef NO_CS4612 +#define EGPIOWR_GPW0 0x00000001 +#define EGPIOWR_GPW1 0x00000002 +#define EGPIOWR_GPW2 0x00000004 +#define EGPIOWR_GPW3 0x00000008 +#define EGPIOWR_GPW4 0x00000010 +#define EGPIOWR_GPW5 0x00000020 +#define EGPIOWR_GPW6 0x00000040 +#define EGPIOWR_GPW7 0x00000080 +#define EGPIOWR_GPW8 0x00000100 +#endif + +/* + * The following defines are for the flags in the extended GPIO pin status + * register. + */ +#ifndef NO_CS4612 +#define EGPIOSR_GPS0 0x00000001 +#define EGPIOSR_GPS1 0x00000002 +#define EGPIOSR_GPS2 0x00000004 +#define EGPIOSR_GPS3 0x00000008 +#define EGPIOSR_GPS4 0x00000010 +#define EGPIOSR_GPS5 0x00000020 +#define EGPIOSR_GPS6 0x00000040 +#define EGPIOSR_GPS7 0x00000080 +#define EGPIOSR_GPS8 0x00000100 +#endif + +/* + * The following defines are for the flags in the serial port 6 configuration + * register. + */ +#ifndef NO_CS4612 +#define SERC6_ASDO2EN 0x00000001 +#endif + +/* + * The following defines are for the flags in the serial port 7 configuration + * register. + */ +#ifndef NO_CS4612 +#define SERC7_ASDI2EN 0x00000001 +#define SERC7_POSILB 0x00000002 +#define SERC7_SIPOLB 0x00000004 +#define SERC7_SOSILB 0x00000008 +#define SERC7_SISOLB 0x00000010 +#endif + +/* + * The following defines are for the flags in the serial port AC link + * configuration register. + */ +#ifndef NO_CS4612 +#define SERACC_CODEC_TYPE_MASK 0x00000001 +#define SERACC_CODEC_TYPE_1_03 0x00000000 +#define SERACC_CODEC_TYPE_2_0 0x00000001 +#define SERACC_TWO_CODECS 0x00000002 +#define SERACC_MDM 0x00000004 +#define SERACC_HSP 0x00000008 +#endif + +/* + * The following defines are for the flags in the AC97 control register 2. + */ +#ifndef NO_CS4612 +#define ACCTL2_RSTN 0x00000001 +#define ACCTL2_ESYN 0x00000002 +#define ACCTL2_VFRM 0x00000004 +#define ACCTL2_DCV 0x00000008 +#define ACCTL2_CRW 0x00000010 +#define ACCTL2_ASYN 0x00000020 +#endif + +/* + * The following defines are for the flags in the AC97 status register 2. + */ +#ifndef NO_CS4612 +#define ACSTS2_CRDY 0x00000001 +#define ACSTS2_VSTS 0x00000002 +#endif + +/* + * The following defines are for the flags in the AC97 output slot valid + * register 2. + */ +#ifndef NO_CS4612 +#define ACOSV2_SLV3 0x00000001 +#define ACOSV2_SLV4 0x00000002 +#define ACOSV2_SLV5 0x00000004 +#define ACOSV2_SLV6 0x00000008 +#define ACOSV2_SLV7 0x00000010 +#define ACOSV2_SLV8 0x00000020 +#define ACOSV2_SLV9 0x00000040 +#define ACOSV2_SLV10 0x00000080 +#define ACOSV2_SLV11 0x00000100 +#define ACOSV2_SLV12 0x00000200 +#endif + +/* + * The following defines are for the flags in the AC97 command address + * register 2. + */ +#ifndef NO_CS4612 +#define ACCAD2_CI_MASK 0x0000007F +#define ACCAD2_CI_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the AC97 command data register + * 2. + */ +#ifndef NO_CS4612 +#define ACCDA2_CD_MASK 0x0000FFFF +#define ACCDA2_CD_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the AC97 input slot valid + * register 2. + */ +#ifndef NO_CS4612 +#define ACISV2_ISV3 0x00000001 +#define ACISV2_ISV4 0x00000002 +#define ACISV2_ISV5 0x00000004 +#define ACISV2_ISV6 0x00000008 +#define ACISV2_ISV7 0x00000010 +#define ACISV2_ISV8 0x00000020 +#define ACISV2_ISV9 0x00000040 +#define ACISV2_ISV10 0x00000080 +#define ACISV2_ISV11 0x00000100 +#define ACISV2_ISV12 0x00000200 +#endif + +/* + * The following defines are for the flags in the AC97 status address + * register 2. + */ +#ifndef NO_CS4612 +#define ACSAD2_SI_MASK 0x0000007F +#define ACSAD2_SI_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the AC97 status data register 2. + */ +#ifndef NO_CS4612 +#define ACSDA2_SD_MASK 0x0000FFFF +#define ACSDA2_SD_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the I/O trap address and control + * registers (all 12). + */ +#ifndef NO_CS4612 +#define IOTAC_SA_MASK 0x0000FFFF +#define IOTAC_MSK_MASK 0x000F0000 +#define IOTAC_IODC_MASK 0x06000000 +#define IOTAC_IODC_16_BIT 0x00000000 +#define IOTAC_IODC_10_BIT 0x02000000 +#define IOTAC_IODC_12_BIT 0x04000000 +#define IOTAC_WSPI 0x08000000 +#define IOTAC_RSPI 0x10000000 +#define IOTAC_WSE 0x20000000 +#define IOTAC_WE 0x40000000 +#define IOTAC_RE 0x80000000 +#define IOTAC_SA_SHIFT 0 +#define IOTAC_MSK_SHIFT 16 +#endif + +/* + * The following defines are for the flags in the I/O trap fast read registers + * (all 8). + */ +#ifndef NO_CS4612 +#define IOTFR_D_MASK 0x0000FFFF +#define IOTFR_A_MASK 0x000F0000 +#define IOTFR_R_MASK 0x0F000000 +#define IOTFR_ALL 0x40000000 +#define IOTFR_VL 0x80000000 +#define IOTFR_D_SHIFT 0 +#define IOTFR_A_SHIFT 16 +#define IOTFR_R_SHIFT 24 +#endif + +/* + * The following defines are for the flags in the I/O trap FIFO register. + */ +#ifndef NO_CS4612 +#define IOTFIFO_BA_MASK 0x00003FFF +#define IOTFIFO_S_MASK 0x00FF0000 +#define IOTFIFO_OF 0x40000000 +#define IOTFIFO_SPIOF 0x80000000 +#define IOTFIFO_BA_SHIFT 0 +#define IOTFIFO_S_SHIFT 16 +#endif + +/* + * The following defines are for the flags in the I/O trap retry read data + * register. + */ +#ifndef NO_CS4612 +#define IOTRRD_D_MASK 0x0000FFFF +#define IOTRRD_RDV 0x80000000 +#define IOTRRD_D_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the I/O trap FIFO pointer + * register. + */ +#ifndef NO_CS4612 +#define IOTFP_CA_MASK 0x00003FFF +#define IOTFP_PA_MASK 0x3FFF0000 +#define IOTFP_CA_SHIFT 0 +#define IOTFP_PA_SHIFT 16 +#endif + +/* + * The following defines are for the flags in the I/O trap control register. + */ +#ifndef NO_CS4612 +#define IOTCR_ITD 0x00000001 +#define IOTCR_HRV 0x00000002 +#define IOTCR_SRV 0x00000004 +#define IOTCR_DTI 0x00000008 +#define IOTCR_DFI 0x00000010 +#define IOTCR_DDP 0x00000020 +#define IOTCR_JTE 0x00000040 +#define IOTCR_PPE 0x00000080 +#endif + +/* + * The following defines are for the flags in the direct PCI data register. + */ +#ifndef NO_CS4612 +#define DPCID_D_MASK 0xFFFFFFFF +#define DPCID_D_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the direct PCI address register. + */ +#ifndef NO_CS4612 +#define DPCIA_A_MASK 0xFFFFFFFF +#define DPCIA_A_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the direct PCI command register. + */ +#ifndef NO_CS4612 +#define DPCIC_C_MASK 0x0000000F +#define DPCIC_C_IOREAD 0x00000002 +#define DPCIC_C_IOWRITE 0x00000003 +#define DPCIC_BE_MASK 0x000000F0 +#endif + +/* + * The following defines are for the flags in the PC/PCI request register. + */ +#ifndef NO_CS4612 +#define PCPCIR_RDC_MASK 0x00000007 +#define PCPCIR_C_MASK 0x00007000 +#define PCPCIR_REQ 0x00008000 +#define PCPCIR_RDC_SHIFT 0 +#define PCPCIR_C_SHIFT 12 +#endif + +/* + * The following defines are for the flags in the PC/PCI grant register. + */ +#ifndef NO_CS4612 +#define PCPCIG_GDC_MASK 0x00000007 +#define PCPCIG_VL 0x00008000 +#define PCPCIG_GDC_SHIFT 0 +#endif + +/* + * The following defines are for the flags in the PC/PCI master enable + * register. + */ +#ifndef NO_CS4612 +#define PCPCIEN_EN 0x00000001 +#endif + +/* + * The following defines are for the flags in the extended PCI power + * management control register. + */ +#ifndef NO_CS4612 +#define EPCIPMC_GWU 0x00000001 +#define EPCIPMC_FSPC 0x00000002 +#endif + +/* + * The following defines are for the flags in the SP control register. + */ +#define SPCR_RUN 0x00000001 +#define SPCR_STPFR 0x00000002 +#define SPCR_RUNFR 0x00000004 +#define SPCR_TICK 0x00000008 +#define SPCR_DRQEN 0x00000020 +#define SPCR_RSTSP 0x00000040 +#define SPCR_OREN 0x00000080 +#ifndef NO_CS4612 +#define SPCR_PCIINT 0x00000100 +#define SPCR_OINTD 0x00000200 +#define SPCR_CRE 0x00008000 +#endif + +/* + * The following defines are for the flags in the debug index register. + */ +#define DREG_REGID_MASK 0x0000007F +#define DREG_DEBUG 0x00000080 +#define DREG_RGBK_MASK 0x00000700 +#define DREG_TRAP 0x00000800 +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_TRAPX 0x00001000 +#endif +#endif +#define DREG_REGID_SHIFT 0 +#define DREG_RGBK_SHIFT 8 +#define DREG_RGBK_REGID_MASK 0x0000077F +#define DREG_REGID_R0 0x00000010 +#define DREG_REGID_R1 0x00000011 +#define DREG_REGID_R2 0x00000012 +#define DREG_REGID_R3 0x00000013 +#define DREG_REGID_R4 0x00000014 +#define DREG_REGID_R5 0x00000015 +#define DREG_REGID_R6 0x00000016 +#define DREG_REGID_R7 0x00000017 +#define DREG_REGID_R8 0x00000018 +#define DREG_REGID_R9 0x00000019 +#define DREG_REGID_RA 0x0000001A +#define DREG_REGID_RB 0x0000001B +#define DREG_REGID_RC 0x0000001C +#define DREG_REGID_RD 0x0000001D +#define DREG_REGID_RE 0x0000001E +#define DREG_REGID_RF 0x0000001F +#define DREG_REGID_RA_BUS_LOW 0x00000020 +#define DREG_REGID_RA_BUS_HIGH 0x00000038 +#define DREG_REGID_YBUS_LOW 0x00000050 +#define DREG_REGID_YBUS_HIGH 0x00000058 +#define DREG_REGID_TRAP_0 0x00000100 +#define DREG_REGID_TRAP_1 0x00000101 +#define DREG_REGID_TRAP_2 0x00000102 +#define DREG_REGID_TRAP_3 0x00000103 +#define DREG_REGID_TRAP_4 0x00000104 +#define DREG_REGID_TRAP_5 0x00000105 +#define DREG_REGID_TRAP_6 0x00000106 +#define DREG_REGID_TRAP_7 0x00000107 +#define DREG_REGID_INDIRECT_ADDRESS 0x0000010E +#define DREG_REGID_TOP_OF_STACK 0x0000010F +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_8 0x00000110 +#define DREG_REGID_TRAP_9 0x00000111 +#define DREG_REGID_TRAP_10 0x00000112 +#define DREG_REGID_TRAP_11 0x00000113 +#define DREG_REGID_TRAP_12 0x00000114 +#define DREG_REGID_TRAP_13 0x00000115 +#define DREG_REGID_TRAP_14 0x00000116 +#define DREG_REGID_TRAP_15 0x00000117 +#define DREG_REGID_TRAP_16 0x00000118 +#define DREG_REGID_TRAP_17 0x00000119 +#define DREG_REGID_TRAP_18 0x0000011A +#define DREG_REGID_TRAP_19 0x0000011B +#define DREG_REGID_TRAP_20 0x0000011C +#define DREG_REGID_TRAP_21 0x0000011D +#define DREG_REGID_TRAP_22 0x0000011E +#define DREG_REGID_TRAP_23 0x0000011F +#endif +#endif +#define DREG_REGID_RSA0_LOW 0x00000200 +#define DREG_REGID_RSA0_HIGH 0x00000201 +#define DREG_REGID_RSA1_LOW 0x00000202 +#define DREG_REGID_RSA1_HIGH 0x00000203 +#define DREG_REGID_RSA2 0x00000204 +#define DREG_REGID_RSA3 0x00000205 +#define DREG_REGID_RSI0_LOW 0x00000206 +#define DREG_REGID_RSI0_HIGH 0x00000207 +#define DREG_REGID_RSI1 0x00000208 +#define DREG_REGID_RSI2 0x00000209 +#define DREG_REGID_SAGUSTATUS 0x0000020A +#define DREG_REGID_RSCONFIG01_LOW 0x0000020B +#define DREG_REGID_RSCONFIG01_HIGH 0x0000020C +#define DREG_REGID_RSCONFIG23_LOW 0x0000020D +#define DREG_REGID_RSCONFIG23_HIGH 0x0000020E +#define DREG_REGID_RSDMA01E 0x0000020F +#define DREG_REGID_RSDMA23E 0x00000210 +#define DREG_REGID_RSD0_LOW 0x00000211 +#define DREG_REGID_RSD0_HIGH 0x00000212 +#define DREG_REGID_RSD1_LOW 0x00000213 +#define DREG_REGID_RSD1_HIGH 0x00000214 +#define DREG_REGID_RSD2_LOW 0x00000215 +#define DREG_REGID_RSD2_HIGH 0x00000216 +#define DREG_REGID_RSD3_LOW 0x00000217 +#define DREG_REGID_RSD3_HIGH 0x00000218 +#define DREG_REGID_SRAR_HIGH 0x0000021A +#define DREG_REGID_SRAR_LOW 0x0000021B +#define DREG_REGID_DMA_STATE 0x0000021C +#define DREG_REGID_CURRENT_DMA_STREAM 0x0000021D +#define DREG_REGID_NEXT_DMA_STREAM 0x0000021E +#define DREG_REGID_CPU_STATUS 0x00000300 +#define DREG_REGID_MAC_MODE 0x00000301 +#define DREG_REGID_STACK_AND_REPEAT 0x00000302 +#define DREG_REGID_INDEX0 0x00000304 +#define DREG_REGID_INDEX1 0x00000305 +#define DREG_REGID_DMA_STATE_0_3 0x00000400 +#define DREG_REGID_DMA_STATE_4_7 0x00000404 +#define DREG_REGID_DMA_STATE_8_11 0x00000408 +#define DREG_REGID_DMA_STATE_12_15 0x0000040C +#define DREG_REGID_DMA_STATE_16_19 0x00000410 +#define DREG_REGID_DMA_STATE_20_23 0x00000414 +#define DREG_REGID_DMA_STATE_24_27 0x00000418 +#define DREG_REGID_DMA_STATE_28_31 0x0000041C +#define DREG_REGID_DMA_STATE_32_35 0x00000420 +#define DREG_REGID_DMA_STATE_36_39 0x00000424 +#define DREG_REGID_DMA_STATE_40_43 0x00000428 +#define DREG_REGID_DMA_STATE_44_47 0x0000042C +#define DREG_REGID_DMA_STATE_48_51 0x00000430 +#define DREG_REGID_DMA_STATE_52_55 0x00000434 +#define DREG_REGID_DMA_STATE_56_59 0x00000438 +#define DREG_REGID_DMA_STATE_60_63 0x0000043C +#define DREG_REGID_DMA_STATE_64_67 0x00000440 +#define DREG_REGID_DMA_STATE_68_71 0x00000444 +#define DREG_REGID_DMA_STATE_72_75 0x00000448 +#define DREG_REGID_DMA_STATE_76_79 0x0000044C +#define DREG_REGID_DMA_STATE_80_83 0x00000450 +#define DREG_REGID_DMA_STATE_84_87 0x00000454 +#define DREG_REGID_DMA_STATE_88_91 0x00000458 +#define DREG_REGID_DMA_STATE_92_95 0x0000045C +#define DREG_REGID_TRAP_SELECT 0x00000500 +#define DREG_REGID_TRAP_WRITE_0 0x00000500 +#define DREG_REGID_TRAP_WRITE_1 0x00000501 +#define DREG_REGID_TRAP_WRITE_2 0x00000502 +#define DREG_REGID_TRAP_WRITE_3 0x00000503 +#define DREG_REGID_TRAP_WRITE_4 0x00000504 +#define DREG_REGID_TRAP_WRITE_5 0x00000505 +#define DREG_REGID_TRAP_WRITE_6 0x00000506 +#define DREG_REGID_TRAP_WRITE_7 0x00000507 +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_WRITE_8 0x00000510 +#define DREG_REGID_TRAP_WRITE_9 0x00000511 +#define DREG_REGID_TRAP_WRITE_10 0x00000512 +#define DREG_REGID_TRAP_WRITE_11 0x00000513 +#define DREG_REGID_TRAP_WRITE_12 0x00000514 +#define DREG_REGID_TRAP_WRITE_13 0x00000515 +#define DREG_REGID_TRAP_WRITE_14 0x00000516 +#define DREG_REGID_TRAP_WRITE_15 0x00000517 +#define DREG_REGID_TRAP_WRITE_16 0x00000518 +#define DREG_REGID_TRAP_WRITE_17 0x00000519 +#define DREG_REGID_TRAP_WRITE_18 0x0000051A +#define DREG_REGID_TRAP_WRITE_19 0x0000051B +#define DREG_REGID_TRAP_WRITE_20 0x0000051C +#define DREG_REGID_TRAP_WRITE_21 0x0000051D +#define DREG_REGID_TRAP_WRITE_22 0x0000051E +#define DREG_REGID_TRAP_WRITE_23 0x0000051F +#endif +#endif +#define DREG_REGID_MAC0_ACC0_LOW 0x00000600 +#define DREG_REGID_MAC0_ACC1_LOW 0x00000601 +#define DREG_REGID_MAC0_ACC2_LOW 0x00000602 +#define DREG_REGID_MAC0_ACC3_LOW 0x00000603 +#define DREG_REGID_MAC1_ACC0_LOW 0x00000604 +#define DREG_REGID_MAC1_ACC1_LOW 0x00000605 +#define DREG_REGID_MAC1_ACC2_LOW 0x00000606 +#define DREG_REGID_MAC1_ACC3_LOW 0x00000607 +#define DREG_REGID_MAC0_ACC0_MID 0x00000608 +#define DREG_REGID_MAC0_ACC1_MID 0x00000609 +#define DREG_REGID_MAC0_ACC2_MID 0x0000060A +#define DREG_REGID_MAC0_ACC3_MID 0x0000060B +#define DREG_REGID_MAC1_ACC0_MID 0x0000060C +#define DREG_REGID_MAC1_ACC1_MID 0x0000060D +#define DREG_REGID_MAC1_ACC2_MID 0x0000060E +#define DREG_REGID_MAC1_ACC3_MID 0x0000060F +#define DREG_REGID_MAC0_ACC0_HIGH 0x00000610 +#define DREG_REGID_MAC0_ACC1_HIGH 0x00000611 +#define DREG_REGID_MAC0_ACC2_HIGH 0x00000612 +#define DREG_REGID_MAC0_ACC3_HIGH 0x00000613 +#define DREG_REGID_MAC1_ACC0_HIGH 0x00000614 +#define DREG_REGID_MAC1_ACC1_HIGH 0x00000615 +#define DREG_REGID_MAC1_ACC2_HIGH 0x00000616 +#define DREG_REGID_MAC1_ACC3_HIGH 0x00000617 +#define DREG_REGID_RSHOUT_LOW 0x00000620 +#define DREG_REGID_RSHOUT_MID 0x00000628 +#define DREG_REGID_RSHOUT_HIGH 0x00000630 + +/* + * The following defines are for the flags in the DMA stream requestor write + */ +#define DSRWP_DSR_MASK 0x0000000F +#define DSRWP_DSR_BG_RQ 0x00000001 +#define DSRWP_DSR_PRIORITY_MASK 0x00000006 +#define DSRWP_DSR_PRIORITY_0 0x00000000 +#define DSRWP_DSR_PRIORITY_1 0x00000002 +#define DSRWP_DSR_PRIORITY_2 0x00000004 +#define DSRWP_DSR_PRIORITY_3 0x00000006 +#define DSRWP_DSR_RQ_PENDING 0x00000008 + +/* + * The following defines are for the flags in the trap write port register. + */ +#define TWPR_TW_MASK 0x0000FFFF +#define TWPR_TW_SHIFT 0 + +/* + * The following defines are for the flags in the stack pointer write + * register. + */ +#define SPWR_STKP_MASK 0x0000000F +#define SPWR_STKP_SHIFT 0 + +/* + * The following defines are for the flags in the SP interrupt register. + */ +#define SPIR_FRI 0x00000001 +#define SPIR_DOI 0x00000002 +#define SPIR_GPI2 0x00000004 +#define SPIR_GPI3 0x00000008 +#define SPIR_IP0 0x00000010 +#define SPIR_IP1 0x00000020 +#define SPIR_IP2 0x00000040 +#define SPIR_IP3 0x00000080 + +/* + * The following defines are for the flags in the functional group 1 register. + */ +#define FGR1_F1S_MASK 0x0000FFFF +#define FGR1_F1S_SHIFT 0 + +/* + * The following defines are for the flags in the SP clock status register. + */ +#define SPCS_FRI 0x00000001 +#define SPCS_DOI 0x00000002 +#define SPCS_GPI2 0x00000004 +#define SPCS_GPI3 0x00000008 +#define SPCS_IP0 0x00000010 +#define SPCS_IP1 0x00000020 +#define SPCS_IP2 0x00000040 +#define SPCS_IP3 0x00000080 +#define SPCS_SPRUN 0x00000100 +#define SPCS_SLEEP 0x00000200 +#define SPCS_FG 0x00000400 +#define SPCS_ORUN 0x00000800 +#define SPCS_IRQ 0x00001000 +#define SPCS_FGN_MASK 0x0000E000 +#define SPCS_FGN_SHIFT 13 + +/* + * The following defines are for the flags in the SP DMA requestor status + * register. + */ +#define SDSR_DCS_MASK 0x000000FF +#define SDSR_DCS_SHIFT 0 +#define SDSR_DCS_NONE 0x00000007 + +/* + * The following defines are for the flags in the frame timer register. + */ +#define FRMT_FTV_MASK 0x0000FFFF +#define FRMT_FTV_SHIFT 0 + +/* + * The following defines are for the flags in the frame timer current count + * register. + */ +#define FRCC_FCC_MASK 0x0000FFFF +#define FRCC_FCC_SHIFT 0 + +/* + * The following defines are for the flags in the frame timer save count + * register. + */ +#define FRSC_FCS_MASK 0x0000FFFF +#define FRSC_FCS_SHIFT 0 + +/* + * The following define the various flags stored in the scatter/gather + * descriptors. + */ +#define DMA_SG_NEXT_ENTRY_MASK 0x00000FF8 +#define DMA_SG_SAMPLE_END_MASK 0x0FFF0000 +#define DMA_SG_SAMPLE_END_FLAG 0x10000000 +#define DMA_SG_LOOP_END_FLAG 0x20000000 +#define DMA_SG_SIGNAL_END_FLAG 0x40000000 +#define DMA_SG_SIGNAL_PAGE_FLAG 0x80000000 +#define DMA_SG_NEXT_ENTRY_SHIFT 3 +#define DMA_SG_SAMPLE_END_SHIFT 16 + +/* + * The following define the offsets of the fields within the on-chip generic + * DMA requestor. + */ +#define DMA_RQ_CONTROL1 0x00000000 +#define DMA_RQ_CONTROL2 0x00000004 +#define DMA_RQ_SOURCE_ADDR 0x00000008 +#define DMA_RQ_DESTINATION_ADDR 0x0000000C +#define DMA_RQ_NEXT_PAGE_ADDR 0x00000010 +#define DMA_RQ_NEXT_PAGE_SGDESC 0x00000014 +#define DMA_RQ_LOOP_START_ADDR 0x00000018 +#define DMA_RQ_POST_LOOP_ADDR 0x0000001C +#define DMA_RQ_PAGE_MAP_ADDR 0x00000020 + +/* + * The following defines are for the flags in the first control word of the + * on-chip generic DMA requestor. + */ +#define DMA_RQ_C1_COUNT_MASK 0x000003FF +#define DMA_RQ_C1_DESTINATION_SCATTER 0x00001000 +#define DMA_RQ_C1_SOURCE_GATHER 0x00002000 +#define DMA_RQ_C1_DONE_FLAG 0x00004000 +#define DMA_RQ_C1_OPTIMIZE_STATE 0x00008000 +#define DMA_RQ_C1_SAMPLE_END_STATE_MASK 0x00030000 +#define DMA_RQ_C1_FULL_PAGE 0x00000000 +#define DMA_RQ_C1_BEFORE_SAMPLE_END 0x00010000 +#define DMA_RQ_C1_PAGE_MAP_ERROR 0x00020000 +#define DMA_RQ_C1_AT_SAMPLE_END 0x00030000 +#define DMA_RQ_C1_LOOP_END_STATE_MASK 0x000C0000 +#define DMA_RQ_C1_NOT_LOOP_END 0x00000000 +#define DMA_RQ_C1_BEFORE_LOOP_END 0x00040000 +#define DMA_RQ_C1_2PAGE_LOOP_BEGIN 0x00080000 +#define DMA_RQ_C1_LOOP_BEGIN 0x000C0000 +#define DMA_RQ_C1_PAGE_MAP_MASK 0x00300000 +#define DMA_RQ_C1_PM_NONE_PENDING 0x00000000 +#define DMA_RQ_C1_PM_NEXT_PENDING 0x00100000 +#define DMA_RQ_C1_PM_RESERVED 0x00200000 +#define DMA_RQ_C1_PM_LOOP_NEXT_PENDING 0x00300000 +#define DMA_RQ_C1_WRITEBACK_DEST_FLAG 0x00400000 +#define DMA_RQ_C1_WRITEBACK_SRC_FLAG 0x00800000 +#define DMA_RQ_C1_DEST_SIZE_MASK 0x07000000 +#define DMA_RQ_C1_DEST_LINEAR 0x00000000 +#define DMA_RQ_C1_DEST_MOD16 0x01000000 +#define DMA_RQ_C1_DEST_MOD32 0x02000000 +#define DMA_RQ_C1_DEST_MOD64 0x03000000 +#define DMA_RQ_C1_DEST_MOD128 0x04000000 +#define DMA_RQ_C1_DEST_MOD256 0x05000000 +#define DMA_RQ_C1_DEST_MOD512 0x06000000 +#define DMA_RQ_C1_DEST_MOD1024 0x07000000 +#define DMA_RQ_C1_DEST_ON_HOST 0x08000000 +#define DMA_RQ_C1_SOURCE_SIZE_MASK 0x70000000 +#define DMA_RQ_C1_SOURCE_LINEAR 0x00000000 +#define DMA_RQ_C1_SOURCE_MOD16 0x10000000 +#define DMA_RQ_C1_SOURCE_MOD32 0x20000000 +#define DMA_RQ_C1_SOURCE_MOD64 0x30000000 +#define DMA_RQ_C1_SOURCE_MOD128 0x40000000 +#define DMA_RQ_C1_SOURCE_MOD256 0x50000000 +#define DMA_RQ_C1_SOURCE_MOD512 0x60000000 +#define DMA_RQ_C1_SOURCE_MOD1024 0x70000000 +#define DMA_RQ_C1_SOURCE_ON_HOST 0x80000000 +#define DMA_RQ_C1_COUNT_SHIFT 0 + +/* + * The following defines are for the flags in the second control word of the + * on-chip generic DMA requestor. + */ +#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK 0x0000003F +#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK 0x00000300 +#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL 0x00000000 +#define DMA_RQ_C2_SIGNAL_EVERY_DMA 0x00000100 +#define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG 0x00000200 +#define DMA_RQ_C2_SIGNAL_DEST_PINGPONG 0x00000300 +#define DMA_RQ_C2_AUDIO_CONVERT_MASK 0x0000F000 +#define DMA_RQ_C2_AC_NONE 0x00000000 +#define DMA_RQ_C2_AC_8_TO_16_BIT 0x00001000 +#define DMA_RQ_C2_AC_MONO_TO_STEREO 0x00002000 +#define DMA_RQ_C2_AC_ENDIAN_CONVERT 0x00004000 +#define DMA_RQ_C2_AC_SIGNED_CONVERT 0x00008000 +#define DMA_RQ_C2_LOOP_END_MASK 0x0FFF0000 +#define DMA_RQ_C2_LOOP_MASK 0x30000000 +#define DMA_RQ_C2_NO_LOOP 0x00000000 +#define DMA_RQ_C2_ONE_PAGE_LOOP 0x10000000 +#define DMA_RQ_C2_TWO_PAGE_LOOP 0x20000000 +#define DMA_RQ_C2_MULTI_PAGE_LOOP 0x30000000 +#define DMA_RQ_C2_SIGNAL_LOOP_BACK 0x40000000 +#define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE 0x80000000 +#define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT 0 +#define DMA_RQ_C2_LOOP_END_SHIFT 16 + +/* + * The following defines are for the flags in the source and destination words + * of the on-chip generic DMA requestor. + */ +#define DMA_RQ_SD_ADDRESS_MASK 0x0000FFFF +#define DMA_RQ_SD_MEMORY_ID_MASK 0x000F0000 +#define DMA_RQ_SD_SP_PARAM_ADDR 0x00000000 +#define DMA_RQ_SD_SP_SAMPLE_ADDR 0x00010000 +#define DMA_RQ_SD_SP_PROGRAM_ADDR 0x00020000 +#define DMA_RQ_SD_SP_DEBUG_ADDR 0x00030000 +#define DMA_RQ_SD_OMNIMEM_ADDR 0x000E0000 +#define DMA_RQ_SD_END_FLAG 0x40000000 +#define DMA_RQ_SD_ERROR_FLAG 0x80000000 +#define DMA_RQ_SD_ADDRESS_SHIFT 0 + +/* + * The following defines are for the flags in the page map address word of the + * on-chip generic DMA requestor. + */ +#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK 0x00000FF8 +#define DMA_RQ_PMA_PAGE_TABLE_MASK 0xFFFFF000 +#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT 3 +#define DMA_RQ_PMA_PAGE_TABLE_SHIFT 12 + +#define BA1_VARIDEC_BUF_1 0x000 + +#define BA1_PDTC 0x0c0 /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */ +#define BA1_PFIE 0x0c4 /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */ +#define BA1_PBA 0x0c8 /* BA1_PLAY_BUFFER_ADDRESS */ +#define BA1_PVOL 0x0f8 /* BA1_PLAY_VOLUME_REG */ +#define BA1_PSRC 0x288 /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */ +#define BA1_PCTL 0x2a4 /* BA1_PLAY_CONTROL_REG */ +#define BA1_PPI 0x2b4 /* BA1_PLAY_PHASE_INCREMENT_REG */ + +#define BA1_CCTL 0x064 /* BA1_CAPTURE_CONTROL_REG */ +#define BA1_CIE 0x104 /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */ +#define BA1_CBA 0x10c /* BA1_CAPTURE_BUFFER_ADDRESS */ +#define BA1_CSRC 0x2c8 /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */ +#define BA1_CCI 0x2d8 /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */ +#define BA1_CD 0x2e0 /* BA1_CAPTURE_DELAY_REG */ +#define BA1_CPI 0x2f4 /* BA1_CAPTURE_PHASE_INCREMENT_REG */ +#define BA1_CVOL 0x2f8 /* BA1_CAPTURE_VOLUME_REG */ + +#define BA1_CFG1 0x134 /* BA1_CAPTURE_FRAME_GROUP_1_REG */ +#define BA1_CFG2 0x138 /* BA1_CAPTURE_FRAME_GROUP_2_REG */ +#define BA1_CCST 0x13c /* BA1_CAPTURE_CONSTANT_REG */ +#define BA1_CSPB 0x340 /* BA1_CAPTURE_SPB_ADDRESS */ + +/* + * + */ + +#define CS461X_MODE_OUTPUT (1<<0) /* MIDI UART - output */ +#define CS461X_MODE_INPUT (1<<1) /* MIDI UART - input */ + +/**************************************************************************** + * + * The following define the offsets of the AC97 shadow registers, which appear + * as a virtual extension to the base address register zero memory range. + * + ****************************************************************************/ +#define AC97_REG_OFFSET_MASK 0x0000007EL +#define AC97_CODEC_NUMBER_MASK 0x00003000L + +#define BA0_AC97_RESET 0x00001000L +#define BA0_AC97_MASTER_VOLUME 0x00001002L +#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L +#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L +#define BA0_AC97_MASTER_TONE 0x00001008L +#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL +#define BA0_AC97_PHONE_VOLUME 0x0000100CL +#define BA0_AC97_MIC_VOLUME 0x0000100EL +#define BA0_AC97_LINE_IN_VOLUME 0x00001010L +#define BA0_AC97_CD_VOLUME 0x00001012L +#define BA0_AC97_VIDEO_VOLUME 0x00001014L +#define BA0_AC97_AUX_VOLUME 0x00001016L +#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L +#define BA0_AC97_RECORD_SELECT 0x0000101AL +#define BA0_AC97_RECORD_GAIN 0x0000101CL +#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL +#define BA0_AC97_GENERAL_PURPOSE 0x00001020L +#define BA0_AC97_3D_CONTROL 0x00001022L +#define BA0_AC97_MODEM_RATE 0x00001024L +#define BA0_AC97_POWERDOWN 0x00001026L +#define BA0_AC97_EXT_AUDIO_ID 0x00001028L +#define BA0_AC97_EXT_AUDIO_POWER 0x0000102AL +#define BA0_AC97_PCM_FRONT_DAC_RATE 0x0000102CL +#define BA0_AC97_PCM_SURR_DAC_RATE 0x0000102EL +#define BA0_AC97_PCM_LFE_DAC_RATE 0x00001030L +#define BA0_AC97_PCM_LR_ADC_RATE 0x00001032L +#define BA0_AC97_MIC_ADC_RATE 0x00001034L +#define BA0_AC97_6CH_VOL_C_LFE 0x00001036L +#define BA0_AC97_6CH_VOL_SURROUND 0x00001038L +#define BA0_AC97_RESERVED_3A 0x0000103AL +#define BA0_AC97_EXT_MODEM_ID 0x0000103CL +#define BA0_AC97_EXT_MODEM_POWER 0x0000103EL +#define BA0_AC97_LINE1_CODEC_RATE 0x00001040L +#define BA0_AC97_LINE2_CODEC_RATE 0x00001042L +#define BA0_AC97_HANDSET_CODEC_RATE 0x00001044L +#define BA0_AC97_LINE1_CODEC_LEVEL 0x00001046L +#define BA0_AC97_LINE2_CODEC_LEVEL 0x00001048L +#define BA0_AC97_HANDSET_CODEC_LEVEL 0x0000104AL +#define BA0_AC97_GPIO_PIN_CONFIG 0x0000104CL +#define BA0_AC97_GPIO_PIN_TYPE 0x0000104EL +#define BA0_AC97_GPIO_PIN_STICKY 0x00001050L +#define BA0_AC97_GPIO_PIN_WAKEUP 0x00001052L +#define BA0_AC97_GPIO_PIN_STATUS 0x00001054L +#define BA0_AC97_MISC_MODEM_AFE_STAT 0x00001056L +#define BA0_AC97_RESERVED_58 0x00001058L +#define BA0_AC97_CRYSTAL_REV_N_FAB_ID 0x0000105AL +#define BA0_AC97_TEST_AND_MISC_CTRL 0x0000105CL +#define BA0_AC97_AC_MODE 0x0000105EL +#define BA0_AC97_MISC_CRYSTAL_CONTROL 0x00001060L +#define BA0_AC97_LINE1_HYPRID_CTRL 0x00001062L +#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L +#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L +#define BA0_AC97_SPDIF_CONTROL 0x00001068L +#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL +#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL +#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL +#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L +#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L +#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L +#define BA0_AC97_CAL_ADDRESS 0x00001076L +#define BA0_AC97_CAL_DATA 0x00001078L +#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL +#define BA0_AC97_VENDOR_ID1 0x0000107CL +#define BA0_AC97_VENDOR_ID2 0x0000107EL diff --git a/kernel/drv/oss_cs461x/cs461x_dsp.h b/kernel/drv/oss_cs461x/cs461x_dsp.h new file mode 100644 index 0000000..44c6da6 --- /dev/null +++ b/kernel/drv/oss_cs461x/cs461x_dsp.h @@ -0,0 +1,3474 @@ +/* + * Purpose: Firmware for cs461x/cs461x cards. + */ +/* + * + * 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. + * + */ +struct cs461x_firmware_struct cs461x_firmware = { + {{0x00000000, 0x00003000}, {0x00010000, 0x00003800}, + {0x00020000, 0x00007000}}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000163, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00200040, 0x00008010, 0x00000000, + 0x00000000, 0x80000001, 0x00000001, 0x00060000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00900080, 0x00000173, 0x00000000, + 0x00000000, 0x00000010, 0x00800000, 0x00900000, + 0xf2c0000f, 0x00000200, 0x00000000, 0x00010600, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000163, 0x330300c2, + 0x06000000, 0x00000000, 0x80008000, 0x80008000, + 0x3fc0000f, 0x00000301, 0x00010400, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00b00000, 0x00d0806d, 0x330480c3, + 0x04800000, 0x00000001, 0x00800001, 0x0000ffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x066a0130, 0x06350070, 0x0000929d, 0x929d929d, + 0x00000000, 0x0000735a, 0x00000600, 0x00000000, + 0x929d735a, 0x00000000, 0x00010000, 0x735a735a, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000f0, 0x0000804f, 0x000000c3, + 0x05000000, 0x00a00010, 0x00000000, 0x80008000, + 0x00000000, 0x00000000, 0x00000700, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000080, 0x00a00000, 0x0000809a, 0x000000c2, + 0x07400000, 0x00000000, 0x80008000, 0xffffffff, + 0x00c80028, 0x00005555, 0x00000000, 0x000107a0, + 0x00c80028, 0x000000c2, 0x06800000, 0x00000000, + 0x06e00080, 0x00300000, 0x000080bb, 0x000000c9, + 0x07a00000, 0x04000000, 0x80008000, 0xffffffff, + 0x00c80028, 0x00005555, 0x00000000, 0x00000780, + 0x00c80028, 0x000000c5, 0xff800000, 0x00000000, + 0x00640080, 0x00c00000, 0x00008197, 0x000000c9, + 0x07800000, 0x04000000, 0x80008000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0000805e, 0x000000c1, + 0x00000000, 0x00800000, 0x80008000, 0x80008000, + 0x00020000, 0x0000ffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x07c00000, 0x00900000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0000018e, 0x000000c2, + 0x07c00000, 0x00000000, 0x80008000, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00e00100, 0x00000173, 0x00000000, + 0x00000000, 0x00400010, 0x00800000, 0x00e00000, + 0x00000000, 0x00000000, 0x08400000, 0x00900000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x01100000, 0x0000018e, 0x000000c2, + 0x08400000, 0x00000000, 0x80008000, 0xffffffff, + 0x007fff80, 0x00280058, 0x01300000, 0x00000000, + 0x00000000, 0x2aab0000, 0x00000000, 0x00000000, + 0x00000000, 0x01200000, 0x0000026c, 0x000000c2, + 0x08c00000, 0x18000000, 0x80008000, 0x80008000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0000805e, 0x000000c1, + 0x00000000, 0x01000000, 0x80008000, 0x80008000, + 0x00000000, 0x00000110, 0x00000000, 0x00000000, + 0x00000000, 0x00000082, 0x09000000, 0x00000000, + 0x00000000, 0x00000600, 0x013d0233, 0x20ff0040, + 0x00000000, 0x0000804c, 0x000101d8, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x929d0600, 0x929d929d, 0x929d929d, 0x929d0000, + 0x929d929d, 0x929d929d, 0x929d929d, 0x929d929d, + 0x929d929d, 0x00100635, 0x060b013f, 0x00000004, + 0x00000001, 0x007a0002, 0x00000000, 0x066e0610, + 0x0105929d, 0x929d929d, 0x929d929d, 0x929d929d, + 0x929d929d, 0xa431ac75, 0x0001735a, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0x735a0051, + 0x00000000, 0x929d929d, 0x929d929d, 0x929d929d, + 0x929d929d, 0x929d929d, 0x929d929d, 0x929d929d, + 0x929d929d, 0x929d929d, 0x00000000, 0x06400136, + 0x0000270f, 0x00010000, 0x007a0000, 0x00000000, + 0x068e0645, 0x0105929d, 0x929d929d, 0x929d929d, + 0x929d929d, 0x929d929d, 0xa431ac75, 0x0001735a, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0xa431ac75, 0xa431ac75, 0xa431ac75, 0xa431ac75, + 0x735a0100, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010004, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00001705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00009705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00011705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00019705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00021705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00029705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00031705, 0x00001400, 0x000a411e, 0x00001003, + 0x00040730, 0x00001002, 0x000f619e, 0x00001003, + 0x00039705, 0x00001400, 0x000a411e, 0x00001003, + 0x000fe19e, 0x00001003, 0x0009c730, 0x00001003, + 0x0008e19c, 0x00001003, 0x000083c1, 0x00093040, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00009705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00011705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00019705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00021705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00029705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00031705, 0x00001400, 0x000a211e, 0x00001003, + 0x00098730, 0x00001002, 0x000ee19e, 0x00001003, + 0x00039705, 0x00001400, 0x000a211e, 0x00001003, + 0x0000a730, 0x00001008, 0x000e2730, 0x00001002, + 0x0000a731, 0x00001002, 0x0000a731, 0x00001002, + 0x0000a731, 0x00001002, 0x0000a731, 0x00001002, + 0x0000a731, 0x00001002, 0x0000a731, 0x00001002, + 0x00000000, 0x00000000, 0x000f619c, 0x00001003, + 0x0007f801, 0x000c0000, 0x00000037, 0x00001000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000c0000, 0x00000000, 0x00000000, + 0x0000373c, 0x00001000, 0x00000000, 0x00000000, + 0x000ee19c, 0x00001003, 0x0007f801, 0x000c0000, + 0x00000037, 0x00001000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0000273c, 0x00001000, + 0x00000033, 0x00001000, 0x000e679e, 0x00001003, + 0x00007705, 0x00001400, 0x000ac71e, 0x00001003, + 0x00087fc1, 0x000c3be0, 0x0007f801, 0x000c0000, + 0x00000037, 0x00001000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0000a730, 0x00001003, + 0x00000033, 0x00001000, 0x0007f801, 0x000c0000, + 0x00000037, 0x00001000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x000c0000, + 0x00000032, 0x00001000, 0x0000273d, 0x00001000, + 0x0004a730, 0x00001003, 0x00000f41, 0x00097140, + 0x0000a841, 0x0009b240, 0x0000a0c1, 0x0009f040, + 0x0001c641, 0x00093540, 0x0001cec1, 0x0009b5c0, + 0x00000000, 0x00000000, 0x0001bf05, 0x0003fc40, + 0x00002725, 0x000aa400, 0x00013705, 0x00093a00, + 0x0000002e, 0x0009d6c0, 0x00038630, 0x00001004, + 0x0004ef0a, 0x000eb785, 0x0003fc8a, 0x00000000, + 0x00000000, 0x000c70e0, 0x0007d182, 0x0002c640, + 0x00000630, 0x00001004, 0x000799b8, 0x0002c6c0, + 0x00031705, 0x00092240, 0x00039f05, 0x000932c0, + 0x0003520a, 0x00000000, 0x00040731, 0x0000100b, + 0x00010705, 0x000b20c0, 0x00000000, 0x000eba44, + 0x00032108, 0x000c60c4, 0x00065208, 0x000c2917, + 0x000406b0, 0x00001007, 0x00012f05, 0x00036880, + 0x0002818e, 0x000c0000, 0x0004410a, 0x00000000, + 0x00040630, 0x00001007, 0x00029705, 0x000c0000, + 0x00000000, 0x00000000, 0x00003fc1, 0x0003fc40, + 0x000037c1, 0x00091b40, 0x00003fc1, 0x000911c0, + 0x000037c1, 0x000957c0, 0x00003fc1, 0x000951c0, + 0x000037c1, 0x00000000, 0x00003fc1, 0x000991c0, + 0x000037c1, 0x00000000, 0x00003fc1, 0x0009d1c0, + 0x000037c1, 0x00000000, 0x0001ccc1, 0x000915c0, + 0x0001c441, 0x0009d800, 0x0009cdc1, 0x00091240, + 0x0001c541, 0x00091d00, 0x0009cfc1, 0x00095240, + 0x0001c741, 0x00095c80, 0x000e8ca9, 0x00099240, + 0x000e85ad, 0x00095640, 0x00069ca9, 0x00099d80, + 0x000e952d, 0x00099640, 0x000eaca9, 0x0009d6c0, + 0x000ea5ad, 0x00091a40, 0x0006bca9, 0x0009de80, + 0x000eb52d, 0x00095a40, 0x000ecca9, 0x00099ac0, + 0x000ec5ad, 0x0009da40, 0x000edca9, 0x0009d300, + 0x000a6e0a, 0x00001000, 0x000ed52d, 0x00091e40, + 0x000eeca9, 0x00095ec0, 0x000ee5ad, 0x00099e40, + 0x0006fca9, 0x00002500, 0x000fb208, 0x000c59a0, + 0x000ef52d, 0x0009de40, 0x00068ca9, 0x000912c1, + 0x000683ad, 0x00095241, 0x00020f05, 0x000991c1, + 0x00000000, 0x00000000, 0x00086f88, 0x00001000, + 0x0009cf81, 0x000b5340, 0x0009c701, 0x000b92c0, + 0x0009de81, 0x000bd300, 0x0009d601, 0x000b1700, + 0x0001fd81, 0x000b9d80, 0x0009f501, 0x000b57c0, + 0x000a0f81, 0x000bd740, 0x00020701, 0x000b5c80, + 0x000a1681, 0x000b97c0, 0x00021601, 0x00002500, + 0x000a0701, 0x000b9b40, 0x000a0f81, 0x000b1bc0, + 0x00021681, 0x00002d00, 0x00020f81, 0x000bd800, + 0x000a0701, 0x000b5bc0, 0x00021601, 0x00003500, + 0x000a0f81, 0x000b5f40, 0x000a0701, 0x000bdbc0, + 0x00021681, 0x00003d00, 0x00020f81, 0x000b1d00, + 0x000a0701, 0x000b1fc0, 0x00021601, 0x00020500, + 0x00020f81, 0x000b1341, 0x000a0701, 0x000b9fc0, + 0x00021681, 0x00020d00, 0x00020f81, 0x000bde80, + 0x000a0701, 0x000bdfc0, 0x00021601, 0x00021500, + 0x00020f81, 0x000b9341, 0x00020701, 0x000b53c1, + 0x00021681, 0x00021d00, 0x000a0f81, 0x000d0380, + 0x0000b601, 0x000b15c0, 0x00007b01, 0x00000000, + 0x00007b81, 0x000bd1c0, 0x00007b01, 0x00000000, + 0x00007b81, 0x000b91c0, 0x00007b01, 0x000b57c0, + 0x00007b81, 0x000b51c0, 0x00007b01, 0x000b1b40, + 0x00007b81, 0x000b11c0, 0x00087b01, 0x000c3dc0, + 0x0007e488, 0x000d7e45, 0x00000000, 0x000d7a44, + 0x0007e48a, 0x00000000, 0x00011f05, 0x00084080, + 0x00000000, 0x00000000, 0x00001705, 0x000b3540, + 0x00008a01, 0x000bf040, 0x00007081, 0x000bb5c0, + 0x00055488, 0x00000000, 0x0000d482, 0x0003fc40, + 0x0003fc88, 0x00000000, 0x0001e401, 0x000b3a00, + 0x0001ec81, 0x000bd6c0, 0x0004ef08, 0x000eb784, + 0x000c86b0, 0x00001007, 0x00008281, 0x000bb240, + 0x0000b801, 0x000b7140, 0x00007888, 0x00000000, + 0x0000073c, 0x00001000, 0x0007f188, 0x000c0000, + 0x00000000, 0x00000000, 0x00055288, 0x000c555c, + 0x0005528a, 0x000c0000, 0x0009fa88, 0x000c5d00, + 0x0000fa88, 0x00000000, 0x00000032, 0x00001000, + 0x0000073d, 0x00001000, 0x0007f188, 0x000c0000, + 0x00000000, 0x00000000, 0x0008c01c, 0x00001003, + 0x00002705, 0x00001008, 0x0008b201, 0x000c1392, + 0x0000ba01, 0x00000000, 0x00008731, 0x00001400, + 0x0004c108, 0x000fe0c4, 0x00057488, 0x00000000, + 0x000a6388, 0x00001001, 0x0008b334, 0x000bc141, + 0x0003020e, 0x00000000, 0x000886b0, 0x00001008, + 0x00003625, 0x000c5dfa, 0x000a638a, 0x00001001, + 0x0008020e, 0x00001002, 0x0008a6b0, 0x00001008, + 0x0007f301, 0x00000000, 0x00000000, 0x00000000, + 0x00002725, 0x000a8c40, 0x000000ae, 0x00000000, + 0x000d8630, 0x00001008, 0x00000000, 0x000c74e0, + 0x0007d182, 0x0002d640, 0x000a8630, 0x00001008, + 0x000799b8, 0x0002d6c0, 0x0000748a, 0x000c3ec5, + 0x0007420a, 0x000c0000, 0x00062208, 0x000c4117, + 0x00070630, 0x00001009, 0x00000000, 0x000c0000, + 0x0001022e, 0x00000000, 0x0003a630, 0x00001009, + 0x00000000, 0x000c0000, 0x00000036, 0x00001000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0002a730, 0x00001008, 0x0007f801, 0x000c0000, + 0x00000037, 0x00001000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0002a730, 0x00001008, + 0x00000033, 0x00001000, 0x0002a705, 0x00001008, + 0x00007a01, 0x000c0000, 0x000e6288, 0x000d550a, + 0x0006428a, 0x00000000, 0x00060730, 0x0000100a, + 0x00000000, 0x000c0000, 0x00000000, 0x00000000, + 0x0007aab0, 0x00034880, 0x00078fb0, 0x0000100b, + 0x00057488, 0x00000000, 0x00033b94, 0x00081140, + 0x000183ae, 0x00000000, 0x000786b0, 0x0000100b, + 0x00022f05, 0x000c3545, 0x0000eb8a, 0x00000000, + 0x00042731, 0x00001003, 0x0007aab0, 0x00034880, + 0x00048fb0, 0x0000100a, 0x00057488, 0x00000000, + 0x00033b94, 0x00081140, 0x000183ae, 0x00000000, + 0x000806b0, 0x0000100b, 0x00022f05, 0x00000000, + 0x00007401, 0x00091140, 0x00048f05, 0x000951c0, + 0x00042731, 0x00001003, 0x0000473d, 0x00001000, + 0x000f19b0, 0x000bbc47, 0x00080000, 0x000bffc7, + 0x000fe19e, 0x00001003, 0x00000000, 0x00000000, + 0x0008e19c, 0x00001003, 0x000083c1, 0x00093040, + 0x00000f41, 0x00097140, 0x0000a841, 0x0009b240, + 0x0000a0c1, 0x0009f040, 0x0001c641, 0x00093540, + 0x0001cec1, 0x0009b5c0, 0x00000000, 0x000fdc44, + 0x00055208, 0x00000000, 0x00010705, 0x000a2880, + 0x0000a23a, 0x00093a00, 0x0003fc8a, 0x000df6c5, + 0x0004ef0a, 0x000c0000, 0x00012f05, 0x00036880, + 0x00065308, 0x000c2997, 0x000d86b0, 0x0000100a, + 0x0004410a, 0x000d40c7, 0x00000000, 0x00000000, + 0x00080730, 0x00001004, 0x00056f0a, 0x000ea105, + 0x00000000, 0x00000000, 0x0000473d, 0x00001000, + 0x000f19b0, 0x000bbc47, 0x00080000, 0x000bffc7, + 0x0000273d, 0x00001000, 0x00000000, 0x000eba44, + 0x00048f05, 0x0000f440, 0x00007401, 0x0000f7c0, + 0x00000734, 0x00001000, 0x00010705, 0x000a6880, + 0x00006a88, 0x000c75c4, 0x00000000, 0x000e5084, + 0x00000000, 0x000eba44, 0x00087401, 0x000e4782, + 0x00000734, 0x00001000, 0x00010705, 0x000a6880, + 0x00006a88, 0x000c75c4, 0x0007c108, 0x000c0000, + 0x0007e721, 0x000bed40, 0x00005f25, 0x000badc0, + 0x0003ba97, 0x000beb80, 0x00065590, 0x000b2e00, + 0x00033217, 0x00003ec0, 0x00065590, 0x000b8e40, + 0x0003ed80, 0x000491c0, 0x00073fb0, 0x00074c80, + 0x000283a0, 0x0000100c, 0x000ee388, 0x00042970, + 0x00008301, 0x00021ef2, 0x000b8f14, 0x0000000f, + 0x000c4d8d, 0x0000001b, 0x000d6dc2, 0x000e06c6, + 0x000032ac, 0x000c3916, 0x0004edc2, 0x00074c80, + 0x00078898, 0x00001000, 0x00038894, 0x00000032, + 0x000c4d8d, 0x00092e1b, 0x000d6dc2, 0x000e06c6, + 0x0004edc2, 0x000c1956, 0x0000722c, 0x00034a00, + 0x00041705, 0x0009ed40, 0x00058730, 0x00001400, + 0x000d7488, 0x000c3a00, 0x00048f05, 0x00000000, + 0x0007bfb0, 0x000bc240, 0x00000c2e, 0x000c6084, + 0x000e8630, 0x0000100c, 0x00006408, 0x000efb84, + 0x00016008, 0x00000000, 0x0001c088, 0x000c0000, + 0x000fc908, 0x000e3392, 0x0005f488, 0x000efb84, + 0x0001d402, 0x000b2e00, 0x0003d418, 0x00001000, + 0x0008d574, 0x000c4293, 0x00065625, 0x000ea30e, + 0x00096c01, 0x000c6f92, 0x0001a58a, 0x000c6085, + 0x00002f43, 0x00000000, 0x000103a0, 0x0000100d, + 0x0005e608, 0x000c0000, 0x00000000, 0x00000000, + 0x000ca108, 0x000dcca1, 0x00003bac, 0x000c3205, + 0x00073843, 0x00000000, 0x00040730, 0x0000100d, + 0x0001600a, 0x000c0000, 0x00057488, 0x00000000, + 0x00000000, 0x000e5084, 0x00000000, 0x000eba44, + 0x00087401, 0x000e4782, 0x00000734, 0x00001000, + 0x00010705, 0x000a6880, 0x00006a88, 0x000c75c4, + 0x0006a108, 0x000cf2c4, 0x0004f4c0, 0x00000000, + 0x000fa418, 0x0000101f, 0x0005d402, 0x0001c500, + 0x000e8630, 0x0000100d, 0x00004418, 0x00001380, + 0x000e243d, 0x000d394a, 0x00049705, 0x00000000, + 0x0007d530, 0x000b4240, 0x000d80f2, 0x0000100d, + 0x00009134, 0x000ca20a, 0x00004c90, 0x00001000, + 0x0005d705, 0x00000000, 0x00004f25, 0x00098240, + 0x00004725, 0x00000000, 0x0000e48a, 0x00000000, + 0x00027295, 0x0009c2c0, 0x0003df25, 0x00000000, + 0x000e0030, 0x0000100e, 0x0005f718, 0x000ac600, + 0x0007cf30, 0x000c2a01, 0x0007a630, 0x0000100e, + 0x000484a0, 0x0000100e, 0x00029314, 0x000bcb80, + 0x0003cf25, 0x000b0e00, 0x0004f5c0, 0x00000000, + 0x00049118, 0x000d888a, 0x0007dd02, 0x000c6efa, + 0x00000000, 0x00000000, 0x0004f5c0, 0x00069c80, + 0x0000d402, 0x00000000, 0x000e0630, 0x0000100e, + 0x00079130, 0x00000000, 0x00049118, 0x00090e00, + 0x0006c10a, 0x00000000, 0x00000000, 0x000c0000, + 0x0007cf30, 0x00030580, 0x00005725, 0x00000000, + 0x000d04a0, 0x0000100e, 0x00029314, 0x000b4780, + 0x0003cf25, 0x000b8600, 0x00000000, 0x00000000, + 0x00000000, 0x000c0000, 0x00000000, 0x00042c80, + 0x0001dec1, 0x000e488c, 0x00031114, 0x00000000, + 0x0004f5c2, 0x00000000, 0x0003640a, 0x00000000, + 0x00000000, 0x000e5084, 0x00000000, 0x000eb844, + 0x00007001, 0x00000000, 0x00000734, 0x00001000, + 0x00010705, 0x000a6880, 0x00006a88, 0x000c75c4, + 0x00036488, 0x00000000, 0x0000c403, 0x00001000, + 0x000fa6b1, 0x00001010, 0x00014403, 0x00001000, + 0x0006a6b1, 0x00001011, 0x0006a108, 0x000cf2c4, + 0x0004f4c0, 0x000d5384, 0x0007e48a, 0x00000000, + 0x00067718, 0x00001000, 0x0007a418, 0x00001000, + 0x0007221a, 0x00000000, 0x0005d402, 0x00014500, + 0x000d8630, 0x0000100f, 0x00004418, 0x00001780, + 0x000e243d, 0x000d394a, 0x00049705, 0x00000000, + 0x0007d530, 0x000b4240, 0x000cc0f2, 0x0000100f, + 0x00014414, 0x00000000, 0x00004c90, 0x00001000, + 0x0005d705, 0x00000000, 0x00004f25, 0x00098240, + 0x00004725, 0x00000000, 0x0000e48a, 0x00000000, + 0x00027295, 0x0009c2c0, 0x0007df25, 0x00000000, + 0x000cc030, 0x00001010, 0x0005f718, 0x000fe798, + 0x00029314, 0x000bcb80, 0x00000930, 0x000b0e00, + 0x0004f5c0, 0x000de204, 0x000a84a0, 0x00001010, + 0x0007cf25, 0x000e3560, 0x00049118, 0x00000000, + 0x00049118, 0x000d888a, 0x0007dd02, 0x000c6efa, + 0x0000c434, 0x00030040, 0x000fda82, 0x000c2312, + 0x000fdc0e, 0x00001001, 0x00083402, 0x000c2b92, + 0x000906b0, 0x00001010, 0x00075a82, 0x00000000, + 0x0000d625, 0x000b0940, 0x0000840e, 0x00001002, + 0x0000aabc, 0x000c511e, 0x00098730, 0x00001010, + 0x0000aaf4, 0x000e910a, 0x0004628a, 0x00000000, + 0x00006aca, 0x00000000, 0x00000930, 0x00000000, + 0x0004f5c0, 0x00069c80, 0x00046ac0, 0x00000000, + 0x0003c40a, 0x000fc898, 0x00049118, 0x00090e00, + 0x0006c10a, 0x00000000, 0x00000000, 0x000e5084, + 0x00000000, 0x000eb844, 0x00007001, 0x00000000, + 0x00000734, 0x00001000, 0x00010705, 0x000a6880, + 0x00006a88, 0x000c75c4, 0x00048f05, 0x00001402, + 0x00051705, 0x00001402, 0x00046dc0, 0x000feac1, + 0x0005a6b0, 0x00001011, 0x00085f25, 0x000c2b92, + 0x000475c2, 0x00000000, 0x00005f05, 0x00001400, + 0x00046dc2, 0x00000000, 0x00000f05, 0x00001402, + 0x0003a508, 0x00000000, 0x00005f05, 0x00001400, + 0x00046dc2, 0x00000000, 0x00004438, 0x000d9205, + 0x0000273d, 0x00001000, 0x00048f05, 0x00001402, + 0x00085f25, 0x000c2b92, 0x00046dc2, 0x000c621c, + 0x0003240a, 0x000c0000, 0x00046dc0, 0x00000000, + 0x0000273d, 0x00001000, 0x00066488, 0x00000000, + 0x0000c403, 0x00001000, 0x0009a6b1, 0x00001012, + 0x00014403, 0x00001000, 0x0003a6b1, 0x00001013, + 0x0006a108, 0x00000000, 0x00023c18, 0x00001000, + 0x0004f4c0, 0x000c3245, 0x0000a418, 0x00001000, + 0x0003a20a, 0x00000000, 0x00004418, 0x00001380, + 0x000e243d, 0x000d394a, 0x000c9705, 0x000def92, + 0x0006c030, 0x00001012, 0x0005f718, 0x000fe798, + 0x000504a0, 0x00001012, 0x00029314, 0x000b4780, + 0x0003cf25, 0x000b8600, 0x00005725, 0x00000000, + 0x00000000, 0x000c05d7, 0x00000000, 0x00042c80, + 0x0001dec1, 0x000e488c, 0x000b1114, 0x000c2f12, + 0x0004f5c2, 0x00000000, 0x0004a918, 0x00098600, + 0x0006c28a, 0x00000000, 0x00000000, 0x000e5084, + 0x00000000, 0x000eb844, 0x00007001, 0x00000000, + 0x00000734, 0x00001000, 0x00010705, 0x000a6880, + 0x00006a88, 0x000c75c4, 0x00069705, 0x00001402, + 0x00038f05, 0x00001400, 0x000475c0, 0x000feac1, + 0x000fa6b0, 0x00001012, 0x00046dc0, 0x00000000, + 0x00085518, 0x0000100f, 0x00045534, 0x000f9285, + 0x00068f05, 0x00001402, 0x00046588, 0x000feedd, + 0x00046dc2, 0x00000000, 0x00070f05, 0x00001402, + 0x0005e588, 0x000e36e1, 0x00000000, 0x000c5084, + 0x00002f25, 0x000f2a84, 0x00005518, 0x000017fc, + 0x0006550a, 0x00000000, 0x0000551a, 0x00001002, + 0x0003450a, 0x000f6145, 0x0000473d, 0x00001000, + 0x00004438, 0x000f1205, 0x00005f25, 0x00000000, + 0x00068f05, 0x00001402, 0x00005725, 0x000e36e1, + 0x0000c438, 0x000f1205, 0x0000273d, 0x00001000, + 0x0002a880, 0x000b4e40, 0x00042214, 0x000e5548, + 0x000542bf, 0x00000000, 0x00000000, 0x000481c0, + 0x00000000, 0x00000000, 0x00000000, 0x00000030, + 0x0000072d, 0x000fbf8a, 0x00077f94, 0x000ea7df, + 0x0002ac95, 0x000d3145, 0x00002731, 0x00001400, + 0x00006288, 0x000c71c4, 0x00014108, 0x000e6044, + 0x00035408, 0x00000000, 0x00025418, 0x000a0ec0, + 0x0001443d, 0x000ca21e, 0x00046595, 0x000d730c, + 0x0006538e, 0x00000000, 0x0000c630, 0x00001014, + 0x000e7b0e, 0x000df782, 0x0001c6b0, 0x00001014, + 0x00036f05, 0x000c0000, 0x00043695, 0x000d598c, + 0x0005331a, 0x000f2185, 0x00000000, 0x00000000, + 0x000007ae, 0x000bdb00, 0x00040630, 0x00001400, + 0x0005e708, 0x000c0000, 0x0007ef30, 0x000b1c00, + 0x000806a0, 0x00001014, 0x00066408, 0x000c0000, + 0x00000000, 0x00000000, 0x00021843, 0x00000000, + 0x00000cac, 0x00062c00, 0x00001dac, 0x00063400, + 0x00002cac, 0x0006cc80, 0x000db943, 0x000e5ca1, + 0x00000000, 0x00000000, 0x0006680a, 0x000f3205, + 0x00042730, 0x00001400, 0x00014108, 0x000f2204, + 0x00025418, 0x000a2ec0, 0x00015dbd, 0x00038100, + 0x00015dbc, 0x00000000, 0x0005e415, 0x00034880, + 0x0001258a, 0x000d730c, 0x0006538e, 0x000baa40, + 0x00008630, 0x00001015, 0x00067b0e, 0x000ac380, + 0x0003ef05, 0x00000000, 0x0000f734, 0x0001c300, + 0x000586b0, 0x00001400, 0x000b6f05, 0x000c3a00, + 0x00048f05, 0x00000000, 0x0005b695, 0x0008c380, + 0x0002058e, 0x00000000, 0x000500b0, 0x00001400, + 0x0002b318, 0x000e998d, 0x0006430a, 0x00000000, + 0x00000000, 0x000ef384, 0x00004725, 0x000c0000, + 0x00000000, 0x000f3204, 0x00004f25, 0x000c0000, + 0x00080000, 0x000e5ca1, 0x000cb943, 0x000e5ca1, + 0x0004b943, 0x00000000, 0x00040730, 0x00001400, + 0x000cb943, 0x000e5ca1, 0x0004b943, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000} +}; diff --git a/kernel/drv/oss_cs461x/oss_cs461x.c b/kernel/drv/oss_cs461x/oss_cs461x.c new file mode 100644 index 0000000..e024fc6 --- /dev/null +++ b/kernel/drv/oss_cs461x/oss_cs461x.c @@ -0,0 +1,1931 @@ +/* + * Purpose: Driver for Crystal cs461x and cs461x PCI audio controllers + */ +/* + * + * 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_cs461x_cfg.h" +#include "midi_core.h" +#include "ac97.h" +#include "oss_pci.h" +#include "cs461x.h" + +extern int cs461x_clkrun_fix; + +#define CRYSTAL_VENDOR_ID 0x1013 +#define CRYSTAL_CS4610_ID 0x6001 +#define CRYSTAL_CS461x_ID 0x6003 +#define CRYSTAL_CS4615_ID 0x6004 + +#define USE_SG + +#define WRITEB(a,d) devc->bRegister0[a] = d +#define READB(a) devc->bRegister0[a] +#define WRITEW(a,d) devc->wRegister0[a>>1] = d +#define READW(a) devc->wRegister0[a>>1] + +#define READ0L(a) (devc->dwRegister0[a>>2]) +#define WRITE0L(a, d) (devc->dwRegister0[a>>2] = d) +#define READ1L(a) (devc->dwRegister1[a>>2]) +#define WRITE1L(a,d) (devc->dwRegister1[a>>2] = d) + +#define READ1L(a) (devc->dwRegister1[a>>2]) + +#ifdef OSS_BIG_ENDIAN +static unsigned int +ymf_swap (unsigned int x) +{ + return ((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24); +} + +#define LSWAP(x) ymf_swap(x) +#else +#define LSWAP(x) x +#endif + +#define MAX_PORTC 2 + +typedef struct cs461x_portc +{ + int speed, bits, channels; + int open_mode; + int audio_enabled; + int trigger_bits; + int audiodev; +} +cs461x_portc; + +typedef struct cs461x_devc +{ + oss_device_t *osdev; + char *chip_name; + unsigned short subsysid; + + oss_native_word bar0addr, bar1addr; + unsigned int *bar0virt, *bar1virt; + volatile unsigned int *dwRegister0, *dwRegister1; + volatile unsigned short *wRegister0, *wRegister1; + volatile unsigned char *bRegister0, *bRegister1; + int irq; + int dual_codec; + unsigned int *play_sgbuf; + unsigned int play_sgbuf_phys; + oss_dma_handle_t play_sgbuf_dma_handle; + + /* Mutex */ + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* MIDI */ + int midi_opened; + int midi_dev; + oss_midi_inputbyte_t midi_input_intr; + + /* Mixer parameters */ + ac97_devc ac97devc, ac97devc2; + int mixer_dev, mixer2_dev; + + /* Audio parameters */ + cs461x_portc portc[MAX_PORTC]; + int open_mode; + oss_native_word PCTL; /*Play Control Register */ + oss_native_word CCTL; /*Record Control Register */ + int processor_started; +} +cs461x_devc; + +#define MAX_CS461x 6 + +static int ac97_write (void *devc, int addr, int data); +static int ac97_read (void *devc, int addr); + +static void +PokeBA0 (cs461x_devc * devc, unsigned int offset, unsigned int value) +{ + WRITE0L (offset, value); +} + +static unsigned int +PeekBA0 (cs461x_devc * devc, unsigned int offset) +{ + unsigned int value; + + value = READ0L (offset); + return (value); + +} + +static int +ac97_read (void *devc_, int offset) +{ + cs461x_devc *devc = devc_; + int count; + unsigned int status, value; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Make sure that there is not data sitting around from a previous + * uncompleted access. ACSDA = Status Data Register = 47Ch + */ + status = PeekBA0 (devc, BA0_ACSDA); + /* Get the actual AC97 register from the offset */ + PokeBA0 (devc, BA0_ACCAD, offset - BA0_AC97_RESET); + PokeBA0 (devc, BA0_ACCDA, 0); + PokeBA0 (devc, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | + ACCTL_ESYN | ACCTL_RSTN); + + /* Wait for the read to occur. */ + for (count = 0; count < 10; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (100); + /* + * Now, check to see if the read has completed. + * ACCTL = 460h, DCV should be reset by now and 460h = 17h + */ + status = PeekBA0 (devc, BA0_ACCTL); + if (!(status & ACCTL_DCV)) + { + break; + } + } + + /* Make sure the read completed. */ + if (status & ACCTL_DCV) + { + cmn_err (CE_WARN, "AC97 Read Timedout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* Wait for the valid status bit to go active. */ + + for (count = 0; count < 10; count++) + { + /* + * Read the AC97 status register. + * ACSTS = Status Register = 464h + */ + status = PeekBA0 (devc, BA0_ACSTS); + /* + * See if we have valid status. + * VSTS - Valid Status + */ + if (status & ACSTS_VSTS) + break; + + /* + * Wait for a short while. + */ + oss_udelay (100); + } + /* Make sure we got valid status. */ + if (!(status & ACSTS_VSTS)) + { + cmn_err (CE_WARN, "AC97 Read Timedout(2)\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* + * Read the data returned from the AC97 register. + * ACSDA = Status Data Register = 474h + */ + value = PeekBA0 (devc, BA0_ACSDA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (value); +} + +static int +ac97_write (void *devc_, int offset, int data) +{ + cs461x_devc *devc = devc_; + int count; + unsigned int status = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + PokeBA0 (devc, BA0_ACCAD, offset); + PokeBA0 (devc, BA0_ACCDA, data); + PokeBA0 (devc, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); + for (count = 0; count < 10; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (100); + /* Now, check to see if the write has completed. */ + /* ACCTL = 460h, DCV should be reset by now and 460h = 07h */ + status = PeekBA0 (devc, BA0_ACCTL); + if (!(status & ACCTL_DCV)) + break; + } + + /* write didn't completed. */ + if (status & ACCTL_DCV) + { + cmn_err (CE_WARN, "AC97 Write timeout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static int +ac97_read2 (void *devc_, int offset) +{ + cs461x_devc *devc = devc_; + int count; + unsigned int status, value; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Make sure that there is not data sitting around from a previous + * uncompleted access. ACSDA = Status Data Register = 47Ch + */ + status = PeekBA0 (devc, BA0_ACSDA2); + + /* Get the actual AC97 register from the offset */ + PokeBA0 (devc, BA0_ACCAD, offset); + PokeBA0 (devc, BA0_ACCDA, 0); + PokeBA0 (devc, BA0_ACCTL, + ACCTL_DCV | ACCTL_TC | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | + ACCTL_RSTN); + + + /* Wait for the read to occur. */ + for (count = 0; count < 10; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (1000); + /* + * Now, check to see if the read has completed. + * ACCTL = 460h, DCV should be reset by now and 460h = 17h + */ + status = PeekBA0 (devc, BA0_ACCTL); + if (!(status & ACCTL_DCV)) + break; + } + + /* Make sure the read completed. */ + if (PeekBA0 (devc, BA0_ACCTL) & ACCTL_DCV) + { + cmn_err (CE_WARN, "Secondary AC97 Read Timedout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* Wait for the valid status bit to go active. */ + + for (count = 0; count < 10; count++) + { + /* + * Read the AC97 status register. + * ACSTS = Status Register = 464h + */ + status = PeekBA0 (devc, BA0_ACSTS2); + /* + * See if we have valid status. + * VSTS - Valid Status + */ + if (status & ACSTS_VSTS) + break; + + /* + * Wait for a short while. + */ + oss_udelay (1000); + } + /* Make sure we got valid status */ + if (!(status & ACSTS_VSTS)) + { + cmn_err (CE_WARN, "Secondary AC97 Read Timedout(2)\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + + /* + * Read the data returned from the AC97 register. + * ACSDA = Status Data Register = 474h + */ + value = PeekBA0 (devc, BA0_ACSDA2); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (value); +} + +static int +ac97_write2 (void *devc_, int offset, int data) +{ + cs461x_devc *devc = devc_; + int count; + unsigned int status = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + PokeBA0 (devc, BA0_ACCAD, offset); + PokeBA0 (devc, BA0_ACCDA, data); + PokeBA0 (devc, BA0_ACCTL, + ACCTL_DCV | ACCTL_TC | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); + for (count = 0; count < 10; count++) + { + /* First, we want to wait for a short time. */ + oss_udelay (1000); + /* Now, check to see if the write has completed. */ + /* ACCTL = 460h, DCV should be reset by now and 460h = 07h */ + status = PeekBA0 (devc, BA0_ACCTL); + if (!(status & ACCTL_DCV)) + break; + } + + /* write didn't completed. */ + if (status & ACCTL_DCV) + { + cmn_err (CE_WARN, "Secondary AC97 Write timeout\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +/* + * this is 3*1024 for parameter, 3.5*1024 for sample and 2*3.5*1024 + * for code since each instruction is 40 bits and takes two dwords + */ +#define INKY_BA1_DWORD_SIZE (13 * 1024 + 512) +/* this is parameter, sample, and code */ +#define INKY_MEMORY_COUNT 3 +struct cs461x_firmware_struct +{ + struct + { + unsigned int ulDestAddr; + unsigned int ulSourceSize; + } + MemoryStat[INKY_MEMORY_COUNT]; + unsigned int BA1Array[INKY_BA1_DWORD_SIZE]; +}; +#include "cs461x_dsp.h" + +static void +DoTransfer (cs461x_devc * devc, unsigned int *fpulSrc, + unsigned int ulByteDestOffset, unsigned int ulByteLength) +{ + int dwByteCounter; + + if (ulByteDestOffset & 0x3) + { + cmn_err (CE_WARN, "invalid DMA address\n"); + return; + } + + for (dwByteCounter = 0; dwByteCounter < ulByteLength; dwByteCounter += 4) + { + WRITE1L ((ulByteDestOffset + dwByteCounter), + fpulSrc[dwByteCounter / 4]); + } +} + +static void +install_ucode (cs461x_devc * devc) +{ + unsigned int i, count; + + count = 0; + for (i = 0; i < INKY_MEMORY_COUNT; i++) + { + + DoTransfer (devc, (unsigned int *) (cs461x_firmware.BA1Array + count), + cs461x_firmware.MemoryStat[i].ulDestAddr, + cs461x_firmware.MemoryStat[i].ulSourceSize); + count += cs461x_firmware.MemoryStat[i].ulSourceSize / 4; + } +} + +void +clear_serial_fifo (cs461x_devc * devc) +{ + unsigned int ulIdx, ulLoop; + unsigned int ulStatus = 0; + unsigned int ulCLKCR1; + + + ulCLKCR1 = PeekBA0 (devc, BA0_CLKCR1); + + if (!(ulCLKCR1 & CLKCR1_SWCE)) + { + PokeBA0 (devc, BA0_CLKCR1, ulCLKCR1 | CLKCR1_SWCE); + } + PokeBA0 (devc, BA0_SERBWP, 0); + + for (ulIdx = 0; ulIdx < 256; ulIdx++) + { + /* + * Make sure the previous FIFO write operation has completed. + */ + for (ulLoop = 0; ulLoop < 5; ulLoop++) + { + oss_udelay (100); + ulStatus = PeekBA0 (devc, BA0_SERBST); + if (!(ulStatus & SERBST_WBSY)) + { + break; + } + } + + if (ulStatus & SERBST_WBSY) + { + if (!(ulCLKCR1 & CLKCR1_SWCE)) + { + PokeBA0 (devc, BA0_CLKCR1, ulCLKCR1); + } + } + + /* Write the serial port FIFO index. */ + + PokeBA0 (devc, BA0_SERBAD, ulIdx); + + /* + * Tell the serial port to load the new value into the FIFO location. + */ + PokeBA0 (devc, BA0_SERBCM, SERBCM_WRC); + } + + /* + * Now, if we powered up the devices, then power them back down again. + * This is kinda ugly, but should never happen. + */ + if (!(ulCLKCR1 & CLKCR1_SWCE)) + { + PokeBA0 (devc, BA0_CLKCR1, ulCLKCR1); + } + +} + +static int +cs461x_reset_processor (cs461x_devc * devc) +{ + unsigned int ulIdx; + + /* Write the reset bit of the SP control register. */ + WRITE1L (BA1_SPCR, SPCR_RSTSP); + WRITE1L (BA1_SPCR, SPCR_DRQEN); + + /* Clear the trap registers. */ + for (ulIdx = 0; ulIdx < 8; ulIdx++) + { + WRITE1L (BA1_DREG, DREG_REGID_TRAP_SELECT + ulIdx); + WRITE1L (BA1_TWPR, 0xFFFF); + } + + WRITE1L (BA1_DREG, 0); + WRITE1L (BA1_FRMT, 0xadf); + return (0); +} + +static int +cs461x_start_processor (cs461x_devc * devc) +{ + + unsigned int ulCount; + int ulTemp = 0; + + /* reset the processor first */ + cs461x_reset_processor (devc); + + /* reload the ucode */ + install_ucode (devc); + + /* Set the frame timer to reflect the number of cycles per frame. */ + WRITE1L (BA1_FRMT, 0xADF); + + /* + * Turn on the run, run at frame, and DMA enable bits in the local copy of + * the SP control register. + */ + WRITE1L (BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); + + /* + * Wait until the run at frame bit resets itself in the SP control + * register. + */ + for (ulCount = 0; ulCount < 25; ulCount++) + { + /* Wait a little bit, so we don't issue PCI reads too frequently. */ + oss_udelay (100); + + /* Fetch the current value of the SP status register. */ + ulTemp = READ1L (BA1_SPCR); + + /* If the run at frame bit has reset, then stop waiting. */ + if (!(ulTemp & SPCR_RUNFR)) + break; + } + /* If the run at frame bit never reset, then return an error. */ + if (ulTemp & SPCR_RUNFR) + { + cmn_err (CE_WARN, "Start(): SPCR_RUNFR never reset.\n"); + } + devc->processor_started = 1; + return 0; +} + +static int +cs461xintr (oss_device_t * osdev) +{ + cs461x_devc *devc = (cs461x_devc *) osdev->devc; + cs461x_portc *portc; + unsigned int status; + int i; + unsigned int uart_stat; + int serviced = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + +/* Read the Interrupt Status Register */ + status = PeekBA0 (devc, BA0_HISR); + +/* + * This is the MIDI read interrupt service. First check to see + * if the MIDI interrupt flag is set in the HISR register. Next + * read the MIDI status register. See if Receive Buffer Empty + * is empty (0=FIFO Not empty, 1=FIFO is empty + */ + if ((devc->midi_opened & OPEN_READ) && (status & HISR_MIDI)) + { + uart_stat = PeekBA0 (devc, BA0_MIDSR); +/* + * read one byte of MIDI data and hand it off the the sequencer module + * to decode this. Keep checking to see if the data is available. Stop + * when no more data is there in the FIFO. + */ + while (!(uart_stat & MIDSR_RBE)) + { + unsigned char d; + d = PeekBA0 (devc, BA0_MIDRP); + + if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, d); + uart_stat = PeekBA0 (devc, BA0_MIDSR); + } + } + +/* Audio interrupt handling */ + if (status & 0x3) + { + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + if (status & 0x1) + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + int ptr, n; + + ptr = READ1L (BA1_PBA) - dmap->dmabuf_phys; + ptr = ptr / dmap->fragment_size; + if (ptr < 0 || ptr >= dmap->nfrags) + ptr = 0; + n = 0; + while (dmap_get_qhead (dmap) != ptr && n++ < dmap->nfrags) + oss_audio_outputintr (portc->audiodev, 0); + } + + if (status & 0x2) + if (portc->trigger_bits & PCM_ENABLE_INPUT) + { + + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in; + int ptr, n; + + ptr = READ1L (BA1_CBA) - dmap->dmabuf_phys; + ptr = ptr / (dmap->fragment_size); + + if (ptr < 0 || ptr >= dmap->nfrags) + ptr = 0; + n = 0; + while (dmap_get_qtail (dmap) != ptr && n++ < dmap->nfrags) + oss_audio_inputintr (portc->audiodev, 0); + } + } + } + + serviced = 1; + PokeBA0 (devc, BA0_HICR, 0x03); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return serviced; +} + +static int +cs461x_audio_set_rate (int dev, int arg) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (audio_engines[dev]->flags & ADEV_FIXEDRATE) + { + audio_engines[dev]->fixed_rate = 48000; + arg = 48000; + } + else + audio_engines[dev]->fixed_rate = 0; + + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +cs461x_audio_set_channels (int dev, short arg) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + + 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 +cs461x_audio_set_format (int dev, unsigned int arg) +{ + cs461x_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 +cs461x_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void cs461x_audio_trigger (int dev, int state); + +static void +cs461x_audio_reset (int dev) +{ + cs461x_audio_trigger (dev, 0); +} + +static void +cs461x_audio_reset_input (int dev) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + cs461x_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +cs461x_audio_reset_output (int dev) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + cs461x_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +cs461x_audio_open (int dev, int mode, int open_flags) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + cs461x_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 0 + if (mode & OPEN_READ) + { + dmapin->buffsize = 4096; + audio_engines[dev]->fixed_rate = 48000; + audio_engines[dev]->min_rate = 48000; + audio_engines[dev]->max_rate = 48000; + audio_engines[dev]->flags |= + ADEV_FIXEDRATE | ADEV_16BITONLY | ADEV_STEREOONLY; + } + if (mode & OPEN_WRITE) + { + audio_engines[dev]->min_rate = 5000; + audio_engines[dev]->max_rate = 48000; + audio_engines[dev]->flags &= + ~(ADEV_FIXEDRATE | ADEV_16BITONLY | ADEV_STEREOONLY); + audio_engines[dev]->fixed_rate = 0; + } +#endif + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +cs461x_audio_close (int dev, int mode) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + cs461x_devc *devc = audio_engines[dev]->devc; + + cs461x_audio_reset (dev); + portc->audio_enabled &= ~mode; + devc->open_mode &= ~mode; + portc->open_mode = 0; +} + +/*ARGSUSED*/ +static void +cs461x_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +cs461x_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + cs461x_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +cs461x_audio_trigger (int dev, int state) +{ + oss_native_word flags, tmp; + cs461x_devc *devc = audio_engines[dev]->devc; + cs461x_portc *portc = audio_engines[dev]->portc; + + 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)) + { + tmp = READ1L (BA1_PCTL); + tmp &= 0xFFFF; + tmp |= devc->PCTL; + WRITE1L (BA1_PCTL, tmp); + 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; + tmp = READ1L (BA1_PCTL); + tmp &= 0xFFFF; + WRITE1L (BA1_PCTL, tmp); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + tmp = READ1L (BA1_CCTL); + tmp &= 0xFFFF0000; + tmp |= devc->CCTL; + WRITE1L (BA1_CCTL, tmp); + 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; + tmp = READ1L (BA1_CCTL); + tmp &= 0xFFFF0000; + WRITE1L (BA1_CCTL, tmp); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +cs461x_play_rate (cs461x_devc * devc, unsigned int ulInRate) +{ +/*define GOF_PER_SEC 200*/ + unsigned int ulTemp1, ulTemp2; + unsigned int ulPhiIncr; + unsigned int ulCorrectionPerGOF, ulCorrectionPerSec; + unsigned int ulOutRate = 48000; + + ulTemp1 = ulInRate << 16; + ulPhiIncr = ulTemp1 / ulOutRate; + ulTemp1 -= ulPhiIncr * ulOutRate; + ulTemp1 <<= 10; + ulPhiIncr <<= 10; + ulTemp2 = ulTemp1 / ulOutRate; + ulPhiIncr += ulTemp2; + ulTemp1 -= ulTemp2 * ulOutRate; + ulCorrectionPerGOF = ulTemp1 / 200; + ulTemp1 -= ulCorrectionPerGOF * 200; + ulCorrectionPerSec = ulTemp1; + + /* Fill in the SampleRateConverter control block. */ + WRITE1L (BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | + (ulCorrectionPerGOF & 0xFFFF)); + WRITE1L (BA1_PPI, ulPhiIncr); + return 0; +} + +static int +cs461x_record_rate (cs461x_devc * devc, int ulOutRate) +{ + unsigned int ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2; + unsigned int ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay; + unsigned int ulInRate = 48000; + + /* + * We can only decimate by up to a factor of 1/9th the hardware rate. + * Return an error if an attempt is made to stray outside that limit. + */ + if ((ulOutRate * 9) < ulInRate) + { + cmn_err (CE_WARN, + "SetCaptureSampleRate(): Requested output rate is below 1/9th of the input rate.\n"); + return (-1); + } + + /* + * We can not capture at at rate greater than the Input Rate (48000). + * Return an error if an attempt is made to stray outside that limit. + */ + if (ulOutRate > ulInRate) + { + cmn_err (CE_WARN, + "SetCaptureSampleRate(): Requested output rate is greater than the input rate."); + return (-1); + } + ulTemp1 = ulOutRate << 16; + ulCoeffIncr = ulTemp1 / ulInRate; + ulTemp1 -= ulCoeffIncr * ulInRate; + ulTemp1 <<= 7; + ulCoeffIncr <<= 7; + ulCoeffIncr += ulTemp1 / ulInRate; + ulCoeffIncr ^= 0xFFFFFFFF; + ulCoeffIncr++; + ulTemp1 = ulInRate << 16; + ulPhiIncr = ulTemp1 / ulOutRate; + ulTemp1 -= ulPhiIncr * ulOutRate; + ulTemp1 <<= 10; + ulPhiIncr <<= 10; + ulTemp2 = ulTemp1 / ulOutRate; + ulPhiIncr += ulTemp2; + ulTemp1 -= ulTemp2 * ulOutRate; + ulCorrectionPerGOF = ulTemp1 / 200; + ulTemp1 -= ulCorrectionPerGOF * 200; + ulCorrectionPerSec = ulTemp1; + ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate; + /* Fill in the VariDecimate control block. */ + WRITE1L (BA1_CSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | + (ulCorrectionPerGOF & 0xFFFF)); + WRITE1L (BA1_CCI, ulCoeffIncr); + WRITE1L (BA1_CD, + (((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) + | 0x80); + WRITE1L (BA1_CPI, ulPhiIncr); +#if 0 + { + unsigned int frameGroupLength, cnt; + int rate = ulOutRate; + + frameGroupLength = 1; + for (cnt = 2; cnt <= 64; cnt *= 2) + { + if (((rate / cnt) * cnt) != rate) + frameGroupLength *= 2; + } + if (((rate / 3) * 3) != rate) + { + frameGroupLength *= 3; + } + for (cnt = 5; cnt <= 125; cnt *= 5) + { + if (((rate / cnt) * cnt) != rate) + frameGroupLength *= 5; + } + + WRITE1L (BA1_CFG1, frameGroupLength); + WRITE1L (BA1_CFG2, (0x00800000 | frameGroupLength)); + WRITE1L (BA1_CCST, 0x0000FFFF); + WRITE1L (BA1_CSPB, ((65536 * rate) / 24000)); + WRITE1L ((BA1_CSPB + 4), 0x0000FFFF); + } +#endif + return (0); +} + +struct InitStruct +{ + unsigned long off; + unsigned long val; +} +InitArray[] = +{ + { + 0x00000040, 0x3fc0000f} + , + { + 0x0000004c, 0x04800000} + , + { + 0x000000b3, 0x00000780} + , + { + 0x000000b7, 0x00000000} + , + { + 0x000000bc, 0x07800000} + , + { + 0x000000cd, 0x00800000} +,}; + + +/* + * "SetCaptureSPValues()" -- Initialize record task values before each + * capture startup. + */ +void +SetCaptureSPValues (cs461x_devc * devc) +{ + unsigned i, offset; + for (i = 0; i < sizeof (InitArray) / sizeof (struct InitStruct); i++) + { + offset = InitArray[i].off * 4; /* 8bit to 32bit offset value */ + WRITE1L (offset, InitArray[i].val); + } +} + +/*ARGSUSED*/ +static int +cs461x_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + cs461x_devc *devc = audio_engines[dev]->devc; + cs461x_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + /* Start the processor */ + if (!devc->processor_started) + cs461x_start_processor (devc); + + /* Set Capture S/P values */ + SetCaptureSPValues (devc); + /* set the record rate */ + cs461x_record_rate (devc, portc->speed); + + /* write the buffer address */ + WRITE1L (BA1_CBA, dmap->dmabuf_phys); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +cs461x_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + cs461x_devc *devc = audio_engines[dev]->devc; + cs461x_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* Start the processor */ + if (!devc->processor_started) + cs461x_start_processor (devc); + +#ifdef USE_SG + { + unsigned int sg_temp[9], sg_npages = 0; + int i; + oss_native_word Count, playFormat, tmp, tmp2; + + sg_npages = (dmap->bytes_in_use) / 4096; + + devc->play_sgbuf[0] = dmap->dmabuf_phys; + devc->play_sgbuf[1] = 0x00000008; + + for (i = 0; i < sg_npages; i++) + { + devc->play_sgbuf[2 * i] = dmap->dmabuf_phys + 4096 * i; + if (i == sg_npages - 1) + tmp2 = 0xbfff0000; + else + tmp2 = 0x80000000 + 8 * (i + 1); + + devc->play_sgbuf[2 * i + 1] = tmp2; + } + sg_temp[0] = 0x82c0200d; + sg_temp[1] = 0xffff0000; + sg_temp[2] = devc->play_sgbuf[0]; + sg_temp[3] = 0x00010600; + sg_temp[4] = devc->play_sgbuf[2]; + sg_temp[5] = 0x80000010; + sg_temp[6] = devc->play_sgbuf[0]; + sg_temp[7] = devc->play_sgbuf[2]; + sg_temp[8] = (devc->play_sgbuf_phys & 0xffff000) | 0x10; + + for (i = 0; i < sizeof (sg_temp) / 4; i++) + WRITE1L ((BA1_PDTC + i * 4), sg_temp[i]); + + WRITE1L (BA1_PBA, dmap->dmabuf_phys); + + cs461x_play_rate (devc, (unsigned int) portc->speed); + + Count = 4; + playFormat = READ1L (BA1_PFIE); + playFormat &= ~0x0000f03f; + + if ((portc->channels == 2)) + { + playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO; + Count *= 2; + } + else + playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO; + + if ((portc->bits == 16)) + { + playFormat &= + ~(DMA_RQ_C2_AC_8_TO_16_BIT | DMA_RQ_C2_AC_SIGNED_CONVERT); + Count *= 2; + } + else + playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT | DMA_RQ_C2_AC_SIGNED_CONVERT); + + WRITE1L (BA1_PFIE, playFormat); + + tmp = READ1L (BA1_PDTC); + tmp &= 0xfffffe00; + WRITE1L (BA1_PDTC, tmp | --Count); + } +#else + { + unsigned int pdtc_value, pfie_value; + /* Set the sample rate converter */ + cs461x_play_rate (devc, (unsigned int) portc->speed); + + pfie_value = READ1L (BA1_PFIE); + pfie_value &= ~0x0000f03f; + + pdtc_value = READ1L (BA1_PDTC); + pdtc_value &= ~0x000003ff; + + /* Now set the sample size/stereo/mono */ + if ((portc->bits == 8) && (portc->channels == 1)) + { + pdtc_value |= 0x03; + pfie_value |= 0xB000; /*8bit mono */ + } + if ((portc->bits == 8) && (portc->channels == 2)) + { + pdtc_value |= 0x07; + pfie_value |= 0xA000; /*8bit stereo */ + } + if ((portc->bits == 16) && (portc->channels == 1)) + { + pdtc_value |= 0x07; + pfie_value |= 0x2000; /*16bit mono */ + } + if ((portc->bits == 16) && (portc->channels == 2)) + { + pdtc_value |= 0x0F; + pfie_value |= 0x0000; /*16bit stereo */ + } + + WRITE1L (BA1_PDTC, pdtc_value); + WRITE1L (BA1_PFIE, pfie_value); + WRITE1L (BA1_PBA, dmap->dmabuf_phys); + } +#endif + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +cs461x_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + +#ifdef USE_SG + int err; +#else + oss_native_word phaddr; + cs461x_devc *devc = audio_engines[dev]->devc; +#endif + + if (dmap->dmabuf != NULL) + return 0; + +#ifdef USE_SG + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + { + cmn_err (CE_WARN, "Failed to allocate a DMA buffer\n"); + return err; + } +#else + dmap->dmabuf = + (void *) CONTIG_MALLOC (devc->osdev, 4096, MEMLIMIT_32BITS, &phaddr, dmap->dmabuf_dma_handle); + dmap->dmabuf_phys = phaddr; +# ifdef linux + oss_reserve_pages (dmap->dmabuf, dmap->dmabuf + 4096 - 1); +# endif + dmap->buffsize = 4096; +#endif + return 0; +} + +/*ARGSUSED*/ +static int +cs461x_free_buffer (int dev, dmap_t * dmap, int direction) +{ +#ifndef USE_SG + cs461x_devc *devc = audio_engines[dev]->devc; +#endif +#ifdef USE_SG + oss_free_dmabuf (dev, dmap); + dmap->dmabuf = 0; +#else + if (dmap->dmabuf == NULL) + return 0; + CONTIG_FREE (devc->osdev, dmap->dmabuf, 4096, dmap->dmabuf_dma_handle); +# ifdef linux + oss_unreserve_pages (dmap->dmabuf, dmap->dmabuf + 4096 - 1); +# endif + dmap->dmabuf = 0; +#endif + return 0; + +} + +static int +cs461x_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + cs461x_devc *devc = audio_engines[dev]->devc; + unsigned int ptr = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + ptr = READ1L (BA1_PBA) - dmap->dmabuf_phys; + } + if (direction == PCM_ENABLE_INPUT) + { + ptr = READ1L (BA1_CBA) - dmap->dmabuf_phys; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + +static audiodrv_t cs461x_audio_driver = { + cs461x_audio_open, + cs461x_audio_close, + cs461x_audio_output_block, + cs461x_audio_start_input, + cs461x_audio_ioctl, + cs461x_audio_prepare_for_input, + cs461x_audio_prepare_for_output, + cs461x_audio_reset, + NULL, + NULL, + cs461x_audio_reset_input, + cs461x_audio_reset_output, + cs461x_audio_trigger, + cs461x_audio_set_rate, + cs461x_audio_set_format, + cs461x_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + cs461x_alloc_buffer, + cs461x_free_buffer, + NULL, + NULL, + cs461x_get_buffer_pointer +}; + +/***********************MIDI PORT ROUTINES ****************/ + +/*ARGSUSED*/ +static int +cs461x_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + cs461x_devc *devc = (cs461x_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + + /* first reset the MIDI port */ + PokeBA0 (devc, BA0_MIDCR, 0x10); + PokeBA0 (devc, BA0_MIDCR, 0x00); + + /* Now check if we're in Read or Write mode */ + if (mode & OPEN_READ) + { + /* enable MIDI Input intr and receive enable */ + PokeBA0 (devc, BA0_MIDCR, MIDCR_RXE | MIDCR_RIE); + } + + if (mode & OPEN_WRITE) + { + /* enable MIDI transmit enable without interrupt mode */ + PokeBA0 (devc, BA0_MIDCR, MIDCR_TXE); + } + PokeBA0 (devc, BA0_HICR, HICR_IEV | HICR_CHGM); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static void +cs461x_midi_close (int dev, int mode) +{ + cs461x_devc *devc = (cs461x_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); +/* Reset the device*/ + PokeBA0 (devc, BA0_MIDCR, 0x10); + PokeBA0 (devc, BA0_MIDCR, 0x00); + devc->midi_opened = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +cs461x_midi_out (int dev, unsigned char midi_byte) +{ + cs461x_devc *devc = (cs461x_devc *) midi_devs[dev]->devc; + unsigned char uart_stat; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + uart_stat = PeekBA0 (devc, BA0_MIDSR); + +/* Check if Transmit buffer full flag is set - if so return */ + if ((uart_stat & MIDSR_TBF)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } +/* Now put the MIDI databyte in the write port */ + PokeBA0 (devc, BA0_MIDWP, midi_byte); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 1; +} + +/*ARGSUSED*/ +static int +cs461x_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t cs461x_midi_driver = { + cs461x_midi_open, + cs461x_midi_close, + cs461x_midi_ioctl, + cs461x_midi_out +}; + +static int +init_cs461x (cs461x_devc * devc) +{ + + int my_mixer, my_mixer2, i; + unsigned int ulCount = 0; + unsigned int ulStatus = 0; + unsigned int tmp; + int first_dev = 0; + int adev; + oss_native_word phaddr; + +/****************BEGIN HARDWARE INIT*****************/ + /* + * First, blast the clock control register to zero so that the PLL starts + * out in a known state, and blast the master serial port control register + * to zero so that the serial ports also start out in a known state. + */ + PokeBA0 (devc, BA0_CLKCR1, 0x0); + PokeBA0 (devc, BA0_SERMC1, 0x0); + oss_udelay (1000); + /* + * If we are in AC97 mode, then we must set the part to a host controlled + * AC-link. Otherwise, we won't be able to bring up the link. + */ + if (devc->dual_codec) + PokeBA0 (devc, BA0_SERACC, + SERACC_HSP | SERACC_TWO_CODECS | SERACC_CODEC_TYPE_2_0); + else + PokeBA0 (devc, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* AC97 1.03 */ + + /* + * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 + * spec) and then drive it high. This is done for non AC97 modes since + * there might be logic external to the CS461x that uses the ARST# line + * for a reset. + */ + PokeBA0 (devc, BA0_ACCTL, 1); + oss_udelay (10000); + PokeBA0 (devc, BA0_ACCTL, 0); + oss_udelay (10000); + PokeBA0 (devc, BA0_ACCTL, ACCTL_RSTN); + /* + * The first thing we do here is to enable sync generation. As soon + * as we start receiving bit clock, we'll start producing the SYNC + * signal. + */ + PokeBA0 (devc, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); + + /* + * Now wait for a short while to allow the AC97 part to start + * generating bit clock (so we don't try to start the PLL without an + * input clock). + */ + oss_udelay (500000); + /* + * Set the serial port timing configuration, so that + * the clock control circuit gets its clock from the correct place. + */ + PokeBA0 (devc, BA0_SERMC1, SERMC1_PTC_AC97); + oss_udelay (500000); + /* + * Write the selected clock control setup to the hardware. Do not turn on + * SWCE yet (if requested), so that the devices clocked by the output of + * PLL are not clocked until the PLL is stable. + */ + PokeBA0 (devc, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); + PokeBA0 (devc, BA0_PLLM, 0x3a); + PokeBA0 (devc, BA0_CLKCR2, CLKCR2_PDIVS_8); + + /* + * Power up the PLL. + */ + PokeBA0 (devc, BA0_CLKCR1, CLKCR1_PLLP); + + /* + * Wait until the PLL has stabilized. + */ + oss_udelay (100000); + /* + * Turn on clocking of the core so that we can setup the serial ports. + */ + tmp = PeekBA0 (devc, BA0_CLKCR1) | CLKCR1_SWCE; + PokeBA0 (devc, BA0_CLKCR1, tmp); + + /* Clear the FIFOs */ + clear_serial_fifo (devc); + /* PokeBA0 (devc, BA0_SERBSP, 0); */ + + /* + * Write the serial port configuration to the part. The master + * enable bit is not set until all other values have been written. + */ + PokeBA0 (devc, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); + PokeBA0 (devc, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); + PokeBA0 (devc, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); + + PokeBA0 (devc, BA0_SERC7, SERC7_ASDI2EN); + PokeBA0 (devc, BA0_SERC3, 0); + PokeBA0 (devc, BA0_SERC4, 0); + PokeBA0 (devc, BA0_SERC5, 0); + PokeBA0 (devc, BA0_SERC6, 0); + + oss_udelay (100000); + + + /* Wait for the codec ready signal from the AC97 codec. */ + for (ulCount = 0; ulCount < 1000; ulCount++) + { + /* + * First, lets wait a short while to let things settle out a bit, + * and to prevent retrying the read too quickly. + */ + oss_udelay (10000); + /* + * Read the AC97 status register to see if we've seen a CODEC READY + * signal from the AC97 codec. + */ + ulStatus = PeekBA0 (devc, BA0_ACSTS); + if (ulStatus & ACSTS_CRDY) + break; + } + + if (!(ulStatus & ACSTS_CRDY)) + { + cmn_err (CE_WARN, "Initialize() Never read Codec Ready from AC97.\n"); + return 0; + } + + if (devc->dual_codec) + { + for (ulCount = 0; ulCount < 1000; ulCount++) + { + /* + * + * First, lets wait a short while to let things settle out a bit, + * and to prevent retrying the read too quickly. + * + */ + oss_udelay (10000); + /* + * Read the AC97 status register to see if we've seen a CODEC READY + * signal from the AC97 codec. + */ + ulStatus = PeekBA0 (devc, BA0_ACSTS2); + if (ulStatus & ACSTS_CRDY) + break; + } + + if (!(ulStatus & ACSTS_CRDY)) + { + cmn_err (CE_WARN, + "Initialize() Never read Codec Ready from second AC97.\n"); + } + } + /* + * Assert the vaid frame signal so that we can start sending commands + * to the AC97 codec. + */ + PokeBA0 (devc, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); + /* + * Wait until we've sampled input slots 3 and 4 as valid, meaning that + * the codec is pumping ADC data across the AC-link. + */ + for (ulCount = 0; ulCount < 1000; ulCount++) + { + /* + * First, lets wait a short while to let things settle out a bit, + * and to prevent retrying the read too quickly. + */ + oss_udelay (10000); + /* + * Read the input slot valid register and see if input slots 3 and + * 4 are valid yet. + */ + ulStatus = PeekBA0 (devc, BA0_ACISV); + if ((ulStatus & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) + break; + } + /* + * Make sure we sampled valid input slots 3 and 4. If not, then return + * an error. + */ + if ((ulStatus & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4)) + cmn_err (CE_WARN, "Initialize(%x) Never sampled ISV3 & ISV4 from AC97.\n", + (int) ulStatus); + /* + * Now, assert valid frame and the slot 3 and 4 valid bits. This will + * commense the transfer of digital audio data to the AC97 codec. + */ + PokeBA0 (devc, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); + + /* Reset the Processor */ + cs461x_reset_processor (devc); + /* Now download the image */ + install_ucode (devc); + + devc->processor_started = 0; + + /* Save the play and capture parameters and write 0 to stop DMA */ + devc->PCTL = READ1L (BA1_PCTL) & 0xFFFF0000; + WRITE1L (BA1_PCTL, devc->PCTL & 0x0000FFFF); + devc->CCTL = READ1L (BA1_CCTL) & 0x0000FFFF; + WRITE1L (BA1_CCTL, devc->CCTL & 0xFFFF0000); + + /* + * Enable interrupts on the part. + */ + PokeBA0 (devc, BA0_HICR, HICR_IEV | HICR_CHGM); + + ulStatus = READ1L (BA1_PFIE); + ulStatus &= ~0x0000f03f; + WRITE1L (BA1_PFIE, ulStatus); /* playback interrupt enable */ + + ulStatus = READ1L (BA1_CIE); + ulStatus &= ~0x0000003f; + ulStatus |= 0x00000001; + WRITE1L (BA1_CIE, ulStatus); /* capture interrupt enable */ + +/****** END OF HARDWARE INIT *****/ + + my_mixer = + ac97_install (&devc->ac97devc, "CS461x AC97 Mixer", ac97_read, ac97_write, + devc, devc->osdev); + + if (my_mixer >= 0) + { + devc->mixer_dev = my_mixer; + if (devc->subsysid == 0x5053) /* SantaCruz has dual codec */ + { + my_mixer2 = + ac97_install (&devc->ac97devc2, "CS4630 AC97 Secondary", + ac97_read2, ac97_write2, devc, devc->osdev); + if (my_mixer2 >= 0) + { + devc->mixer2_dev = my_mixer2; + ac97_write2 (devc, BA0_AC97_6CH_VOL_C_LFE, 0x7FFF); + ac97_write2 (devc, BA0_AC97_6CH_VOL_SURROUND, 0x7FFF); + } + } + } + else + return 0; + + /* Turn on amp on the CS4297 on TB/Videologic */ + if (devc->subsysid == 0x5053) + { + unsigned short u16PinConfig, u16LogicType, u16ValidSlots, u16Idx; + unsigned short u16Status = 0; + int i; + + + ac97_write (devc, 0x26, ac97_read (devc, 0x26) | 0x8000); +#if 0 + /* Set SPDIF */ + PokeBA0 (devc, BA0_ASER_MASTER, 1); /*ASER_MASTER_ME */ + WRITE1L (0x8049, 0x00000001); +#endif + /* + * Set GPIO pin's 7 and 8 so that they are configured for output. + */ + u16PinConfig = ac97_read2 (devc, BA0_AC97_GPIO_PIN_CONFIG); + u16PinConfig &= 0x27F; + ac97_write2 (devc, BA0_AC97_GPIO_PIN_CONFIG, u16PinConfig); + + /* + * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic. + */ + u16LogicType = ac97_read2 (devc, BA0_AC97_GPIO_PIN_TYPE); + u16LogicType &= 0x27F; + ac97_write2 (devc, BA0_AC97_GPIO_PIN_TYPE, u16LogicType); + + u16ValidSlots = PeekBA0 (devc, BA0_ACOSV); + u16ValidSlots |= 0x200; + PokeBA0 (devc, BA0_ACOSV, u16ValidSlots); + + /* + * Fill slots 12 with the correct value for the GPIO pins. + */ + for (u16Idx = 0x90; u16Idx <= 0x9F; u16Idx++) + { + + /* + * Initialize the fifo so that bits 7 and 8 are on. + * + * Remember that the GPIO pins in bonzo are shifted by 4 bits to + * the left. 0x1800 corresponds to bits 7 and 8. + */ + PokeBA0 (devc, BA0_SERBWP, 0x1800); + + /* + * Make sure the previous FIFO write operation has completed. + */ + for (i = 0; i < 5; i++) + { + u16Status = PeekBA0 (devc, BA0_SERBST); + if (!(u16Status & SERBST_WBSY)) + { + break; + } + oss_udelay (10000); + } + + /* + * Write the serial port FIFO index. + */ + PokeBA0 (devc, BA0_SERBAD, u16Idx); + + /* + * Tell the serial port to load the new value into the FIFO location. + */ + PokeBA0 (devc, BA0_SERBCM, SERBCM_WRC); + } + } + /* Hercules Game Theater Amp */ + if (devc->subsysid == 0x1681) + { + PokeBA0 (devc, BA0_EGPIODR, EGPIODR_GPOE2); /* enable EGPIO2 output */ + PokeBA0 (devc, BA0_EGPIOPTR, EGPIOPTR_GPPT2); /* open-drain on output */ + + } + +#ifdef USE_SG + devc->play_sgbuf = + (unsigned int *) CONTIG_MALLOC (devc->osdev, 4096, MEMLIMIT_32BITS, + &phaddr, devc->play_sgbuf_dma_handle); + if (devc->play_sgbuf == NULL) + { + cmn_err (CE_WARN, + "cs461x: Failed to allocate play scatter/gather buffer.\n"); + return 0; + } + devc->play_sgbuf_phys = phaddr; +#endif + + for (i = 0; i < MAX_PORTC; i++) + { + char tmp_name[100]; + cs461x_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX; + } + else + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX | ADEV_SHADOW; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &cs461x_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_S16_LE | AFMT_U8, 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]->min_rate = 5000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->min_block = 4096; + audio_engines[adev]->max_block = 4096; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + portc->open_mode = 0; + portc->audiodev = adev; + portc->audio_enabled = 0; + portc->trigger_bits = 0; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + + } + +#ifndef sparc + devc->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "CS461x", + "CS461x MIDI Port", &cs461x_midi_driver, + sizeof (midi_driver_t), + 0, devc, devc->osdev); +#endif + devc->midi_opened = 0; + return 1; +} + +int +oss_cs461x_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision, pci_irq_inta; + unsigned short pci_command, vendor, device; + unsigned int ioaddr; + int err; + cs461x_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered CS461x probe routine\n")); +#if 0 + if (cs461x_clkrun_fix) + while ((osdev = (pci_find_class (0x680 << 8, osdev)))) + + { + unsigned char pp; + unsigned int port, control; + unsigned short vendor, device; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != 0x8086 || device != 0x7113) + continue; + + pci_read_config_byte (osdev, 0x41, &pp); + port = pp << 8; + control = INW (devc->osdev, port + 0x10); + OUTW (devc->osdev, control | 0x2000, port + 0x10); + oss_udelay (100); + OUTW (devc->osdev, control & ~0x2000, port + 0x10); + } +#endif + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != CRYSTAL_VENDOR_ID || device != CRYSTAL_CS461x_ID) + 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; + + oss_pci_byteswap (osdev, 1); + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_byte (osdev, PCI_INTERRUPT_LINE + 1, &pci_irq_inta); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &ioaddr); + devc->bar0addr = ioaddr; + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, &ioaddr); + devc->bar1addr = ioaddr; + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &devc->subsysid); + + switch (device) + { + case CRYSTAL_CS461x_ID: + devc->chip_name = "Crystal CS461x"; + break; + + case CRYSTAL_CS4610_ID: + devc->chip_name = "Crystal CS4610"; + break; + + case CRYSTAL_CS4615_ID: + devc->chip_name = "Crystal CS4615"; + break; + + default: + devc->chip_name = "CrystalPCI"; + } + + if (devc->subsysid == 0x5053) + { + devc->chip_name = "Crystal CS4630"; + devc->dual_codec = 1; + } + + /* activate the device enable bus master/memory space */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if ((devc->bar0addr == 0) || (devc->bar1addr == 0)) + { + cmn_err (CE_WARN, "Undefined MEMORY I/O address.\n"); + return 0; + } + + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS.\n"); + return 0; + } + + /* Map the shared memory area */ + devc->bar0virt = + (unsigned int *) MAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, 0x2000); + devc->bar1virt = + (unsigned int *) MAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, 0x40000); + devc->dwRegister0 = (unsigned int *) devc->bar0virt; + devc->wRegister0 = (unsigned short *) devc->bar0virt; + devc->bRegister0 = (unsigned char *) devc->bar0virt; + devc->dwRegister1 = (unsigned int *) devc->bar1virt; + devc->wRegister1 = (unsigned short *) devc->bar1virt; + devc->bRegister1 = (unsigned char *) devc->bar1virt; + + devc->irq = pci_irq_line; + + 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, cs461xintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + return init_cs461x (devc); /*Detected */ +} + + +int +oss_cs461x_detach (oss_device_t * osdev) +{ + cs461x_devc *devc = (cs461x_devc *) osdev->devc; + + + if (oss_disable_device (osdev) < 0) + return 0; + + PokeBA0 (devc, BA0_HICR, 0x02); /*enable intena */ + cs461x_reset_processor (devc); +#ifdef USE_SG + CONTIG_FREE (devc->osdev, devc->play_sgbuf, 4096, devc->play_sgbuf_dma_handle); +#endif + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + UNMAP_PCI_MEM (devc->osdev, 0, devc->bar0addr, devc->bar0virt, 0x2000); + UNMAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, devc->bar1virt, 0x40000); + + devc->bar0addr = 0; + devc->bar1addr = 0; + + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_cs461x/oss_cs461x.man b/kernel/drv/oss_cs461x/oss_cs461x.man new file mode 100644 index 0000000..11edced --- /dev/null +++ b/kernel/drv/oss_cs461x/oss_cs461x.man @@ -0,0 +1,24 @@ +NAME +oss_cs461x - Cirrus Logic CS461x/CS4280 audio driver. + +DESCRIPTION +Open Sound System driver for Crystal Semiconductor (Cirrus Logic) CS4280 and +461x, audio controllers. + +CS4280 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +o cs461x_clk_run_fix=0|1 (feature not used anylonger) +Certain IBM Thinkpads required the CLK_RUN bit flipped in order to wake up +the audio device. + + +FILES +CONFIGFILEPATH/oss_cs461x.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_digi96/.devices b/kernel/drv/oss_digi96/.devices new file mode 100644 index 0000000..84196cc --- /dev/null +++ b/kernel/drv/oss_digi96/.devices @@ -0,0 +1,4 @@ +oss_digi96 pci10ee,3fc0 RME Digi96 +oss_digi96 pci10ee,3fc1 RME Digi96/8 +oss_digi96 pci10ee,3fc2 RME Digi96/8 PRO +oss_digi96 pci10ee,3fc3 RME Digi96/8 PAD diff --git a/kernel/drv/oss_digi96/.name b/kernel/drv/oss_digi96/.name new file mode 100644 index 0000000..8b0b06c --- /dev/null +++ b/kernel/drv/oss_digi96/.name @@ -0,0 +1 @@ +RME Digi96 diff --git a/kernel/drv/oss_digi96/oss_digi96.c b/kernel/drv/oss_digi96/oss_digi96.c new file mode 100644 index 0000000..6a93285 --- /dev/null +++ b/kernel/drv/oss_digi96/oss_digi96.c @@ -0,0 +1,1097 @@ +/* + * Purpose: Driver for RME Digi96 family + */ +/* + * + * 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_digi96_cfg.h" +#include "oss_pci.h" + +#define RME_VENDOR_ID2 0x10ee +#define RME_DIGI96 0x3fc0 +#define RME_DIGI96_8 0x3fc1 +#define RME_DIGI96_PRO 0x3fc2 +#define RME_DIGI96_PAD 0x3fc3 + +#define MAX_AUDIO_CHANNEL 2 + +/* + * Control register pCTRL1 + */ +#define CTRL1_STARTPLAY 0x00000001 +#define CTRL1_STARTREC 0x00000002 +#define CTRL1_GAIN 0x0000000c +#define CTRL1_MODE24_PLAY 0x00000010 +#define CTRL1_MODE24_REC 0x00000020 +#define CTRL1_PLAYBM 0x00000040 +#define CTRL1_RECBM 0x00000080 +#define CTRL1_ADAT 0x00000100 +#define CTRL1_FREQ 0x00000600 +#define CTRL1_FREQ32 0x00000200 +#define CTRL1_FREQ44 0x00000400 +#define CTRL1_FREQ48 0x00000600 +#define CTRL1_DS 0x00000800 +#define CTRL1_PRO 0x00001000 +#define CTRL1_EMP 0x00002000 +#define CTRL1_SEL 0x00004000 +#define CTRL1_MASTER 0x00008000 +#define CTRL1_PD 0x00010000 +#define CTRL1_INPUTSEL 0x00060000 +#define CTRL1_INPUTSHIFT 17 +#define CTRL1_THRU 0x07f80000 +#define CTRL1_AC3 0x08000000 +#define CTRL1_MONITOR 0x30000000 +#define CTRL1_ISEL 0x40000000 +#define CTRL1_IDIS 0x80000000 + +/* + * Control register pCTRL2 + */ +#define CTRL2_WSEL 0x00000001 +#define CTRL2_ANALOG 0x00000002 /* PAD only */ +#define CTRL2_FREQAD 0x0000001c /* PAD */ +#define CTRL2_PD2 0x00000020 +# +/* Next ones are only for new Digi96/8Pro (blue board) and PAD */ +#define CTRL2_DAC_EN 0x00000040 +#define CTRL2_CLATCH 0x00000080 +#define CTRL2_CCLK 0x00000100 +#define CTRL2_CDATA 0x00000200 +/* + * For reads from the pPLAYPOS and pRECPOS registers + */ + +#define POS_PLAYIRQ 0x80000000 +#define POS_AUTOSYNC 0x40000000 +#define POS_FBITS 0x38000000 +#define POS_FSHIFT 27 +#define POS_ERF 0x04000000 +#define POS_CONSTANT11 0x03000000 +#define POS_LOCK 0x00800000 +#define POS_DEVID 0x00600000 +#define POS_CONSTANT000 0x008c0000 +#define POS_TOUT 0x00020000 +#define POS_RECIRQ 0x00010000 +#define POS_ADDR 0x000fffff + +typedef struct digi96_portc +{ + int open_mode; + int audio_dev; + int channels, bits; + int speed, speedsel; + int trigger_bits; +} +digi96_portc; + +typedef struct digi96_devc +{ + oss_device_t *osdev; + oss_mutex_t mutex; + + char *chip_name; + int have_adat; + int have_analog; + int mode; +#define MD_SPDIF 0 +#define MD_AES 1 +#define MD_ADAT 2 + + oss_native_word physaddr; + char *linaddr; + unsigned int *pPLAYBUF; + unsigned int *pRECBUF; + unsigned int *pCTRL1, ctrl1_bits; + unsigned int *pCTRL2, ctrl2_bits; + unsigned int *pPLAYACK; + unsigned int *pRECACK; + unsigned int *pPLAYPOS; + unsigned int *pRECPOS; + unsigned int *pRESETPLAY; + unsigned int *pRESETREC; + + int irq; + + digi96_portc portc[MAX_AUDIO_CHANNEL]; + int open_mode; +#define TY_READ 0 +#define TY_WRITE 1 +#define TY_BOTH 2 + int mixer_dev; + + int master; + int external_locked; + int input_source; + int doublespeed; + int adatrate; +} +digi96_devc; + +static int fbit_tab[8] = { + 0, 0, 0, 96000, 88200, 48000, 44100, 32000 +}; + + +static void +write_ctrl1 (digi96_devc * devc, unsigned int ctrl) +{ + devc->ctrl1_bits = ctrl; + + PCI_WRITEL (devc->osdev, devc->pCTRL1, ctrl); +} + +static void +write_ctrl2 (digi96_devc * devc, unsigned int ctrl) +{ + devc->ctrl2_bits = ctrl; + + PCI_WRITEL (devc->osdev, devc->pCTRL2, ctrl); +} + +static int +digi96intr (oss_device_t * osdev) +{ + int i, serviced = 0; + unsigned int playstat, recstat; + digi96_devc *devc = (digi96_devc *) osdev->devc; + digi96_portc *portc; + + playstat = PCI_READL (devc->osdev, devc->pPLAYPOS); + recstat = PCI_READL (devc->osdev, devc->pRECPOS); + + for (i = 0; i < 2; i++) + { + portc = &devc->portc[i]; + + if (playstat & POS_PLAYIRQ) + { + serviced = 1; + PCI_WRITEL (devc->osdev, devc->pPLAYACK, 0); + oss_audio_outputintr (portc->audio_dev, 0); + } + + if (recstat & POS_RECIRQ) + { + serviced = 1; + PCI_WRITEL (devc->osdev, devc->pRECACK, 0); + oss_audio_inputintr (portc->audio_dev, 0); + } + } + return serviced; +} + + +/*********************************** + * Audio routines + ***********************************/ + +static int +digi96_set_rate (int dev, int arg) +{ + digi96_devc *devc = audio_engines[dev]->devc; + digi96_portc *portc = audio_engines[dev]->portc; + + static int speed_table[6] = { 32000, 44100, 48000, 64000, 88200, 96000 }; + int i, best = 2, dif, bestdif = 0x7fffffff; + + if (arg) + { + if (devc->external_locked || (portc->open_mode & OPEN_READ)) + arg = portc->speed; /* Speed locked to input */ + + for (i = 0; i < 6; i++) + { + if (arg == speed_table[i]) /* Exact match */ + { + portc->speed = arg; + portc->speedsel = i; + return portc->speed; + } + + dif = arg - speed_table[i]; + if (dif < 0) + dif *= -1; + if (dif <= bestdif) + { + best = i; + bestdif = dif; + } + + } + + portc->speed = speed_table[best]; + portc->speedsel = best; + } + + return portc->speed; +} + +static short +digi96_set_channels (int dev, short arg) +{ + digi96_portc *portc = audio_engines[dev]->portc; + digi96_devc *devc = audio_engines[dev]->devc; + + if (arg == 0) + return portc->channels; + + if (devc->mode == MD_ADAT) + arg = 8; + else + arg = 2; + return portc->channels = arg; +} + +static unsigned int +digi96_set_format (int dev, unsigned int arg) +{ + digi96_portc *portc = audio_engines[dev]->portc; + + if (arg != AFMT_S16_LE && arg != AFMT_AC3 && arg != AFMT_S32_LE) + return portc->bits; + + return portc->bits = arg; +} + +/*ARGSUSED*/ +static int +digi96_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void digi96_trigger (int dev, int state); + +static void +digi96_reset (int dev) +{ + digi96_trigger (dev, 0); +} + +static void +digi96_reset_input (int dev) +{ + digi96_portc *portc = audio_engines[dev]->portc; + digi96_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +digi96_reset_output (int dev) +{ + digi96_portc *portc = audio_engines[dev]->portc; + digi96_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +static int +verify_input (digi96_devc * devc, digi96_portc * portc) +{ + int i, status, savedstatus; + int tmp; + oss_native_word flags; + + tmp = devc->ctrl1_bits & ~CTRL1_INPUTSEL; + tmp |= (devc->input_source & 0x3) << CTRL1_INPUTSHIFT; + write_ctrl1 (devc, tmp); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + i = 0; + status = PCI_READL (devc->osdev, devc->pRECPOS); + + if (status & POS_LOCK) /* ADAT input */ + { + devc->mode = MD_ADAT; + portc->channels = 8; + + switch (devc->adatrate) + { + case 0: /* Autodetect */ + if (status & POS_AUTOSYNC) + portc->speed = 48000; + else + portc->speed = 44100; + DDB (cmn_err + (CE_WARN, "ADAT input detected, sr=%d Hz\n", portc->speed)); + break; + + case 1: + portc->speed = 44100; + break; + + case 2: + portc->speed = 48000; + break; + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 1; + } + + while (i++ < 100 && status & POS_ERF) + { + oss_udelay (10); + status = PCI_READL (devc->osdev, devc->pRECPOS); + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + savedstatus = status; + + status &= POS_ERF; + + if (status) + cmn_err (CE_WARN, "Cannot sync with the input signal\n"); + else + { + int fbits = (savedstatus & POS_FBITS) >> POS_FSHIFT; + portc->speed = fbit_tab[fbits]; + DDB (cmn_err + (CE_WARN, "digi96: Measured input sampling rate is %d\n", + portc->speed)); + } + return devc->external_locked = !status; +} + +/*ARGSUSED*/ +static int +digi96_open (int dev, int mode, int open_flags) +{ + unsigned int tmp; + digi96_portc *portc = audio_engines[dev]->portc; + digi96_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode != 0 || (devc->open_mode & mode)) /* Busy? */ + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + devc->open_mode |= mode; + portc->audio_dev = dev; + portc->trigger_bits = 0; + + tmp = devc->ctrl1_bits; + devc->external_locked = 0; + if (devc->master) + tmp |= CTRL1_MASTER; + else + { + tmp &= ~CTRL1_MASTER; + devc->external_locked = 1; + } + write_ctrl1 (devc, tmp); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (devc->external_locked || (portc->open_mode & OPEN_READ)) + verify_input (devc, portc); + + if (devc->mode == MD_ADAT) + { + audio_engines[dev]->min_block = 8 * 1024; + audio_engines[dev]->max_block = 8 * 1024; + audio_engines[dev]->caps &= ~DSP_CH_MASK; + audio_engines[dev]->caps |= DSP_CH_MULTI; + audio_engines[dev]->min_channels = 8; + audio_engines[dev]->max_channels = 8; + write_ctrl1 (devc, devc->ctrl1_bits & ~CTRL1_ISEL); + } + else + { + audio_engines[dev]->min_block = 2 * 1024; + audio_engines[dev]->max_block = 2 * 1024; + audio_engines[dev]->caps &= ~DSP_CH_MASK; + audio_engines[dev]->caps |= DSP_CH_STEREO; + audio_engines[dev]->min_channels = 2; + audio_engines[dev]->max_channels = 2; + write_ctrl1 (devc, devc->ctrl1_bits | CTRL1_ISEL); + } + + return 0; +} + +static void +digi96_close (int dev, int mode) +{ + digi96_devc *devc = audio_engines[dev]->devc; + digi96_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + digi96_reset (dev); + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + devc->open_mode &= ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +digi96_output_block (int dev, oss_native_word ptr, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +digi96_start_input (int dev, oss_native_word ptr, int count, int fragsize, + int intrflag) +{ +} + +static void +digi96_trigger (int dev, int state) +{ + digi96_devc *devc = audio_engines[dev]->devc; + digi96_portc *portc = audio_engines[dev]->portc; + unsigned int tmp = devc->ctrl1_bits; + + state &= portc->open_mode; + + if (portc->open_mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + tmp |= CTRL1_STARTPLAY; + else + tmp &= ~CTRL1_STARTPLAY; + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + tmp |= CTRL1_STARTREC; + else + tmp &= ~CTRL1_STARTREC; + } + + portc->trigger_bits = state; + write_ctrl1 (devc, tmp); +} + +/*ARGSUSED*/ +static int +digi96_prepare_for_output (int dev, int bsize, int bcount) +{ + digi96_devc *devc = audio_engines[dev]->devc; + digi96_portc *portc = audio_engines[dev]->portc; + + int cmd = devc->ctrl1_bits; + int doublespeed; + + PCI_WRITEL (devc->osdev, devc->pRESETPLAY, 0); + if (devc->master) + cmd |= CTRL1_MASTER; + else + cmd &= ~CTRL1_MASTER; + if (portc->channels == 8) + cmd |= CTRL1_ADAT; + else + cmd &= ~CTRL1_ADAT; + write_ctrl1 (devc, cmd); + + if (!devc->master) + { + if (!verify_input (devc, portc)) + return OSS_EIO; + } + + cmd = devc->ctrl1_bits; + doublespeed = (portc->speedsel > 3); + + cmd &= ~(CTRL1_DS | CTRL1_FREQ); + if (doublespeed) + cmd |= CTRL1_DS; + + cmd |= ((portc->speedsel % 3) + 1) << 9; + write_ctrl1 (devc, cmd); + + if (doublespeed != devc->doublespeed) + { + devc->doublespeed = doublespeed; + write_ctrl1 (devc, cmd | CTRL1_PD); /* Reset the DAC */ + } + + if (portc->bits == AFMT_AC3) + write_ctrl1 (devc, devc->ctrl1_bits | CTRL1_AC3 | CTRL1_PD); + else + { + if (portc->bits == AFMT_S32_LE) + { + write_ctrl1 (devc, devc->ctrl1_bits | CTRL1_MODE24_PLAY); + } + else + write_ctrl1 (devc, devc->ctrl1_bits & ~(CTRL1_MODE24_PLAY)); + + write_ctrl1 (devc, devc->ctrl1_bits & ~(CTRL1_AC3 | CTRL1_PD)); /* Unmute DAC */ + } + return 0; +} + +/*ARGSUSED*/ +static int +digi96_prepare_for_input (int dev, int bsize, int bcount) +{ + digi96_devc *devc = audio_engines[dev]->devc; + digi96_portc *portc = audio_engines[dev]->portc; + + int cmd = devc->ctrl1_bits; + + if (portc->channels == 8) + cmd |= CTRL1_ADAT; + else + cmd &= ~CTRL1_ADAT; + + if (portc->bits == AFMT_S32_LE) + cmd |= CTRL1_MODE24_REC; + else + cmd &= ~CTRL1_MODE24_REC; + write_ctrl1 (devc, cmd); + + if (!verify_input (devc, portc)) + return OSS_EIO; + PCI_WRITEL (devc->osdev, devc->pRESETREC, 0); + + return 0; +} + +static int +digi96_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + digi96_devc *devc = audio_engines[dev]->devc; + + if (direction == OPEN_WRITE) + { + dmap->dmabuf = (void *) devc->pPLAYBUF; + dmap->dmabuf_phys = (oss_native_word) devc->pPLAYBUF; + } + else + { + dmap->dmabuf = (void *) devc->pRECBUF; + dmap->dmabuf_phys = (oss_native_word) devc->pRECBUF; + } + dmap->buffsize = 64 * 1024; + + return 0; +} + +/*ARGSUSED*/ +static int +digi96_free_buffer (int dev, dmap_t * dmap, int direction) +{ + dmap->dmabuf = NULL; + dmap->dmabuf_phys = 0; + return 0; +} + +/*ARGSUSED*/ +static void +digi96_setup_fragments (int dev, dmap_p dmap, int direction) +{ + /* Make sure the whole sample RAM is covered by the buffer */ + dmap->nfrags = dmap->buffsize / dmap->fragment_size; +} + +static audiodrv_t digi96_driver = { + digi96_open, + digi96_close, + digi96_output_block, + digi96_start_input, + digi96_ioctl, + digi96_prepare_for_input, + digi96_prepare_for_output, + digi96_reset, + NULL, + NULL, + digi96_reset_input, + digi96_reset_output, + digi96_trigger, + digi96_set_rate, + digi96_set_format, + digi96_set_channels, + NULL, + NULL, + NULL, + NULL, + digi96_alloc_buffer, + digi96_free_buffer, + NULL, + NULL, + NULL, /* digi96_get_buffer_pointer */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + digi96_setup_fragments +}; + +/*ARGSUSED*/ +static int +digi96_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + if (cmd == SOUND_MIXER_PRIVATE1) /* Bogus testing */ + { + int val; + + val = *arg; + return *arg = val; + } + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC) + return *arg = 0; + + if (cmd == SOUND_MIXER_READ_VOLUME || cmd == SOUND_MIXER_READ_PCM) + return *arg = 100 | (100 << 8); + if (cmd == SOUND_MIXER_WRITE_VOLUME || cmd == SOUND_MIXER_WRITE_PCM) + return *arg = 100 | (100 << 8); + return OSS_EINVAL; +} + +static mixer_driver_t digi96_mixer_driver = { + digi96_mixer_ioctl +}; + +static int +digi96_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + digi96_devc *devc = mixer_devs[dev]->devc; + unsigned int tmp; + + if (ctrl < 0) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + switch (ctrl) + { + case 1: + return !!devc->master; + break; + + case 2: + return devc->input_source; + break; + + case 3: + return !!(devc->ctrl1_bits & CTRL1_SEL); + break; + + case 4: + return devc->mode; + break; + + case 5: + return !!(devc->ctrl2_bits & CTRL2_WSEL); + break; + + case 6: + return !!(devc->ctrl1_bits & CTRL1_EMP); + break; + + case 7: + return !!(devc->ctrl1_bits & CTRL1_AC3); + break; + + case 8: + return devc->adatrate; + break; + } + + return OSS_EINVAL; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: + devc->master = !!value; + return !!value; + break; + + case 2: + if (value < 0 || value > 3) + return OSS_EINVAL; + + devc->input_source = value; + return value; + break; + + case 3: + tmp = devc->ctrl1_bits; + if (value) + tmp |= CTRL1_SEL; + else + { + tmp &= ~(CTRL1_SEL | CTRL1_MASTER); + devc->master = 0; + } + write_ctrl1 (devc, tmp); + return value; + break; + + case 4: + if (value > 2 || (!devc->have_adat && value > 1)) + return OSS_EINVAL; + + devc->mode = value; + return value; + break; + + case 5: + if (value) + { + write_ctrl2 (devc, devc->ctrl2_bits | CTRL2_WSEL); + return 1; + } + + write_ctrl2 (devc, devc->ctrl2_bits & ~CTRL2_WSEL); + return 0; + break; + + case 6: + if (value) + { + write_ctrl1 (devc, devc->ctrl1_bits | CTRL1_EMP); + return 1; + } + + write_ctrl1 (devc, devc->ctrl1_bits & ~CTRL1_EMP); + return 0; + break; + + case 7: + if (value) + { + write_ctrl1 (devc, devc->ctrl1_bits | CTRL1_AC3); + return 1; + } + + write_ctrl1 (devc, devc->ctrl1_bits & ~CTRL1_AC3); + return 0; + break; + + case 8: + if (value > 2) + value = 2; + if (value < 0) + value = 0; + + return devc->adatrate = value; + break; + + } + + return OSS_EINVAL; + } + + return OSS_EINVAL; +} + +static int +digi96_mix_init (int dev) +{ + /* digi96_devc *devc = mixer_devs[dev]->devc; */ + int group, err; + + if ((group = mixer_ext_create_group (dev, 0, "DIGI96")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 4, digi96_set_control, + MIXT_ENUM, + "DIGI96_MODE", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, digi96_set_control, + MIXT_ENUM, + "DIGI96_SYNC", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, digi96_set_control, + MIXT_ENUM, + "DIGI96_INPUT", 4, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, digi96_set_control, + MIXT_ENUM, + "DIGI96_SEL", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 5, digi96_set_control, + MIXT_ONOFF, + "DIGI96_WORLDCLK", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 6, digi96_set_control, + MIXT_ONOFF, + "DIGI96_EMPH", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + +#if 0 + if ((err = mixer_ext_create_control (dev, group, + 7, digi96_set_control, + MIXT_ENUM, + "DIGI96_DATA", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; +#endif + + if ((err = mixer_ext_create_control (dev, group, + 8, digi96_set_control, + MIXT_ENUM, + "DIGI96_ADATRATE", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + mixer_ext_set_strings (dev, err, "AUTO 44100 48000", 0); + + return 0; +} + +static int +attach_channel (digi96_devc * devc, int chnum, char *name, + audiodrv_t * drv, int type) +{ + int adev; + digi96_portc *portc; + int opts = ADEV_DUPLEX | ADEV_COLD | ADEV_AUTOMODE | ADEV_NOVIRTUAL; + + if (chnum < 0 || chnum >= MAX_AUDIO_CHANNEL) + return 0; + + if (type == TY_BOTH) + opts = ADEV_SHADOW; + + portc = &devc->portc[chnum]; + + devc->master = 1; + devc->input_source = 0; + devc->doublespeed = 0; + devc->external_locked = 0; + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + name, + drv, + sizeof (audiodrv_t), + opts, + AFMT_AC3 | AFMT_S16_LE | AFMT_S32_LE, + devc, -1)) < 0) + { + return 0; + } + + audio_engines[adev]->mixer_dev = devc->mixer_dev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->caps |= DSP_CH_STEREO; + audio_engines[adev]->min_block = 2 * 1024; + audio_engines[adev]->max_block = 2 * 1024; + audio_engines[adev]->min_rate = 32000; + audio_engines[adev]->max_rate = 96000; + portc->open_mode = 0; + devc->open_mode = 0; + portc->audio_dev = adev; + + portc->speed = 48000; + portc->speedsel = 3; + portc->bits = AFMT_S16_LE; + portc->channels = 2; + return 1; +} + +int +init_digi96 (digi96_devc * devc) +{ + int my_mixer; + int ret; + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "RME Digi96 Control panel", + &digi96_mixer_driver, + sizeof (mixer_driver_t), devc)) < 0) + { + + devc->mixer_dev = -1; + return 0; + } + else + + { + mixer_devs[my_mixer]->priority = -1; /* Don't use as the default mixer */ + devc->mixer_dev = my_mixer; + mixer_ext_set_init_fn (my_mixer, digi96_mix_init, 20); + } + + ret = attach_channel (devc, 0, devc->chip_name, &digi96_driver, 0); + if (ret > 0) + { + ret = + attach_channel (devc, 1, devc->chip_name, &digi96_driver, TY_BOTH); + } + +/* + * Set some defaults + */ + write_ctrl2 (devc, 0); + write_ctrl1 (devc, CTRL1_ISEL | CTRL1_FREQ48 | CTRL1_PD); /* Reset DAC */ + write_ctrl1 (devc, CTRL1_ISEL | CTRL1_FREQ48 | CTRL1_MASTER | CTRL1_SEL); + write_ctrl2 (devc, CTRL2_DAC_EN); /* Soft unmute the DAC (blue PRO boards) */ + return ret; +} + + +int +oss_digi96_attach (oss_device_t * osdev) +{ + digi96_devc *devc; + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int err; + + DDB (cmn_err (CE_WARN, "Entered Digi96 detect routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + if (vendor != RME_VENDOR_ID2 || + (device != RME_DIGI96_PRO && + device != RME_DIGI96_PAD && + device != RME_DIGI96 && device != RME_DIGI96_8)) + + return 0; + + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &pci_ioaddr); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "BAR0 not initialized by BIOS\n"); + 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->physaddr = pci_ioaddr; + + devc->have_adat = 0; + devc->have_analog = 0; + devc->mode = MD_SPDIF; + + switch (device) + { + case RME_DIGI96: + devc->chip_name = "RME Digi96"; + break; + + case RME_DIGI96_8: + devc->chip_name = "RME Digi96/8"; + devc->have_adat = 1; + break; + + case RME_DIGI96_PRO: + devc->have_adat = 1; + if (pci_revision < 2) + { + devc->chip_name = "RME Digi96/8 PRO (green)"; + } + else + { + devc->chip_name = "RME Digi96/8 PRO (blue)"; + } + break; + + case RME_DIGI96_PAD: + devc->have_adat = 1; + devc->have_analog = 1; + devc->chip_name = "RME Digi96/8 PAD"; + break; + } + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + + oss_register_device (osdev, devc->chip_name); + + devc->linaddr = + (char *) MAP_PCI_MEM (devc->osdev, 0, devc->physaddr, 0x60000); + if (devc->linaddr == NULL) + { + cmn_err (CE_WARN, "Can't map PCI registers (0x%08lx)\n", + devc->physaddr); + return 0; + } + + if ((err = oss_register_interrupts (devc->osdev, 0, digi96intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + devc->pPLAYBUF = (unsigned int *) devc->linaddr; + devc->pRECBUF = (unsigned int *) (devc->linaddr + 0x10000); + devc->pCTRL1 = (unsigned int *) (devc->linaddr + 0x20000); + devc->pCTRL2 = (unsigned int *) (devc->linaddr + 0x20004); + devc->pPLAYACK = (unsigned int *) (devc->linaddr + 0x20008); + devc->pRECACK = (unsigned int *) (devc->linaddr + 0x2000c); + devc->pPLAYPOS = (unsigned int *) (devc->linaddr + 0x20000); + devc->pRECPOS = (unsigned int *) (devc->linaddr + 0x30000); + devc->pRESETPLAY = (unsigned int *) (devc->linaddr + 0x4fffc); + devc->pRESETREC = (unsigned int *) (devc->linaddr + 0x5fffc); + + return init_digi96 (devc); /* Detected */ +} + +int +oss_digi96_detach (oss_device_t * osdev) +{ + digi96_devc *devc = (digi96_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + write_ctrl2 (devc, 0); /* Soft mute */ + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + + UNMAP_PCI_MEM (devc->osdev, 0, devc->physaddr, devc->linaddr, 0x60000); + + oss_unregister_device (devc->osdev); + + return 1; + +} diff --git a/kernel/drv/oss_digi96/oss_digi96.man b/kernel/drv/oss_digi96/oss_digi96.man new file mode 100644 index 0000000..f13fb66 --- /dev/null +++ b/kernel/drv/oss_digi96/oss_digi96.man @@ -0,0 +1,63 @@ +NAME +oss_digi96 - RME Digi96 professional audio driver. + +DESCRIPTION +Audio driver for the RME Digi96 family of profressional audio controllers. +- Only 16 and 24/32 bit audio formats are supported. +- All Digi96 family members support 32kHz, 44.1kHz, 48kHz, 64kHz, 88.2kHz and +96kHz. sampling rates. + + +MIXER PANEL + +Note! For recording you need to set digi96.sync to INTERNAL and the values + of digi96.mode and digi96.input to match your studio setup. Otherwise + recordings will fail with I/O error. + +There are several settings that can be changed using the ossmix program +shipped with OSS. Note that some features don't work with all Digi96 +family members. For example ADAT mode is not supported by the base +model. + +o digi96.mode <SPDIF|AESEBU|ADAT>: +This setting controls the output mode which can be S/PDIF (consumer), +AES/EBU (professional) or ADAT. The input mode is detected automatically. +If ADAT input is detected the output mode will be switched to ADAT +automatically (this doesn't work in the other direction). + +o digi96.sync <EXTERNAL|INTERNAL>: +This setting tells if the playback sampling rate is based on the internal +oscillator or the sample rate detected in the input port. See also the +definition of the digi96.worldclk setting. + +o digi96.input <OPTICAL|COAXIAL|INTERNAL|XLR>: Selects the active input. + +o digi96.sel <BYPASS|NORMAL>: +When set to BYPASS the input signal will be routed directly to the +output (also sets digi96.sync automatically to EXTERNAL). In this mode +audio data written to /dev/dsp will be muted. + +o digi96.worldclk ON|OFF: +Setting this control to ON will enable the optional worldclock input as +the sample rate source (overrides the digi96.sync setting). + +o digi96.emph ON|OFF: +Enables/disables the de-emphasis option on the analog (monitor) output +connector. + +o digi96.data <AUDIO|AC3>: +Specifies if the output signal is audio or AC3 data (sets the non-audio +bit in the channel status data). + + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_digi96.conf Device configuration file + +AUTHOR +4Front Technologies + + + diff --git a/kernel/drv/oss_emu10k1x/.config b/kernel/drv/oss_emu10k1x/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_emu10k1x/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_emu10k1x/.devices b/kernel/drv/oss_emu10k1x/.devices new file mode 100644 index 0000000..7565a33 --- /dev/null +++ b/kernel/drv/oss_emu10k1x/.devices @@ -0,0 +1 @@ +oss_emu10k1x pci1102,6 Creative Sound Blaster 5.1 (Dell) diff --git a/kernel/drv/oss_emu10k1x/.name b/kernel/drv/oss_emu10k1x/.name new file mode 100644 index 0000000..af96a5f --- /dev/null +++ b/kernel/drv/oss_emu10k1x/.name @@ -0,0 +1 @@ +Creative Sound Blaster 5.1 (Dell) diff --git a/kernel/drv/oss_emu10k1x/.params b/kernel/drv/oss_emu10k1x/.params new file mode 100644 index 0000000..19c1a21 --- /dev/null +++ b/kernel/drv/oss_emu10k1x/.params @@ -0,0 +1,5 @@ +int emu10k1x_spdif_enable=0; +/* + * Enable SPDIF on Combo Jack + * Values: 1=Enable 0=Disable Default: 0 + */ diff --git a/kernel/drv/oss_emu10k1x/oss_emu10k1x.c b/kernel/drv/oss_emu10k1x/oss_emu10k1x.c new file mode 100644 index 0000000..5a66ff7 --- /dev/null +++ b/kernel/drv/oss_emu10k1x/oss_emu10k1x.c @@ -0,0 +1,1243 @@ +/* + * Purpose: Driver for Creative emu10k1x audio controller + * + * This device is usually called as SB Live! 5.1 and it has been used in + * some Dell machines. However it has nothing to do with the original + * SB Live! design. + */ +/* + * + * 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_emu10k1x_cfg.h" +#include "oss_pci.h" +#include "ac97.h" +#include "midi_core.h" +#include "remux.h" + +#define PCI_VENDOR_ID_CREATIVE 0x1102 +#define PCI_DEVICE_ID_CREATIVE_EMU10K1X 0x0006 + +#define USE_DUALBUF + +/* + * Indirect registers + */ + +#define PTBA 0x000 +#define PTBS 0x001 +#define PTCA 0x002 +#define PFBA 0x004 +#define PFBS 0x005 +#define CPFA 0x006 +#define PFEA 0x007 +#define CPCAV 0x008 +#define RFBA 0x010 +#define RFBS 0x011 +#define CRFA 0x012 +#define CRCAV 0x013 +#define CDL 0x020 +#define CDR 0x030 +#define SA 0x040 +#define EA_aux 0x041 +#define SCS0 0x042 +#define SCS1 0x043 +#define SCS2 0x044 +#define SPC 0x045 +#define WMARK 0x046 +#define MUDAT 0x047 +#define MUCMD 0x048 +#define RCD 0x050 + +/* Interrupt bits + */ + +#define INTR_RFF (1<<19) +#define INTR_RFH (1<<16) +#define INTR_PFF (1<<11) +#define INTR_PFH (1<<8) +#define INTR_EAI (1<<29) +#define INTR_PCI 1 +#define INTR_UART_RX 2 +#define INTR_UART_TX 4 +#define INTR_AC97 0x10 +#define INTR_GPIO 0x40 + +#define PLAY_INTR_ENABLE (INTR_PFF|INTR_PFH) +#define RECORD_INTR_ENABLE (INTR_RFF|INTR_RFH) + +#define EMU_BUFSIZE 32*1024 +#define MAX_PORTC 3 + +extern int emu10k1x_spdif_enable; + +typedef struct +{ + int audio_dev; + int port_number; + int open_mode; + int trigger_bits; + int audio_enabled; + int channels; + int fmt; + int speed; + unsigned char *playbuf, *recbuf; + oss_native_word playbuf_phys, recbuf_phys; + + oss_dma_handle_t playbuf_dma_handle, recbuf_dma_handle; + + int play_cfrag, play_chalf, rec_cfrag, rec_chalf; +} +emu10k1x_portc; + +typedef struct +{ + oss_device_t *osdev; + int loaded; + oss_native_word base; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + int irq; + char *card_name; + unsigned int subvendor; + + int mixer_dev; + ac97_devc ac97devc; + +/* + * UART + */ + oss_midi_inputbyte_t midi_input_intr; + int midi_opened, midi_disabled; + volatile unsigned char input_byte; + int midi_dev; + int mpu_attached; + + emu10k1x_portc portc[MAX_PORTC]; + +} +emu10k1x_devc; + + +static void emu10k1xuartintr (emu10k1x_devc * devc); + +static unsigned int +read_reg (emu10k1x_devc * devc, int reg, int chn) +{ + oss_native_word flags; + unsigned int val; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTL (devc->osdev, (reg << 16) | (chn & 0xffff), devc->base + 0x00); /* Pointer */ + val = INL (devc->osdev, devc->base + 0x04); /* Data */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + +/* printk("Read reg %03x (ch %d) = %08x\n", reg, chn, val); */ + return val; +} + +static void +write_reg (emu10k1x_devc * devc, int reg, int chn, unsigned int value) +{ + oss_native_word flags; + + /* printk("Write reg %03x (ch %d) = %08x\n", reg, chn, value); */ + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTL (devc->osdev, (reg << 16) | (chn & 0xffff), devc->base + 0x00); /* Pointer */ + OUTL (devc->osdev, value, devc->base + 0x04); /* Data */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +#if 0 + { + char tmp[100]; + int ok = 1; + sprintf (tmp, "@w%d %04x/%s %x", chn, reg, emu_regname (reg, &ok), value); + if (ok) + oss_do_timing (tmp); + } +#endif +} + +static void +recording_intr (emu10k1x_devc * devc, emu10k1x_portc * portc, int status) +{ +#ifdef USE_DUALBUF + unsigned char *frombuf, *tobuf; + dmap_p dmap = audio_engines[portc->audio_dev]->dmap_in; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* "Auto sync" the play half counters with the device */ + if (status & INTR_RFH) /* 1st half completed */ + portc->rec_chalf = 0; /* Reuse the first half */ + else + portc->rec_chalf = 1; /* Reuse the second half */ + + tobuf = dmap->dmabuf + (portc->rec_cfrag * dmap->fragment_size); + frombuf = portc->recbuf + (portc->rec_chalf * dmap->fragment_size); + + memcpy (tobuf, frombuf, dmap->fragment_size); + +/* printk("rec %d/%d\n", portc->rec_cfrag, portc->rec_chalf); */ + portc->rec_cfrag = (portc->rec_cfrag + 1) % dmap->nfrags; + portc->rec_chalf = !portc->rec_chalf; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +#endif + oss_audio_inputintr (portc->audio_dev, 0); +} + +static void +playback_intr (emu10k1x_devc * devc, emu10k1x_portc * portc, + unsigned int status) +{ +#ifdef USE_DUALBUF + dmap_p dmap = audio_engines[portc->audio_dev]->dmap_out; + unsigned char *frombuf, *tobuf; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* "Auto sync" the play half counters with the device */ + if (status & (INTR_PFH << portc->port_number)) /* 1st half completed */ + { + portc->play_chalf = 0; /* Reuse the first half */ + } + else + { + portc->play_chalf = 1; /* Reuse the second half */ + } + + + frombuf = dmap->dmabuf + (portc->play_cfrag * dmap->fragment_size); + tobuf = portc->playbuf + (portc->play_chalf * dmap->fragment_size); + + memcpy (tobuf, frombuf, dmap->fragment_size); + +/* printk("play %d/%d\n", portc->play_cfrag, portc->play_chalf); */ + portc->play_cfrag = (portc->play_cfrag + 1) % dmap->nfrags; + portc->play_chalf = !portc->play_chalf; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +#endif + oss_audio_outputintr (portc->audio_dev, 0); +} + +static int +emu10k1xintr (oss_device_t * osdev) +{ + int serviced = 0; + unsigned int status; + emu10k1x_devc *devc = (emu10k1x_devc *) osdev->devc; + int portnum; + + status = INL (devc->osdev, devc->base + 0x08); + + if (status & 0x2) /* MIDI RX interrupt */ + { + emu10k1xuartintr (devc); + serviced = 1; + } + + if (status & (INTR_PFF | INTR_PFH | INTR_RFF | INTR_RFH)) + { + for (portnum = 0; portnum < 3; portnum++) + { + emu10k1x_portc *portc = &devc->portc[portnum]; + + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && + (status & ((INTR_PFF | INTR_PFH) << portc->port_number))) + playback_intr (devc, portc, status); + if ((portc->trigger_bits & PCM_ENABLE_INPUT) && + (status & (INTR_RFF | INTR_RFH))) + recording_intr (devc, portc, status); + + } + serviced = 1; + OUTL (devc->osdev, status, devc->base + 0x08); /* Acknowledge */ + } + return serviced; +} + +/*ARGSUSED*/ +static int +emu10k1x_set_rate (int dev, int arg) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + + return portc->speed = 48000; +} + +static short +emu10k1x_set_channels (int dev, short arg) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->channels; + + if (portc->open_mode & OPEN_READ) + return portc->channels = 2; + + if (arg != 1 && arg != 2) + return portc->channels = 2; + return portc->channels = arg; +} + +static unsigned int +emu10k1x_set_format (int dev, unsigned int arg) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->fmt; + + if (arg == AFMT_AC3) + if ((portc->open_mode & OPEN_READ) || !emu10k1x_spdif_enable) + arg = AFMT_S16_LE; + + if (arg != AFMT_AC3 && arg != AFMT_S16_LE) + return portc->fmt = AFMT_S16_LE; + + return portc->fmt = arg; +} + +/*ARGSUSED*/ +static int +emu10k1x_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void emu10k1x_trigger (int dev, int state); + +static void +emu10k1x_reset (int dev) +{ + emu10k1x_trigger (dev, 0); +} + +static void +emu10k1x_reset_input (int dev) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + emu10k1x_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +emu10k1x_reset_output (int dev) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + emu10k1x_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +emu10k1x_open (int dev, int mode, int open_flags) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + emu10k1x_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; + } + + portc->open_mode = mode; + portc->audio_enabled = ~mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +emu10k1x_close (int dev, int mode) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + + emu10k1x_trigger (dev, 0); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +emu10k1x_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +emu10k1x_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + emu10k1x_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + + +static void +emu10k1x_trigger (int dev, int state) +{ + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + int tmp; + oss_native_word flags; + + 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)) + { + /* Enable play channel and set mono/stereo mode */ + tmp = read_reg (devc, SA, 0); + tmp &= ~(0x10000 << portc->port_number); + if (portc->channels == 1) + tmp |= (0x10000 << portc->port_number); + tmp |= 1 << portc->port_number; + write_reg (devc, SA, 0, tmp); + + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + /* Disable Play channel */ + tmp = read_reg (devc, SA, 0); + tmp &= ~(1 << portc->port_number); + write_reg (devc, SA, 0, tmp); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Enable Rec Channel */ + tmp = read_reg (devc, SA, 0); + tmp |= 0x100; + write_reg (devc, SA, 0, tmp); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + /* disable channel */ + tmp = read_reg (devc, SA, 0); + tmp &= ~0x100; + write_reg (devc, SA, 0, tmp); + } + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +emu10k1x_prepare_for_input (int dev, int bsize, int bcount) +{ + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); +#ifndef USE_DUALBUF + /* Single buffering mode */ + dmap->nfrags = 2; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + write_reg (devc, RFBA, 0, dmap->dmabuf_phys); + write_reg (devc, RFBS, 0, (dmap->bytes_in_use - 4) << 16); +#else + write_reg (devc, RFBA, 0, portc->recbuf_phys); + write_reg (devc, RFBS, 0, (dmap->fragment_size * 2) << 16); +#endif + memset (portc->recbuf, 0, EMU_BUFSIZE); + portc->rec_cfrag = portc->rec_chalf = 0; + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +emu10k1x_prepare_for_output (int dev, int bsize, int bcount) +{ + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + unsigned int tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->fmt == AFMT_AC3) + portc->channels = 2; + + write_reg (devc, PTBA, portc->port_number, 0); + write_reg (devc, PTBS, portc->port_number, 0); + write_reg (devc, PTCA, portc->port_number, 0); + + write_reg (devc, CPFA, portc->port_number, 0); + write_reg (devc, PFEA, portc->port_number, 0); + write_reg (devc, CPCAV, portc->port_number, 0); + +#ifndef USE_DUALBUF + /* Single buffering mode */ + dmap->nfrags = 2; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + write_reg (devc, PFBA, portc->port_number, dmap->dmabuf_phys); + write_reg (devc, PFBS, portc->port_number, (dmap->bytes_in_use - 4) << 16); +#else + /* Dual buffering mode */ + write_reg (devc, PFBA, portc->port_number, portc->playbuf_phys); + write_reg (devc, PFBS, portc->port_number, (dmap->fragment_size * 2) << 16); +#endif + memset (portc->playbuf, 0, EMU_BUFSIZE); + portc->play_cfrag = portc->play_chalf = 0; + + if (portc->fmt == AFMT_AC3) + { + tmp = read_reg (devc, EA_aux, 0); + tmp &= ~(0x03 << (portc->port_number * 2)); + if (portc->port_number == 2) + tmp &= ~0x10000; + write_reg (devc, EA_aux, 0, tmp); + write_reg (devc, SCS0 + portc->port_number, 0, 0x02108506); /* Data */ + } + else + { + tmp = read_reg (devc, EA_aux, 0); + tmp |= (0x03 << (portc->port_number * 2)); + + if (emu10k1x_spdif_enable == 0) + if (portc->port_number == 2) + tmp |= 0x10000; + + write_reg (devc, EA_aux, 0, tmp); + write_reg (devc, SCS0 + portc->port_number, 0, 0x02108504); /* Audio */ + } + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +emu10k1x_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + int err; + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + oss_native_word phaddr; + + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + return err; + + if (direction == OPEN_READ) + { + if (portc->port_number == 0) + { + portc->recbuf = + CONTIG_MALLOC (devc->osdev, EMU_BUFSIZE, MEMLIMIT_32BITS, &phaddr, portc->recbuf_dma_handle); + if (portc->recbuf == NULL) + return OSS_ENOMEM; + portc->recbuf_phys = phaddr; + } + } + else + { + portc->playbuf = + CONTIG_MALLOC (devc->osdev, EMU_BUFSIZE, MEMLIMIT_32BITS, &phaddr, portc->playbuf_dma_handle); + if (portc->playbuf == NULL) + return OSS_ENOMEM; + portc->playbuf_phys = phaddr; + } + return 0; +} + +/*ARGSUSED*/ +static int +emu10k1x_free_buffer (int dev, dmap_t * dmap, int direction) +{ + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + + oss_free_dmabuf (dev, dmap); + + if (portc->playbuf != NULL) + { + CONTIG_FREE (devc->osdev, portc->playbuf, EMU_BUFSIZE, portc->playbuf_dma_handle); + portc->playbuf = NULL; + } + + if (portc->recbuf != NULL) + { + CONTIG_FREE (devc->osdev, portc->recbuf, EMU_BUFSIZE, portc->recbuf_dma_handle); + portc->recbuf = NULL; + } + + return 0; +} + +#if 0 +static int +emu10k1x_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + unsigned int p = 0; + + emu10k1x_devc *devc = audio_engines[dev]->devc; + emu10k1x_portc *portc = audio_engines[dev]->portc; + + dmap = audio_engines[dev]->dmap_out; + if (direction == PCM_ENABLE_OUTPUT) + p = read_reg (devc, CPFA, portc->port_number); + + if (direction == PCM_ENABLE_INPUT) + p = read_reg (devc, CRFA, portc->port_number); + + p %= (dmap->bytes_in_use - 4); + + return p; +} +#endif + +static audiodrv_t emu10k1x_audio_driver = { + emu10k1x_open, + emu10k1x_close, + emu10k1x_output_block, + emu10k1x_start_input, + emu10k1x_ioctl, + emu10k1x_prepare_for_input, + emu10k1x_prepare_for_output, + emu10k1x_reset, + NULL, + NULL, + emu10k1x_reset_input, + emu10k1x_reset_output, + emu10k1x_trigger, + emu10k1x_set_rate, + emu10k1x_set_format, + emu10k1x_set_channels, + NULL, + NULL, + NULL, + NULL, + emu10k1x_alloc_buffer, + emu10k1x_free_buffer, + NULL, + NULL, + NULL /*emu10k1x_get_buffer_pointer */ +}; + + +#define MUADAT 0x47 +#define MUACMD 0x48 +#define MUASTAT 0x48 + +static __inline__ int +emu10k1xuart_status (emu10k1x_devc * devc) +{ + return read_reg (devc, MUASTAT, 0); +} + +#define input_avail(devc) (!(emu10k1xuart_status(devc)&INPUT_AVAIL)) +#define output_ready(devc) (!(emu10k1xuart_status(devc)&OUTPUT_READY)) +static void +emu10k1xuart_cmd (emu10k1x_devc * devc, unsigned char cmd) +{ + write_reg (devc, MUACMD, 0, cmd); +} + +static __inline__ int +emu10k1xuart_read (emu10k1x_devc * devc) +{ + return read_reg (devc, MUADAT, 0); +} + +static __inline__ void +emu10k1xuart_write (emu10k1x_devc * devc, unsigned char byte) +{ + write_reg (devc, MUADAT, 0, byte); +} + +#define OUTPUT_READY 0x40 +#define INPUT_AVAIL 0x80 +#define MPU_ACK 0xFE +#define MPU_RESET 0xFF +#define UART_MODE_ON 0x3F + +static int reset_emu10k1xuart (emu10k1x_devc * devc); +static void enter_uart_mode (emu10k1x_devc * devc); + +static void +emu10k1xuart_input_loop (emu10k1x_devc * devc) +{ + while (input_avail (devc)) + { + unsigned char c = emu10k1xuart_read (devc); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, c); + } +} + +static void +emu10k1xuartintr (emu10k1x_devc * devc) +{ + emu10k1xuart_input_loop (devc); +} + +/*ARGSUSED*/ +static int +emu10k1xuart_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + emu10k1x_devc *devc = (emu10k1x_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + while (input_avail (devc)) + emu10k1xuart_read (devc); + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + enter_uart_mode (devc); + devc->midi_disabled = 0; + + return 0; +} + +/*ARGSUSED*/ +static void +emu10k1xuart_close (int dev, int mode) +{ + emu10k1x_devc *devc = (emu10k1x_devc *) midi_devs[dev]->devc; + + reset_emu10k1xuart (devc); + oss_udelay (10); + enter_uart_mode (devc); + reset_emu10k1xuart (devc); + devc->midi_opened = 0; +} + + +static int +emu10k1xuart_out (int dev, unsigned char midi_byte) +{ + int timeout; + emu10k1x_devc *devc = (emu10k1x_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + /* + * Test for input since pending input seems to block the output. + */ + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (input_avail (devc)) + emu10k1xuart_input_loop (devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + /* + * Sometimes it takes about 130000 loops before the output becomes ready + * (After reset). Normally it takes just about 10 loops. + */ + + for (timeout = 130000; timeout > 0 && !output_ready (devc); timeout--); + + if (!output_ready (devc)) + { + cmn_err (CE_WARN, "UART timeout - Device not responding\n"); + devc->midi_disabled = 1; + reset_emu10k1xuart (devc); + enter_uart_mode (devc); + return 1; + } + + emu10k1xuart_write (devc, midi_byte); + return 1; +} + +/*ARGSUSED*/ +static int +emu10k1xuart_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t emu10k1x_midi_driver = { + emu10k1xuart_open, + emu10k1xuart_close, + emu10k1xuart_ioctl, + emu10k1xuart_out +}; + + +static void +enter_uart_mode (emu10k1x_devc * devc) +{ + int ok, timeout; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + emu10k1xuart_cmd (devc, UART_MODE_ON); + + ok = 0; + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) + ok = 1; + else if (input_avail (devc)) + if (emu10k1xuart_read (devc) == MPU_ACK) + ok = 1; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + +void +attach_emu10k1xuart (emu10k1x_devc * devc) +{ + enter_uart_mode (devc); + + devc->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "EMU10K1X", "SB P16X UART", + &emu10k1x_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev); + devc->midi_opened = 0; +} + +static int +reset_emu10k1xuart (emu10k1x_devc * devc) +{ + int ok, timeout, n; + + /* + * Send the RESET command. Try again if no success at the first time. + */ + + ok = 0; + + for (n = 0; n < 2 && !ok; n++) + { + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + emu10k1xuart_cmd (devc, MPU_RESET); + + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail (devc)) + if (emu10k1xuart_read (devc) == MPU_ACK) + ok = 1; + + } + + + + if (ok) + emu10k1xuart_input_loop (devc); /* + * Flush input before enabling interrupts + */ + + return ok; +} + + +int +probe_emu10k1xuart (emu10k1x_devc * devc) +{ + int ok = 0; + oss_native_word flags; + + DDB (cmn_err (CE_CONT, "Entered probe_emu10k1xuart\n")); + + devc->midi_input_intr = NULL; + devc->midi_opened = 0; + devc->input_byte = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ok = reset_emu10k1xuart (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (ok) + { + DDB (cmn_err (CE_CONT, "Reset UART401 OK\n")); + } + else + { + DDB (cmn_err + (CE_WARN, "Reset UART401 failed (no hardware present?).\n")); + DDB (cmn_err + (CE_WARN, "mpu401 status %02x\n", emu10k1xuart_status (devc))); + } + + DDB (cmn_err (CE_WARN, "emu10k1xuart detected OK\n")); + return ok; +} + +void +unload_emu10k1xuart (emu10k1x_devc * devc) +{ + reset_emu10k1xuart (devc); +} + + +static void +attach_mpu (emu10k1x_devc * devc) +{ + devc->mpu_attached = 1; + attach_emu10k1xuart (devc); +} + + +static int +emu10k1x_ac97_read (void *devc_, int wAddr) +{ + emu10k1x_devc *devc = devc_; + int dtemp = 0, i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + dtemp = INW (devc->osdev, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dtemp & 0xffff; +} + +static int +emu10k1x_ac97_write (void *devc_, int wAddr, int wData) +{ + emu10k1x_devc *devc = devc_; + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + OUTW (devc->osdev, wData, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + +static const int bindings[MAX_PORTC] = { + DSP_BIND_FRONT, + DSP_BIND_SURR, + DSP_BIND_CENTER_LFE +}; + +static void +install_audio_devices (emu10k1x_devc * devc) +{ + int i; + unsigned int tmp; + int firstdev = -1; + char name[64]; + +#if 0 + if (emu10k1x_spdif_enable == 1) + n = 2; +#endif + + /* Enable play interrupts for all 3 channels */ + for (i = 0; i < MAX_PORTC; i++) + { + tmp = INL (devc->osdev, devc->base + 0x0c); + tmp |= PLAY_INTR_ENABLE << i; + OUTL (devc->osdev, tmp, devc->base + 0x0c); + } + + /* Enable record interrupts */ + tmp = INL (devc->osdev, devc->base + 0x0c); + tmp |= RECORD_INTR_ENABLE; + OUTL (devc->osdev, tmp, devc->base + 0x0c); + + for (i = 0; i < MAX_PORTC; i++) + { + int adev, flags; + emu10k1x_portc *portc = &devc->portc[i]; + + flags = ADEV_AUTOMODE | ADEV_FIXEDRATE | ADEV_16BITONLY | ADEV_COLD; + + switch (i) + { + case 0: + sprintf (name, "%s (front)", devc->card_name); + break; + case 1: + sprintf (name, "%s (surround)", devc->card_name); + break; + case 2: + if (emu10k1x_spdif_enable == 1) + sprintf (name, "%s (SPDIF)", devc->card_name); + else + sprintf (name, "%s (center/LFE)", devc->card_name); + break; + } + + if (i == 0) + flags |= ADEV_DUPLEX; + else + flags |= ADEV_NOINPUT; + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + name, + &emu10k1x_audio_driver, + sizeof (audiodrv_t), + flags, AFMT_S16_LE | AFMT_AC3, devc, + -1)) < 0) + { + return; + } + + if (i == 0) + firstdev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->mixer_dev = devc->mixer_dev; + audio_engines[adev]->rate_source = firstdev; + audio_engines[adev]->min_rate = 48000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + /*audio_engines[adev]->max_block = EMU_BUFSIZE / 2; *//* Never change this */ + audio_engines[adev]->fixed_rate = 48000; + audio_engines[adev]->binding = bindings[i]; + audio_engines[adev]->vmix_flags = VMIX_MULTIFRAG; + portc->audio_dev = adev; + portc->open_mode = 0; + portc->port_number = i; + portc->channels = 2; + portc->fmt = AFMT_S16_LE; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + +#ifdef USE_REMUX + if (firstdev >= 0) + { + if (emu10k1x_spdif_enable == 1) + { + sprintf (name, "%s 4.0 output", devc->card_name); + remux_install (name, devc->osdev, firstdev, firstdev + 1, -1, -1); + } + else + { + sprintf (name, "%s 5.1 output", devc->card_name); + remux_install (name, devc->osdev, firstdev, firstdev + 1, + firstdev + 2, -1); + } + } +#endif +} + +static void +select_out3_mode (emu10k1x_devc * devc, int mode) +{ + /* + * Set the out3/spdif combo jack format. + * mode0=analog rear/center, 1=spdif + */ + + if (mode == 0) + { + write_reg (devc, SPC, 0, 0x00000700); + write_reg (devc, EA_aux, 0, 0x0001000f); + } + else + { + write_reg (devc, SPC, 0, 0x00000000); + write_reg (devc, EA_aux, 0, 0x0000070f); + } +} + +int +oss_emu10k1x_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + unsigned int subvendor; + int err; + emu10k1x_devc *devc = NULL; + + DDB (cmn_err (CE_WARN, "Entered EMU10K1X probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != PCI_VENDOR_ID_CREATIVE || + device != PCI_DEVICE_ID_CREATIVE_EMU10K1X) + + return 0; + + pci_read_config_dword (osdev, 0x2c, &subvendor); + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + 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.\n"); + 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->card_name = "Sound Blaster Live (P16X)"; + devc->subvendor = subvendor; + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + devc->base &= ~0x3; + + devc->irq = pci_irq_line; + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + + oss_register_device (osdev, devc->card_name); + + if ((err = + oss_register_interrupts (devc->osdev, 0, emu10k1xintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + +/* + * Init mixer + */ + devc->mixer_dev = ac97_install (&devc->ac97devc, devc->card_name, + emu10k1x_ac97_read, emu10k1x_ac97_write, + devc, devc->osdev); + if (devc->mixer_dev < 0) + { + cmn_err (CE_WARN, "Mixer install failed - cannot continue\n"); + return 0; + } + + write_reg (devc, SCS0, 0, 0x02108504); + write_reg (devc, SCS1, 0, 0x02108504); + write_reg (devc, SCS2, 0, 0x02108504); + select_out3_mode (devc, emu10k1x_spdif_enable); + OUTL (devc->osdev, 0x00000000, devc->base + 0x18); /* GPIO */ + OUTL (devc->osdev, INTR_PCI | INTR_UART_RX, devc->base + 0x0c); + OUTL (devc->osdev, 0x00000009, devc->base + 0x14); /* Enable audio */ + install_audio_devices (devc); + attach_mpu (devc); + return 1; +} + +static void +unload_mpu (emu10k1x_devc * devc) +{ + if (devc->mpu_attached) + { + unload_emu10k1xuart (devc); + devc->mpu_attached = 0; + } +} + +int +oss_emu10k1x_detach (oss_device_t * osdev) +{ + emu10k1x_devc *devc = (emu10k1x_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + write_reg (devc, SA, 0, 0); + OUTL (devc->osdev, 0x00000000, devc->base + 0x0c); /* Interrupt disable */ + OUTL (devc->osdev, 0x00000001, devc->base + 0x14); + + unload_mpu (devc); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_emu10k1x/oss_emu10k1x.man b/kernel/drv/oss_emu10k1x/oss_emu10k1x.man new file mode 100644 index 0000000..f3bb3bc --- /dev/null +++ b/kernel/drv/oss_emu10k1x/oss_emu10k1x.man @@ -0,0 +1,27 @@ +NAME +oss_emu10k1x - Creative Labs P16x (EMU10K1X) driver. + +DESCRIPTION +Open Sound System driver for Creative Labs SBLive 5.1 Dell OEM version +soundcards. The device has a chipset called the EMU10K1X and is not the same +as the SBLive EMU10K1/EMU10K2 audio processors found in the SBLive! and Audigy +soundcards. + +EMU10K1X device characteristics: + o 8/16/24 bit playback/record + o mono/stereo/4/5.1 playback + o 8KHz to 192Khz sample rate. + +OPTIONS +o emu10k1x_spdif_enable=<0|1> +The EMU10K1X has a versa-jack (orange) that can be set as SPDIF output +or the Side-Surround left/right speakers in a 5.1 setup. +When set as SPDIF, you can get play PCM/AC3 audio to a Dolby(R) capable +receiver. + +FILES +CONFIGFILEPATH/oss_emu10k1x.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_envy24/.config b/kernel/drv/oss_envy24/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_envy24/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_envy24/.devices b/kernel/drv/oss_envy24/.devices new file mode 100644 index 0000000..cc44831 --- /dev/null +++ b/kernel/drv/oss_envy24/.devices @@ -0,0 +1,13 @@ +oss_envy24 pci1412,1712 Generic ENVY24 based device +oss_envy24 pcs1412,d630 M Audio Delta 1010 +oss_envy24 pcs1412,d631 M Audio Delta DiO 2496 +oss_envy24 pcs1412,d632 M Audio Delta 66 +oss_envy24 pcs1412,d633 M Audio Delta 44 +oss_envy24 pcs1412,d634 M Audio Audiophile 2496 +oss_envy24 pcs1412,d635 M Audio Delta TDIF +oss_envy24 pcs1412,d638 M Audio Delta 410 +oss_envy24 pcs1412,d63b M Audio Delta 1010LT +oss_envy24 pcs153b,1115 Terratec EWS88MT +oss_envy24 pcs153b,112b Terratec EWS88D +oss_envy24 pcs153b,1130 Terratec EWX 24/96 +oss_envy24 pcs153b,1138 Terratec DMX 6Fire diff --git a/kernel/drv/oss_envy24/.name b/kernel/drv/oss_envy24/.name new file mode 100644 index 0000000..d9991f3 --- /dev/null +++ b/kernel/drv/oss_envy24/.name @@ -0,0 +1 @@ +VIA Envy24 (ICE1712) sound chipset diff --git a/kernel/drv/oss_envy24/.params b/kernel/drv/oss_envy24/.params new file mode 100644 index 0000000..d98c9f8 --- /dev/null +++ b/kernel/drv/oss_envy24/.params @@ -0,0 +1,80 @@ +int envy24_skipdevs = 2; +/* + * envy24_skipdevs: By default OSS creates an audio device file for each + * stereo pair. However it's possible to change OSS to create a device file + * for each input/output channel. See also the envy24_force_mono option + * if you want to set the card to mono-only mode. + * Values: 1 to 8. Default is 2 (stereo mode). + * + * Note that the application(s) using the device files can request any number + * of channels regardless of the envy24_skipdevs option. + */ +int envy24_force_mono = 0; +/* + * envy24_force_mono: Forces all device files to work only in mono mode + * (to be used together with envy24_skipdevs=1). This option is necessary + * with some software packages that otherwise open the devices in stereo mode. + * There is no need to use this option with properly implemented applications. + * Values: 0 (default) any number of channels can be used, 1 means that + * the device files will only be available in mono mode. + * + * Note that even envy24_force_mono=1 the application can request and get + * stereo. In this way both channel signals will be identical. + */ +int envy24_swapdevs = 0; +/* + * envy24_swapdevs: By default OSS will create the output device files before + * the recording ones. Some applications may expect input devices to be before + * the output ones. + * Values: 0=outputs before inputs (default), 1=inputs before outputs. + */ +int envy24_devmask = 65535; +/* + * envy24_devmask: Selects the device files to be created. By default OSS + * will create all available device files. However in some systems it may + * be necessary to conserve device numbers. + * + * Values: The envy24_devmask number is the SUM of the following values: + * 1 - Create primary (analog/ADAT/TDIF) outputs + * 2 - Create primary (analog/ADAT/TDIF) inputs + * 4 - Create S/PDIF outputs + * 8 - Create S/PDIF inputs + * 16 - Create monitor input device + * 32 - Create the "raw" input and output devices. + * + * For example envy24_devmask=12 (4+8) creates only the S/PDIF devices. + * To enable all possible (current or future) device files set envy24_devmask + * to 65535 (default). + */ +int envy24_realencoder_hack = 0; +/* + * envy24_realencoder_hack: Older versions of realencoder expect a mixer device + * for each audio device file. This option makes OSS to create dummy micers to + * make realencoder happy. + * Values: 0=normal (default), 1=create dmmy mixers. + */ +int envy24_gain_sliders = 0; +/* + * envy24_gain_sliders: By default OSS will create the gain controls as + * selection controls (+4 dB / CONSUMER / -10 dB) which is ideal for + * professional environments. However home users may prefer having volume + * sliders instead. + * Values: 0=level selectors (default), 1=volume sliders. + */ +int envy24_nfrags = 16; +/* + * envy24_nfrags: For normal operation this setting must be 16. + */ +int envy24_mixerstyle = 1; +/* + * envy24_mixerstyle: Defines layout of the peak meter and monitor mixer + * sections in the control panel. + * NOTE! The envy24_skipdevs parameter must be set to 2. Otherwise the + * traditional mixer style will be used regardless of the value of + * this parameter. + * Possible values: + * 1=Traditional mixer with separate peak meter and monitor gain sections + * (default). + * 2=Alternative style with peak meters and monitor gain sliders grouped + * together (separate output and input sections). + */ diff --git a/kernel/drv/oss_envy24/envy24.h b/kernel/drv/oss_envy24/envy24.h new file mode 100644 index 0000000..dceac89 --- /dev/null +++ b/kernel/drv/oss_envy24/envy24.h @@ -0,0 +1,279 @@ +/* + * Purpose: Common definitions for the Envy24 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. + * + */ +#include "uart401.h" + +#define DEV_BUFSIZE (64*1024) /* Buffer size per channel */ + +#define HW_PLAYBUFFSIZE (10*2048) +#define HW_RECBUFFSIZE (12*2048) +#define HW_ALLOCSIZE (24*1024) /* Must be bigger or equal than HW_PLAYBUFFSIZE and HW_RECBUFFSIZE */ + +typedef struct envy24_auxdrv envy24_auxdrv_t; + +typedef struct +{ + unsigned int svid; + char *product; + int nr_outs, nr_ins; /* # of analog channels */ + int flags; +#define MF_MAUDIO 0x00000001 /* Made by M Audio */ +#define MF_MIDI1 0x00000002 /* Has MIDI 1 port */ +#define MF_SPDIF 0x00000004 /* Has S/PDIF */ +#define MF_AKMCODEC 0x00000008 /* Has AKM codecs */ +#define MF_WCLOCK 0x00000010 /* Has World clock input */ +#define MF_SPDSELECT 0x00000020 /* Optical+coax S/PDIF */ +#define MF_EWS88 0x00000040 /* Terratec EWS88MT */ +#define MF_AP 0x00000080 /* M Audio Audiophile family */ +#define MF_MIDI2 0x00000100 /* Has MIDI 2 port */ +#define MF_EWX2496 0x00000200 /* Terratec EWX 24/96 */ +#define MF_CONSUMER 0x00000400 /* Force consumer AC97 codec detection */ +#define MF_HOONTECH 0x00000800 +#define MF_D410 0x00001000 /* Delta 410 */ +#define MF_MEEPROM 0x00002000 /* M Audio EEPROM interface */ +#define MF_AC97 0x00004000 /* Consumer AC97 codec */ + envy24_auxdrv_t *auxdrv; + unsigned char *eeprom_data; +} +card_spec; + +#define ICENSEMBLE_VENDOR_ID 0x1412 +#define ICENSEMBLE_ENVY24_ID 0x1712 + +#define AKM_A 0x40 +#define AKM_B 0x80 + +#ifdef USE_LICENSING +extern int options_data; +#endif + +#define MAX_ODEV 10 +#define MAX_IDEV 12 + +#ifdef DO_RIAA +typedef struct +{ + int32_t x1, x2, x3; + int32_t y1, y2, y3; +} +riaa_t; +#endif + +typedef struct +{ + int flags; +#define PORTC_SPDOUT 0x00000001 +#define PORTC_SPDIN 0x00000002 + int dev; + int chnum; + int direction; +#define DIR_INPUT ADEV_NOOUTPUT +#define DIR_OUTPUT ADEV_NOINPUT + int open_mode; + + char name[16]; + + int bits, channels; + volatile int is_active; + volatile int trigger_bits; + int pcm_qlen; + int riaa_filter; +#ifdef DO_RIAA + riaa_t riaa_parms[12]; +#endif +} +envy24_portc; + +/* + * Hoontech specific structure + */ +typedef union +{ + struct + { + unsigned int box:2; + unsigned int darear:1; + unsigned int id0:2; + unsigned int clock0:1; + unsigned int res0:2; + + unsigned int ch1:1; + unsigned int ch2:1; + unsigned int ch3:1; + unsigned int id1:2; + unsigned int clock1:1; + unsigned int res1:2; + + unsigned int ch4:1; + unsigned int midiin:1; + unsigned int midi1:1; + unsigned int id2:2; + unsigned int clock2:1; + unsigned int res2:2; + + unsigned int midi2:1; + unsigned int mute:1; + unsigned int insel:1; + unsigned int id3:2; + unsigned int clock3:1; + unsigned int res3:2; + } + b; + + struct + { + unsigned int b0:8; + unsigned int b1:8; + unsigned int b2:8; + unsigned int b3:8; + } + w; + + unsigned int dwVal; + +} +ADSP; + +#define _adsp devc->adsp +/*****************/ + +typedef struct envy24d_portc +{ + int audio_dev; + int open_mode; + int channels; + int direction; + int trigger_bits; +} +envy24d_portc; + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + int mpu1_attached, mpu2_attached; + oss_native_word ccs_base, mt_base; + int irq; + card_spec *model_data; + envy24_auxdrv_t *auxdrv; + int skipdevs; /* envy24_skipdevs option */ + + unsigned char eeprom[32]; + +/* + * MT mixer + */ + + int mixer_dev; + +/* + * Consumer (AC97) mixer + */ + + ac97_devc ac97devc; + int consumer_mixer_dev; + int consumer_ac97_present; + + int nr_outdevs, nr_indevs; + int curr_outch, curr_inch; + int inportmask, outportmask; + envy24_portc play_portc[MAX_ODEV]; + envy24_portc rec_portc[MAX_IDEV]; + envy24d_portc direct_portc_in, direct_portc_out; + int direct_audio_opened; + + int rec_bufsize, play_bufsize; + + unsigned char *playbuf, *recbuf; + int playbuffsize, recbuffsize; + oss_native_word playbuf_phys, recbuf_phys; + oss_dma_handle_t playbuf_dma_handle, recbuf_dma_handle; + int hw_rfragsize, hw_pfragsize, hw_fragsamples, hw_nfrags; + volatile int hw_playfrag, hw_recfrag; + volatile int active_inputs, active_outputs; + volatile int open_inputs, open_outputs; + volatile int playback_started, recording_started; + volatile int playback_prepared, recording_prepared; + int speed, pending_speed_sel, speedbits; + int syncsource; + int gpio_tmp; +#define SYNC_INTERNAL 0 +#define SYNC_SPDIF 1 +#define SYNC_WCLOCK 2 + + int play_channel_mask, rec_channel_mask; + int nr_play_channels, nr_rec_channels; + int writeahead; + + int use_src; + int ratelock; + +/* Spdif parameters */ + int spdif_pro_mode; + unsigned char spdif_cbits[24]; + int sync_locked; + int ac3_mode; + + short akm_gains[0xff]; + ADSP adsp; /* Hoontech only */ + uart401_devc uart401devc1; + uart401_devc uart401devc2; + + int first_dev; +} +envy24_devc; + +struct envy24_auxdrv +{ + void (*card_init) (envy24_devc * devc); + int (*mixer_init) (envy24_devc * devc, int dev, int group); + void (*spdif_init) (envy24_devc * devc); + void (*spdif_set) (envy24_devc * devc, int ctrl0); + int (*spdif_ioctl) (envy24_devc * devc, int dev, unsigned int cmd, + ioctl_arg arg); + int (*spdif_read_reg) (envy24_devc * devc, int reg); + void (*spdif_write_reg) (envy24_devc * devc, int reg, int val); + void (*set_rate) (envy24_devc * devc); + int (*get_locked_status) (envy24_devc * devc); + int (*spdif_mixer_init) (envy24_devc * devc, int dev, int group); + void (*card_uninit) (envy24_devc * devc); +}; + +struct speed_sel +{ + int speed, speedbits; +}; + +/* extern struct speed_sel speed_tab[]; */ + +void envy24d_install (envy24_devc * devc); +void envy24d_playintr (envy24_devc * devc); +void envy24d_recintr (envy24_devc * devc); +void envy24_prepare_play_engine (envy24_devc * devc); +void envy24_launch_play_engine (envy24_devc * devc); +void envy24_stop_playback (envy24_devc * devc); +void envy24_start_recording (envy24_devc * devc); +void envy24_launch_recording (envy24_devc * devc); +void envy24_stop_recording (envy24_devc * devc); + +void envy24_write_cci (envy24_devc * devc, int pos, int data); +int envy24_read_cci (envy24_devc * devc, int pos); +extern int cs8427_spdif_ioctl (envy24_devc * devc, int dev, unsigned int cmd, + ioctl_arg arg); +extern void init_cs8427_spdif (envy24_devc * devc); +extern int cs8427_spdif_mixer_init (envy24_devc * devc, int dev, int group); +void WriteGPIObit (envy24_devc * devc, int sel, int what); +int ReadGPIObit (envy24_devc * devc, int sel); +void write_cs8427_spdif (envy24_devc * devc, int d); +extern void envy24_set_enum_mask (int dev, int ctl, oss_native_word mask); diff --git a/kernel/drv/oss_envy24/envy24_1010lt.c b/kernel/drv/oss_envy24/envy24_1010lt.c new file mode 100644 index 0000000..5d31891 --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_1010lt.c @@ -0,0 +1,582 @@ +/* + * Purpose: Card specific routines for M Audio Delta 1010LT + */ +/* + * + * 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_config.h" +#include <ac97.h> +#include "envy24.h" + +#define CH_STEREO 0x80 + +/* SPI chip select codes */ +#define CS8_CS 0x4 +#define CDC_CS 0x0 +#define NONE_CS 0x7 + +#define SPI_CLK 1 +#define SPI_DIN 2 +#define SPI_DOUT 3 +#define WCLOCK_ENABLE 7 + +#define CS8_ADDR 0x20 /* Chip SPI/I2C address */ +#define CS8_RD 0x01 +#define CS8_WR 0x00 + +#define BIT0 0x01 +#define BIT1 0x02 +#define BIT2 0x04 +#define BIT3 0x08 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +/* ----- DEFINITION OF GPIOs ----- */ + +#define FPGA_PROGRAM_L 7 /* FPGA program control select line (active low) */ +#define FPGA_CLK 1 /* FPGA program clock */ +#define EXT_REG_CLK 0 /* Was GPIO Fast mode (debug) */ +#define FPGA_D0 3 /* FPGA program data */ + +#define LATCH_EN_L 4 /* Strobe for external latch (active low) */ +#define FPGA_MUTE 5 + +#define FPGA_INIT_STATE 0xFC /* Init state for extern register to allow */ + /* FPGA initialization. */ + +#define FPGA_MASTER 5 + +extern int envy24_gain_sliders; +extern int envy24_virtualout; +extern int envy24_zerolatency; /* Testing in progress */ + +static void +SPI_select (envy24_devc * devc, int sel) +{ + int tmp; + + tmp = envy24_read_cci (devc, 0x20); + tmp &= ~0x70; + tmp |= (sel & 0x7) << 4; + envy24_write_cci (devc, 0x20, tmp); +} + +static void +write_d1010lt_codec (envy24_devc * devc, int sel, int bRegister, + unsigned char bData) +{ + int bMask; + + WriteGPIObit (devc, SPI_DOUT, 0); + WriteGPIObit (devc, SPI_CLK, 1); + + SPI_select (devc, sel); + oss_udelay (1); + bRegister = (bRegister & 0x0F) | 0xA0; /* Add I2C address field. */ + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + + /* Write the register address byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + + SPI_select (devc, NONE_CS); +} + +static void +d1010lt_card_init (envy24_devc * devc) +{ + int i; + + SPI_select (devc, NONE_CS); + + for (i = 0; i < 4; i++) + { + write_d1010lt_codec (devc, i, 0, 0x07); + write_d1010lt_codec (devc, i, 1, 0x03); + write_d1010lt_codec (devc, i, 2, 0x60); + write_d1010lt_codec (devc, i, 3, 0x19); + write_d1010lt_codec (devc, i, 4, 0x7f); + write_d1010lt_codec (devc, i, 5, 0x7f); + write_d1010lt_codec (devc, i, 6, 0x7f); + write_d1010lt_codec (devc, i, 7, 0x7f); + } + +} + +static int +envy24_set_d1010lt (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int codec, level; + static unsigned char levels[] = { 0x7f, 0x8c, 0x98 }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + codec = (ctrl & 0x7) / 2; + if (envy24_gain_sliders) + { + level = value & 0xff; + if (level < 0) + level = 0; + if (level > 144) + level = 144; + } + else + { + if (value < 0 || value > 2) + value = 0; + level = levels[value]; + } + + switch (ctrl & 0x89) /* IN/OUT, LEFT/RIGHT, Gang switches */ + { + case 0x00: /* Left output channel only */ + write_d1010lt_codec (devc, codec, 6, level); + break; + + case 0x01: /* Right output channel only */ + write_d1010lt_codec (devc, codec, 7, level); + break; + + case 0x80: /* Both output channels */ + write_d1010lt_codec (devc, codec, 6, level); + write_d1010lt_codec (devc, codec, 7, level); + break; + + case 0x08: /* Left input channel only */ + write_d1010lt_codec (devc, codec, 4, level); + break; + + case 0x09: /* Right input channel only */ + write_d1010lt_codec (devc, codec, 5, level); + break; + + case 0x88: /* Both input channels */ + write_d1010lt_codec (devc, codec, 4, level); + write_d1010lt_codec (devc, codec, 5, level); + break; + } + + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + + +static int +d1010lt_mix_init (envy24_devc * devc, int dev, int group) +{ + int i, mask = devc->outportmask, err, skip; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 144; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + if ((err = mixer_ext_create_control (dev, group, + i | CH_STEREO, + envy24_set_d1010lt, typ, tmp, + range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + if ((err = mixer_ext_create_control (dev, group, + i, envy24_set_d1010lt, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + if ((err = mixer_ext_create_control (dev, group, + (8 + i) | CH_STEREO, + envy24_set_d1010lt, typ, tmp, + range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDINL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDINR"); + else + sprintf (tmp, "ENVY24_IN%d", i + 1); + + if ((err = mixer_ext_create_control (dev, group, + 8 + i, envy24_set_d1010lt, + typ, + tmp, range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +static void +write_d1010lt_spdif_reg (envy24_devc * devc, int bRegister, int bData) +{ + unsigned char bMask; + unsigned char bSPI; + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + SPI_select (devc, CS8_CS); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR | CS8_WR; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + SPI_select (devc, NONE_CS); +} + +static int +read_d1010lt_spdif_reg (envy24_devc * devc, int reg) +{ + unsigned char bMask; + unsigned char bRet = 0; + unsigned char bSPI; + + + /****** WRITE MAP ADDRESS FIRST ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + SPI_select (devc, CS8_CS); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_WR; /* SPI address field plus WRITE operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & reg) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + /* De-assert chip select(s). */ + /* */ + SPI_select (devc, NONE_CS); + + + /****** NOW READ THE DATA ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + SPI_select (devc, CS8_CS); + + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_RD; /* SPI address field plus READ operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, SPI_DOUT, 1); + else + WriteGPIObit (devc, SPI_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + + /* Read the data byte. */ + /* */ + bRet = 0; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock low. */ + WriteGPIObit (devc, SPI_CLK, 0); + + /* Read current data bit. */ + if (ReadGPIObit (devc, SPI_DIN)) + bRet |= bMask; + + /* Raise clock. */ + WriteGPIObit (devc, SPI_CLK, 1); + } + + + /* De-assert chip selects. */ + /* */ + SPI_select (devc, NONE_CS); + + /* Return value. */ + + return bRet; +} + +static void +set_d1010lt_speed (envy24_devc * devc) +{ + int tmp; + + tmp = devc->speedbits; + + switch (devc->syncsource) + { + case SYNC_INTERNAL: + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + WriteGPIObit (devc, WCLOCK_ENABLE, 0); + write_d1010lt_spdif_reg (devc, 4, + read_d1010lt_spdif_reg (devc, 4) & (~BIT0)); + break; + + case SYNC_SPDIF: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + WriteGPIObit (devc, WCLOCK_ENABLE, 0); + write_d1010lt_spdif_reg (devc, 4, + read_d1010lt_spdif_reg (devc, 4) | BIT0); + break; + + case SYNC_WCLOCK: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + WriteGPIObit (devc, WCLOCK_ENABLE, 1); + write_d1010lt_spdif_reg (devc, 4, + read_d1010lt_spdif_reg (devc, 4) & (~BIT0)); + if (devc->model_data->svid == 0xd63014ff) + { + /* + * 1010 rev E only + * don't aks me why, but it seems to work + */ + WriteGPIObit (devc, 6, 0); + WriteGPIObit (devc, WCLOCK_ENABLE, 1); + } + break; + } +} + +static int +d1010lt_get_locked_status (envy24_devc * devc) +{ + /* TODO */ + return 1; +} + +envy24_auxdrv_t d1010lt_auxdrv = { + d1010lt_card_init, + d1010lt_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + cs8427_spdif_ioctl, + read_d1010lt_spdif_reg, + write_d1010lt_spdif_reg, + set_d1010lt_speed, + d1010lt_get_locked_status, + cs8427_spdif_mixer_init +}; diff --git a/kernel/drv/oss_envy24/envy24_6fire.c b/kernel/drv/oss_envy24/envy24_6fire.c new file mode 100644 index 0000000..469ceab --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_6fire.c @@ -0,0 +1,781 @@ +/* + * Purpose: Card specific routines for Terratec DMX6fire. + */ +/* + * + * 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_config.h" +#include "ac97.h" +#include "envy24.h" + +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +#define DEFAULT_FRONTBOX_SETUP 0xfd + +extern int envy24_gain_sliders; +extern int envy24_virtualout; + +#define EWX_DIG_ADDR 0x24 /* IIC address of digital traceiver chip of 6fire */ + +/*============================================================================= + Function : IIC_GetSDA +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned long dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static unsigned char +IIC_GetSDA (envy24_devc * devc) +{ + + unsigned char bReg, bSDA; + + /* FMB TEST: RW line */ + /* set write mask */ + bReg = ~(0x08); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* set RW line LOW */ + bReg = 0; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + /* Set direction: SDA to input and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= 0x20; /* SCL output = 1 */ + bReg &= ~0x10; /* SDA input = 0 */ + envy24_write_cci (devc, 0x22, bReg); + + /* Get SDA line state */ + bSDA = envy24_read_cci (devc, 0x20); + + + /* set RW line HIGH */ + bReg = 0x08; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + return 1; + /* return ((bSDA & 0x10) == 0x10); */ + +} + +/*============================================================================= + Function : IIC_SetIic +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> + : unsigned char fSDA -> + : unsigned char fSCL -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +IIC_SetIic (envy24_devc * devc, unsigned char fSDA, unsigned char fSCL) +{ + unsigned char bReg; + + /* Set direction: SDA and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= (0x20 | 0x10); /* 1 -> output */ + envy24_write_cci (devc, 0x22, bReg); + + /* set write mask */ + bReg = ~(0x20 | 0x10); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* Set line state */ + /* FMB TEST: RW line */ + bReg = 0x08; + if (fSDA) + bReg += 0x10; + if (fSCL) + bReg += 0x20; + envy24_write_cci (devc, 0x20, bReg); + +} + +/*============================================================================= + Function : IIC_Start +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ +static void +IIC_Start (envy24_devc * devc) +{ + /* falling edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, 1, 1); + oss_udelay (30); + IIC_SetIic (devc, 0, 1); +} + +/*============================================================================= + Function : IIC_Stop +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ + +static void +IIC_Stop (envy24_devc * devc) +{ + /* rising edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, 0, 1); + IIC_SetIic (devc, 1, 1); +} + + +/*============================================================================= + Function : IIC_SendByte +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned int dwPortAddr -> + : unsigned char bByte -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ +static unsigned char +IIC_SendByte (envy24_devc * devc, unsigned char bByte) +{ + unsigned char bDataBit, bAck; + int i; + + for (i = 7; i >= 0; i--) /* send byte (MSB first) */ + { + bDataBit = (bByte >> i) & 0x01; + + IIC_SetIic (devc, bDataBit, 0); + IIC_SetIic (devc, bDataBit, 1); + IIC_SetIic (devc, bDataBit, 0); + } /* end for i */ + + IIC_SetIic (devc, 1, 0); + + /* Get acknowledge */ + IIC_SetIic (devc, 1, 1); + bAck = IIC_GetSDA (devc); + /* FMB this is a start condition but never mind */ + IIC_SetIic (devc, 0, 0); +#if 0 + if (bAck) + cmn_err (CE_CONT, "SendByte failed %02x\n", bByte); + else + cmn_err (CE_CONT, "SendByte OK %02x\n", bByte); +#endif + return 1; + /* return (!bAck); *//* bAck = 0 --> success */ +} + +#if 0 +/*============================================================================= + Function : IIC_WriteByte +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned int dwPortAddr -> + : unsigned char bIicAddress -> + : unsigned char bByte -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static unsigned char +IIC_WriteByte (envy24_devc * devc, unsigned char bIicAddress, + unsigned char bByte) +{ + IIC_Start (devc); + + /* send IIC address and data byte */ + if (!IIC_SendByte (devc, bIicAddress)) + { + cmn_err (CE_CONT, "IIC_SendByte 1 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, bByte)) + { + cmn_err (CE_CONT, "IIC_SendByte 2 failed\n"); + goto FAILED; + } + + IIC_Stop (devc); + return 1; + +FAILED: + IIC_Stop (devc); + return 0; +} +#endif + +static unsigned char +IIC_WriteWord (envy24_devc * devc, unsigned char bIicAddress, + unsigned char reg, unsigned char bByte) +{ + IIC_Start (devc); + + /* send IIC address and data byte */ + if (!IIC_SendByte (devc, bIicAddress)) + { + cmn_err (CE_CONT, "IIC_SendByte 1 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, reg)) + { + cmn_err (CE_CONT, "IIC_SendByte 2 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, bByte)) + { + cmn_err (CE_CONT, "IIC_SendByte 3 failed\n"); + goto FAILED; + } + + IIC_Stop (devc); + return 1; + +FAILED: + IIC_Stop (devc); + return 0; +} + +static void +FrontboxControl (envy24_devc * devc, int b) +{ + IIC_WriteWord (devc, 0x40, 0x01, b); /* Output register */ + devc->gpio_tmp = b; +} + +static int +HW_AK4525_SetChipSelect (envy24_devc * devc, unsigned char bCsMask) +{ + unsigned char b; + /* check validity */ + if (bCsMask > 0x07) + { + cmn_err (CE_CONT, "Invalid bCsMask %02x\n", bCsMask); + return 0; /* invalid */ + } + + envy24_write_cci (devc, 0x21, 0x00); + envy24_write_cci (devc, 0x22, 0xff); + b = envy24_read_cci (devc, 0x20); + b &= ~0x07; + + b |= bCsMask & 0x07; + + envy24_write_cci (devc, 0x20, b); + + return 1; +} + +#define HW_AK4525_SetLines IIC_SetIic + +/*============================================================================= + FUNCTION: HW_AK4525_WriteRegister +------------------------------------------------------------------------------- + PURPOSE: + PARAMETERS: unsigned int port - port address for IIC port + unsigned char bCsMask - CoDec bitmask (bits 0..3) + or 0xFF for all codecs together + unsigned char bRegIdx - offset to desired register + unsigned char bReg - new register value + RETURNS: +------------------------------------------------------------------------------- + NOTES: The Chip Selects must have been set prior to this call + PCF8574_CODEC_IIC_ADDRESS + + +-----------------------------------------------------------------+ + | B15 B14 B13 B12 B11 B10 B09 B08|B07 B06 B05 B04 B03 B02 B01 B00 | + +--------+---+-------------------+--------------------------------+ + | C1 C0 |R/W|A4 A3 A2 A1 A0 |D7 D6 D5 D4 D3 D2 D1 D0 | + | 1 0 |1 | <= 7 | data | + +--------+---+-------------------+--------------------------------+ + +=============================================================================*/ +static unsigned char +HW_AK4525_WriteRegister (envy24_devc * devc, unsigned char bCsMask, + unsigned char bRegIdx, unsigned char bRegData) +{ + + unsigned short wCmd; + unsigned char i; + unsigned char fData; + + /* format buffer */ + wCmd = 0xA000 + /* chip address + R/W */ + (((unsigned short) bRegIdx) << 8) + /* register address */ + bRegData; + + HW_AK4525_SetLines (devc, 0, 0); + + /* start write cycle */ + if (!HW_AK4525_SetChipSelect (devc, bCsMask)) + { + cmn_err (CE_CONT, "HW_AK4525_SetChipSelect failed\n"); + return 0; /* = CS to LOW -> data latched */ + } + + + for (i = 0; i < 16; i++) + { + fData = (wCmd & 0x8000) ? 1 : 0; + HW_AK4525_SetLines (devc, fData, 0); + HW_AK4525_SetLines (devc, fData, 1); /* data is clocked in on rising edge of CCLK */ + HW_AK4525_SetLines (devc, fData, 0); + wCmd <<= 1; + } + + /* leave data line HIGH (= default for IIC) */ + HW_AK4525_SetLines (devc, fData, 0); /* data is clocked in on rising edge of CCLK */ + + /* end write cycle */ + if (!HW_AK4525_SetChipSelect (devc, 0x00)) + { + cmn_err (CE_CONT, "HW_AK4525_SetChipSelect 2 failed\n"); + return 0; /* = all CS to HIGH -> CS to default */ + } + + /* default */ + HW_AK4525_SetLines (devc, 1, 1); /* data is clocked in on rising edge of CCLK */ + + return 1; +} + + +/* Register offsets */ +enum +{ + AK4525_REG_POWER, + AK4525_REG_RESET, + AK4525_REG_FORMAT, + AK4525_REG_DEEMPHASIS, + AK4525_REG_LEFT_INPUT, + AK4525_REG_RIGHT_INPUT, + AK4525_REG_LEFT_OUTPUT, + AK4525_REG_RIGHT_OUTPUT +}; + + +/*============================================================================= + Function : HW_AK4525_Reset +------------------------------------------------------------------------------- + Description : + Returns : unsigned char + Parameters : PCUST_HW_INSTANCE_DATA devc - + int nCodecIdx -> 0..3 index of Codec ,-1 -> all +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static unsigned char +HW_AK4525_Reset (envy24_devc * devc, int nCodecIdx) +{ + unsigned char bCodecMask = 0; + if (nCodecIdx == -1) + bCodecMask = 0x07; + else + bCodecMask = 0x01 << (nCodecIdx); + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_RESET, 0x00)) /* DACs,ADCs -> reset */ + { + cmn_err (CE_CONT, "REG_RESET failed\n"); + return 0; + } + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_FORMAT, 0x60)) /* IIS, 256 fsn, normal speed */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_RESET, 0x03)) /* DACs,ADCs -> normal operation */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_POWER, 0x07)) /* power on */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* soft mute timeout --> short */ + AK4525_REG_DEEMPHASIS, 0x19)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_LEFT_INPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_RIGHT_INPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_LEFT_OUTPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_RIGHT_OUTPUT, 0x7f)) + return 0; + + return 1; +} + +static void +set_dmx6fire_speed (envy24_devc * devc) +{ + unsigned char tmp; + + tmp = devc->speedbits; + if (devc->syncsource != SYNC_INTERNAL) + { + tmp |= 0x10; /* S/PDIF input clock select */ + if (devc->model_data->flags & MF_WCLOCK) /* Has world clock too */ + { + int cmd = envy24_read_cci (devc, 0x20); + cmd |= 0x10; /* S/PDIF */ + if (devc->syncsource == SYNC_WCLOCK) + cmd &= ~0x10; /* World clock */ + envy24_write_cci (devc, 0x20, cmd); + } + } + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); +} + +#if 0 +/* + * S/PDIF register access doesn't work so this feature is not enabled. + */ + +#define EWX_CLK 0x20 +#define EWX_DTA 0x10 + +static void +dmx6fire_iic_write_byte (envy24_devc * devc, unsigned char data, + unsigned char save) +{ + int i; + unsigned char gpio; + + for (i = 0; i < 8; i++) + { + int fData = (data & 0x80) ? 1 : 0; + + gpio = 0x08; + if (fData) + gpio |= EWX_DTA; /* DATA */ + envy24_write_cci (devc, 0x20, gpio | save); + envy24_write_cci (devc, 0x20, gpio | EWX_CLK | save); /* Clock pulse */ + envy24_write_cci (devc, 0x20, gpio | save); + + data <<= 1; + } + + envy24_write_cci (devc, 0x20, EWX_DTA | save); + envy24_write_cci (devc, 0x20, EWX_DTA | EWX_CLK | save); /* Clock pulse (ACK) */ + envy24_write_cci (devc, 0x20, EWX_DTA | save); +} + +static unsigned char +dmx6fire_iic_read_byte (envy24_devc * devc, unsigned char save) +{ + int i; + unsigned char data = 0; + int b; + + PRT_STATUS (0x01); + save |= EWX_DTA; + envy24_write_cci (devc, 0x20, save); + oss_udelay (10); +#if 1 + save &= ~8; /* R/W bit */ + envy24_write_cci (devc, 0x22, ~EWX_DTA); /* GPIO direction */ + envy24_write_cci (devc, 0x21, EWX_DTA); /* GPIO write mask */ +#endif + + for (i = 0; i < 8; i++) + { + + envy24_write_cci (devc, 0x20, EWX_CLK | save); /* Clock pulse */ + b = envy24_read_cci (devc, 0x20); + if (b & EWX_DTA) + data |= 0x80; + envy24_write_cci (devc, 0x20, save); + + data >>= 1; + } + + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + envy24_write_cci (devc, 0x20, (save & ~EWX_DTA) | 0x08); /* Low for the ACK bit */ + envy24_write_cci (devc, 0x20, (save & ~EWX_DTA) | 0x08 | EWX_CLK); /* Clock for the ACK bit */ + envy24_write_cci (devc, 0x20, save | 0x08); + oss_udelay (10); + return data; +} + +#if 0 +static void +dmx6fire_iic_write (envy24_devc * devc, int addr, + unsigned char bRegIdx, unsigned char bRegData) +{ + unsigned char save; + + /* start write cycle */ + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + + save = (envy24_read_cci (devc, 0x20) & ~(EWX_CLK | EWX_DTA)) | 0x08 /* R/W bit */ + ; + /* Send start */ + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + envy24_write_cci (devc, 0x20, save); + + dmx6fire_iic_write_byte (devc, addr, save); + dmx6fire_iic_write_byte (devc, bRegIdx, save); + dmx6fire_iic_write_byte (devc, bRegData, save); + + /* Send stop */ + envy24_write_cci (devc, 0x20, save); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); +} +#endif + +static unsigned char +dmx6fire_iic_read (envy24_devc * devc, int addr, unsigned char bRegIdx) +{ + unsigned char save, data; + + /* dmx6fire_iic_write(devc, addr, bRegIdx, 0x55); */ + PRT_STATUS (0x80); + + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + + save = (envy24_read_cci (devc, 0x20) & ~(EWX_DTA | EWX_CLK)) | 0x08 /* R/W bit */ + ; + PRT_STATUS (0x02); + /* Send start */ + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + envy24_write_cci (devc, 0x20, save); + + dmx6fire_iic_write_byte (devc, addr | 0x01, save); + data = dmx6fire_iic_read_byte (devc, save); + + /* Send stop */ + envy24_write_cci (devc, 0x20, save); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + PRT_STATUS (0x00); + return data; +} + +static int +read_dmx6fire_spdif_reg (envy24_devc * devc, int bRegister) +/* +***************************************************************************** +* Reads a byte from a specific CS8427 register. +****************************************************************************/ +{ + + unsigned char ret; + ret = dmx6fire_iic_read (devc, EWX_DIG_ADDR, bRegister); + + return ret; +} + +static void +write_dmx6fire_spdif_reg (envy24_devc * devc, int bRegister, int bData) +{ + + /*dmx6fire_iic_write(devc, EWX_DIG_ADDR, bRegister, bData); */ + IIC_WriteWord (devc, EWX_DIG_ADDR, bRegister, bData); +} +#else +static int +read_dmx6fire_spdif_reg (envy24_devc * devc, int bRegister) +{ + return 0; +} + +static void +write_dmx6fire_spdif_reg (envy24_devc * devc, int bRegister, int bData) +{ +} +#endif + +static void +dmx6fire_card_init (envy24_devc * devc) +{ + envy24_write_cci (devc, 0x20, 0xff); + envy24_write_cci (devc, 0x21, 0x00); + envy24_write_cci (devc, 0x22, 0xff); + envy24_write_cci (devc, 0x20, 0xff); + HW_AK4525_SetChipSelect (devc, 0x00); +#if 1 + + IIC_WriteWord (devc, 0x40, 0x02, 0x00); /* Polarity register */ + IIC_WriteWord (devc, 0x40, 0x03, 0x00); /* Direction register */ + + FrontboxControl (devc, DEFAULT_FRONTBOX_SETUP); /* Set default values */ + + if (!HW_AK4525_Reset (devc, -1)) + cmn_err (CE_CONT, "Envy24: DMX6fire reset failed\n");; +#endif + +} + +static int +dmx6fire_mixer_set (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 1: + if (devc->skipdevs == 2) + return devc->rec_portc[2].riaa_filter; + else + return devc->rec_portc[4].riaa_filter; + break; + + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 1: + if (devc->skipdevs == 2) + return devc->rec_portc[2].riaa_filter = !!value; + else + return devc->rec_portc[4].riaa_filter = !!value; + break; + + } + + return OSS_EINVAL; +} + +static int +dmx6fire_mix_init (envy24_devc * devc, int dev, int group) +{ + int err; +#if 0 + int i, mask = devc->outportmask, skip, codec, ports; + int range = 3; + int typ = MIXT_ENUM; + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 164; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + char tmp[32]; + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_tdif, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_tdif, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } +#endif + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_6FIRE")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 1, dmx6fire_mixer_set, + MIXT_ONOFF, + "6FIRE_RIAA", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +envy24_auxdrv_t dmx6fire_auxdrv = { + dmx6fire_card_init, + dmx6fire_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + NULL, + read_dmx6fire_spdif_reg, + write_dmx6fire_spdif_reg, + set_dmx6fire_speed, + NULL, + cs8427_spdif_mixer_init +}; diff --git a/kernel/drv/oss_envy24/envy24_default.c b/kernel/drv/oss_envy24/envy24_default.c new file mode 100644 index 0000000..21baa45 --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_default.c @@ -0,0 +1,2384 @@ +/* + * Purpose: Card specific routines for several Envy24 based cards. + */ +/* + * + * 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_config.h" +#include "ac97.h" +#include "envy24.h" + +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +extern int envy24_gain_sliders; +extern int envy24_virtualout; +extern int envy24_zerolatency; /* Testing in progress */ + +#define EWX_DIG_ADDR 0x20 /* IIC address of digital traceiver chip of EWX2496 */ + +/* + * Playback engine management + */ + +static void +write_spdif (envy24_devc * devc, int d) +{ + int i, cmd; + + cmd = envy24_read_cci (devc, 0x20); + for (i = 7; i >= 0; i--) + { + cmd &= ~0x04; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); + if (d & (1 << i)) + cmd |= 0x08; + else + cmd &= ~0x08; + cmd |= 0x04; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); + } + cmd &= ~0x04; + envy24_write_cci (devc, 0x20, cmd); +} + +static void +write_codec (envy24_devc * devc, int codec, int addr, int data) +{ + unsigned char cmd; + int i; + int tmp; + cmd = envy24_read_cci (devc, 0x20); + cmd &= ~codec; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); + addr &= 0x07; + tmp = 0xa000 | (addr << 8) | data; + for (i = 15; i >= 0; i--) + { + cmd &= ~0x30; + if (tmp & (1 << i)) + cmd |= 0x10; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); + cmd |= 0x20; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); + } + cmd |= codec; + envy24_write_cci (devc, 0x20, cmd); + oss_udelay (1); +} + +#define CDC_CLK 1 /* Clock input to the CODEC's, rising edge clocks data. */ +#define CDC_DIN 2 /* Data input to Envy from the CODEC. */ +#define CDC_DOUT 3 /* Data output from Envy to the CODEC. */ +#define DIG_CS 4 /* Chip select (0=select) for the SPDIF tx/rx. */ +#define CDC_CS 5 /* Chip select (0=select) for the CODEC. */ +#define D410_MUTE 7 /* Delta 410 codec mute */ +#define CS_ASSERT 0 /* Asserted chip select (selects are inverted). */ +#define CS_RELEASE 1 /* Idle chip select (selects are inverted). */ + + +#define CS8_CLK CDC_CLK +#define CS8_DIN CDC_DIN +#define CS8_DOUT CDC_DOUT +#define CS8_CS DIG_CS +#define CS_1 CS_ASSERT +#define CS_0 CS_RELEASE +#define CS8_ADDR 0x20 /* Chip SPI/I2C address */ +#define CS8_RD 0x01 +#define CS8_WR 0x00 + +#define EWX_DIG_CS 0 +#define EWX_CDC_CLK 5 +#define EWX_CDC_DOUT 4 +#define EWX_CDC_DIN EWX_CDC_DOUT +#define EWX_IIC_WRITE 3 +#define CX_ASSERT 0 /* Asserted chip select (selects are inverted). */ +#define CX_RELEASE 1 /* Idle chip select (selects are inverted). */ + +void +WriteGPIObit (envy24_devc * devc, int sel, int what) +{ + unsigned char gpio; + + gpio = envy24_read_cci (devc, 0x20); + gpio &= ~(1 << sel); + gpio |= (what << sel); + envy24_write_cci (devc, 0x20, gpio); +} + +int +ReadGPIObit (envy24_devc * devc, int sel) +{ + unsigned char gpio; + + gpio = envy24_read_cci (devc, 0x20); + return !!(gpio & (1 << sel)); +} + +static void +write_ap_codec (envy24_devc * devc, int bRegister, unsigned char bData) +/* + +***************************************************************************** +* Writes a byte to a specific register of the Delta-AP CODEC. +* Register must be (0..15). +****************************************************************************/ +{ + unsigned char bMask; + + if (devc->model_data->flags & MF_D410) + bRegister = (bRegister & 0x0F) | 0x20; /* Add I2C address field. */ + else + bRegister = (bRegister & 0x0F) | 0xA0; /* Add I2C address field. */ + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + WriteGPIObit (devc, CDC_CS, CS_ASSERT); + WriteGPIObit (devc, DIG_CS, CS_RELEASE); + + /* Write the register address byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + WriteGPIObit (devc, CDC_CS, CS_RELEASE); +} +static int +read_ap_spdif_reg (envy24_devc * devc, int bRegister) +/* +***************************************************************************** +* Reads a byte from a specific CS8427 register. +****************************************************************************/ +{ + unsigned char bMask; + unsigned char bRet = 0; + unsigned char bSPI; + + /****** WRITE MAP ADDRESS FIRST ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + WriteGPIObit (devc, DIG_CS, CS_ASSERT); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_WR; /* SPI address field plus WRITE operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + /* De-assert chip select(s). */ + /* */ + WriteGPIObit (devc, DIG_CS, CS_RELEASE); + + + /****** NOW READ THE DATA ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + WriteGPIObit (devc, DIG_CS, CS_ASSERT); + + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_RD; /* SPI address field plus READ operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Read the data byte. */ + /* */ + bRet = 0; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Read current data bit. */ + if (ReadGPIObit (devc, CDC_DIN)) + bRet |= bMask; + + /* Raise clock. */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* De-assert chip selects. */ + /* */ + WriteGPIObit (devc, DIG_CS, CS_RELEASE); + + /* Return value. */ + + return bRet; +} + +static unsigned char +ewx2496_iic_read (envy24_devc * devc, int addr, unsigned char bRegIdx); + +static int +read_ewx2496_spdif_reg (envy24_devc * devc, int bRegister) +/* +***************************************************************************** +* Reads a byte from a specific CS8427 register. +****************************************************************************/ +{ + unsigned char ret; + + ret = ewx2496_iic_read (devc, EWX_DIG_ADDR, bRegister); + + return ret; +} + +#define read_cs8427_spdif_reg(d, r) devc->model_data->auxdrv->spdif_read_reg(d, r) + +static void +write_ap_spdif_reg (envy24_devc * devc, int bRegister, int bData) +/* +***************************************************************************** +* Writes a byte to a specific register of the Delta-AP S/PDIF chip. +* Register must be (0..55). +****************************************************************************/ +{ + unsigned char bMask; + unsigned char bSPI; + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + WriteGPIObit (devc, CDC_CS, CS_0); + WriteGPIObit (devc, CS8_CS, CS_1); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR | CS8_WR; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + WriteGPIObit (devc, CS8_CS, CS_0); +} + +static void +ewx2496_iic_write (envy24_devc * devc, int addr, + unsigned char bRegIdx, unsigned char bRegData); + +static void +write_ewx2496_spdif_reg (envy24_devc * devc, int bRegister, int bData) +{ + ewx2496_iic_write (devc, EWX_DIG_ADDR, bRegister, bData); + +} + +#define write_cs8427_spdif_reg(d, r, b) devc->model_data->auxdrv->spdif_write_reg(d, r, b) + +#define BIT0 0x01 +#define BIT1 0x02 +#define BIT2 0x04 +#define BIT3 0x08 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + +static void +lock_cs8427_spdif (envy24_devc * devc) +{ + write_cs8427_spdif_reg (devc, 18, read_cs8427_spdif_reg (devc, 18) & ~BIT5); + write_cs8427_spdif_reg (devc, 18, read_cs8427_spdif_reg (devc, 18) | BIT2); +} + +static void +unlock_cs8427_spdif (envy24_devc * devc) +{ + write_cs8427_spdif_reg (devc, 18, read_cs8427_spdif_reg (devc, 18) & ~BIT2); +} + +static unsigned char +bitswap (unsigned char bIn) +/* +***************************************************************************** +* Endian reversing routine. +****************************************************************************/ +{ + unsigned char bOut = 0; + unsigned char bImask = 0x01; + unsigned char bOmask = 0x80; + + while (bImask) + { + if (bIn & bImask) + bOut |= bOmask; + bImask = bImask << 1; + bOmask = (bOmask >> 1) & 0x7F; + } + + return bOut; +} + + +static unsigned char +ReadCsByte (envy24_devc * devc, unsigned char bByteNum) +/* +***************************************************************************** +* Reads a byte from Channel Status block buffer in CS8427. +* +* bByteNum is in the range (0..23) +* +* This routine assumes that CS8427 register 18 bit 5 is cleared so that the +* CS buffer is windowed, and that register 18 bit 2 is set so that CS output +* transfers are currently disabled. +****************************************************************************/ +{ + unsigned char bTemp; + + /* CS block window starts at reg #32... */ + bTemp = read_cs8427_spdif_reg (devc, bByteNum + 32); + + /* CS block access is reverse endian. */ + return bitswap (bTemp); +} + +static void +WriteCsByte (envy24_devc * devc, unsigned char bByteNum, unsigned char bData) +/* +***************************************************************************** +* Writes a byte to Channel Status block buffer in CS8427. +* +* bByteNum is in the range (0..23) +* +* This routine assumes that CS8427 register 18 bit 5 is cleared so that the +* CS buffer is windowed, and that register 18 bit 2 is set so that CS output +* transfers are currently disabled. +****************************************************************************/ +{ + /* CS block access is reverse endian. */ + bData = bitswap (bData); + + /* CS Window starts at reg #32... */ + write_cs8427_spdif_reg (devc, bByteNum + 32, bData); +} + +void +InitConsumerModeCS (envy24_devc * devc) +{ + int i; + + /* Set CS8427 registers 32-55 to window CS block, and disable CS output. */ + lock_cs8427_spdif (devc); + + /* Zero all the general CS bits. */ + /* */ + for (i = 0; i < 24; i++) + WriteCsByte (devc, i, 0x00); + /* */ + /* Consumer (usually SPDIF or AC3) mode static bit settings. */ + /* */ + WriteCsByte (devc, 0, 0x00); /* Consumer format (bit0 = 0). */ + WriteCsByte (devc, 1, 0x02); /* Category = PCM encoder/decoder. */ + + unlock_cs8427_spdif (devc); +} + +void +init_cs8427_spdif (envy24_devc * devc) +{ + int tmp; + + /* Select iunternal sync */ + write_cs8427_spdif_reg (devc, 4, read_cs8427_spdif_reg (devc, 4) & (~BIT0)); +/* +***************************************************************************** +* Initializes core (mainly static) registers of the CS8427. +* Returns 1 if initialization OK, otherwise 0. +****************************************************************************/ + /* Assumes Envy24 GPIO's have been initialized. They should be just fine */ + /* in the Windows driver as they are initialized from EEPROM info. */ + + /* Verify device ID register. Must be 0x71. */ + if ((tmp = read_cs8427_spdif_reg (devc, 127)) != 0x71 && tmp != 0) + { + cmn_err (CE_CONT, "Envy24: Unrecognized S/PDIF chip ID %02x\n", + read_cs8427_spdif_reg (devc, 127)); + cmn_err (CE_CONT, + " Hardware stalled. Please reboot and try again.\n"); + return; + } + + /* Turn off RUN bit while making changes to configuration. */ + write_cs8427_spdif_reg (devc, 4, read_cs8427_spdif_reg (devc, 4) & (~BIT6)); + + /* RMCK default function, set Validity, disable mutes, TCBL=output. */ + write_cs8427_spdif_reg (devc, 1, 0x01); /* validity* is BIT6. */ + + /* Hold last valid audio sample, RMCK=256*Fs, normal stereo operation. */ + write_cs8427_spdif_reg (devc, 2, 0x00); + /* Output drivers normal operation, Tx <== serial audio port, */ + /* Rx ==> serial audio port. */ + write_cs8427_spdif_reg (devc, 3, 0x0C); + + /* RUN off, OMCK=256xFs, output time base = OMCK, input time base = */ + /* recovered input clock, recovered input clock source is Envy24. */ + write_cs8427_spdif_reg (devc, 4, 0x00); + + /* Serial audio input port data format = I2S. */ + write_cs8427_spdif_reg (devc, 5, BIT2 | BIT0); /* SIDEL=1, SILRPOL=1. */ + + /* Serial audio output port data format = I2S. */ + write_cs8427_spdif_reg (devc, 6, BIT2 | BIT0); /* SODEL=1, SOLRPOL=1. */ + + /* Turn off CS8427 interrupt stuff that we don't implement in our hardware. */ + write_cs8427_spdif_reg (devc, 9, 0x00); + write_cs8427_spdif_reg (devc, 10, 0x00); + write_cs8427_spdif_reg (devc, 11, 0x00); + write_cs8427_spdif_reg (devc, 12, 0x00); + write_cs8427_spdif_reg (devc, 13, 0x00); + write_cs8427_spdif_reg (devc, 14, 0x00); + + /* Unmask the input PLL lock, V, confidence, biphase, parity status bits. */ + write_cs8427_spdif_reg (devc, 17, + (unsigned char) BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + + /* Registers 32-55 window to CS buffer. */ + /* Inhibit D->E transfers from overwriting first 5 bytes of CS data. */ + /* Inhibit D->E transfers (all) of CS data. */ + /* Allow E->F transfers of CS data. */ + /* One-byte mode: both A/B channels get same written CS data. */ + /* A channel info is output to chip's EMPH* pin. */ + /* */ + write_cs8427_spdif_reg (devc, 18, 0x18); + + /* Use internal buffer to transmit User (U) data. */ + /* Chip's U pin is an output. */ + /* Transmit all 0's for user data. */ + /* */ + write_cs8427_spdif_reg (devc, 19, 0x10); + + /* Turn on chip's RUN bit, rock and roll! */ + /* */ + write_cs8427_spdif_reg (devc, 4, read_cs8427_spdif_reg (devc, 4) | BIT6); + InitConsumerModeCS (devc); + +} + +#if 0 +static void +WriteCsField (envy24_devc * devc, unsigned char bByteNum, + unsigned short bMask, unsigned short bBits) +/* +***************************************************************************** +* Writes a specific field within the Channel Status block buffer. +* bByteNum is CS byte number to access (0..23). +* bMask is the field to be written (set bits define field). +* bBits is the value to write into that field. +* +* Assumes: Reg 18 Bit 5 is cleared so CS buffer is accessible. +* Reg 18 Bit 2 is set so E->F buffer transfer is stopped. +****************************************************************************/ +{ + /* Get current reg value. */ + unsigned char bTemp = ReadCsByte (devc, bByteNum); + + /* Clear field to be written. */ + bTemp &= ~(bMask); + + /* Set new values. */ + WriteCsByte (devc, bByteNum, (unsigned char) (bTemp | (bBits & bMask))); +} +#endif + +/*ARGSUSED*/ +void +write_cs8427_spdif (envy24_devc * devc, int d) +{ + int i; + + if (devc->syncsource == SYNC_INTERNAL) + { + write_cs8427_spdif_reg (devc, 4, + read_cs8427_spdif_reg (devc, 4) & ~BIT0); + } + else + { + write_cs8427_spdif_reg (devc, 4, + read_cs8427_spdif_reg (devc, 4) | BIT0); + } + + lock_cs8427_spdif (devc); + for (i = 0; i < 24; i++) + { + WriteCsByte (devc, i, devc->spdif_cbits[i]); + } + unlock_cs8427_spdif (devc); +} + +/* + * Terratec stuff + */ + +/*============================================================================= + Function : IIC_GetSDA +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned long dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*ARGSUSED*/ +static unsigned char +IIC_GetSDA (envy24_devc * devc, unsigned long dwPortAddr) +{ + + unsigned char bReg, bSDA; + + /* FMB TEST: RW line */ + /* set write mask */ + bReg = ~(0x08); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* set RW line LOW */ + bReg = 0; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + /* Set direction: SDA to input and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= 0x20; /* SCL output = 1 */ + bReg &= ~0x10; /* SDA input = 0 */ + envy24_write_cci (devc, 0x22, bReg); + + /* Get SDA line state */ + bSDA = envy24_read_cci (devc, 0x20); + + + /* set RW line HIGH */ + bReg = 0x08; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + return 1; + /* return ((bSDA & 0x10) == 0x10); */ + +} + +/*============================================================================= + Function : IIC_SetIic +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> + : unsigned char fSDA -> + : unsigned char fSCL -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*ARGSUSED*/ +static void +IIC_SetIic (envy24_devc * devc, unsigned int dwPortAddr, unsigned char fSDA, + unsigned char fSCL) +{ + unsigned char bReg; + + /* Set direction: SDA and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= (0x20 | 0x10); /* 1 -> output */ + envy24_write_cci (devc, 0x22, bReg); + + /* set write mask */ + bReg = ~(0x20 | 0x10); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* Set line state */ + /* FMB TEST: RW line */ + bReg = 0x08; +/* bReg = 0; */ + if (fSDA) + bReg += 0x10; + if (fSCL) + bReg += 0x20; + envy24_write_cci (devc, 0x20, bReg); + +} + +/*============================================================================= + Function : IIC_Start +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ +static void +IIC_Start (envy24_devc * devc, unsigned int dwPortAddr) +{ + /* falling edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, dwPortAddr, 1, 1); + IIC_SetIic (devc, dwPortAddr, 0, 1); +} + +/*============================================================================= + Function : IIC_Stop +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ + +static void +IIC_Stop (envy24_devc * devc, unsigned int dwPortAddr) +{ + /* rising edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, dwPortAddr, 0, 1); + IIC_SetIic (devc, dwPortAddr, 1, 1); +} + + +/*============================================================================= + Function : IIC_SendByte +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned int dwPortAddr -> + : unsigned char bByte -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ +static unsigned char +IIC_SendByte (envy24_devc * devc, unsigned int dwPortAddr, + unsigned char bByte) +{ + unsigned char bDataBit, bAck; + int i; + + for (i = 7; i >= 0; i--) /* send byte (MSB first) */ + { + bDataBit = (bByte >> i) & 0x01; + + IIC_SetIic (devc, dwPortAddr, bDataBit, 0); + IIC_SetIic (devc, dwPortAddr, bDataBit, 1); + } /* end for i */ + + IIC_SetIic (devc, dwPortAddr, 1, 0); + + /* Get acknowledge */ + IIC_SetIic (devc, dwPortAddr, 1, 1); + bAck = IIC_GetSDA (devc, dwPortAddr); + /* FMB this is a start condition but never mind */ + IIC_SetIic (devc, dwPortAddr, 0, 0); + return 1; + /* return (!bAck); *//* bAck = 0 --> success */ +} + +/*============================================================================= + Function : IIC_WriteByte +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned int dwPortAddr -> + : unsigned char bIicAddress -> + : unsigned char bByte -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static unsigned char +IIC_WriteByte (envy24_devc * devc, int dwPortAddr, unsigned char bIicAddress, + unsigned char bByte) +{ + IIC_Start (devc, dwPortAddr); + + /* send IIC address and data byte */ + if (!IIC_SendByte (devc, dwPortAddr, bIicAddress)) + { + cmn_err (CE_CONT, "IIC_SendByte 1 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, dwPortAddr, bByte)) + { + cmn_err (CE_CONT, "IIC_SendByte 2 failed\n"); + goto FAILED; + } + + IIC_Stop (devc, dwPortAddr); + return 1; + +FAILED: + IIC_Stop (devc, dwPortAddr); + return 0; +} + +/*============================================================================= + FUNCTION: HW_AK4525_SetChipSelect +------------------------------------------------------------------------------- + PURPOSE: + PARAMETERS: PDEVICE_EXTENSION pDevExt - contains the port address + and the OUT_SEL state + unsigned char bCsMask - AK4525 CS Mask: 1 means selected + RETURNS: int +------------------------------------------------------------------------------- + NOTES: - We use the fact that the parameter bCsMask has the same layout + as the IIC command byte we have to send to the PCF8574 + (wrong polarity, however) + - We also have to care that we don't change the output switch + setting. We remember the value in the Device Extension + - It is important that the CODECS are deselected (CS to HIGH) + after sue. Otherwise some IIC functions might accidentally + change our CODEC registers!!! +=============================================================================*/ +static unsigned char +HW_AK4525_SetChipSelect (envy24_devc * devc, unsigned char bCsMask) +{ + unsigned char bDataByte; + /* check validity */ + if (bCsMask > 0x0F) + { + cmn_err (CE_CONT, "Invalid bCsMask %02x\n", bCsMask); + return 0; /* invalid */ + } + + /* Format data byte */ + bDataByte = (~bCsMask) & 0x0F; + /* FMB PCF8574 HIGH means -10dbV, */ + /* OutputLevelSwitch is 1 for +4dbU */ + /* if (!pDevExt->Ews88mt.OutputLevelSwitch) */ + /* bDataByte += 0x40; */ + + /* Set Chip select to LOW for selected Codecs (via IIC) */ + if (!IIC_WriteByte (devc, devc->ccs_base, 0x48, bDataByte)) + { + cmn_err (CE_CONT, "IIC_WriteByte failed\n"); + return 0; + } + + return 1; +} + +#define HW_AK4525_SetLines IIC_SetIic + +/*============================================================================= + FUNCTION: HW_AK4525_WriteRegister +------------------------------------------------------------------------------- + PURPOSE: + PARAMETERS: unsigned int port - port address for IIC port + unsigned char bCsMask - CoDec bitmask (bits 0..3) + or 0xFF for all codecs together + unsigned char bRegIdx - offset to desired register + unsigned char bReg - new register value + RETURNS: +------------------------------------------------------------------------------- + NOTES: The Chip Selects must have been set prior to this call + PCF8574_CODEC_IIC_ADDRESS + + +-----------------------------------------------------------------+ + | B15 B14 B13 B12 B11 B10 B09 B08|B07 B06 B05 B04 B03 B02 B01 B00 | + +--------+---+-------------------+--------------------------------+ + | C1 C0 |R/W|A4 A3 A2 A1 A0 |D7 D6 D5 D4 D3 D2 D1 D0 | + | 1 0 |1 | <= 7 | data | + +--------+---+-------------------+--------------------------------+ + +=============================================================================*/ +static unsigned char +HW_AK4525_WriteRegister (envy24_devc * devc, unsigned char bCsMask, + unsigned char bRegIdx, unsigned char bRegData) +{ + + unsigned short wCmd; + unsigned char i; + unsigned int port = devc->ccs_base; + unsigned char fData; + + /* format buffer */ + wCmd = 0xA000 + /* chip address + R/W */ + (((unsigned short) bRegIdx) << 8) + /* register address */ + bRegData; + + /* start write cycle */ + if (!HW_AK4525_SetChipSelect (devc, bCsMask)) + { + cmn_err (CE_CONT, "HW_AK4525_SetChipSelect failed\n"); + return 0; /* = CS to LOW -> data latched */ + } + + + for (i = 0; i < 16; i++) + { + fData = (wCmd & 0x8000) ? 1 : 0; + HW_AK4525_SetLines (devc, port, fData, 0); + HW_AK4525_SetLines (devc, port, fData, 1); /* data is clocked in on rising edge of CCLK */ + wCmd <<= 1; + } + + /* leave data line HIGH (= default for IIC) */ + HW_AK4525_SetLines (devc, port, fData, 0); /* data is clocked in on rising edge of CCLK */ + + /* end write cycle */ + if (!HW_AK4525_SetChipSelect (devc, 0x00)) + { + cmn_err (CE_CONT, "HW_AK4525_SetChipSelect 2 failed\n"); + return 0; /* = all CS to HIGH -> CS to default */ + } + + /* default */ + HW_AK4525_SetLines (devc, port, 1, 1); /* data is clocked in on rising edge of CCLK */ + + return 1; +} + +#define EWX_CLK 0x20 +#define EWX_DTA 0x10 + +static void +ewx2496_iic_write_byte (envy24_devc * devc, unsigned char data, + unsigned char save) +{ + int i; + unsigned char gpio; + + for (i = 0; i < 8; i++) + { + int fData = (data & 0x80) ? 1 : 0; + + gpio = 0x08; + if (fData) + gpio |= EWX_DTA; /* DATA */ + envy24_write_cci (devc, 0x20, gpio | save); + envy24_write_cci (devc, 0x20, gpio | EWX_CLK | save); /* Clock pulse */ + envy24_write_cci (devc, 0x20, gpio | save); + + data <<= 1; + } + + envy24_write_cci (devc, 0x20, EWX_DTA | save); + oss_udelay (3); + envy24_write_cci (devc, 0x20, EWX_DTA | EWX_CLK | save); /* Clock pulse (ACK) */ + oss_udelay (1); + envy24_write_cci (devc, 0x20, EWX_DTA | save); + oss_udelay (1); +} + +static unsigned char +ewx2496_iic_read_byte (envy24_devc * devc, unsigned char save) +{ + int i; + unsigned char data = 0; + int b; + + PRT_STATUS (0x01); + save |= EWX_DTA; + envy24_write_cci (devc, 0x20, save); + oss_udelay (10); +#if 0 + save &= ~8; /* R/W bit */ + envy24_write_cci (devc, 0x22, ~EWX_DTA); /* GPIO direction */ + envy24_write_cci (devc, 0x21, EWX_DTA); /* GPIO write mask */ +#endif + + for (i = 0; i < 8; i++) + { + + envy24_write_cci (devc, 0x20, EWX_CLK | save); /* Clock pulse */ + b = envy24_read_cci (devc, 0x20); + if (b & EWX_DTA) + data |= 0x80; + envy24_write_cci (devc, 0x20, save); + + data >>= 1; + } + + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + envy24_write_cci (devc, 0x20, (save & ~EWX_DTA) | 0x08); /* Low for the ACK bit */ + envy24_write_cci (devc, 0x20, (save & ~EWX_DTA) | 0x08 | EWX_CLK); /* Clock for the ACK bit */ + envy24_write_cci (devc, 0x20, save | 0x08); + oss_udelay (10); + return data; +} + +static void +ewx2496_iic_write (envy24_devc * devc, int addr, + unsigned char bRegIdx, unsigned char bRegData) +{ + unsigned char save; + + /* start write cycle */ + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + + save = (envy24_read_cci (devc, 0x20) & ~(EWX_CLK | EWX_DTA)) | 0x08 /* R/W bit */ + ; + /* Send start */ + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save); + oss_udelay (1); + + ewx2496_iic_write_byte (devc, addr, save); + ewx2496_iic_write_byte (devc, bRegIdx, save); + ewx2496_iic_write_byte (devc, bRegData, save); + + /* Send stop */ + oss_udelay (1); + envy24_write_cci (devc, 0x20, save); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); +} + +static unsigned char +ewx2496_iic_read (envy24_devc * devc, int addr, unsigned char bRegIdx) +{ + unsigned char save, data; + + /* ewx2496_iic_write(devc, addr, bRegIdx, 0x55); */ + PRT_STATUS (0x80); + + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + + save = (envy24_read_cci (devc, 0x20) & ~(EWX_DTA | EWX_CLK)) | 0x08 /* R/W bit */ + ; + PRT_STATUS (0x02); + /* Send start */ + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save); + oss_udelay (1); + + ewx2496_iic_write_byte (devc, addr | 0x01, save); + oss_udelay (10); + data = ewx2496_iic_read_byte (devc, save); + + /* Send stop */ + oss_udelay (1); + envy24_write_cci (devc, 0x20, save); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK); + oss_udelay (1); + envy24_write_cci (devc, 0x20, save | EWX_CLK | EWX_DTA); + oss_udelay (1); + PRT_STATUS (0x00); + return data; +} + +static unsigned char +write_ewx2496_codec (envy24_devc * devc, + unsigned char bRegIdx, unsigned char bRegData) +{ + + unsigned short wCmd; + unsigned char i; + unsigned char fData; + unsigned char gpio, save; + + /* format buffer */ + wCmd = 0xA000 + /* chip address + R/W */ + (((unsigned short) bRegIdx) << 8) + /* register address */ + bRegData; + + /* start write cycle */ + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0x00); /* GPIO write mask */ + + save = envy24_read_cci (devc, 0x20) & ~0x39; + envy24_write_cci (devc, 0x20, save | 0x09); /* CS inactive */ + oss_udelay (200); + envy24_write_cci (devc, 0x20, 0x08); /* CS active */ + oss_udelay (200); + + gpio = 0x08; + + for (i = 0; i < 16; i++) + { + fData = (wCmd & 0x8000) ? 1 : 0; + + gpio = 0x08; + if (fData) + gpio |= 0x10; /* DATA */ + envy24_write_cci (devc, 0x20, gpio | save); + oss_udelay (20); + envy24_write_cci (devc, 0x20, gpio | 0x20 | save); /* Clock pulse */ + oss_udelay (200); + envy24_write_cci (devc, 0x20, gpio | save); + + wCmd <<= 1; + } + + oss_udelay (50); + envy24_write_cci (devc, 0x20, 0x01); /* CS inactive */ + oss_udelay (20); + + return 1; +} + +/* Register offsets */ +enum +{ + AK4525_REG_POWER, + AK4525_REG_RESET, + AK4525_REG_FORMAT, + AK4525_REG_DEEMPHASIS, + AK4525_REG_LEFT_INPUT, + AK4525_REG_RIGHT_INPUT, + AK4525_REG_LEFT_OUTPUT, + AK4525_REG_RIGHT_OUTPUT +}; + + +/*============================================================================= + Function : HW_AK4525_Reset +------------------------------------------------------------------------------- + Description : + Returns : unsigned char + Parameters : PCUST_HW_INSTANCE_DATA devc - + int nCodecIdx -> 0..3 index of Codec ,-1 -> all +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static unsigned char +HW_AK4525_Reset (envy24_devc * devc, int nCodecIdx) +{ + unsigned char bCodecMask = 0; + if (nCodecIdx == -1) + bCodecMask = 0x0F; + else + bCodecMask = 0x01 << (nCodecIdx); + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_RESET, 0x00)) /* DACs,ADCs -> reset */ + { + cmn_err (CE_CONT, "REG_RESET failed\n"); + return 0; + } + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_FORMAT, 0x60)) /* IIS, 256 fsn, normal speed */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_RESET, 0x03)) /* DACs,ADCs -> normal operation */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* 0x0F -> set mode for all codecs */ + AK4525_REG_POWER, 0x07)) /* power on */ + return 0; + + if (!HW_AK4525_WriteRegister (devc, bCodecMask, /* soft mute timeout --> short */ + AK4525_REG_DEEMPHASIS, 0x19)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_LEFT_INPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_RIGHT_INPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_LEFT_OUTPUT, 0x7f)) + return 0; + + if (!HW_AK4525_WriteRegister (devc, + bCodecMask, AK4525_REG_RIGHT_OUTPUT, 0x7f)) + return 0; + + return 1; +} + +unsigned char +ewx2496_AK4525_Reset (envy24_devc * devc, int nCodecIdx) +{ + unsigned char bCodecMask = 0; + if (nCodecIdx == -1) + bCodecMask = 0x0F; + else + bCodecMask = 0x01 << (nCodecIdx); + envy24_write_cci (devc, 0x20, 0x03); /* Default value */ + + if (!write_ewx2496_codec (devc, AK4525_REG_RESET, 0x00)) /* DACs,ADCs -> reset */ + { + cmn_err (CE_CONT, "REG_RESET failed\n"); + return 0; + } + + if (!write_ewx2496_codec (devc, AK4525_REG_FORMAT, 0x60)) /* IIS, 256 fsn, normal speed */ + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_RESET, 0x03)) /* DACs,ADCs -> normal operation */ + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_POWER, 0x07)) /* power on */ + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_DEEMPHASIS, 0x19)) + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_LEFT_INPUT, 0x7f)) + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_RIGHT_INPUT, 0x7f)) + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_LEFT_OUTPUT, 0x7f)) + return 0; + + if (!write_ewx2496_codec (devc, AK4525_REG_RIGHT_OUTPUT, 0x7f)) + return 0; + + return 1; +} + +static void +ews88_init_codecs (envy24_devc * devc) +{ + if (!HW_AK4525_Reset (devc, -1)) + cmn_err (CE_CONT, "Envy24: EWS88MT reset failed\n");; +} + +static void +ewx2496_init_codecs (envy24_devc * devc) +{ + if (!ewx2496_AK4525_Reset (devc, -1)) + cmn_err (CE_CONT, "Envy24: EWS88MT reset failed\n");; +} + +static int +envy24_set_akm (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int codec, level, i; + static unsigned char levels[] = { 0x7f, 0x8c, 0x98 }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = value & 0xff; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + codec = ctrl & 0xf0; + + for (i = 0; i < 4; i++) + { + if (!(ctrl & (1 << i))) + continue; + + write_codec (devc, codec, 4 + i, level); + } + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + +static int +envy24_set_ap (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int level; + static unsigned char levels[] = { 0x60, 0x6f, 0x7f }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = value & 0xff; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + write_ap_codec (devc, 4, level); + write_ap_codec (devc, 5, level); + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + +static int +envy24_set_d410 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int level, n; + static unsigned char levels[] = { 0x00, 0x00, 0x0c }; + + if (ctrl >= 8) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = 255 - value * 2; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + if (ctrl < 6) + n = ctrl + 2; + else + n = ctrl + 5; + write_ap_codec (devc, n, level); + if (devc->skipdevs == 2) + write_ap_codec (devc, n + 1, level); + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + +static unsigned char +write_ewx2496_codec (envy24_devc * devc, + unsigned char bRegIdx, unsigned char bRegData); + +static int +envy24_set_ewx2496 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int level; + static unsigned char levels[] = { 0x60, 0x6f, 0x7f }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = value & 0xff; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + write_ewx2496_codec (devc, 6, level); + write_ewx2496_codec (devc, 7, level); + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + +static unsigned char +HW_AK4525_WriteRegister (envy24_devc * devc, unsigned char bCsMask, + unsigned char bRegIdx, unsigned char bRegData); + +static int +envy24_set_ews88 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int codec, level, i; + static unsigned char levels[] = { 0x7f, 0x8c, 0x98 }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = value & 0xff; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + codec = ctrl & 0xf0; + + for (i = 0; i < 4; i++) + { + if (!(ctrl & (1 << i))) + continue; + + if (!HW_AK4525_WriteRegister (devc, codec >> 4, 4 + i, level)) + return OSS_EIO; + } + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +create_akm_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip, codec, ports; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 144; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_akm, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_akm, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x03; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_akm, + typ, + tmp, range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDINL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDINR"); + else + sprintf (tmp, "ENVY24_IN%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x02 : 0x01; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_akm, + typ, + tmp, range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_ap_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip, codec, ports; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 164; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_ap, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_ap, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_d410_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip; + int typ = MIXT_ENUM, range = 3; + int enum_mask = 0xffffff; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 127; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 127; + } + else + { + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 1; + enum_mask = 0x6; + } + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + if ((err = mixer_ext_create_control (dev, group, + i, envy24_set_d410, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + if ((err = mixer_ext_create_control (dev, group, + i, envy24_set_d410, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + envy24_set_enum_mask (dev, err, enum_mask); + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_ewx2496_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip, codec, ports; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 164; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ewx2496, typ, tmp, + range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ewx2496, typ, tmp, + range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_ews88_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip, codec, ports; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 164; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = 0x10 << (i / 2); + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ews88, typ, tmp, + range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = 0x10 << (i / 2); + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ews88, typ, tmp, + range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + codec = 0x10 << (i / 2); + ports = 0x03; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ews88, typ, tmp, + range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDINL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDINR"); + else + sprintf (tmp, "ENVY24_IN%d", i + 1); + + codec = 0x10 << (i / 2); + ports = (i & 1) ? 0x02 : 0x01; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, + envy24_set_ews88, typ, tmp, + range, + MIXF_RECVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +/* + * Hoontech DSP24 family + */ + + +typedef union +{ + struct + { + unsigned int data:5; + unsigned int clock:1; + unsigned int res0:2; + } + b; + + unsigned int dwVal; +} +CLBYTE; + +#define HOONTECH_CLOCK 0x20 + +static void +hoontech_write_gpio (envy24_devc * devc, unsigned char data) +{ + envy24_write_cci (devc, 0x22, 0xff); /* GPIO direction */ + envy24_write_cci (devc, 0x21, 0xc0); /* GPIO write mask */ + + envy24_write_cci (devc, 0x20, data | HOONTECH_CLOCK); /* GPIO data */ + envy24_write_cci (devc, 0x20, data & ~HOONTECH_CLOCK); /* GPIO data */ + envy24_write_cci (devc, 0x20, data | HOONTECH_CLOCK); /* GPIO data */ +} + +static void +hoontech_init (envy24_devc * devc) +{ + devc->adsp.b.box = 0; + devc->adsp.b.darear = 0; + devc->adsp.b.id0 = 0; + devc->adsp.b.clock0 = 1; + devc->adsp.b.res0 = 0x0; + + devc->adsp.b.ch1 = 0x01; + devc->adsp.b.ch2 = 0x01; + devc->adsp.b.ch3 = 0x01; + devc->adsp.b.id1 = 1; + devc->adsp.b.clock1 = 1; + devc->adsp.b.res1 = 0x0; + + devc->adsp.b.ch4 = 0x01; + devc->adsp.b.midiin = 0x01; + devc->adsp.b.midi1 = 0x0; + devc->adsp.b.id2 = 2; + devc->adsp.b.clock2 = 1; + devc->adsp.b.res2 = 0x0; + + devc->adsp.b.midi2 = 0x0; + devc->adsp.b.mute = 0x0; + devc->adsp.b.insel = 0x1; + devc->adsp.b.id3 = 3; + devc->adsp.b.clock3 = 1; + devc->adsp.b.res3 = 0x0; + + hoontech_write_gpio (devc, devc->adsp.w.b0); + hoontech_write_gpio (devc, devc->adsp.w.b1); + hoontech_write_gpio (devc, devc->adsp.w.b2); + hoontech_write_gpio (devc, devc->adsp.w.b3); +} + +/**************************************************/ + +static void +default_card_init (envy24_devc * devc) +{ + + if (devc->model_data->flags & MF_AKMCODEC) + { + write_codec (devc, AKM_A | AKM_B, 0, 0x07); + write_codec (devc, AKM_A | AKM_B, 1, 0x03); + write_codec (devc, AKM_A | AKM_B, 2, 0x60); + write_codec (devc, AKM_A | AKM_B, 3, 0x19); + write_codec (devc, AKM_A | AKM_B, 4, 0x7f); + write_codec (devc, AKM_A | AKM_B, 5, 0x7f); + write_codec (devc, AKM_A | AKM_B, 6, 0x7f); + write_codec (devc, AKM_A | AKM_B, 7, 0x7f); + } + + if (devc->model_data->flags & MF_AP) + { /* Init the AK4528 codec of Audiophile 2496 */ + write_ap_codec (devc, 0, 0x07); + write_ap_codec (devc, 1, 0x00); + write_ap_codec (devc, 2, 0x60); + write_ap_codec (devc, 3, 0x0d); + write_ap_codec (devc, 4, 0x7f); + write_ap_codec (devc, 1, 0x03); + write_ap_codec (devc, 5, 0x7f); + } + + if (devc->model_data->flags & MF_D410) + { /* Init the AK4529 codec of Delta 410 */ + OUTB (devc->osdev, + INB (devc->osdev, devc->mt_base + 0x02) & ~0x04, + devc->mt_base + 0x02); + + write_ap_codec (devc, 0x00, 0x0c); + write_ap_codec (devc, 0x01, 0x02); + write_ap_codec (devc, 0x02, 0x00); + write_ap_codec (devc, 0x03, 0x00); + write_ap_codec (devc, 0x04, 0x00); + write_ap_codec (devc, 0x05, 0x00); + write_ap_codec (devc, 0x06, 0x00); + write_ap_codec (devc, 0x07, 0x00); + write_ap_codec (devc, 0x0b, 0x00); + write_ap_codec (devc, 0x0c, 0x00); + write_ap_codec (devc, 0x08, 0x15); + write_ap_codec (devc, 0x0a, 0x3f); + } + + if (devc->model_data->flags & MF_EWS88) + ews88_init_codecs (devc); + + if (devc->model_data->flags & MF_EWX2496) + ewx2496_init_codecs (devc); + + if (devc->model_data->flags & MF_HOONTECH) + hoontech_init (devc); +} + +static int +default_mix_init (envy24_devc * devc, int dev, int group) +{ + int err; + + if (devc->model_data->flags & MF_AKMCODEC) + { + if ((err = create_akm_mixer (dev, devc, group)) < 0) + return err; + } + else if (devc->model_data->flags & MF_AP) + { + if ((err = create_ap_mixer (dev, devc, group)) < 0) + return err; + } + else if (devc->model_data->flags & MF_D410) + { + if ((err = create_d410_mixer (dev, devc, group)) < 0) + return err; + } + else if (devc->model_data->flags & MF_EWS88) + { + if ((err = create_ews88_mixer (dev, devc, group)) < 0) + return err; + } + else if (devc->model_data->flags & MF_EWX2496) + { + if ((err = create_ewx2496_mixer (dev, devc, group)) < 0) + return err; + } + return 0; +} + +/*ARGSUSED*/ +int +cs8427_spdif_ioctl (envy24_devc * devc, int dev, unsigned int cmd, + ioctl_arg arg) +{ + oss_digital_control *ctrl = (oss_digital_control *) arg; + + if (arg == NULL) + return OSS_EINVAL; + + switch (cmd) + { + case SNDCTL_DSP_READCTL: + { + int i, rq; + unsigned char status; + + rq = ctrl->valid; + memset (ctrl, 0, sizeof (*ctrl)); + + ctrl->caps = DIG_CBITIN_FULL | DIG_CBITOUT_FULL; + + if (rq & VAL_CBITIN) + { + for (i = 0; i < 24; i++) + ctrl->cbitin[i] = ReadCsByte (devc, i); + ctrl->valid |= VAL_CBITIN; + } + + if (rq & VAL_CBITOUT) + { + for (i = 0; i < 24; i++) + ctrl->cbitin[i] = devc->spdif_cbits[i]; + ctrl->valid |= VAL_CBITOUT; + } + + + if (rq & VAL_ISTATUS) + { + ctrl->valid |= VAL_ISTATUS; + status = read_cs8427_spdif_reg (devc, 15); + if (status & 0x04) + ctrl->in_data = IND_DATA; + else + ctrl->in_data = IND_AUDIO; + + status = read_cs8427_spdif_reg (devc, 16); + if (status & 0x40) + ctrl->in_errors |= INERR_QCODE_CRC; + if (status & 0x20) + ctrl->in_errors |= INERR_CRC; + + if (status & 0x10) + ctrl->in_locked = LOCK_UNLOCKED; + else + ctrl->in_locked = LOCK_LOCKED; + + if (status & 0x08) + ctrl->in_vbit = VBIT_ON; + else + ctrl->in_vbit = VBIT_OFF; + + if (status & 0x04) + ctrl->in_quality = IN_QUAL_POOR; + else + ctrl->in_quality = IN_QUAL_GOOD; + + if (status & 0x02) + ctrl->in_errors |= INERR_BIPHASE; + + if (status & 0x01) + ctrl->in_errors |= INERR_PARITY; + +#if 1 + /* TODO: Better handling required */ + write_cs8427_spdif_reg (devc, 18, 0x00); +#endif + } + } + return 0; + break; + + case SNDCTL_DSP_WRITECTL: + { + int i, rq; + + rq = ctrl->valid; + memset (ctrl, 0, sizeof (*ctrl)); + + ctrl->caps = DIG_CBITOUT_FULL; + + if (rq & VAL_CBITOUT) + { + for (i = 0; i < 24; i++) + devc->spdif_cbits[i] = ctrl->cbitout[i]; + ctrl->valid |= VAL_CBITOUT; + + lock_cs8427_spdif (devc); + for (i = 0; i < 24; i++) + { + WriteCsByte (devc, i, devc->spdif_cbits[i]); + } + unlock_cs8427_spdif (devc); + } + } + return 0; + break; + + default:; + } + return OSS_EINVAL; +} + +static int +set_spdif_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + switch (ctrl) + { + case 1: + return devc->spdif_pro_mode; + break; + } + + return OSS_EIO; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: + return devc->spdif_pro_mode = !!value; + break; + } + + return OSS_EIO; + } + + return OSS_EIO; +} + +/*ARGSUSED*/ +int +cs8427_spdif_mixer_init (envy24_devc * devc, int dev, int group) +{ + int err; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_SPDIF")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 1, set_spdif_control, + MIXT_ENUM, + "SPDIF_MODE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +static void +set_ap_speed (envy24_devc * devc) +{ + unsigned char gpio, tmp; + + tmp = devc->speedbits; + if (devc->syncsource != SYNC_INTERNAL) + { + tmp |= 0x10; /* S/PDIF input clock select */ + if (devc->model_data->flags & MF_WCLOCK) /* Has world clock too */ + { + int cmd = envy24_read_cci (devc, 0x20); + cmd |= 0x10; /* S/PDIF */ + if (devc->syncsource == SYNC_WCLOCK) + cmd &= ~0x10; /* World clock */ + envy24_write_cci (devc, 0x20, cmd); + } + } + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + + if (devc->speed > 48000) + { + write_ap_codec (devc, 0x01, 0x00); + gpio = envy24_read_cci (devc, 0x20); + gpio |= 0x01; /* Turn DFS ON */ + envy24_write_cci (devc, 0x20, gpio); + write_ap_codec (devc, 0x02, 0x65); + write_ap_codec (devc, 0x01, 0x03); + } + else + { + write_ap_codec (devc, 0x01, 0x00); + gpio = envy24_read_cci (devc, 0x20); + gpio &= ~0x01; /* Turn DFS OFF */ + envy24_write_cci (devc, 0x20, gpio); + write_ap_codec (devc, 0x02, 0x60); + write_ap_codec (devc, 0x01, 0x03); + } +} + +envy24_auxdrv_t default_auxdrv = { + default_card_init, + default_mix_init, + NULL, + write_spdif +}; + +envy24_auxdrv_t ap2496_auxdrv = { + default_card_init, + default_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + cs8427_spdif_ioctl, + read_ap_spdif_reg, + write_ap_spdif_reg, + set_ap_speed, + NULL, + cs8427_spdif_mixer_init +}; + +envy24_auxdrv_t d410_auxdrv = { + default_card_init, + default_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + cs8427_spdif_ioctl, + read_ap_spdif_reg, + write_ap_spdif_reg, + NULL, + NULL, + cs8427_spdif_mixer_init +}; + +envy24_auxdrv_t ewx2496_auxdrv = { + default_card_init, + default_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + NULL, + read_ewx2496_spdif_reg, + write_ewx2496_spdif_reg, + NULL, + NULL, + cs8427_spdif_mixer_init +}; diff --git a/kernel/drv/oss_envy24/envy24_direct.c b/kernel/drv/oss_envy24/envy24_direct.c new file mode 100644 index 0000000..9448c6c --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_direct.c @@ -0,0 +1,415 @@ +/* + * Purpose: Direct 24 bit multich driver for Envy24. + * + * This driver implements the all inputs and all outputs audio devices for + * envy24. Unlike the ordinary driver this one doesn't use additional buffering. + */ +/* + * + * 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_config.h" +#include "ac97.h" + +#ifdef USE_LICENSING +#include "private/licensing/licensing.h" +#endif + +#include "envy24.h" + +#define OUTCH_NAMES "CH1/2 CH3/4 CH5/6 CH7/8 digital" +#define INCH_NAMES "CH1/2 CH3/4 CH5/6 CH7/8 digital monitor_mix" + +/* + * Audio routines + */ +extern int envy24_audio_set_rate (int dev, int arg); +int envy24d_get_buffer_pointer (int dev, dmap_t * dmap, int direction); + +void +envy24d_playintr (envy24_devc * devc) +{ + oss_audio_outputintr (devc->direct_portc_out.audio_dev, 0); +} + +void +envy24d_recintr (envy24_devc * devc) +{ + oss_audio_inputintr (devc->direct_portc_in.audio_dev, 0); +} + +/*ARGSUSED*/ +static short +envy24d_audio_set_channels (int dev, short arg) +{ + envy24d_portc *portc = audio_engines[dev]->portc; + return portc->channels; +} + +/*ARGSUSED*/ +static unsigned int +envy24d_audio_set_format (int dev, unsigned int arg) +{ + return AFMT_S32_LE; +} + +/*ARGSUSED*/ +static int +envy24d_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void envy24d_audio_trigger (int dev, int state); + +static void +envy24d_audio_reset (int dev) +{ + envy24d_audio_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +envy24d_audio_open (int dev, int mode, int open_flags) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24d_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + if (!(mode & portc->direction)) + return OSS_EINVAL; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode != 0 || (devc->direct_audio_opened & mode)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + if (mode == OPEN_WRITE && (devc->play_channel_mask != 0)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + if (mode == OPEN_READ && (devc->rec_channel_mask != 0)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + devc->direct_audio_opened |= mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +envy24d_audio_close (int dev, int mode) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24d_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + devc->direct_audio_opened &= ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +envy24d_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ +} + +/*ARGSUSED*/ +static void +envy24d_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ +} + +static void +envy24d_audio_trigger (int dev, int state) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24d_portc *portc = audio_engines[dev]->portc; + int changed; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + changed = state ^ portc->trigger_bits; + + if (portc->direction == OPEN_WRITE && (changed & PCM_ENABLE_OUTPUT)) + { + if (state & PCM_ENABLE_OUTPUT) + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24d: Trigger start output"); +#endif + portc->trigger_bits = state; + envy24_launch_play_engine (devc); + } + else + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24d: Trigger stop output"); +#endif + portc->trigger_bits = state; + envy24_stop_playback (devc); + } + } + + if (portc->direction == OPEN_READ && (changed & PCM_ENABLE_INPUT)) + { + if (state & PCM_ENABLE_INPUT) + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24d: Trigger start input"); +#endif + portc->trigger_bits = state; + envy24_launch_recording (devc); + } + else + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24d: Trigger stop input"); +#endif + portc->trigger_bits = state; + envy24_stop_recording (devc); + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +envy24d_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24_start_recording (devc); + return 0; +} + +/*ARGSUSED*/ +static int +envy24d_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + envy24_devc *devc = audio_engines[dev]->devc; + + envy24_prepare_play_engine (devc); + return 0; +} + +static int +envy24d_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + envy24_devc *devc = audio_engines[dev]->devc; + + if (direction == OPEN_WRITE) + { + if (devc->playbuf == NULL) + { + cmn_err (CE_CONT, "Envy24: No playback DMA buffer available\n"); + return OSS_ENOSPC; + } + + dmap->dmabuf = devc->playbuf; + dmap->buffsize = devc->playbuffsize; + dmap->dmabuf_phys = devc->playbuf_phys; + return 0; + } + + if (direction == OPEN_READ) + { + if (devc->recbuf == NULL) + { + cmn_err (CE_CONT, "Envy24: No recording DMA buffer available\n"); + return OSS_ENOSPC; + } + + dmap->dmabuf = devc->recbuf; + dmap->buffsize = devc->recbuffsize; + dmap->dmabuf_phys = devc->recbuf_phys; + return 0; + } + + return OSS_EIO; +} + +/*ARGSUSED*/ +static int +envy24d_free_buffer (int dev, dmap_t * dmap, int direction) +{ + dmap->dmabuf = NULL; + dmap->dmabuf_phys = 0; + dmap->buffsize = 0; + return 0; +} + +int +envy24d_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + + envy24_devc *devc = audio_engines[dev]->devc; + int pos; + + if (direction == PCM_ENABLE_OUTPUT) + { + pos = INW (devc->osdev, devc->mt_base + 0x14); + pos = (pos + 1) * 4; + pos = dmap->bytes_in_use - pos; + + return pos; + } + + if (direction == PCM_ENABLE_INPUT) + { + pos = INW (devc->osdev, devc->mt_base + 0x24); + pos = (pos + 1) * 4; + pos = dmap->bytes_in_use - pos; + + return pos; + } + + return OSS_EIO; +} + +/*ARGSUSED*/ +static int +envy24d_check_input (int dev) +{ + cmn_err (CE_WARN, "Envy24d: Input timed out.\n"); + return OSS_EIO; +} + +/*ARGSUSED*/ +static int +envy24d_check_output (int dev) +{ + cmn_err (CE_WARN, "Envy24d: Output timed out (%d)\n", GET_JIFFIES ()); + return OSS_EIO; +} + +static const audiodrv_t envy24d_audio_driver = { + envy24d_audio_open, + envy24d_audio_close, + envy24d_audio_output_block, + envy24d_audio_start_input, + envy24d_audio_ioctl, + envy24d_audio_prepare_for_input, + envy24d_audio_prepare_for_output, + envy24d_audio_reset, + NULL, + NULL, + NULL, + NULL, + envy24d_audio_trigger, + envy24_audio_set_rate, + envy24d_audio_set_format, + envy24d_audio_set_channels, + NULL, + NULL, + envy24d_check_input, + envy24d_check_output, + envy24d_alloc_buffer, + envy24d_free_buffer, + NULL, + NULL, + envy24d_get_buffer_pointer +}; + +void +envy24d_install (envy24_devc * devc) +{ + + int adev, out_dev, in_dev; + char tmpname[128]; + envy24d_portc *portc; + + /* + * Output device + */ + sprintf (tmpname, "%s (all outputs)", devc->model_data->product); + + if ((out_dev = adev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmpname, + &envy24d_audio_driver, + sizeof (audiodrv_t), + ADEV_NOVIRTUAL | ADEV_NOINPUT | ADEV_COLD + | ADEV_SPECIAL | ADEV_32BITONLY, + AFMT_S32_LE, devc, -1, + "10ch_out")) >= 0) + { + portc = &devc->direct_portc_out; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = devc->first_dev; + audio_engines[adev]->caps |= DSP_CH_MULTI; + audio_engines[adev]->min_channels = 10; + audio_engines[adev]->max_channels = 10; + audio_engines[adev]->outch_names = OUTCH_NAMES; + audio_engines[adev]->min_block = devc->hw_pfragsize; + audio_engines[adev]->max_block = devc->hw_pfragsize; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 96000; + + audio_engines[adev]->mixer_dev = devc->mixer_dev; + devc->direct_audio_opened = 0; + portc->open_mode = 0; + portc->audio_dev = adev; + portc->channels = 10; + portc->direction = OPEN_WRITE; + audio_engines[adev]->port_number = 0; /* First output channel */ + } + + /* + * Input device + */ + sprintf (tmpname, "%s (all inputs)", devc->model_data->product); + + if ((adev = in_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmpname, + &envy24d_audio_driver, + sizeof (audiodrv_t), + ADEV_NOVIRTUAL | ADEV_NOOUTPUT | ADEV_COLD + | ADEV_SPECIAL | ADEV_32BITONLY, + AFMT_S32_LE, devc, -1, + "12ch_in")) >= 0) + { + portc = &devc->direct_portc_in; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = devc->first_dev; + audio_engines[adev]->caps |= DSP_CH_MULTI; + audio_engines[adev]->min_channels = 12; + audio_engines[adev]->max_channels = 12; + audio_engines[adev]->inch_names = INCH_NAMES; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 96000; + + audio_engines[adev]->mixer_dev = devc->mixer_dev; + devc->direct_audio_opened = 0; + portc->open_mode = 0; + portc->audio_dev = adev; + audio_engines[adev]->min_block = devc->hw_pfragsize; + audio_engines[adev]->max_block = devc->hw_pfragsize; + portc->channels = 12; + portc->direction = OPEN_READ; + audio_engines[adev]->port_number = 10; /* First input channel */ + } +} diff --git a/kernel/drv/oss_envy24/envy24_ews88d.c b/kernel/drv/oss_envy24/envy24_ews88d.c new file mode 100644 index 0000000..c68be60 --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_ews88d.c @@ -0,0 +1,377 @@ +/* + * Purpose: Card specific routines for Terratec EWS88D. + */ +/* + * + * 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_config.h" +#include "ac97.h" +#include "envy24.h" + +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +/* PCF8575 pin assignment (default 0xffff) */ +#define PCF_SPDIN_SELECT 0x0001 /* 0=optical 1=coax */ +#define PCF_OPTOUT 0x0002 /* 0=SPDIF 1=ADAT */ +#define PCF_CLOCKSRC 0x0004 /* 0=ADAT 1=SPDIF */ +#define PCF_ADATEN 0x0008 /* 0=ADAT disabled 1=ADAT enabled */ +#define PCF_ADATLOOP_ 0x0010 /* 0=ADAT in->out loop, 1=no loop */ +#define PCF_CS8414_ERF_ 0x0020 /* Inverted CS8414 ERF */ +#define PCF_SPDIF_ERR 0x0040 /* OR'ed from CS8414 E0..E2 */ +#define PCF_ADAT_ERROR 0x0080 /* ADAT error input */ + +extern int envy24_gain_sliders; +extern int envy24_virtualout; +extern int envy24_zerolatency; /* Testing in progress */ +/* + * Terratec stuff + */ + +/*============================================================================= + Function : IIC_GetSDA +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned long dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static __inline__ unsigned char +IIC_GetSDA (envy24_devc * devc, unsigned long dwPortAddr) +{ + + unsigned char bReg, bSDA; + + /* FMB TEST: RW line */ + /* set write mask */ + bReg = ~(0x08); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* set RW line LOW */ + bReg = 0; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + /* Set direction: SDA to input and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= 0x20; /* SCL output = 1 */ + bReg &= ~0x10; /* SDA input = 0 */ + envy24_write_cci (devc, 0x22, bReg); + + /* Get SDA line state */ + bSDA = envy24_read_cci (devc, 0x20); + + /* set RW line HIGH */ + bReg = 0x08; /* writeable */ + envy24_write_cci (devc, 0x20, bReg); + + return 1; + /* return ((bSDA & 0x10) == 0x10); */ + +} + +/*============================================================================= + Function : IIC_SetIic +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> + : unsigned char fSDA -> + : unsigned char fSCL -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static __inline__ void +IIC_SetIic (envy24_devc * devc, unsigned int dwPortAddr, unsigned char fSDA, + unsigned char fSCL) +{ + unsigned char bReg; + + /* Set direction: SDA and SCL to output */ + bReg = envy24_read_cci (devc, 0x22); + bReg |= (0x20 | 0x10); /* 1 -> output */ + envy24_write_cci (devc, 0x22, bReg); + + /* set write mask */ + bReg = ~(0x20 | 0x10); /* writeable */ + envy24_write_cci (devc, 0x21, bReg); + + /* Set line state */ + /* FMB TEST: RW line */ + bReg = 0x08; +/* bReg = 0; */ + if (fSDA) + bReg += 0x10; + if (fSCL) + bReg += 0x20; + envy24_write_cci (devc, 0x20, bReg); + +} + +/*============================================================================= + Function : IIC_Start +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static __inline__ void +IIC_Start (envy24_devc * devc, unsigned int dwPortAddr) +{ + /* falling edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, dwPortAddr, 1, 1); + IIC_SetIic (devc, dwPortAddr, 0, 1); +} + +/*============================================================================= + Function : IIC_Stop +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : unsigned int dwPortAddr -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static __inline__ void +IIC_Stop (envy24_devc * devc, unsigned int dwPortAddr) +{ + /* rising edge of SDA while SCL is HIGH */ + IIC_SetIic (devc, dwPortAddr, 0, 1); + IIC_SetIic (devc, dwPortAddr, 1, 1); +} + + +/*============================================================================= + Function : IIC_SendByte +------------------------------------------------------------------------------- + Description : + Returns : unsigned char -> + Parameters : unsigned int dwPortAddr -> + : unsigned char bByte -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +/*__inline */ +static unsigned char +IIC_SendByte (envy24_devc * devc, unsigned int dwPortAddr, + unsigned char bByte) +{ + unsigned char bDataBit, bAck; + int i; + + for (i = 7; i >= 0; i--) /* send byte (MSB first) */ + { + bDataBit = (bByte >> i) & 0x01; + + IIC_SetIic (devc, dwPortAddr, bDataBit, 0); + IIC_SetIic (devc, dwPortAddr, bDataBit, 1); + } /* end for i */ + + IIC_SetIic (devc, dwPortAddr, 1, 0); + + /* Get acknowledge */ + IIC_SetIic (devc, dwPortAddr, 1, 1); + bAck = IIC_GetSDA (devc, dwPortAddr); + /* FMB this is a start condition but never mind */ + IIC_SetIic (devc, dwPortAddr, 0, 0); + return 1; + /* return (!bAck); *//* bAck = 0 --> success */ +} + +static unsigned char +IIC_WriteWord (envy24_devc * devc, int dwPortAddr, unsigned char bIicAddress, + unsigned short bByte) +{ + IIC_Start (devc, dwPortAddr); + + /* send IIC address and data byte */ + if (!IIC_SendByte (devc, dwPortAddr, bIicAddress)) + { + cmn_err (CE_CONT, "IIC_SendByte 1 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, dwPortAddr, bByte & 0xff)) + { + cmn_err (CE_CONT, "IIC_SendByte 3 failed\n"); + goto FAILED; + } + if (!IIC_SendByte (devc, dwPortAddr, (bByte >> 8) & 0xff)) + { + cmn_err (CE_CONT, "IIC_SendByte 2 failed\n"); + goto FAILED; + } + + IIC_Stop (devc, dwPortAddr); + return 1; + +FAILED: + IIC_Stop (devc, dwPortAddr); + return 0; +} + +static void +ews88d_set_pcf8575 (envy24_devc * devc, unsigned short d) +{ + if (!IIC_WriteWord (devc, devc->ccs_base, 0x40, d)) + { + cmn_err (CE_CONT, "IIC_WriteWord failed\n"); + } + devc->gpio_tmp = d; +} + +static void +ews88d_card_init (envy24_devc * devc) +{ + ews88d_set_pcf8575 (devc, 0xffff); +} + +static void +set_ews88d_speed (envy24_devc * devc) +{ + int tmp; + + tmp = devc->speedbits; + + switch (devc->syncsource) + { + case SYNC_INTERNAL: + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + break; + + case SYNC_SPDIF: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + devc->gpio_tmp &= ~PCF_CLOCKSRC; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + break; + + case SYNC_WCLOCK: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + devc->gpio_tmp |= PCF_CLOCKSRC; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + break; + } + + if (devc->speed > 48000) + { + devc->gpio_tmp &= ~PCF_ADATEN; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + } + else + { + devc->gpio_tmp |= PCF_ADATEN; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + } +} + +static int +ews88d_mixer_set (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 1: + return !!(devc->gpio_tmp & PCF_SPDIN_SELECT); + break; + + case 2: + return !!(devc->gpio_tmp & PCF_OPTOUT); + break; + + case 3: + return !(devc->gpio_tmp & PCF_ADATLOOP_); + break; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 1: + devc->gpio_tmp &= ~PCF_SPDIN_SELECT; + if (value) + devc->gpio_tmp |= PCF_SPDIN_SELECT; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + return !!(devc->gpio_tmp & PCF_SPDIN_SELECT); + break; + + case 2: + devc->gpio_tmp &= ~PCF_OPTOUT; + if (value) + devc->gpio_tmp |= PCF_OPTOUT; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + return !!(devc->gpio_tmp & PCF_OPTOUT); + break; + + case 3: + devc->gpio_tmp &= ~PCF_ADATLOOP_; + if (!value) + devc->gpio_tmp |= PCF_ADATLOOP_; + ews88d_set_pcf8575 (devc, devc->gpio_tmp); + return !(devc->gpio_tmp & PCF_ADATLOOP_); + break; + } + + return OSS_EINVAL; +} + +static int +ews88d_mix_init (envy24_devc * devc, int dev, int group) +{ + int err; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_EWS88D")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 1, ews88d_mixer_set, + MIXT_ENUM, + "EWS88D_SPDIN", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, ews88d_mixer_set, + MIXT_ENUM, + "EWS88D_OPTOUT", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, ews88d_mixer_set, + MIXT_ONOFF, + "EWS88D_ADATLOOP", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +envy24_auxdrv_t ews88d_auxdrv = { + ews88d_card_init, + ews88d_mix_init, + NULL, + NULL, + NULL, + NULL, + NULL, + set_ews88d_speed, + NULL, + cs8427_spdif_mixer_init +}; diff --git a/kernel/drv/oss_envy24/envy24_tdif.c b/kernel/drv/oss_envy24/envy24_tdif.c new file mode 100644 index 0000000..4f247fd --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_tdif.c @@ -0,0 +1,687 @@ +/* + * Purpose: Card specific routines for M Audio Delta TDIF + */ +/* + * + * 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_config.h" +#include "ac97.h" +#include "envy24.h" +#include "envy24_tdif.h" + +#define CDC_CLK 1 /* Clock input to the CODEC's, rising edge clocks data. */ +#define CDC_DIN 2 /* Data input to Envy from the CODEC. */ +#define CDC_DOUT 3 /* Data output from Envy to the CODEC. */ +#define CS8_CS 2 /* Chip select (0=select) for the SPDIF tx/rx. */ +#define CDC_CS 3 /* Chip select (0=select) for the CODEC. */ +#define CS_ASSERT 0 /* Asserted chip select (selects are inverted). */ +#define CS_RELEASE 1 /* Idle chip select (selects are inverted). */ + + +#define BIT0 0x01 +#define BIT1 0x02 +#define BIT2 0x04 +#define BIT3 0x08 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + +#define CS8_CLK CDC_CLK +#define CS8_DIN CDC_DIN +#define CS8_DOUT CDC_DOUT +#define CS_TRUE CS_ASSERT +#define CS_FALSE CS_RELEASE +#define CS8_ADDR 0x20 /* Chip SPI/I2C address */ +#define CS8_RD 0x01 +#define CS8_WR 0x00 + +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +/* ----- DEFINITION OF GPIOs ----- */ + +#define FPGA_PROGRAM_L 7 /* FPGA program control select line (active low) */ +#define FPGA_CLK 1 /* FPGA program clock */ +#define EXT_REG_CLK 0 /* Was GPIO Fast mode (debug) */ +#define FPGA_D0 3 /* FPGA program data */ + +#define LATCH_EN_L 4 /* Strobe for external latch (active low) */ +#define FPGA_MUTE 5 + +#define FPGA_INIT_STATE 0xFC /* Init state for extern register to allow */ + /* FPGA initialization. */ + +#define FPGA_MASTER 5 + +extern int envy24_gain_sliders; +extern int envy24_virtualout; +extern int envy24_zerolatency; /* Testing in progress */ + +static void +WriteExternReg (envy24_devc * devc, unsigned char bData) +/* Initialize external register by serially shifting the data out */ +/* and then strobe the external latch. */ +{ + int i; + + devc->gpio_tmp = bData; + + WriteGPIObit (devc, LATCH_EN_L, 0); /* DISABLE External Latch */ + + /* FPGA clock to low */ + WriteGPIObit (devc, EXT_REG_CLK, 0); + + for (i = 0; i < 8; i++) + { + /* Present data */ + WriteGPIObit (devc, FPGA_D0, !!(bData & 0x80)); + /* clock data in */ + WriteGPIObit (devc, EXT_REG_CLK, 1); + WriteGPIObit (devc, EXT_REG_CLK, 0); + /* next bit */ + bData = bData << 1; + } + + WriteGPIObit (devc, LATCH_EN_L, 1); /* STROBE External Latch */ + WriteGPIObit (devc, LATCH_EN_L, 0); /* DISABLE External Latch */ +} + +static void +WriteExternRegBit (envy24_devc * devc, int bit, int value) +{ + devc->gpio_tmp &= ~(1 << bit); + if (value) + devc->gpio_tmp |= (1 << bit); + WriteExternReg (devc, devc->gpio_tmp); +} + +static void +tdif_pause (int n) +/* +***************************************************************************** +* Programmable pause. +****************************************************************************/ +{ + static int d; + int i; + + for (i = 0; i < n; i++) + for (d = 1000L; d--;); +} + +/****************************************************************************/ + + +static void +TDIF_InitFPGA (envy24_devc * devc) +/* +***************************************************************************** +* Initialize FPGA +* wInst = PCI slot code of specific board. +* Hardware = Spartan II FPGA (XC2S50-5TQ144) +****************************************************************************/ +{ + int bReadByte; + int i, j; + +#if 0 + if (envy24_read_cci (devc, 0x20) & 0x40) + { + DDB (cmn_err (CE_CONT, "envy24: FPGA is already up and running\n")); + return; + } +#endif + + cmn_err (CE_CONT, "Envy24: Loading FPGA - please wait\n"); + + /*Init external register */ + WriteGPIObit (devc, FPGA_PROGRAM_L, 1); /*DISABLE FPGA Programming */ + WriteGPIObit (devc, LATCH_EN_L, 0); /*DISABLE External Latch */ + + bReadByte = FPGA_INIT_STATE; + + WriteExternReg (devc, bReadByte); + + /*Pull PROGRAM# pin LOW to start loading configuration data */ + WriteGPIObit (devc, FPGA_PROGRAM_L, 0); + tdif_pause (10); + WriteGPIObit (devc, FPGA_PROGRAM_L, 1); + + for (j = 0; j < sizeof (fpga_code); j++) + { + bReadByte = fpga_code[j]; + for (i = 0; i < 8; i++) + { + /*FPGA clock to low */ + WriteGPIObit (devc, FPGA_CLK, 0); + /*Present data */ + WriteGPIObit (devc, FPGA_D0, !!(bReadByte & 0x80)); + /*clock data in */ + WriteGPIObit (devc, FPGA_CLK, 1); + + /*next bit */ + bReadByte = bReadByte << 1; + } + + } + + /*Some clocks to start FPGA */ + for (i = 0; i < 64; i++) + { + /*FPGA clock to low */ + WriteGPIObit (devc, FPGA_CLK, 0); + /*clock data in */ + WriteGPIObit (devc, FPGA_CLK, 1); + } + + if (!(envy24_read_cci (devc, 0x20) & 0x40)) + cmn_err (CE_CONT, "Envy24: FPGA failed to initialize\n"); + else + DDB (cmn_err (CE_CONT, "FPGA is up and running\n")); + + oss_udelay (10); + WriteExternRegBit (devc, FPGA_MUTE, 1); /* Keep it still muted */ + +} + +static void +write_tdif_codec (envy24_devc * devc, int bRegister, unsigned char bData) +/* + +***************************************************************************** +* Writes a byte to a specific register of the Delta-AP CODEC. +* Register must be (0..15). +****************************************************************************/ +{ + unsigned char bMask; + + bRegister = (bRegister & 0x0F) | 0xA0; /* Add I2C address field. */ + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + WriteExternRegBit (devc, CDC_CS, CS_TRUE); + + /* Write the register address byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + WriteExternRegBit (devc, CDC_CS, CS_FALSE); +} + +static void write_tdif_spdif_reg (envy24_devc * devc, int bRegister, + int bData); +static int read_tdif_spdif_reg (envy24_devc * devc, int bRegister); + +static void +tdif_card_init (envy24_devc * devc) +{ + WriteExternReg (devc, 0xfc); + TDIF_InitFPGA (devc); + write_tdif_spdif_reg (devc, 4, read_tdif_spdif_reg (devc, 4) & (~BIT0)); + WriteGPIObit (devc, FPGA_MASTER, 1); + WriteExternRegBit (devc, 4, 1); /* Disable TDIF master PLL */ + WriteExternRegBit (devc, 6, 0); /* Don't route PLL master clock to Envy24. */ + + write_tdif_codec (devc, 0, 0x07); + write_tdif_codec (devc, 1, 0x00); + write_tdif_codec (devc, 2, 0x60); + write_tdif_codec (devc, 3, 0x0d); + write_tdif_codec (devc, 4, 0x7f); + write_tdif_codec (devc, 1, 0x03); + write_tdif_codec (devc, 5, 0x7f); +} + +static void +tdif_card_uninit (envy24_devc * devc) +{ + WriteGPIObit (devc, FPGA_PROGRAM_L, 1); /*DISABLE FPGA Programming */ + WriteGPIObit (devc, LATCH_EN_L, 0); /*DISABLE External Latch */ + WriteGPIObit (devc, FPGA_PROGRAM_L, 0); +} + +static int +envy24_set_tdif (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int level; + static unsigned char levels[] = { 0x60, 0x6f, 0x7f }; + + if (ctrl >= 0xff) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + if (envy24_gain_sliders) + return devc->akm_gains[ctrl]; + return devc->akm_gains[ctrl]; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + + if (envy24_gain_sliders) + level = value & 0xff; + else + { + if (value > 2) + return OSS_EINVAL; + level = levels[value]; + } + + write_tdif_codec (devc, 4, level); + write_tdif_codec (devc, 5, level); + return devc->akm_gains[ctrl] = value; + } + return OSS_EINVAL; +} + + +static int +tdif_mix_init (envy24_devc * devc, int dev, int group) +{ + int i, mask = devc->outportmask, err, skip, codec, ports; + int typ = MIXT_ENUM, range = 3; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_GAIN")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + if (envy24_gain_sliders) + { + typ = MIXT_MONOSLIDER; + range = 164; + + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0x7f; + } + else + for (i = 0; i < 0xff; i++) + devc->akm_gains[i] = 0; + + for (i = 0; i < 8; i += skip) + { + + if (!(mask & (1 << i))) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = 0x0c; /* Both output ports */ + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_tdif, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + + codec = (i > 1) ? AKM_B : AKM_A; + ports = (i & 1) ? 0x08 : 0x04; + if ((err = mixer_ext_create_control (dev, group, + codec | ports, envy24_set_tdif, + typ, + tmp, range, + MIXF_MAINVOL | + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + } + } + + return 0; +} + +static void +set_tdif_speed (envy24_devc * devc) +{ + int tmp; + + WriteExternRegBit (devc, FPGA_MUTE, 1); /* Mute FPGA */ + /* Set the TDIF sampling rate */ + devc->gpio_tmp &= ~0x03; + switch (devc->speed) + { + case 32000: + devc->gpio_tmp |= 0x01; + break; + case 44100: + devc->gpio_tmp |= 0x02; + break; + case 48000: + devc->gpio_tmp |= 0x01; + break; + default: + devc->gpio_tmp |= 0x01; + break; + } + WriteExternReg (devc, devc->gpio_tmp); + + tmp = devc->speedbits; + + switch (devc->syncsource) + { + case SYNC_INTERNAL: + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + WriteGPIObit (devc, FPGA_MASTER, 1); + write_tdif_spdif_reg (devc, 4, read_tdif_spdif_reg (devc, 4) & (~BIT0)); + WriteExternRegBit (devc, 4, 1); /* Disable TDIF master PLL */ + WriteExternRegBit (devc, 6, 0); /* Don't route PLL master clock to Envy24. */ + break; + + case SYNC_SPDIF: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + WriteGPIObit (devc, FPGA_MASTER, 1); + write_tdif_spdif_reg (devc, 4, read_tdif_spdif_reg (devc, 4) | BIT0); + WriteExternRegBit (devc, 6, 1); /* Do route PLL master clock to Envy24. */ + WriteExternRegBit (devc, 4, 1); /* Disable TDIF master PLL */ + break; + + case SYNC_WCLOCK: + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + write_tdif_spdif_reg (devc, 4, read_tdif_spdif_reg (devc, 4) & (~BIT0)); + WriteExternRegBit (devc, 4, 0); /* Enable TDIF master PLL */ + WriteExternRegBit (devc, 6, 1); /* Do route PLL master clock to Envy24. */ + WriteGPIObit (devc, FPGA_MASTER, 0); + break; + } + + if (devc->speed > 48000) + { + write_tdif_codec (devc, 0x01, 0x00); + write_tdif_codec (devc, 0x02, 0x65); + write_tdif_codec (devc, 0x01, 0x03); + } + else + { + write_tdif_codec (devc, 0x01, 0x00); + write_tdif_codec (devc, 0x02, 0x60); + write_tdif_codec (devc, 0x01, 0x03); + } + WriteExternRegBit (devc, FPGA_MUTE, 0); /* Unmute */ +} + +static void +write_tdif_spdif_reg (envy24_devc * devc, int bRegister, int bData) +{ + unsigned char bMask; + unsigned char bSPI; + + /* Assert the CODEC chip select and wait at least 150 nS. */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_TRUE); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR | CS8_WR; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bRegister) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + + /* Write the data byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop SPI clock low. */ + WriteGPIObit (devc, CS8_CLK, 0); + + /* Write current data bit. */ + if (bMask & bData) + WriteGPIObit (devc, CS8_DOUT, 1); + else + WriteGPIObit (devc, CS8_DOUT, 0); + + /* Raise SPI clock to "clock data in". */ + WriteGPIObit (devc, CS8_CLK, 1); + } + + /* De-assert chip select. */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_FALSE); +} + +static int +read_tdif_spdif_reg (envy24_devc * devc, int reg) +{ + unsigned char bMask; + unsigned char bRet = 0; + unsigned char bSPI; + + + /****** WRITE MAP ADDRESS FIRST ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_TRUE); + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_WR; /* SPI address field plus WRITE operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Write the address (MAP) byte. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & reg) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + /* De-assert chip select(s). */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_FALSE); + + + /****** NOW READ THE DATA ******/ + + /* Drop the chip select low. */ + /* Wait at least 150 nS. */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_TRUE); + + + /* Write the SPI address/cmd byte. */ + /* */ + bSPI = CS8_ADDR + CS8_RD; /* SPI address field plus READ operation. */ + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock (GPIO5) low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Write current data bit. */ + if (bMask & bSPI) + WriteGPIObit (devc, CDC_DOUT, 1); + else + WriteGPIObit (devc, CDC_DOUT, 0); + + /* Raise clock (GPIO5). */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* Read the data byte. */ + /* */ + bRet = 0; + /* */ + for (bMask = 0x80; bMask; bMask = (bMask >> 1) & 0x7F) + { + /* Drop clock low. */ + WriteGPIObit (devc, CDC_CLK, 0); + + /* Read current data bit. */ + if (ReadGPIObit (devc, CDC_DIN)) + bRet |= bMask; + + /* Raise clock. */ + WriteGPIObit (devc, CDC_CLK, 1); + } + + + /* De-assert chip selects. */ + /* */ + WriteExternRegBit (devc, CS8_CS, CS_FALSE); + + /* Return value. */ + + return bRet; +} + +static int +tdif_get_locked_status (envy24_devc * devc) +{ + switch (devc->syncsource) + { + case SYNC_INTERNAL: + return 1; + break; + + case SYNC_SPDIF: + return !(read_tdif_spdif_reg (devc, 16) & 0x17); + break; + + case SYNC_WCLOCK: + /* The SPI input pin shows the TDIF locked status */ + if (envy24_read_cci (devc, 0x20) & (1 << 2)) + return 1; + return 0; + break; + } + + return 1; +} + +envy24_auxdrv_t tdif_auxdrv = { + tdif_card_init, + tdif_mix_init, + init_cs8427_spdif, + write_cs8427_spdif, + cs8427_spdif_ioctl, + read_tdif_spdif_reg, + write_tdif_spdif_reg, + set_tdif_speed, + tdif_get_locked_status, + cs8427_spdif_mixer_init, + tdif_card_uninit +}; diff --git a/kernel/drv/oss_envy24/envy24_tdif.h b/kernel/drv/oss_envy24/envy24_tdif.h new file mode 100644 index 0000000..8fd1f9f --- /dev/null +++ b/kernel/drv/oss_envy24/envy24_tdif.h @@ -0,0 +1,5836 @@ +/* + * Purpose: FPGA firmware for M-Audio Delta TDIF + */ +static unsigned char fpga_code[] = { + 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, + 0x01, 0x61, 0x00, 0x0b, 0x74, 0x64, 0x69, 0x66, 0x5f, 0x31, 0x2e, 0x6e, + 0x63, 0x64, 0x00, 0x62, 0x00, 0x0a, 0x32, 0x73, 0x35, 0x30, 0x74, 0x71, + 0x31, 0x34, 0x34, 0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x30, 0x31, 0x2f, + 0x30, 0x31, 0x2f, 0x32, 0x30, 0x00, 0x64, 0x00, 0x09, 0x30, 0x31, 0x3a, + 0x33, 0x38, 0x3a, 0x30, 0x38, 0x00, 0x65, 0x00, 0x01, 0x11, 0x0c, 0xff, + 0xff, 0xff, 0xff, 0xaa, 0x99, 0x55, 0x66, 0x30, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x07, 0x30, 0x01, 0x60, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x30, + 0x01, 0x20, 0x01, 0x00, 0x80, 0x3f, 0x2d, 0x30, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x09, 0x30, + 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x30, 0x00, 0x40, 0x00, 0x50, 0x00, 0x3e, 0x04, 0x00, + 0x12, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x28, 0x00, 0x12, 0x00, 0x02, 0x80, + 0x01, 0x80, 0x00, 0x70, 0x00, 0x1c, 0x00, 0x02, 0x80, 0x00, 0xa0, 0x00, + 0x28, 0x3f, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0x7c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xe0, 0x03, 0xf4, 0x02, 0xc7, 0x00, 0x3f, 0xc0, 0x2c, 0xf1, + 0x03, 0x30, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x90, 0x02, 0xe4, 0x20, 0x8b, 0x00, 0x2f, 0xd0, 0x08, 0xb0, + 0x02, 0x30, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x38, 0x02, 0xe4, 0x80, 0x83, 0x00, 0x2c, 0x44, 0x28, 0x32, + 0x02, 0x32, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x98, 0x02, 0xe4, 0x10, 0x8b, 0x00, 0x2e, 0x40, 0x28, 0x30, + 0x02, 0x30, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0x7b, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb8, 0x03, 0xc4, 0x00, 0xcb, 0x00, 0x3f, 0xe0, 0x0c, 0xb0, + 0x03, 0x10, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0d, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xd0, 0x03, 0xf5, 0x00, 0xff, 0x00, 0x3e, 0xc8, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, + 0xc0, 0x0f, 0xb0, 0x03, 0xe4, 0x40, 0xfb, 0x00, 0x3a, 0x40, 0x0e, 0xb0, + 0x03, 0x90, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, + 0xc0, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xbf, 0x08, 0x21, 0x40, 0x08, 0xb8, + 0x02, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0xa0, + 0xc0, 0x0b, 0x10, 0x02, 0xc7, 0x20, 0xb3, 0x80, 0x28, 0x40, 0x0a, 0x38, + 0x02, 0xb8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x21, + 0xe0, 0x0b, 0x5c, 0x02, 0xde, 0x00, 0xb7, 0x82, 0x21, 0x60, 0x08, 0x7c, + 0x02, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xfb, 0x00, 0x30, + 0xc0, 0x0f, 0x10, 0x03, 0xc4, 0x00, 0xf3, 0x00, 0x18, 0xc0, 0x0e, 0xb0, + 0x83, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xd0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc2, 0x2f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xfb, 0x10, 0x30, 0x48, 0x0c, 0xb0, + 0x63, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x50, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x21, 0x62, 0x28, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x58, 0x02, 0xd6, 0x00, 0xb3, 0x80, 0x21, 0xe0, 0x08, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x10, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0xa0, 0xc0, 0x08, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0x60, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x32, 0x80, 0x0c, 0xa0, + 0x23, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x88, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3c, 0x00, 0x0f, 0x84, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x32, 0x40, 0x0e, 0x90, + 0x03, 0x82, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x98, 0x02, 0x24, 0x00, 0xb1, 0x40, 0xa2, 0x40, 0x08, 0x96, + 0x02, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x92, 0x0a, 0x24, 0x00, 0xb9, 0x08, 0x22, 0x40, 0x2a, 0x11, + 0x42, 0x86, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x9a, 0x02, 0x04, 0x00, 0xb1, 0x28, 0x20, 0x4a, 0x08, 0x10, + 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x85, 0x03, 0x21, 0x40, 0xf8, 0x20, 0x32, 0x08, 0x0e, 0x80, + 0x0b, 0xae, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, + 0x40, 0x0f, 0xd1, 0x03, 0xf4, 0x00, 0xf9, 0x28, 0x3f, 0x40, 0x2f, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0xd0, 0x03, 0x34, 0x00, 0xf5, 0x00, 0x3f, 0x60, 0x0c, 0xd1, + 0x03, 0x26, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x12, 0x20, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x08, 0x88, + 0x02, 0x0e, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x0a, 0x04, 0x00, 0xb3, 0x00, 0x2e, 0xc4, 0x08, 0x30, + 0x0a, 0x02, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x22, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x08, 0x90, + 0x02, 0x06, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x96, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3c, 0x40, 0x2c, 0x90, + 0x03, 0x28, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x08, 0x3e, 0x50, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x4f, 0x82, 0x0b, 0x20, 0x24, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xe0, 0x02, 0x38, 0x00, 0xbe, 0x40, 0x22, 0x80, 0x0b, 0xe0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0xb0, 0x02, 0x05, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0xb0, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x20, 0x2d, + 0xc0, 0x0b, 0x30, 0x42, 0x18, 0x00, 0xb5, 0x80, 0x21, 0xc0, 0x0b, 0x60, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x58, 0x03, 0x16, 0x00, 0xf6, 0x80, 0x3d, 0xe0, 0x0f, 0x68, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x90, 0x03, 0xe8, 0x00, 0xf8, 0x00, 0xbe, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x88, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xf2, 0x02, 0xcf, 0x80, 0x33, 0xe1, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x71, 0x02, 0xdc, 0x00, 0x8f, 0x00, 0xa1, 0xc0, 0x0b, 0x60, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x50, 0x02, 0xd0, 0x00, 0x87, 0x00, 0x21, 0xc0, 0x0b, 0x60, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x00, 0x02, 0xec, 0x40, 0x83, 0x00, 0x20, 0xc0, 0x0b, 0x10, + 0x02, 0x88, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xff, 0x00, 0x3e, + 0xc0, 0x0f, 0x80, 0x03, 0xea, 0x00, 0xc9, 0x00, 0x32, 0xc0, 0x0f, 0x90, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x85, 0x83, 0xe9, 0x00, 0xf9, 0x00, 0xbe, 0xc0, 0x0f, 0x80, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xc0, 0x03, 0xfa, 0x00, 0xcc, 0x00, 0x3f, 0xc0, 0x0f, 0xc9, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x8c, 0x02, 0xeb, 0x02, 0x88, 0x80, 0x2e, 0xe4, 0x0b, 0xd8, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x88, 0x82, 0xe9, 0x80, 0x8b, 0x80, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x00, 0x02, 0xc8, 0x00, 0x83, 0x00, 0x2c, 0x40, 0x0b, 0x00, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x80, 0x03, 0xc8, 0x00, 0xcb, 0x00, 0x3e, 0x40, 0x0f, 0x80, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xd0, 0x03, 0xf8, 0x00, 0xff, 0x00, 0x3f, 0x40, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0x7c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf4, + 0x0b, 0x30, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xa0, 0x0a, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x84, + 0x02, 0x30, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x26, + 0x02, 0x32, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xa8, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x80, + 0x02, 0x30, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0x6c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xa8, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xc0, + 0x03, 0x10, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x01, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0x51, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0d, 0xa8, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x91, + 0x03, 0x10, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xbc, 0x02, 0xfc, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x9d, + 0x02, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x09, 0xb0, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x10, + 0x02, 0x38, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x4c, 0x02, 0xde, 0x00, 0xb7, 0x81, 0x2d, 0xe0, 0x0b, 0x69, + 0x02, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0d, 0x10, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x80, + 0x0b, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xe0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x80, 0x03, 0xec, 0x40, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xa0, + 0x03, 0x2a, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0xcb, 0xf0, + 0x0a, 0x32, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x48, 0x02, 0xde, 0x80, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x82, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x4b, 0x36, + 0x02, 0x12, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xe8, 0xd3, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xe4, + 0x03, 0x3a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x00, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x9a, + 0x03, 0x82, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x91, 0x82, 0xe4, 0x00, 0xb9, 0x00, 0x0e, 0x40, 0x4b, 0x98, + 0x02, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0x86, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x12, 0x02, 0xc4, 0x80, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x32, + 0x82, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x85, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x82, + 0x0b, 0xae, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0xa0, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0xd1, 0x03, 0xe4, 0x40, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xd2, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0xd0, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xf8, + 0x83, 0x26, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x0a, 0x20, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x8c, + 0x02, 0x8e, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x90, 0x02, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x3a, + 0x82, 0x02, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x92, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x8b, 0x90, + 0x02, 0x86, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0x28, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x98, 0x83, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x10, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3a, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x82, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0x64, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xe0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x28, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x14, 0x02, 0xcc, 0x00, 0x93, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x81, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x50, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x39, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x80, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x68, 0x03, 0xde, 0x00, 0xd7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0d, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc1, 0x0f, 0x90, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x20, + 0xef, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xc8, 0x03, 0x3e, 0x00, 0xcf, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xfc, 0x00, + 0x87, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0x1c, 0x00, 0x87, 0x00, 0x2d, 0xc0, 0x0b, 0x50, + 0x0a, 0x2a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xa7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0x1c, 0x00, 0x87, 0x00, 0x2d, 0xc0, 0x0b, 0x74, + 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x39, 0x02, 0x0c, 0x00, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x10, + 0x02, 0x08, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xfc, 0x00, + 0xeb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x94, 0x0b, 0x2c, 0x02, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xbc, + 0x0b, 0x2a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc1, 0x0f, 0x18, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0x60, 0x83, 0x2c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0x20, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xd8, + 0x02, 0x20, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x80, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb8, + 0x02, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x0a, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x18, + 0x0a, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0x30, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x90, + 0x03, 0x20, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x4f, 0x60, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xd4, 0x00, 0xff, 0x00, 0x33, 0xc0, 0x0c, 0xf1, + 0x03, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xe1, 0x20, 0xbb, 0x00, 0x22, 0xc0, 0x08, 0xb0, + 0x06, 0x30, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xc2, 0xc0, 0xb3, 0x00, 0x20, 0xc0, 0x08, 0x32, + 0x02, 0x72, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xe6, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x08, 0xb0, + 0x02, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xe2, 0x00, 0xfb, 0x00, 0x32, 0xc0, 0x0c, 0xb0, + 0x03, 0x50, 0x44, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xf4, 0x00, 0xff, 0x00, 0x3d, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xe2, 0x00, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xb1, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2f, + 0xc0, 0x0b, 0xb0, 0x02, 0xe4, 0x00, 0x87, 0x80, 0x2f, 0xc0, 0x4b, 0xb8, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xc0, 0x00, 0x83, 0x80, 0x2c, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xdf, 0x00, 0x87, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xc0, 0x02, 0xc3, 0x08, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc2, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x10, 0x3f, 0xc2, 0x0f, 0xf0, + 0x03, 0xd0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xe0, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x91, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc8, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc8, 0x0b, 0x70, + 0x02, 0xf2, 0x26, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x9e, 0x10, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe8, 0x0b, 0x78, 0x02, 0xd2, 0x00, 0xb7, 0x90, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xc8, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x12, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xda, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xf8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe2, 0x00, 0xf8, 0x00, 0x1e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x04, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x01, 0x2e, 0x40, 0x0b, 0x91, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe6, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xce, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x4a, 0x0b, 0x10, 0x02, 0xc6, 0x80, 0xb1, 0x28, 0x2c, 0x4a, 0x0b, 0x10, + 0x02, 0xca, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x08, 0x0f, 0x80, 0x03, 0xe1, 0x40, 0xf8, 0x20, 0x3e, 0x08, 0x4f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x9d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xf4, 0x48, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x92, + 0x83, 0xe6, 0x24, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xf4, 0x00, 0xcd, 0x00, 0x3e, 0x40, 0x0f, 0xd4, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0x88, 0x00, 0x2e, 0x00, 0x09, 0x88, + 0x02, 0xce, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0x81, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xd2, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x8b, 0x90, 0x02, 0xe4, 0x00, 0x89, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x80, 0xc9, 0x00, 0x3e, 0x40, 0x8f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xc4, 0x02, 0xf9, 0x00, 0x3e, 0x40, 0x0d, 0x90, + 0x03, 0xd2, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x23, 0xe1, 0x20, 0xc8, 0x00, 0x32, 0x00, 0x0f, 0x80, + 0x03, 0xc2, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xf8, 0x00, 0x8a, 0x00, 0x22, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcf, 0x00, 0x83, 0x80, 0x20, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x42, 0xdd, 0x00, 0x81, 0xc0, 0x21, 0xc0, 0x0b, 0x70, + 0x82, 0xe0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xfe, 0x02, 0xc7, 0x80, 0xb1, 0xe0, 0x0f, 0x58, + 0x03, 0xe2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x00, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0xc0, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xf6, 0x02, 0xcd, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x71, 0x02, 0xd4, 0x40, 0x85, 0x00, 0x2d, 0xc0, 0x0b, 0x50, + 0x02, 0xea, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xd4, 0x00, 0x85, 0x00, 0x2d, 0xc0, 0x0b, 0x50, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xec, 0x40, 0x81, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x00, 0xc8, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xe7, 0x00, 0xcb, 0x00, 0x2e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xe4, 0x80, 0xf9, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3d, + 0xc0, 0x0c, 0xf0, 0x03, 0xe6, 0x00, 0xcf, 0x40, 0x3f, 0xc0, 0x0f, 0xd0, + 0x03, 0xe8, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x08, 0xb0, 0x02, 0xe7, 0x20, 0x89, 0x80, 0x2e, 0xc0, 0x0b, 0xd0, + 0x02, 0xe8, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x08, 0xb0, 0x02, 0xe4, 0x80, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0x93, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x09, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x08, 0x30, 0x02, 0xc4, 0x00, 0x81, 0x00, 0x2c, 0xc0, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0c, 0xb0, 0x03, 0xe4, 0x02, 0xcb, 0x02, 0x7e, 0xc0, 0x0f, 0x90, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xf0, 0x00, 0xfd, 0x00, 0x7f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xd2, 0x0d, 0xe4, + 0x03, 0x30, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc1, 0x0b, 0xa0, 0x02, 0xec, 0x00, 0xbb, 0x04, 0x2e, 0xd0, 0x08, 0x94, + 0x22, 0x30, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0a, 0x28, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc8, 0x09, 0x16, + 0x02, 0x32, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb8, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb8, + 0x06, 0x30, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x02, 0x3e, + 0xc0, 0x0e, 0x88, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x4d, 0xc8, + 0x0b, 0x00, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xc0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3d, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xe0, 0x0c, 0x90, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0x92, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbf, 0x00, 0x2e, + 0xc0, 0x08, 0x90, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x37, 0xc0, 0x0b, 0xb4, + 0x82, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x08, 0x20, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, 0xc2, 0x4b, 0x8c, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x08, 0x68, 0x02, 0xde, 0x00, 0xb7, 0x82, 0x25, 0xe0, 0x0b, 0x78, + 0x12, 0xf8, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x02, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0c, 0x30, 0x03, 0xcc, 0x00, 0xfb, 0x00, 0x30, 0xc0, 0x0f, 0x10, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3d, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc2, 0x8f, 0xf0, + 0x03, 0xd0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x80, 0x32, + 0xc0, 0x0f, 0xa0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x07, 0x80, + 0x23, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x40, 0x21, + 0xc0, 0x0b, 0x60, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x8b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb3, 0xa0, 0xa1, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x58, + 0x02, 0xf0, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, + 0xc0, 0x0b, 0x30, 0x42, 0xcc, 0x00, 0xb3, 0x00, 0x2e, 0xc1, 0x0b, 0x31, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x32, + 0x80, 0x0f, 0xe4, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xe8, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x83, 0xe0, 0x00, 0xf8, 0x01, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0c, 0x18, + 0x0b, 0x02, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x50, 0x08, 0x9a, + 0x02, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x60, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x28, 0x92, + 0x02, 0x06, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x28, 0x2c, + 0x40, 0x0b, 0x12, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x4a, 0x08, 0x12, + 0x82, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x88, 0x0c, 0x82, + 0x03, 0x2e, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0xd1, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x4a, 0x0f, 0xd2, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, + 0x40, 0x0f, 0xb0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0xd8, + 0x83, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x04, 0x2e, 0x2a, 0x0b, 0x8c, + 0x02, 0xce, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x32, + 0x82, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x94, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x8b, 0x98, + 0x82, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x14, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x83, 0xca, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x04, 0x1e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x84, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x02, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x04, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2f, 0xb0, 0x0b, 0xe0, + 0x02, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xe0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x11, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc2, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xd1, 0x0b, 0x70, + 0x02, 0xc8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0xc0, 0x3d, 0xe0, 0x0f, 0x58, + 0x03, 0xca, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x90, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0x3e, 0x00, 0xff, 0x80, 0x3f, 0x60, 0x0f, 0xf8, + 0x03, 0xd0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0x44, 0x0b, 0x70, + 0x12, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0x40, 0x0b, 0x54, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x34, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2e, 0x40, 0x0b, 0x10, + 0x02, 0xd8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb5, 0x0b, 0x2c, 0x00, 0xff, 0x00, 0x3e, 0x40, 0x0f, 0xbc, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x04, 0x3e, 0x50, 0x0f, 0xb1, + 0x43, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xe0, 0x0f, 0xb0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0x40, 0x0c, 0xd0, + 0x03, 0x20, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xe0, 0x4b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2f, 0x60, 0x08, 0x58, + 0x02, 0x20, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc4, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xe2, 0x08, 0xb8, + 0x02, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x28, 0x18, + 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x08, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0c, 0x90, + 0x03, 0x20, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x40, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0x80, 0x0f, 0xe0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x40, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xf0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x83, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0x40, 0x0b, 0x72, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x10, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x4a, 0x0b, 0x12, 0x82, 0x84, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x08, 0x0f, 0x82, 0x03, 0x20, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0xa0, 0xf9, 0x00, 0x3e, 0x4a, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3a, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0xc0, 0x8b, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x8b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x28, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x44, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3a, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x60, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0c, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x08, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x28, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x80, 0xb7, 0x00, 0x2d, 0xec, 0x08, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x80, 0xf7, 0x80, 0x3f, 0xe0, 0x0c, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0c, 0xf8, 0x03, 0xfe, 0x20, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0a, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x08, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xe4, 0x0a, 0x30, 0x02, 0xec, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xe0, 0x0c, 0xb0, 0x43, 0xfc, 0x00, 0xfb, 0x00, 0x3f, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x13, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3e, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xcf, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x6c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xab, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x4c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x8b, 0x30, 0x02, 0xcc, 0x00, 0xa3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0x7c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x33, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x40, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x40, 0x3f, 0xcc, 0x8f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2a, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0x40, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xdc, 0x09, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x20, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x40, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x20, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2a, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0x40, 0x0b, 0xb8, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xbb, 0x00, 0x3e, + 0x40, 0x0f, 0xa8, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3e, 0xc1, 0x0d, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x02, 0x3e, + 0x40, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3a, 0xc0, 0x0e, 0xb0, + 0x03, 0x90, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbf, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x03, 0xc0, 0x00, 0xb0, + 0x02, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xbb, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x52, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x08, 0xc0, 0x0a, 0x30, + 0x00, 0xb8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x09, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0x60, 0x0b, 0x58, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x21, 0xe0, 0x08, 0x78, + 0x12, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0x40, 0x0f, 0x10, 0x03, 0xcc, 0x00, 0xfb, 0x00, 0x38, 0xc0, 0x0e, 0xb0, + 0x03, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0d, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x40, 0x0f, 0xd0, 0x02, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf1, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x80, 0x32, + 0x40, 0x0f, 0x80, 0x03, 0xee, 0x00, 0xcb, 0x00, 0x3e, 0xc4, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x20, 0x29, + 0xc0, 0x0b, 0x60, 0x02, 0xdc, 0x00, 0x87, 0x00, 0x2d, 0xc1, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb3, 0x90, 0x21, + 0x62, 0x0b, 0x78, 0x02, 0xfe, 0x02, 0x87, 0x80, 0x2d, 0xe8, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x28, + 0xe0, 0x0b, 0x38, 0x02, 0xcc, 0x00, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x32, + 0x80, 0x0f, 0xea, 0x03, 0xe8, 0x00, 0xca, 0x00, 0x3e, 0x80, 0x4f, 0xa0, + 0x23, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x40, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x8f, 0x88, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0b, 0x80, + 0x01, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x80, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x2c, 0x10, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x30, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2c, + 0x40, 0x08, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x58, 0x08, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x28, 0x2e, + 0x40, 0x08, 0x12, 0x0a, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x4a, 0x8b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x3e, + 0x14, 0x0c, 0x80, 0x0b, 0x00, 0x00, 0xf8, 0x00, 0x3e, 0x08, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x28, 0x3e, 0x40, 0x0b, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, + 0x40, 0x0f, 0xf1, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x4b, 0x0f, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xfd, 0x00, 0x3e, 0x41, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x05, 0x3e, 0x41, 0xcf, 0x90, + 0x43, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xf0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x2e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x9c, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0b, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x99, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3a, + 0x08, 0x0f, 0x84, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xbe, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x23, + 0xb0, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x0e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x28, + 0x40, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb3, 0x80, 0x21, + 0x10, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x01, 0x2d, 0xc0, 0x0b, 0x73, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x39, + 0x20, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xf8, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x00, 0x8f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x10, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xa0, 0x0c, 0xf9, 0x03, 0x3e, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2f, + 0xc0, 0x08, 0x70, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0x00, 0x08, 0x70, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x00, 0x28, 0x38, 0x00, 0x0c, 0x00, 0xb3, 0x00, 0x2e, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xf8, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x40, 0x0c, 0x38, 0x83, 0x2c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0b, 0xf0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xf8, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x21, 0x2f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x20, 0x33, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x00, 0x0c, 0xb0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0e, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x20, 0x2a, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0x00, 0x28, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xb0, 0x00, 0x22, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2c, + 0x80, 0x08, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0a, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb0, 0x00, 0x28, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x08, 0xb0, 0x0a, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x00, 0x0c, 0xb0, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0e, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x00, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x02, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc1, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x26, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x37, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x0e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0b, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x4b, 0x72, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x7a, + 0x13, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb1, + 0x83, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc4, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x03, 0x6a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0xb0, + 0x06, 0x48, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xf0, + 0x03, 0x2a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x13, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0x20, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x70, + 0x03, 0x20, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xd0, 0x0c, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x10, 0x3f, 0xcc, 0x0f, 0xf1, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x10, 0xbb, 0x00, 0x2e, + 0xc0, 0x08, 0xb0, 0x02, 0xec, 0x00, 0xb3, 0x20, 0x2f, 0xdc, 0x0b, 0xb2, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc8, 0x0a, 0x30, 0x02, 0xcc, 0x00, 0xa3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0a, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x01, 0x3e, + 0xc0, 0x2e, 0xb0, 0x03, 0xec, 0x00, 0xeb, 0x00, 0x3e, 0xc0, 0x8f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3d, + 0xc0, 0x0d, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3a, 0xc0, 0x0e, 0xb0, + 0x03, 0x10, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x6f, + 0xdc, 0x0b, 0xf0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x23, 0xc0, 0x08, 0xb0, + 0x03, 0x72, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x8b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x28, 0xc0, 0x0a, 0x30, + 0x02, 0x38, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x20, 0xe0, 0x08, 0x78, + 0x02, 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x2c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x38, 0xc0, 0x0e, 0xb0, + 0x03, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc2, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb1, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xd2, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x10, 0xb7, 0x00, 0x2d, + 0xc8, 0x0b, 0x72, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xd0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe8, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x10, 0xbb, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xba, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x4f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x01, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x68, 0x0c, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3a, 0x40, 0x0e, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x60, 0x28, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x22, 0x40, 0x08, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2c, + 0x40, 0x08, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x28, 0x40, 0x0a, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x48, 0x08, 0x12, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x20, 0x4a, 0x08, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x14, 0x2c, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3a, 0x08, 0x0e, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x41, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x44, 0x0f, 0x91, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x4a, 0x0f, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, + 0x40, 0x0c, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x08, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x08, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x08, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x2c, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x02, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0e, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2f, + 0xb0, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0x3a, 0x00, 0x2e, 0x80, 0x08, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2e, + 0x84, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0a, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0x40, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x30, 0x2d, 0xe0, 0x08, 0x71, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0x20, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x88, 0x3f, 0xec, 0x0e, 0x7a, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x02, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x2f, 0xe4, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xa0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe2, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0x80, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0x80, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x80, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x80, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x40, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x00, 0x0f, 0x70, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3d, 0xc0, 0x0e, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0x80, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0a, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x80, 0x0b, 0x30, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x80, 0x0f, 0xb0, 0x03, 0x2c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0e, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x80, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0xb3, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x82, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x32, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x42, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x01, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x10, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x82, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2f, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x38, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb9, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb5, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xf9, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb5, 0x00, 0x2d, 0xc8, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe4, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc1, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf1, 0x00, 0x3a, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x22, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2a, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x28, 0x20, 0x4a, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x3a, 0x08, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x92, 0x83, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xfd, 0x28, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xd0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x8a, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x82, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x80, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0x20, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0x28, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x38, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x5e, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x30, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x7a, 0x23, 0x1e, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x1f, 0x0b, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xdc, 0x1b, 0x3e, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x0a, 0x1c, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x50, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0xb0, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xf0, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xff, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x90, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3d, 0xc0, 0x2c, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x90, 0x0a, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x90, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x50, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0c, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0x40, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x88, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xa8, 0x0f, 0xf0, 0x03, 0xfc, 0x04, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xb0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x10, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xcb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0x90, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x00, 0x0b, 0xb0, 0x02, 0xfc, 0x00, 0xdb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0x8b, 0x00, 0x2f, 0xc0, 0x0e, 0xf0, + 0x02, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0x83, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xb8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0x97, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x06, 0xee, 0x00, 0x87, 0x80, 0x2d, 0xe0, 0x0a, 0x78, + 0x02, 0x38, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0b, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xec, 0x00, 0x83, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xc3, 0x00, 0x3c, 0xc0, 0xcf, 0x30, + 0x07, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf1, 0x03, 0xfc, 0x40, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfe, 0x00, 0xff, 0x00, 0x3f, 0xc2, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0e, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xee, 0x00, 0xcb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdd, 0x00, 0x87, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc8, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xce, 0x00, 0x87, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x7b, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0x83, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x10, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3f, 0x90, 0x0f, 0xa0, 0x03, 0xe8, 0x02, 0xca, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x08, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x13, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3c, 0x40, 0x0c, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0a, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x08, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x4a, 0x0b, 0x10, 0x02, 0xc4, 0xa0, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x4a, 0x0a, 0x12, + 0x82, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x08, 0x0f, 0x80, 0x03, 0xe1, 0xc0, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xf0, 0x00, 0xf8, 0x00, 0x3e, 0x08, 0x0c, 0x82, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0xa0, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0x90, 0x03, 0xe6, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x40, 0x0f, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x60, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x41, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x50, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x10, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x41, 0x1c, 0x80, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x10, 0x2d, 0xc1, 0x0b, 0x72, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x80, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x7e, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x40, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x20, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0c, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x33, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0a, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xbf, 0x00, 0x35, 0xc4, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2c, 0xc0, 0x08, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x21, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xec, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0a, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x24, 0xc0, 0x0b, 0xb0, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xbc, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0c, 0xb0, 0x03, 0xfc, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xff, 0x00, 0x32, 0xc0, 0x0f, 0xf0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xef, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3d, 0xc0, 0x0c, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0x20, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0a, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x42, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xab, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xa3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0a, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xeb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0c, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0x20, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xdf, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0x70, 0x0b, 0x3c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x33, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x0a, 0x0c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x30, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, + 0x03, 0xc0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb8, 0x03, 0xac, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbf, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xbb, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0x1e, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0x8c, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x91, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0x5e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x04, 0xfa, 0x01, 0x3e, 0x81, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0x68, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0b, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x98, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x26, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x28, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x36, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x9d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xd0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x8b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x30, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x43, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x88, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xe4, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x20, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0xc0, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xca, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x01, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x33, 0xe0, 0x0f, 0xf8, + 0x03, 0xd0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x12, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x21, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x21, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xbb, 0x00, 0x20, 0xc0, 0x0b, 0x30, + 0x02, 0xd8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xa0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xff, 0x00, 0xb2, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xa4, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xfb, 0x00, 0xb3, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xa4, 0x42, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xbc, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xd0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xf8, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x0e, + 0xc0, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xbb, 0x00, 0x26, 0xc0, 0x09, 0xb0, + 0x02, 0x70, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xc8, 0x09, 0xb0, 0x00, 0x2c, + 0x80, 0x0b, 0x30, 0x02, 0xc4, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xe8, 0x00, 0xb8, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe4, 0x00, 0xbb, 0x00, 0x26, 0xc0, 0x09, 0xb0, + 0x02, 0x70, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x40, 0x0f, 0xc0, 0x03, 0xf8, 0x00, 0xfe, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xe8, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x8f, 0x90, 0x03, 0xe4, 0x00, 0xfa, 0x04, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xe8, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe4, 0x00, 0xba, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xc8, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x8b, 0x78, 0x02, 0xde, 0x40, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x68, 0x02, 0xda, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xc8, 0x00, 0xf0, 0x00, 0x3c, + 0x80, 0x0f, 0x30, 0x03, 0xc4, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xf8, 0x00, 0xfc, 0x00, 0x3f, + 0x80, 0x0b, 0xe0, 0x02, 0xf4, 0x00, 0xff, 0x03, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x43, 0xce, 0x00, 0xcb, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xa7, 0x00, 0x2d, + 0x40, 0x09, 0x40, 0x02, 0xd8, 0x00, 0xb6, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xfa, 0x00, 0x84, 0x80, 0x2d, + 0x20, 0x0b, 0x58, 0x02, 0xd6, 0x00, 0xb6, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xc8, 0x00, 0xa0, 0x00, 0x2c, + 0x24, 0x0b, 0x00, 0x02, 0xc4, 0x00, 0xb2, 0x40, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xca, 0x00, 0x3e, + 0xa1, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x50, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0d, 0x81, 0x03, 0xf0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0x64, 0x00, 0xbd, 0x00, 0x2f, + 0x40, 0x0b, 0xd0, 0x02, 0xf4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb5, 0x00, 0x2d, + 0x40, 0x0b, 0x50, 0x02, 0xd4, 0x00, 0xb5, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xfc, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x2e, 0x40, 0x0f, 0x92, 0x83, 0xe4, 0x00, 0xfb, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x07, 0x92, + 0x83, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe8, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe8, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x8b, 0x80, + 0x02, 0xce, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x6e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x42, 0x0b, 0x90, 0x12, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x1b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x14, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x8f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x10, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe5, 0x40, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x8f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x84, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe6, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x32, + 0x10, 0x0c, 0x80, 0x03, 0x21, 0x00, 0xc8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x04, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x16, + 0x80, 0x0d, 0xa0, 0x03, 0x68, 0x00, 0xda, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x20, + 0xc0, 0x08, 0x30, 0x02, 0x0c, 0x00, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x1b, 0x70, 0x06, 0xdc, 0x01, 0xbf, 0x80, 0x67, + 0xe0, 0x09, 0xf8, 0x02, 0x7e, 0x00, 0x97, 0x00, 0x2d, 0xc0, 0x0b, 0x72, + 0x02, 0xc8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x31, + 0xe0, 0x0c, 0x78, 0x03, 0x1e, 0x00, 0xc7, 0x80, 0x3d, 0xe0, 0x0f, 0x7a, + 0x03, 0xca, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x23, 0xcc, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb1, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x83, 0xfe, 0x00, 0xff, 0x80, 0x33, + 0xe0, 0x0c, 0xf8, 0x02, 0x3e, 0x00, 0xc7, 0x80, 0x33, 0xe0, 0x0f, 0xf8, + 0x03, 0x10, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x29, + 0xc0, 0x0a, 0x70, 0x02, 0x9c, 0x80, 0xa7, 0x00, 0x29, 0xc0, 0x0b, 0xf0, + 0x03, 0x6a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xbf, 0x00, 0x23, + 0xc0, 0x08, 0xf0, 0x02, 0x3c, 0x00, 0x8f, 0x00, 0x21, 0xc0, 0x0b, 0x70, + 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0xb0, 0x00, 0xcc, 0x00, 0xb3, 0x00, 0x28, + 0xc0, 0x0a, 0x30, 0x82, 0x8c, 0x20, 0xa3, 0x00, 0x28, 0xc0, 0x1b, 0x30, + 0x02, 0x58, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0b, 0xf0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x32, + 0xc0, 0x0c, 0xb0, 0x03, 0x2c, 0x00, 0xcb, 0x00, 0x32, 0xc0, 0x0f, 0xf0, + 0x03, 0x2a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x13, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xee, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x07, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x50, 0xfc, 0x10, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xac, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x08, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x23, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0b, 0xf0, 0x02, 0xfc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x03, 0xdc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0e, 0xf0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x04, 0x2e, 0xc0, 0x08, 0x94, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0a, 0x04, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xa0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0e, 0x8d, 0x83, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x44, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3d, 0xc0, 0x0f, 0x68, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x94, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x36, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd1, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2f, 0xc0, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x00, 0x42, 0x0c, 0x00, 0xb3, 0x00, 0x24, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x28, 0x02, 0x1e, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xfc, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x10, 0x03, 0x0c, 0x00, 0xf3, 0x00, 0x34, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf1, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xe0, 0x0c, 0x80, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xd0, 0x08, 0x60, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x24, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2c, 0xe8, 0x08, 0x58, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xe0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0c, 0xe1, 0x83, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x2f, 0x00, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x13, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x4a, 0x0b, 0x12, 0x8a, 0x04, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x08, 0x0f, 0x82, 0x03, 0x20, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x4a, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xd0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x4f, 0x90, + 0x03, 0xe6, 0x26, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0c, 0x98, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x08, 0x80, 0x02, 0x20, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x08, 0x14, 0x02, 0x04, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xd2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x08, 0x96, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0c, 0x90, 0x03, 0x24, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3c, 0x40, 0x2f, 0x10, 0x0b, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xda, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc4, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc4, 0x0b, 0x71, 0x82, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2e, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3f, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb8, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x10, 0xfc, 0x08, 0xff, 0x00, 0x3f, 0xc0, 0x0d, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x08, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x6e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0d, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x37, + 0xc0, 0x0c, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x18, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x04, 0x20, + 0xc0, 0x0a, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x26, 0x00, 0x09, 0x80, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x24, + 0x80, 0x08, 0x30, 0x02, 0xcc, 0x01, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x22, 0xec, 0x00, 0xbb, 0x00, 0x22, + 0x80, 0x0a, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x26, 0x00, 0x09, 0x80, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xac, 0x00, 0xfb, 0x00, 0x36, + 0xc0, 0x0c, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xec, 0x00, 0xf7, 0x00, 0x3f, + 0xc0, 0x0b, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0xc0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xdb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x02, 0xcb, 0x00, 0x3e, + 0x80, 0x0e, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x2e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xfc, 0x00, 0x8f, 0x00, 0x2e, + 0x80, 0x0d, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x04, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0x83, 0x00, 0x2e, + 0xc0, 0x08, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x03, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x10, 0x5e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0x87, 0x80, 0x2d, + 0xe0, 0x09, 0x48, 0x02, 0xd2, 0x00, 0xb4, 0x80, 0x2d, 0x20, 0x0b, 0x48, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x4c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xb3, 0x00, 0x3c, 0xc0, 0x0f, 0x31, 0x03, 0xcc, 0x00, 0xc3, 0x00, 0x3c, + 0x80, 0x0e, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x10, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x80, 0x03, 0xc0, 0x02, 0xf0, 0x00, 0xfc, 0x00, 0x3f, 0x00, 0x0f, 0xc9, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x40, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb8, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x99, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x80, 0xb7, 0x60, 0x2d, + 0xc0, 0x0b, 0x40, 0x02, 0x90, 0x00, 0xb4, 0x04, 0x25, 0x00, 0x09, 0x40, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x91, 0xb7, 0x80, 0x2d, + 0xa0, 0x0b, 0xf8, 0x02, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x04, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0x80, 0x0b, 0x00, 0x02, 0x80, 0x00, 0xb0, 0x00, 0x24, 0x00, 0x09, 0x00, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0x28, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x01, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x1f, 0x00, 0x0b, 0xc0, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0x99, 0x00, 0x2e, + 0x40, 0x0b, 0xd0, 0x02, 0xf4, 0x00, 0xbd, 0x00, 0x2f, 0x40, 0x0b, 0xd0, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x14, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0xa0, 0xb1, 0x28, 0x2c, + 0x40, 0x0b, 0x50, 0x02, 0xd4, 0x10, 0xb5, 0x00, 0x2d, 0x40, 0x0b, 0x50, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x80, 0xd8, 0x20, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0xc0, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x95, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x2c, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x4a, 0x07, 0x10, 0x01, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x4f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xd9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0x24, 0x00, 0xc9, 0x00, 0x32, 0x40, 0x0c, 0x90, + 0x03, 0x26, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x18, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0xc0, 0x02, 0xa0, 0x00, 0xa8, 0x00, 0x2a, 0x00, 0x0a, 0x80, + 0x02, 0x8e, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x84, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x90, 0x02, 0x24, 0x00, 0x89, 0x00, 0x22, 0x40, 0x0a, 0x90, + 0x02, 0x02, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x04, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x42, 0x0b, 0x90, 0x02, 0xa4, 0x00, 0xa9, 0x00, 0x2a, 0x40, 0x0a, 0x90, + 0x02, 0x86, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0x04, 0x00, 0xc9, 0x00, 0x30, 0x40, 0x0e, 0x10, + 0x03, 0x28, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x3e, + 0x10, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x81, 0x0b, 0xa0, 0x42, 0xe8, 0x10, 0xba, 0x04, 0x2e, + 0x80, 0x0b, 0x25, 0x02, 0xe8, 0x00, 0xb2, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x4c, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x34, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x43, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x11, 0x9c, 0x04, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0x37, 0x30, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc4, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0xa0, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0x5e, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x79, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0x7b, 0x00, 0x1e, + 0xd0, 0x07, 0xb0, 0x01, 0xec, 0x00, 0x7b, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xbe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3d, + 0xf0, 0x0c, 0xe8, 0x03, 0xde, 0x00, 0xcf, 0x80, 0x31, 0xe0, 0x0c, 0x78, + 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x18, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0a, 0x61, 0x02, 0xdc, 0x40, 0xa7, 0x14, 0x29, 0xc6, 0x0a, 0x71, + 0x82, 0xaa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2f, + 0xc0, 0x08, 0x60, 0x02, 0xfc, 0x00, 0x8f, 0x00, 0x23, 0xc0, 0x0a, 0xf0, + 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x04, 0x8c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xbb, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0a, 0x28, 0x02, 0xce, 0x00, 0xa3, 0x80, 0x28, 0xd0, 0x0a, 0x34, + 0x02, 0x88, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xff, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3f, + 0xc0, 0x0c, 0xbc, 0x03, 0xed, 0x20, 0xcb, 0x48, 0x32, 0xe5, 0x0e, 0xb8, + 0x03, 0x2a, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x13, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb3, 0x03, 0xec, 0x80, 0xfb, 0x20, 0x3e, 0xc0, 0x07, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x33, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x03, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x83, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2a, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0x30, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, 0x02, 0x6c, 0x00, 0xbb, 0x00, 0x26, + 0xc0, 0x09, 0xa0, 0x02, 0x2c, 0x00, 0x9b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x14, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x28, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x20, 0x02, 0x0c, 0x00, 0xb3, 0x02, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x32, 0xc0, 0x0f, 0xb0, 0x03, 0x6c, 0x00, 0xfb, 0x00, 0x37, + 0xc0, 0x0d, 0xa0, 0x0b, 0x2c, 0x00, 0xdb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc1, 0x0f, 0xf0, 0x43, 0xfc, 0x10, 0xff, 0x04, 0x3f, + 0xc1, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xf7, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0x3b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x44, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0d, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x43, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xfe, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x24, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xe0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x26, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xd2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xda, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0x33, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x4f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x12, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3d, 0xc0, 0x0b, 0xf0, 0x03, 0x7c, 0x00, 0xff, 0x00, 0x3d, + 0xc0, 0x0d, 0xc0, 0x03, 0xf0, 0x00, 0xfd, 0x00, 0x3f, 0x00, 0x0f, 0xe0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0x20, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x08, 0x80, 0x02, 0xec, 0x00, 0xb9, 0x00, 0x2e, 0x80, 0x0b, 0xb0, + 0x02, 0x70, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0xb0, 0x02, 0x4c, 0x00, 0xb3, 0x00, 0x2e, + 0xc0, 0x09, 0x20, 0x02, 0xc0, 0x00, 0xb2, 0x00, 0x2c, 0x00, 0x0b, 0x20, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x04, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0x20, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x88, 0xa0, 0x02, 0xec, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xb0, + 0x02, 0x70, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x20, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0x6c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0d, 0x84, 0x03, 0xe0, 0x00, 0xf9, 0x00, 0x3e, 0x08, 0x0f, 0xa0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, + 0x00, 0x0f, 0xc0, 0x03, 0xfc, 0x00, 0xfd, 0x00, 0x3f, 0x80, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x40, 0x3a, 0xc2, 0x0e, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0e, 0xa4, 0x03, 0xe0, 0x00, 0xfa, 0x00, 0x3e, 0x10, 0x0f, 0xa0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x22, 0x10, 0x08, 0x00, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2c, + 0x00, 0x08, 0xa0, 0x02, 0xec, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb2, 0x00, 0x28, 0xd0, 0x0a, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0a, 0x10, 0x02, 0xc0, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x20, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xbe, 0x80, 0x23, 0x20, 0x08, 0x48, 0x02, 0xd2, 0x00, 0xb4, 0x80, 0x2f, + 0x20, 0x08, 0x58, 0x02, 0xde, 0x00, 0xb5, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf2, 0x00, 0x38, 0xc0, 0x0e, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc4, 0x9e, 0x34, 0x03, 0xc0, 0x00, 0xf2, 0x01, 0x3c, 0x40, 0x1f, 0x20, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xf6, 0x00, 0x3f, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, + 0x20, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0x7e, 0x00, 0x3f, 0xc0, 0x0f, 0xf8, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfa, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xce, 0x00, 0xd3, 0x80, 0x36, + 0xc0, 0x0f, 0x90, 0x03, 0xe0, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0xa0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb6, 0x00, 0x2d, 0x00, 0x0b, 0x40, 0x02, 0xd0, 0x00, 0x84, 0x00, 0x21, + 0x00, 0x0b, 0x50, 0x02, 0xdc, 0x00, 0xb5, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb6, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xfe, 0x00, 0x9f, 0x80, 0x25, + 0xe0, 0x0b, 0x78, 0x02, 0xd2, 0x00, 0xb6, 0x80, 0x2d, 0x60, 0x0b, 0x68, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb2, 0x00, 0x2c, 0x00, 0x0b, 0x00, 0x02, 0xc0, 0x00, 0x80, 0x00, 0x20, + 0x00, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb2, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x11, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xda, 0x00, 0x36, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3c, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3f, 0x00, 0x0f, 0xc4, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xfc, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xa4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x10, 0x03, 0x24, 0x00, 0xc9, 0x00, 0x32, 0x40, 0x0c, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0e, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x10, 0x82, 0x24, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x0a, 0x04, 0x02, 0x81, 0x00, 0xa2, 0x40, 0x28, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2f, 0x40, 0x0b, 0xd0, 0x02, 0xb4, 0x00, 0xbd, 0x00, 0x2f, + 0x40, 0x0b, 0xd0, 0x02, 0x34, 0x00, 0x8d, 0x00, 0x23, 0x40, 0x08, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0a, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2d, 0x40, 0x0b, 0x50, 0x02, 0x14, 0x00, 0xb5, 0x00, 0x2d, + 0x40, 0x0b, 0xd0, 0x02, 0x34, 0x00, 0x8d, 0x00, 0x23, 0x40, 0x08, 0x50, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xa0, 0x00, 0xf8, 0x00, 0x3f, + 0x00, 0x0f, 0x80, 0x03, 0x20, 0x00, 0xc8, 0x00, 0x32, 0x00, 0x0c, 0xc0, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0xa0, 0xf9, 0x00, 0x3e, 0x40, 0x0e, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x28, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x10, 0x03, 0xc4, 0x00, 0xf1, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0x24, 0x00, 0xcd, 0x00, 0x32, 0x40, 0x08, 0x90, + 0x03, 0x26, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2f, 0x00, 0x0b, 0xc0, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x0a, 0x00, 0x02, 0x88, 0x00, 0xa2, 0x00, 0x28, 0x80, + 0x0a, 0x0e, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x08, 0xb1, 0x02, 0x2c, + 0x40, 0x8b, 0x90, 0x22, 0x24, 0x08, 0x89, 0x00, 0x22, 0x40, 0x08, 0x90, + 0x02, 0x02, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0x24, 0x00, 0x89, 0x10, 0x22, 0x40, 0x48, 0x90, + 0x02, 0x06, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x98, 0x03, 0x24, 0x00, 0xc9, 0x60, 0x30, 0x40, 0x0c, 0x90, + 0x03, 0x28, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x92, 0x03, 0xf4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x32, 0x00, 0x0e, 0x80, 0x03, 0xa0, 0x00, 0xe8, 0x00, 0x3a, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xc8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x01, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x10, + 0xba, 0x00, 0x2a, 0x80, 0x08, 0xa0, 0x12, 0x28, 0x04, 0x8a, 0x01, 0x22, + 0x80, 0x4b, 0x20, 0x12, 0xc8, 0x00, 0x82, 0xa0, 0x2e, 0x80, 0x0b, 0x20, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x20, 0xc0, 0x0a, 0x30, 0x02, 0x8c, 0x00, 0xa3, 0x00, 0x28, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0x81, 0x80, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0xc0, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0xa0, 0x2b, 0xa0, 0x88, 0xf8, 0x02, 0x3e, 0x00, 0x8f, 0x80, 0x21, + 0xc0, 0x0b, 0x70, 0x02, 0xfc, 0x00, 0x85, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xff, 0xc0, 0x31, 0xe4, 0x0e, 0x68, 0x03, 0x9e, 0x00, 0xe7, 0x80, 0x39, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xc5, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3c, 0x90, 0x0f, 0xa0, 0x83, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xee, 0x02, 0xf9, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x01, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0x3e, 0x00, 0xf7, 0x80, 0x33, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x01, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0x80, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x29, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x60, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0xf0, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x21, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xec, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x04, 0x2c, 0xa4, 0x0b, 0x29, 0x02, 0xce, 0x40, 0xb3, 0x90, 0x2c, + 0xfc, 0x0b, 0x30, 0x0a, 0x0c, 0x00, 0xb3, 0x30, 0x28, 0xe0, 0x0b, 0x34, + 0x82, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xbc, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xff, 0x00, 0x3e, 0xe0, 0x0f, 0xb8, 0x03, 0xee, 0x00, 0xfb, 0x80, 0x3e, + 0xe0, 0x0f, 0xb0, 0x03, 0x2e, 0x80, 0xf9, 0x80, 0x32, 0xc0, 0x0f, 0xb4, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xbb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x82, 0x0f, 0xb0, 0x83, 0xec, 0x20, 0xfb, 0x09, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xf9, 0x00, 0x3e, 0xc4, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x02, 0xcf, 0x04, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x02, 0x3f, 0xc0, 0x0e, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x20, 0xfd, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2c, 0x80, 0x08, 0xa0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xb9, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0a, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x14, 0x0c, 0x00, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0x80, 0x08, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x6c, 0x00, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0e, 0xa0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x80, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x07, 0x70, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xdf, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x00, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x14, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x04, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x04, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x1b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x09, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xef, 0x00, 0x3f, 0x80, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xcc, 0x00, 0x3f, + 0x00, 0x07, 0xc0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x33, 0xc0, 0x0d, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0x8b, 0x00, 0x2e, 0x80, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xf0, 0x00, 0x2c, + 0x00, 0x09, 0x80, 0x22, 0xac, 0x00, 0xbb, 0x02, 0x2a, 0xc0, 0x08, 0xb0, + 0x02, 0xf0, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xa3, 0x00, 0x2c, 0xc0, 0x0a, 0x00, 0x02, 0xc8, 0x00, 0x80, 0x00, 0x2c, + 0x00, 0x0b, 0x00, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x20, 0xc0, 0x09, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0x80, 0x02, 0xc8, 0x00, 0xa8, 0x00, 0x2e, + 0x02, 0x09, 0x00, 0x02, 0xac, 0x08, 0xbb, 0x00, 0x2a, 0xc0, 0x08, 0xb0, + 0x02, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xeb, 0x00, 0x3e, 0x80, 0x0e, 0x8a, 0x03, 0xe0, 0x80, 0x8b, 0x00, 0x3e, + 0x90, 0x0f, 0xb0, 0x0b, 0x2c, 0x04, 0xfb, 0x00, 0x32, 0xc0, 0x0d, 0xb0, + 0x03, 0xd0, 0x44, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x80, 0x0f, 0xc9, 0x03, 0xf0, 0x02, 0xff, 0x00, 0x3f, + 0x80, 0x0d, 0xf0, 0x83, 0xfc, 0x00, 0xf7, 0x00, 0x2f, 0xc0, 0x0b, 0xb0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0d, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xe0, 0x0f, 0x81, 0x03, 0xea, 0x20, 0xfb, 0x10, 0x32, + 0xb0, 0x0e, 0xb8, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0x90, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xe0, 0x0b, 0x84, 0x02, 0xea, 0x00, 0xbb, 0xc0, 0x36, + 0xa4, 0x0d, 0xbc, 0x03, 0x6c, 0x00, 0xbf, 0x00, 0x2c, 0xc0, 0x0b, 0xf0, + 0x02, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xec, 0x00, + 0xb3, 0x00, 0x2c, 0x80, 0x0b, 0x30, 0x02, 0x44, 0x00, 0x90, 0x00, 0x20, + 0x40, 0x08, 0x00, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xa1, 0x0b, 0x7c, 0x02, 0xd6, 0x00, 0xb4, 0xc0, 0x25, + 0x61, 0x09, 0x48, 0x02, 0x5e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0x38, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0f, 0x30, 0x03, 0x4c, 0x00, 0xd0, 0x00, 0xb0, + 0x40, 0x24, 0x80, 0x0b, 0x0c, 0x40, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0x92, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf1, 0x03, 0xfc, 0x40, 0xfc, 0x00, 0x3f, + 0x44, 0x0f, 0xc0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xeb, 0x00, 0x3a, 0x80, 0x0f, 0xb8, 0x01, 0x24, 0x00, 0xfb, 0x80, 0x36, + 0xe0, 0x0c, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x91, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0x80, 0x0b, 0xf0, 0x02, 0x94, 0x00, 0xbf, 0x00, 0x23, + 0xc0, 0x0a, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x20, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x26, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0x9e, 0x00, 0xb7, 0x80, 0x25, + 0xe0, 0x08, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x90, 0x2d, 0xe0, 0x0b, 0x7b, + 0x02, 0xc8, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x00, 0x8c, 0x00, 0xb3, 0xc0, 0x20, + 0xe4, 0x0a, 0x35, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xda, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x0b, 0xa8, 0x00, 0xfa, 0xa0, 0x36, + 0x80, 0x2c, 0xa8, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x22, 0xe0, 0x00, 0xf8, 0x08, 0x3e, + 0x00, 0x0f, 0x80, 0x83, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x98, 0x02, 0xe5, 0x00, 0xb9, 0x80, 0x2e, + 0x50, 0x0b, 0x94, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x60, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0x99, 0x00, 0x2e, 0x40, 0x0b, 0xd8, 0x02, 0x74, 0x00, 0xbd, 0x80, 0x2f, + 0x40, 0x0b, 0xd0, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x44, 0x0b, 0x90, + 0x02, 0xce, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x50, 0x02, 0xd6, 0x00, 0xb5, 0x00, 0x2d, + 0x60, 0x0b, 0x58, 0x02, 0xc4, 0x00, 0xb1, 0x28, 0x2c, 0x40, 0x0b, 0x12, + 0x82, 0xca, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xd8, 0x00, 0x3e, 0x00, 0x0f, 0xa0, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x7e, + 0x00, 0x0f, 0xc0, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x3e, 0x14, 0x0f, 0x82, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x9d, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0xa0, + 0xf9, 0x00, 0x3e, 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0xa0, 0xf9, 0x28, 0x3e, + 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x24, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x01, + 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0xd0, 0x03, 0x34, 0x00, 0xcd, 0x00, 0x3f, + 0x40, 0x0f, 0xd0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x3e, 0x00, 0x0b, 0x80, 0x02, 0xa0, 0x00, 0xa8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0f, 0x80, + 0x02, 0xce, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0x04, 0x00, 0x81, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2a, 0x40, 0x0b, 0x10, 0x02, 0xa4, 0x00, 0xa9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0a, 0x90, + 0x02, 0xc6, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x48, 0x0f, 0x90, 0x0b, 0x26, 0x02, 0xc9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0b, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x80, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xd2, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x02, 0x3e, 0x10, 0x0e, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x20, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0c, 0x80, + 0x03, 0xc2, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x10, + 0xba, 0x00, 0x2e, 0x80, 0x08, 0xe2, 0x02, 0xf8, 0x00, 0xbe, 0x40, 0x2f, + 0x82, 0x0b, 0xe0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0xa8, 0x08, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0x93, 0x00, 0x24, 0xc0, 0x0a, 0x38, 0x02, 0xee, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x04, 0xb7, 0x30, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x80, + 0xb7, 0x00, 0x2d, 0x70, 0x08, 0x60, 0x02, 0xd4, 0x20, 0xb6, 0x00, 0x2d, + 0x40, 0x0b, 0x54, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xe0, 0x08, 0x70, + 0x02, 0xe0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x80, + 0xd7, 0x80, 0x37, 0xe0, 0x2e, 0x58, 0x23, 0xda, 0x00, 0xf5, 0x80, 0x3d, + 0xa0, 0x0f, 0x68, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x2c, 0x78, + 0x03, 0xe2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x80, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xfa, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3c, 0xda, 0x0b, 0xb0, + 0x03, 0xc2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x20, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0c, 0xf8, + 0x03, 0xc0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x40, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2f, 0xc0, 0x0f, 0x70, + 0x02, 0xea, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xd8, 0x00, 0xb5, 0x00, 0x2d, + 0x80, 0x0b, 0x60, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0x40, 0x08, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xbb, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x1b, 0x10, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0x40, 0x0a, 0x30, + 0x02, 0xc8, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xff, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xfc, 0x00, + 0xfb, 0x00, 0x2e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0x40, 0x08, 0xb0, + 0x23, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xa4, 0x03, 0xe1, 0x00, 0xf8, 0x40, 0x3e, + 0x10, 0x0f, 0x84, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3b, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xc0, 0x03, 0xf8, 0x00, 0xfd, 0x00, 0x3f, + 0x80, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0x60, 0x0c, 0xf0, + 0x03, 0xe8, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x22, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x44, 0x0b, 0x84, 0x02, 0xe1, 0x40, 0xb8, 0x50, 0x2e, + 0x14, 0x0b, 0x85, 0x02, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0x40, 0x0a, 0xb0, + 0x02, 0xe8, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2a, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x0b, 0xb0, 0x82, 0xe4, 0x20, 0xba, 0x08, 0x2e, + 0x42, 0x0b, 0x90, 0x82, 0xec, 0x00, 0xbb, 0x00, 0x2c, 0xc4, 0x00, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x20, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0x40, 0x0b, 0x00, 0x02, 0xc0, 0x00, 0xb0, 0x00, 0x2c, + 0x00, 0x0b, 0x00, 0x02, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0a, 0x30, + 0x02, 0xc2, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3a, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xa0, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3f, 0x40, 0x0c, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x7f, 0x40, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, + 0x00, 0x0f, 0xc0, 0x03, 0x7c, 0x00, 0xff, 0x00, 0x3f, 0x40, 0x0f, 0xf0, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x04, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x07, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x33, + 0x00, 0x0d, 0xf0, 0x63, 0xfc, 0x00, 0xff, 0x00, 0x1f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x0b, 0xa0, 0x02, 0xc0, 0x00, 0xba, 0x00, 0x2a, + 0x80, 0x89, 0xf0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0x00, 0x0b, 0x10, 0x02, 0xc0, 0x00, 0xb0, 0x00, 0x20, + 0x00, 0x09, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x0b, 0xb0, 0x02, 0xe0, 0x00, 0xba, 0x00, 0x2a, + 0x80, 0x09, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x0e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x04, 0x0f, 0x80, 0x03, 0xec, 0x00, 0xf9, 0x00, 0xb2, + 0x08, 0x0d, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x60, 0x0f, 0xe0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0x81, 0x8f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0x6c, 0x00, + 0xfb, 0x00, 0x3e, 0x00, 0x0c, 0x98, 0x03, 0xec, 0x00, 0xc9, 0x80, 0x3e, + 0x00, 0x0f, 0xb0, 0x43, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x8f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x78, 0x08, 0xb8, 0x02, 0xed, 0x00, 0x8b, 0x90, 0x2e, + 0xb0, 0x03, 0xf0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xa0, 0x28, 0x00, 0x02, 0xc0, 0x00, 0x88, 0x01, 0x2c, + 0x60, 0x03, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xf0, 0x08, 0x68, 0x02, 0xd3, 0x00, 0x86, 0x80, 0x2d, + 0xf2, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3e, 0x80, 0x0c, 0x10, 0x03, 0xc0, 0x02, 0xc0, 0x00, 0x3c, + 0x40, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x01, 0xf0, 0x00, 0xfe, 0x00, 0x3f, + 0xc0, 0x0f, 0xfc, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xbb, 0x00, 0x3e, 0xa0, 0x0c, 0x80, 0x03, 0xec, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0xb4, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x08, 0x60, 0x02, 0xdc, 0x00, 0xf7, 0x06, 0x2d, + 0xc0, 0x0b, 0x7a, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0x97, 0x80, 0x2e, 0xa0, 0x28, 0x58, 0x02, 0xde, 0x00, 0xb5, 0x80, 0x2d, + 0x60, 0x0b, 0x79, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, 0x12, 0xcf, 0x40, 0xa3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xda, 0x00, 0x3e, 0x80, 0x0c, 0xa0, 0x03, 0xea, 0x00, 0xba, 0x40, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe1, 0x20, 0x78, 0x08, 0x3e, + 0x10, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x20, 0x3e, 0x40, 0x0f, 0x90, 0x01, 0x64, 0x00, 0xf9, 0x90, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x62, 0x0b, 0x94, 0x02, 0xe7, 0x00, 0xb9, 0xc0, 0x2e, + 0x60, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2f, 0x60, 0x0b, 0xd0, 0x42, 0x76, 0x20, 0xbd, 0x00, 0x2f, + 0x70, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2d, 0x40, 0x0b, 0x58, 0x22, 0xd4, 0x00, 0xb5, 0x80, 0x2d, + 0x40, 0x0b, 0x12, 0x82, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x3f, + 0x00, 0x0f, 0x82, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x28, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x28, 0x3e, 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0xa0, 0xf9, 0x28, 0x3e, + 0x4a, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xfd, 0x00, 0x3f, 0x40, 0x0f, 0xd0, 0x03, 0xf4, 0x02, 0xcd, 0x00, 0x3f, + 0x40, 0x0c, 0x90, 0x03, 0x64, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2c, 0x00, 0x0b, 0x00, 0x02, 0xe0, 0x00, 0xa0, 0x00, 0x2e, + 0x00, 0x0a, 0x80, 0x02, 0x20, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0x81, 0x00, 0x2c, + 0x40, 0x08, 0x10, 0x02, 0x44, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0a, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x82, 0xe4, 0x00, 0xa9, 0x00, 0x2c, + 0x40, 0x0a, 0x90, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x94, 0x03, 0xe4, 0x00, 0xc9, 0x00, 0x3e, + 0x40, 0x2c, 0x90, 0x03, 0x64, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0e, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x32, 0x00, 0x0f, 0x80, 0x07, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0c, 0x80, 0x03, 0x20, 0x00, 0xf8, 0x00, 0x32, + 0x00, 0x0c, 0x00, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x22, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2f, 0x80, 0x08, 0xe0, 0x00, 0x38, 0x80, 0xbe, 0x00, 0x37, + 0x80, 0x08, 0xa0, 0x02, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0xa0, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x28, 0x30, 0x0a, 0x2c, 0x00, 0xb3, 0x00, 0xa0, + 0xc0, 0x28, 0x30, 0x02, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x08, 0xb7, 0xa0, 0x21, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xa0, 0x08, 0x58, 0x02, 0x18, 0x00, 0xb5, 0x80, 0x25, + 0x80, 0x08, 0x30, 0x02, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xff, 0xe0, 0x31, 0xe0, 0x0f, 0x78, 0x02, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0x60, 0x0c, 0x68, 0x03, 0x16, 0x00, 0xf6, 0x80, 0x33, + 0x60, 0x0c, 0x78, 0x03, 0x5e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x80, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x1e, 0xc0, 0x0f, 0x80, 0x01, 0xe4, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x33, 0xe0, 0x0f, 0xf8, 0x03, 0x3e, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xbf, 0x00, 0x21, 0x80, 0x0b, 0xd0, 0x82, 0x18, 0x00, 0xb5, 0x08, 0x2d, + 0x82, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0xa1, 0x40, 0x0b, 0x60, 0x0a, 0x9c, 0x00, 0xb6, 0x00, 0x2d, + 0x40, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x20, 0xd0, 0x0b, 0x08, 0x02, 0x8c, 0x00, 0xb3, 0x80, 0x2c, + 0xe0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xff, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xf9, 0x00, 0x32, 0xd0, 0x0f, 0xb8, 0x03, 0xac, 0x00, 0xfb, 0x80, 0x3e, + 0xe0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xf9, 0x00, 0x3e, 0x88, 0x0f, 0xb4, 0x01, 0x68, 0x00, 0xf9, 0x00, 0x1e, + 0x80, 0x07, 0xb0, 0x01, 0xec, 0x00, 0x7b, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x40, 0x0f, 0xf2, 0x03, 0xf4, 0x00, 0xfe, 0x00, 0x3f, + 0x40, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb4, 0x82, 0xe4, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xb9, 0x10, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb1, 0x00, 0x2c, 0x80, 0x8b, 0x30, 0x02, 0xc8, 0x08, 0xb1, 0x02, 0x2c, + 0x80, 0x8b, 0x30, 0x22, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfa, 0x00, 0x3e, + 0x40, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x10, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x12, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x44, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd4, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xfe, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x91, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x24, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xe0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x9d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x26, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xd2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xda, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0x80, 0x0f, 0xc0, 0x03, 0x30, 0x00, 0xfc, 0x00, 0x33, + 0x00, 0x0c, 0xc0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x80, 0x02, 0xa0, 0x00, 0xba, 0x00, 0x2a, + 0x00, 0x0a, 0x80, 0x0a, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x00, 0xcc, 0x00, + 0x33, 0x00, 0x2c, 0x80, 0x0b, 0x20, 0x02, 0x08, 0x00, 0xb0, 0x00, 0x20, + 0x80, 0x0a, 0x00, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x26, 0xc0, 0x0b, 0x24, 0x26, 0xa8, 0x00, 0xba, 0x00, 0x28, + 0x82, 0x1a, 0x02, 0x02, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x80, 0x0f, 0x80, 0x03, 0x20, 0x80, 0xf8, 0x48, 0x32, + 0x10, 0x0e, 0x90, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x7e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x4f, 0xc0, 0x0b, 0xf0, 0x00, 0xfe, 0x08, 0x3f, + 0x00, 0x2f, 0xd0, 0x03, 0xfc, 0x01, 0xff, 0x01, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x01, 0xfb, 0x00, 0x7e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x80, 0x8d, 0xac, 0x83, 0x68, 0x04, 0xf8, 0xc0, 0x3e, + 0xb2, 0x0c, 0x90, 0x03, 0xec, 0x00, 0xcb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x8b, 0xb0, 0x22, 0xec, 0x01, + 0xbb, 0x00, 0x0e, 0xe0, 0x07, 0xac, 0x07, 0x6b, 0x00, 0xba, 0xc0, 0x2e, + 0xb0, 0x05, 0x9c, 0x02, 0xec, 0x04, 0x8b, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x12, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xa4, 0x09, 0x14, 0x02, 0x04, 0x00, 0xb9, 0x00, 0x2c, + 0x40, 0x09, 0x29, 0x02, 0xcc, 0x02, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0a, 0x59, 0x02, 0x57, 0x20, 0xb7, 0x80, 0x2d, + 0x60, 0x09, 0x6c, 0x02, 0xee, 0x00, 0x87, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xb3, 0x01, 0x3e, 0x80, 0x0d, 0xb0, 0x03, 0x4c, 0x00, 0xf1, 0x00, 0x3e, + 0xc0, 0x0d, 0x20, 0x03, 0xcc, 0x00, 0xc3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x07, 0xf0, 0x03, 0xfc, 0x00, + 0x7f, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc4, 0x0f, 0xe0, 0x03, 0xfe, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x88, 0x0f, 0x98, 0x03, 0xa4, 0x00, 0xf9, 0x00, 0x3e, + 0x60, 0x0e, 0xb8, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc1, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc4, 0x0b, 0x50, 0x02, 0x14, 0x00, 0xb7, 0x00, 0x2f, + 0x40, 0x08, 0xf0, 0x02, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xa0, 0x0b, 0x78, 0x02, 0x9e, 0x00, 0xb5, 0x80, 0x2d, + 0xe0, 0x0a, 0x78, 0x02, 0x1e, 0x00, 0xb7, 0x80, 0x25, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc1, 0x0b, 0x30, 0x42, 0xcc, 0x04, + 0xb3, 0x00, 0x24, 0xc0, 0x0b, 0x30, 0x42, 0x8c, 0x01, 0xb3, 0x00, 0x6c, + 0xc0, 0x08, 0x30, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xa8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x2e, 0xa5, 0x03, 0x28, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x01, 0x61, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x84, 0x0b, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x44, 0x0f, 0x94, 0x03, 0xe4, 0x00, 0xf9, 0x10, 0x3e, + 0x44, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x1e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x94, 0x02, 0xe7, 0x00, 0xb9, 0x40, 0x2e, + 0x50, 0x0b, 0x9c, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0xd0, 0x02, 0xf7, 0x00, 0xbd, 0x00, 0x2f, + 0x40, 0x0b, 0xdc, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x04, 0x31, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x41, 0x0b, 0x58, 0x02, 0xd4, 0x00, 0xb5, 0x80, 0x2d, + 0x60, 0x0b, 0x50, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3f, 0x00, 0x0f, 0x00, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x10, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0xa0, + 0xf9, 0x00, 0x3e, 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0xa0, 0xf9, 0x28, 0x3e, + 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x02, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0xd0, 0x03, 0xf4, 0x00, 0xed, 0x00, 0x33, + 0x40, 0x0e, 0xd0, 0x03, 0xe4, 0x00, 0xc9, 0x00, 0x3f, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x03, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xa8, 0x00, 0x2a, + 0x00, 0x08, 0x80, 0x02, 0xe0, 0x00, 0x88, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xa1, 0x00, 0x28, + 0x40, 0x0a, 0x10, 0x02, 0xe4, 0x00, 0x81, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0x64, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xc4, 0x00, 0xa1, 0x00, 0x28, + 0x40, 0x08, 0x90, 0x02, 0xe4, 0x00, 0x89, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x14, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x98, 0x03, 0xe6, 0x02, 0xe9, 0x00, 0x3a, + 0x60, 0x0e, 0x90, 0x03, 0xe4, 0x00, 0xc9, 0x00, 0x1e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0xa4, 0x00, 0xf9, 0x01, 0x3e, 0x40, 0x0f, 0x90, 0x13, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x4f, 0x92, 0x13, 0xe7, 0x00, 0xf9, 0x00, 0xbe, + 0x48, 0x4f, 0x90, 0x03, 0xc4, 0x02, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x10, 0x3e, + 0x04, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0c, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x04, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x02, 0x2e, 0x80, 0x03, 0xe3, 0x00, 0xf8, 0xc0, 0x3e, 0x80, 0x0f, + 0x80, 0x0b, 0xe1, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0a, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0xa0, 0x2c, + 0xc8, 0x0b, 0x34, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0x40, 0x08, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0xc0, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x50, 0x02, 0xd8, 0x00, 0xb5, 0x00, 0x2d, + 0x40, 0x0b, 0x60, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0x60, 0x02, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x80, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x68, 0x03, 0xd6, 0x00, 0xf6, 0x80, 0x3d, + 0xa0, 0x0f, 0x58, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0x60, 0x0c, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xbb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x04, 0x3e, 0x40, 0x0f, 0xa0, 0x43, 0xe8, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x80, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3c, 0x40, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xef, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xef, 0x80, 0x33, + 0xe0, 0x0f, 0xf8, 0x03, 0xbe, 0x00, 0xff, 0x80, 0x3f, 0x60, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xfc, 0x00, + 0x87, 0x00, 0x2d, 0xc0, 0x0b, 0x40, 0x02, 0xf4, 0x40, 0xae, 0x18, 0xa1, + 0x84, 0x0b, 0x70, 0x02, 0x1c, 0x40, 0xb7, 0x00, 0x2d, 0x40, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xa7, 0x00, 0x2d, 0xc0, 0x0b, 0x50, 0x02, 0xd0, 0x00, 0xa4, 0x00, 0x21, + 0x00, 0x0b, 0x40, 0x02, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0x40, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x14, 0xcc, 0x10, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0x83, 0x04, 0x2c, 0x50, 0x0b, 0x00, 0x42, 0xc0, 0x02, 0xa0, 0x00, 0x20, + 0x00, 0x0b, 0x00, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0x40, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xfc, 0x01, + 0xeb, 0x00, 0x3c, 0x50, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xeb, 0x80, 0x32, + 0xc0, 0x0f, 0xb0, 0x03, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x02, 0x3e, 0x40, 0x07, 0x90, 0x03, 0xe8, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x80, 0x43, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xea, 0x0c, 0x60, 0x03, 0x34, 0x00, 0xfe, 0x00, 0x3f, + 0x80, 0x0f, 0xf9, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0x40, 0x07, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x08, 0xa0, 0x02, 0xa8, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x80, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0x40, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x10, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x40, 0x08, 0xb0, 0x02, 0xac, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x22, 0xec, 0x04, 0xbb, 0x02, 0x2e, 0x40, 0x0b, 0xb0, + 0x42, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x40, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2e, 0x40, 0x28, 0x80, 0x02, 0x84, 0x00, 0xb2, 0x00, 0x2c, + 0x80, 0x0b, 0x10, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0x40, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0c, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0c, 0x90, 0x03, 0xa0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x07, 0x20, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0x40, 0x07, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x2f, 0x40, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x3f, + 0x00, 0x0f, 0xc0, 0x43, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0x40, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x15, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0xbc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, + 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, + 0xc0, 0x0f, 0x30, 0x03, 0xcc, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x0f, 0x30, + 0x03, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, + 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, + 0x02, 0xf0, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, + 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, + 0x03, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x10, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, + 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, + 0x02, 0xce, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, + 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, + 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0xa0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, + 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, + 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x1c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x1e, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, + 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, + 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3f, 0xe0, 0x0f, 0xf8, + 0x03, 0xd0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, + 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xc4, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xda, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x02, 0xe4, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, + 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x05, 0xfc, 0x14, 0xff, 0x00, 0x3f, 0xc0, 0x0d, 0xf0, 0x01, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xc0, 0x43, 0xb0, 0x00, 0xec, 0x00, 0x33, + 0x00, 0x0e, 0xc0, 0x03, 0x3c, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0c, 0xf0, + 0x03, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x10, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0x80, 0x02, 0x20, 0x00, 0xa8, 0x00, 0x2a, + 0x00, 0x0a, 0x00, 0x02, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0a, 0xb0, + 0x02, 0xf0, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc1, 0x01, 0x30, 0x02, 0xcc, 0x08, + 0xb3, 0x00, 0x0c, 0xc0, 0x1b, 0x00, 0x02, 0x80, 0x00, 0xa2, 0x00, 0x20, + 0x00, 0x0a, 0x00, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x08, 0x30, + 0x02, 0xf2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x15, 0xac, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0x6c, 0x00, + 0x9b, 0x00, 0x0e, 0xc0, 0x0b, 0x00, 0x02, 0x00, 0x00, 0xa2, 0x00, 0x28, + 0x00, 0x0a, 0x80, 0x02, 0xac, 0x04, 0xbb, 0x00, 0x0e, 0xc0, 0x1a, 0xb0, + 0x02, 0xf0, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x15, 0xec, 0x00, 0xfb, 0x06, 0x3e, 0xc0, 0x0d, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x0b, 0xac, 0x02, 0xe9, 0x00, 0x32, + 0xc0, 0x2e, 0x98, 0x03, 0x2c, 0x00, 0xfb, 0x06, 0x3e, 0xc0, 0x0c, 0xb0, + 0x43, 0xd0, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, + 0x01, 0xbc, 0x08, 0xff, 0x00, 0x3f, 0xc0, 0x4f, 0xf0, 0x03, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x8f, 0xf0, 0x83, 0xfc, 0x00, 0xfd, 0x00, 0x3f, + 0xc0, 0x0f, 0xd9, 0x03, 0xfc, 0x04, 0xff, 0x00, 0x7d, 0xc0, 0x0f, 0xf0, + 0x03, 0xf8, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x10, 0xac, 0x00, 0xfb, 0x06, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x10, + 0xfb, 0x00, 0x7e, 0xc0, 0x0f, 0xb8, 0x03, 0x6c, 0x00, 0xfb, 0x88, 0x32, + 0xc0, 0x03, 0x90, 0x03, 0x2c, 0x00, 0xfb, 0x02, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xd0, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x16, 0xec, 0x04, + 0xbb, 0x01, 0x2e, 0xc0, 0x0b, 0xbc, 0x03, 0x6d, 0x00, 0xbb, 0x80, 0x36, + 0xf0, 0x0b, 0x94, 0x03, 0x6c, 0x10, 0xbb, 0x02, 0x2f, 0xc0, 0x0b, 0xb0, + 0x02, 0xf2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x05, 0x4c, 0x14, 0xb3, 0x01, 0x2c, 0xc0, 0x4b, 0x30, 0x02, 0xcc, 0x10, + 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x04, 0x00, 0x00, 0x40, 0x30, 0x00, 0x20, + 0x01, 0x03, 0xa0, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x00, 0xf8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x1e, 0x10, 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x78, 0x02, 0xde, 0x00, + 0xb7, 0x80, 0x2d, 0xe0, 0x0b, 0x48, 0x02, 0x53, 0x00, 0xb4, 0x80, 0x25, + 0x33, 0x09, 0x6c, 0x02, 0xde, 0x00, 0xb7, 0x80, 0x0d, 0xe1, 0x0b, 0x78, + 0x02, 0xf8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x08, 0x0c, 0x00, 0xf3, 0x00, 0x2c, 0xc4, 0x0f, 0x30, 0x02, 0xcc, 0x54, + 0xf3, 0x00, 0x2c, 0xc0, 0x8f, 0x80, 0x0b, 0x40, 0x00, 0xfa, 0x00, 0xb0, + 0x04, 0x0f, 0x20, 0x0b, 0x8c, 0x00, 0xf3, 0x00, 0x3c, 0xc0, 0x07, 0x32, + 0x43, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x1d, 0xbc, 0x00, 0x7f, 0x00, 0x2f, 0xc5, 0x0f, 0xf1, 0x13, 0xfc, 0x00, + 0xbf, 0x00, 0x3f, 0xe0, 0x0f, 0xc0, 0x13, 0xf0, 0x40, 0xfe, 0x10, 0x3f, + 0x00, 0x0f, 0xe1, 0x01, 0x7c, 0x00, 0xff, 0x02, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xd0, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x05, 0xec, 0x14, 0xfb, 0x00, 0x3a, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xe0, 0x0c, 0xb0, 0x03, 0xee, 0x00, 0xc9, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x43, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xea, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x42, 0xdc, 0x00, + 0x97, 0x00, 0x2c, 0xc0, 0x08, 0x70, 0x42, 0xfc, 0x00, 0xa5, 0x00, 0x2d, + 0xc0, 0x09, 0xf0, 0x02, 0x1c, 0x04, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xf2, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, + 0x00, 0x9e, 0x00, 0xb7, 0x85, 0x2d, 0xe0, 0x03, 0x78, 0x02, 0xde, 0x04, + 0xb7, 0x84, 0x2f, 0xe0, 0x28, 0x78, 0x02, 0xde, 0x04, 0x87, 0x80, 0x6d, + 0xe0, 0x0b, 0x78, 0x02, 0x9e, 0x00, 0xb7, 0x80, 0x2d, 0xed, 0x0b, 0x78, + 0x02, 0xf0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc1, 0x0b, 0x30, 0x42, 0xcc, 0x01, + 0xb3, 0x00, 0x6c, 0xc0, 0x08, 0x35, 0x42, 0xcc, 0x00, 0xa3, 0x40, 0x2c, + 0xc0, 0x0b, 0x34, 0x02, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x4b, 0x30, + 0x02, 0xd2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x15, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x0f, 0xa0, 0x03, 0xe8, 0x10, + 0xfa, 0x00, 0x3e, 0x80, 0x4c, 0xa8, 0x03, 0xeb, 0x80, 0xca, 0x00, 0x3e, + 0xb8, 0x0f, 0xa0, 0x0b, 0xa8, 0x00, 0xfa, 0x00, 0x3e, 0x80, 0x4f, 0xa0, + 0x43, 0xfa, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0x58, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x81, 0xe0, 0x20, 0xf8, 0x08, 0x3e, + 0x02, 0x0d, 0x80, 0x83, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xd2, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0xcf, 0x90, 0x43, 0xe4, 0x02, + 0xc9, 0x00, 0x3e, 0x64, 0x0f, 0x98, 0x03, 0xe4, 0x04, 0xf9, 0x00, 0x36, + 0x40, 0x0f, 0x90, 0x03, 0x64, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x07, 0x90, + 0x43, 0xc2, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x64, 0x04, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x00, + 0x89, 0x00, 0x2e, 0x61, 0x0b, 0x94, 0x02, 0x66, 0x00, 0xb9, 0x40, 0x62, + 0x60, 0x0b, 0x98, 0x02, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x4b, 0x90, + 0x02, 0xe0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x05, 0x24, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xc4, 0x00, + 0xa9, 0x00, 0x2e, 0x40, 0x0b, 0xd1, 0x02, 0xf6, 0x00, 0xb5, 0x00, 0x27, + 0x60, 0x0b, 0x58, 0x02, 0x64, 0x01, 0xb9, 0x00, 0x2e, 0x40, 0x1b, 0x90, + 0x02, 0xc6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x04, 0x04, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xe4, 0x00, + 0x81, 0x04, 0x2c, 0x40, 0x0b, 0x58, 0x02, 0x54, 0x00, 0xb5, 0x80, 0x21, + 0xc0, 0x0b, 0x50, 0x02, 0x04, 0x00, 0xb1, 0x02, 0x2c, 0x4a, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x0d, 0x60, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xe8, 0x00, 0x3f, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, 0xf8, 0x00, 0x36, + 0x00, 0x0f, 0xc0, 0x03, 0x60, 0x00, 0xf8, 0x00, 0x3e, 0x08, 0x0f, 0x80, + 0x43, 0xee, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x1d, 0xe4, 0x00, 0xf9, 0x00, 0x2e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, + 0xf9, 0x00, 0x3e, 0x4a, 0x0f, 0x92, 0x92, 0x64, 0xa0, 0xf9, 0x28, 0x3e, + 0x4a, 0x0f, 0x92, 0x83, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x8f, 0x90, + 0x43, 0xe6, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x05, 0xe4, 0x02, 0xc9, 0x00, 0x3e, 0x41, 0x0f, 0x90, 0x03, 0xe4, 0x10, + 0xf9, 0x00, 0x3f, 0x40, 0x0f, 0xd0, 0x03, 0xf4, 0x00, 0xed, 0x00, 0x3f, + 0x40, 0x0c, 0xd0, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xe6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x10, 0xf0, 0x00, 0x88, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x42, 0xf0, 0x00, + 0xb8, 0x00, 0x2e, 0x00, 0x0b, 0x80, 0x02, 0xe0, 0x02, 0x88, 0x01, 0x2e, + 0x00, 0x2a, 0x80, 0x02, 0xe0, 0x04, 0xb8, 0x00, 0x2e, 0x01, 0x0b, 0x80, + 0x02, 0xce, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x05, 0xe4, 0x00, 0x81, 0x04, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, + 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, 0x02, 0xc4, 0x00, 0xa1, 0x00, 0x2c, + 0x40, 0x08, 0x10, 0x02, 0xc4, 0x00, 0xb1, 0x00, 0x2c, 0x40, 0x0b, 0x10, + 0x02, 0xc2, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x15, 0xa4, 0x00, 0x89, 0x00, 0x2e, 0x40, 0x0b, 0x90, 0x02, 0xe4, 0x04, + 0x99, 0x00, 0x2e, 0x40, 0x4b, 0x90, 0x02, 0xe4, 0x00, 0x89, 0x20, 0x2e, + 0x40, 0x0a, 0x90, 0x02, 0xe4, 0x00, 0xb9, 0x00, 0x2e, 0x40, 0x0b, 0x90, + 0x02, 0xc6, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x15, 0xe4, 0x00, 0xc9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x08, + 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe4, 0x00, 0xe9, 0x00, 0x3e, + 0x40, 0x0c, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x43, 0xe8, 0x04, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x01, 0xa4, 0x00, 0xf9, 0x02, 0x3e, 0x40, 0x0f, 0x90, 0x23, 0xe4, 0x14, + 0xf9, 0x04, 0x3e, 0x40, 0x4f, 0x90, 0x13, 0xe4, 0x00, 0xf9, 0x00, 0x3e, + 0x40, 0x4f, 0x90, 0x03, 0xe4, 0x00, 0xf9, 0x00, 0x3e, 0x40, 0x0f, 0x90, + 0x03, 0xca, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x10, 0x80, 0x00, 0xc8, 0x00, 0x3e, 0x00, 0x0f, 0x80, 0x03, 0xe0, 0x00, + 0xf8, 0x04, 0x3e, 0x00, 0x0f, 0x80, 0x23, 0xe0, 0x00, 0xf8, 0x00, 0x36, + 0x00, 0x0f, 0x80, 0x83, 0xe0, 0x00, 0xf8, 0x00, 0x3e, 0x00, 0x0f, 0x80, + 0x03, 0xca, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x28, 0x08, 0x8a, 0x00, 0x2e, 0x80, 0x0b, 0xa0, 0x02, 0xe8, 0x00, + 0x3a, 0x00, 0x0e, 0x80, 0x0b, 0xe0, 0x02, 0xf8, 0x00, 0xbe, 0x08, 0x23, + 0x80, 0x0b, 0xe4, 0x02, 0xe8, 0x00, 0xba, 0x00, 0x2e, 0x80, 0x0b, 0xa0, + 0x02, 0xca, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x05, 0x4c, 0x02, 0x83, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0xc1, 0x03, 0x30, 0x02, 0xed, 0x80, 0xb3, 0x00, 0x26, + 0xc1, 0x0b, 0x30, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc1, 0x0b, 0x30, + 0x02, 0xca, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x01, 0x3c, 0x00, 0x87, 0x00, 0x0d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x00, + 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x50, 0x02, 0xd8, 0x00, 0xb5, 0x80, 0x21, + 0x80, 0x0b, 0x60, 0x02, 0xdc, 0x01, 0xb7, 0x00, 0x2d, 0xc0, 0x03, 0x70, + 0x02, 0xe8, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x08, 0x0e, 0x08, 0xc7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, 0x03, 0xde, 0x00, + 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x68, 0x03, 0xd6, 0x00, 0xfe, 0x80, 0x35, + 0x60, 0x0f, 0x58, 0x03, 0xde, 0x00, 0xf7, 0x80, 0x3d, 0xe0, 0x0f, 0x78, + 0x03, 0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x1d, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x13, 0xec, 0x00, + 0xfb, 0x04, 0x3e, 0xc0, 0x0f, 0xb0, 0x43, 0xe8, 0x00, 0xf9, 0x00, 0x3e, + 0xc0, 0x0f, 0x80, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xc2, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0xfe, 0x00, 0xff, 0x90, 0x3f, 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x40, + 0xcf, 0x90, 0x3f, 0xe0, 0x0e, 0xf8, 0x03, 0x3e, 0x00, 0xff, 0x80, 0x3f, + 0xe0, 0x0f, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x80, 0x3b, 0xe0, 0x0f, 0xf8, + 0x03, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, + 0x11, 0x9c, 0x00, 0xb7, 0x00, 0x2d, 0xc0, 0x0b, 0x70, 0x02, 0xdc, 0x02, + 0x87, 0x00, 0x2f, 0xc0, 0x0f, 0x50, 0x02, 0x9c, 0x00, 0xb7, 0x12, 0x2d, + 0x80, 0x0b, 0x70, 0x02, 0xdc, 0x40, 0xb7, 0x04, 0x2d, 0xc0, 0x0b, 0x70, + 0x02, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x9e, 0x00, 0xb7, 0x02, 0x0d, 0xc0, 0x0b, 0x70, 0x02, 0xee, 0x04, + 0x87, 0x02, 0x2d, 0xc0, 0x0a, 0x60, 0x02, 0x14, 0x00, 0xb6, 0x00, 0x2d, + 0x40, 0x0b, 0x50, 0x02, 0xdc, 0x00, 0xb7, 0x00, 0x29, 0xc0, 0x0b, 0x70, + 0x02, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x14, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0x83, 0x04, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2e, + 0xc0, 0x0b, 0x10, 0x02, 0xcc, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc8, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, + 0x15, 0xac, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xcb, 0x00, 0x3e, 0x40, 0x0e, 0xb0, 0x03, 0x2c, 0x00, 0xfb, 0x00, 0x3e, + 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x01, 0x3a, 0xc1, 0x0f, 0xb0, + 0x03, 0xea, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0xec, 0x00, 0xfb, 0x00, 0x2e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0x40, 0x0f, 0x90, 0x03, 0xe8, 0x00, 0xf9, 0x00, 0x3e, + 0x80, 0x0f, 0xa0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x10, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc1, 0x0f, 0xf0, 0x23, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0x60, 0x03, 0x34, 0x00, 0xfe, 0x00, 0x3f, + 0x40, 0x0d, 0xf9, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe0, 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, + 0x04, 0x6c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0xe0, 0x0b, 0xb0, 0x02, 0xa8, 0x00, 0xb9, 0x00, 0x2e, + 0xc0, 0x08, 0xa0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc1, 0x0b, 0xb0, + 0x42, 0xe0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x05, 0x2c, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, 0x02, 0xec, 0x00, + 0xbb, 0x00, 0x2e, 0x48, 0x0b, 0xb0, 0x02, 0x2c, 0x00, 0xbb, 0x00, 0x2e, + 0xc0, 0x09, 0xb0, 0x02, 0xec, 0x00, 0xbb, 0x00, 0x2e, 0xc0, 0x0b, 0xb0, + 0x02, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x04, 0x0c, 0x00, 0xb3, 0x00, 0x2c, 0xc0, 0x0b, 0x30, 0x02, 0xcc, 0x00, + 0xb3, 0x00, 0x2c, 0x40, 0x0b, 0x90, 0x02, 0x8c, 0x00, 0xb3, 0x00, 0x2c, + 0x80, 0x08, 0x30, 0x02, 0xcc, 0x08, 0x33, 0x00, 0x2c, 0xc0, 0x0b, 0x30, + 0x02, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0d, 0x6c, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, 0x03, 0xec, 0x00, + 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0x20, 0x03, 0x24, 0x00, 0xfa, 0x00, 0x3e, + 0x40, 0x0d, 0xb0, 0x03, 0xec, 0x00, 0xfb, 0x00, 0x3e, 0xc0, 0x0f, 0xb0, + 0x03, 0xe0, 0x03, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x1d, 0xfc, 0x00, 0xff, 0x04, 0x3f, 0xc0, 0x4f, 0xf0, 0x01, 0xfc, 0x00, + 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, + 0xc0, 0x0f, 0xf0, 0x03, 0xfc, 0x00, 0xff, 0x00, 0x3f, 0xc0, 0x0f, 0xf0, + 0x03, 0xe8, 0x06, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x41, 0x03, 0x70, 0x40, 0xdc, 0x10, 0x37, 0x04, 0x0d, 0xc1, 0x03, + 0x70, 0x40, 0xdc, 0x10, 0x37, 0x04, 0x0d, 0xc1, 0x03, 0x70, 0x40, 0xdc, + 0x10, 0x37, 0x04, 0x0d, 0xc1, 0x03, 0x70, 0x40, 0xdc, 0x10, 0x37, 0x04, + 0x0d, 0xc0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x44, 0x05, 0x71, 0x01, 0x5c, 0x40, 0x57, 0x10, 0x15, 0xc4, 0x05, + 0x71, 0x01, 0x5c, 0x40, 0x57, 0x10, 0x15, 0xc4, 0x05, 0x71, 0x01, 0x5c, + 0x40, 0x57, 0x10, 0x15, 0xc4, 0x05, 0x71, 0x01, 0x5c, 0x40, 0x57, 0x10, + 0x15, 0xc0, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x02, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, + 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, + 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, + 0x04, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x01, 0x60, 0x00, 0x58, 0x00, 0x16, 0x00, 0x05, 0x80, 0x01, + 0x60, 0x00, 0x58, 0x00, 0x16, 0x00, 0x05, 0x80, 0x01, 0x60, 0x00, 0x58, + 0x00, 0x16, 0x00, 0x05, 0x80, 0x01, 0x60, 0x00, 0x58, 0x00, 0x16, 0x00, + 0x05, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x48, 0x05, 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, + 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, 0x72, 0x01, 0x5c, + 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, + 0x15, 0xc0, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x40, 0x00, 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, + 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x18, + 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, + 0x01, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x48, 0x04, 0x22, 0x01, 0x08, 0x80, 0x42, 0x20, 0x10, 0x88, 0x04, + 0x22, 0x01, 0x08, 0x80, 0x42, 0x20, 0x10, 0x88, 0x04, 0x22, 0x01, 0x08, + 0x80, 0x42, 0x20, 0x10, 0x88, 0x04, 0x22, 0x01, 0x08, 0x80, 0x42, 0x20, + 0x10, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x4a, 0x05, 0x42, 0x81, 0x50, 0xa0, 0x54, 0x28, 0x15, 0x0a, 0x05, + 0x42, 0x81, 0x50, 0xa0, 0x54, 0x28, 0x15, 0x0a, 0x05, 0x42, 0x81, 0x50, + 0xa0, 0x54, 0x28, 0x15, 0x0a, 0x05, 0x42, 0x81, 0x50, 0xa0, 0x54, 0x28, + 0x15, 0x00, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0c, 0x01, 0x53, 0x00, 0x54, 0xc0, 0x15, 0x30, 0x05, 0x4c, 0x01, + 0x53, 0x00, 0x54, 0xc0, 0x15, 0x30, 0x05, 0x4c, 0x01, 0x53, 0x00, 0x54, + 0xc0, 0x15, 0x30, 0x05, 0x4c, 0x01, 0x53, 0x00, 0x54, 0xc0, 0x15, 0x30, + 0x05, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, + 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, + 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x60, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, + 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, + 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, + 0x08, 0x01, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x40, 0x05, 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, + 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, 0x60, 0x01, 0x58, + 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, + 0x15, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x40, 0x03, 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, + 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, 0x60, 0x00, 0xd8, + 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, + 0x0d, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x42, 0x04, 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, + 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, 0x30, 0x81, 0x0c, + 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, + 0x10, 0xc0, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, + 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, + 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x00, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x02, 0x01, 0x30, 0x80, 0x4c, 0x20, 0x13, 0x08, 0x04, 0xc2, 0x01, + 0x30, 0x80, 0x4c, 0x20, 0x13, 0x08, 0x04, 0xc2, 0x01, 0x30, 0x80, 0x4c, + 0x20, 0x13, 0x08, 0x04, 0xc2, 0x01, 0x30, 0x80, 0x4c, 0x20, 0x13, 0x08, + 0x04, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x42, 0x05, 0x60, 0x81, 0x58, 0x20, 0x56, 0x08, 0x15, 0x82, 0x05, + 0x60, 0x81, 0x58, 0x20, 0x56, 0x08, 0x15, 0x82, 0x05, 0x60, 0x81, 0x58, + 0x20, 0x56, 0x08, 0x15, 0x82, 0x05, 0x60, 0x81, 0x58, 0x20, 0x56, 0x08, + 0x15, 0x80, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x42, 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, + 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x08, + 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, + 0x00, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x42, 0x04, 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, + 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0x81, 0x18, + 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, + 0x11, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x60, 0x05, 0x58, 0x01, 0x56, 0x00, 0x55, 0x80, 0x15, 0x60, 0x05, + 0x58, 0x01, 0x56, 0x00, 0x55, 0x80, 0x15, 0x60, 0x05, 0x58, 0x01, 0x56, + 0x00, 0x55, 0x80, 0x15, 0x60, 0x05, 0x58, 0x01, 0x56, 0x00, 0x55, 0x80, + 0x15, 0x40, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x06, 0x01, 0x41, 0x80, 0x50, 0x60, 0x14, 0x18, 0x05, 0x06, 0x01, + 0x41, 0x80, 0x50, 0x60, 0x14, 0x18, 0x05, 0x06, 0x01, 0x41, 0x80, 0x50, + 0x60, 0x14, 0x18, 0x05, 0x06, 0x01, 0x41, 0x80, 0x50, 0x60, 0x14, 0x18, + 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, + 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, + 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x46, 0x03, 0x51, 0x80, 0xd4, 0x60, 0x35, 0x18, 0x0d, 0x46, 0x03, + 0x51, 0x80, 0xd4, 0x60, 0x35, 0x18, 0x0d, 0x46, 0x03, 0x51, 0x80, 0xd4, + 0x60, 0x35, 0x18, 0x0d, 0x46, 0x03, 0x51, 0x80, 0xd4, 0x60, 0x35, 0x18, + 0x0d, 0x40, 0x31, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x46, 0x05, 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, + 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x5c, + 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, + 0x15, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x46, 0x03, 0x71, 0x80, 0xdc, 0x60, 0x37, 0x18, 0x0d, 0xc6, 0x03, + 0x71, 0x80, 0xdc, 0x60, 0x37, 0x18, 0x0d, 0xc6, 0x03, 0x71, 0x80, 0xdc, + 0x60, 0x37, 0x18, 0x0d, 0xc6, 0x03, 0x71, 0x80, 0xdc, 0x60, 0x37, 0x18, + 0x0d, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x46, 0x05, 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, + 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x5c, + 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, + 0x15, 0xc0, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, + 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, + 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, + 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x01, 0x61, 0x80, 0x58, 0x60, 0x16, 0x18, 0x05, 0x86, 0x01, + 0x61, 0x80, 0x58, 0x60, 0x16, 0x18, 0x05, 0x86, 0x01, 0x61, 0x80, 0x58, + 0x60, 0x16, 0x18, 0x05, 0x86, 0x01, 0x61, 0x80, 0x58, 0x60, 0x16, 0x18, + 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x40, 0x05, 0x70, 0x01, 0x5c, 0x00, 0x57, 0x00, 0x15, 0xc0, 0x05, + 0x70, 0x01, 0x5c, 0x00, 0x57, 0x00, 0x15, 0xc0, 0x05, 0x70, 0x01, 0x5c, + 0x00, 0x57, 0x00, 0x15, 0xc0, 0x05, 0x70, 0x01, 0x5c, 0x00, 0x57, 0x00, + 0x15, 0xc0, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x42, 0x00, 0x60, 0x80, 0x18, 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, + 0x60, 0x80, 0x18, 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, 0x60, 0x80, 0x18, + 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, 0x60, 0x80, 0x18, 0x20, 0x06, 0x08, + 0x01, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x42, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, + 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, 0x20, 0x81, 0x08, + 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, + 0x10, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x42, 0x05, 0x40, 0x81, 0x50, 0x20, 0x54, 0x08, 0x15, 0x02, 0x05, + 0x40, 0x81, 0x50, 0x20, 0x54, 0x08, 0x15, 0x02, 0x05, 0x40, 0x81, 0x50, + 0x20, 0x54, 0x08, 0x15, 0x02, 0x05, 0x40, 0x81, 0x50, 0x20, 0x54, 0x08, + 0x15, 0x00, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x50, 0xc0, 0x54, 0x30, 0x15, 0x0c, 0x05, 0x43, 0x01, + 0x50, 0xc0, 0x54, 0x30, 0x15, 0x0c, 0x05, 0x43, 0x01, 0x50, 0xc0, 0x54, + 0x30, 0x15, 0x0c, 0x05, 0x43, 0x01, 0x50, 0xc0, 0x54, 0x30, 0x15, 0x0c, + 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, + 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, 0x42, 0x00, 0x10, + 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x42, 0x02, 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, + 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, 0x00, 0x80, 0x80, + 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, + 0x08, 0x00, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x40, 0x05, 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, + 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, 0x60, 0x01, 0x58, + 0x00, 0x56, 0x00, 0x15, 0x80, 0x05, 0x60, 0x01, 0x58, 0x00, 0x56, 0x00, + 0x15, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc5, 0x40, 0x03, 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, + 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, 0x60, 0x00, 0xd8, + 0x00, 0x36, 0x00, 0x0d, 0x80, 0x03, 0x60, 0x00, 0xd8, 0x00, 0x36, 0x00, + 0x0d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x30, 0x01, 0x0c, 0x00, 0x43, 0x00, 0x10, 0xc0, 0x04, + 0x30, 0x01, 0x0c, 0x00, 0x43, 0x00, 0x10, 0xc0, 0x04, 0x30, 0x01, 0x0c, + 0x00, 0x43, 0x00, 0x10, 0xc0, 0x04, 0x30, 0x01, 0x0c, 0x00, 0x43, 0x00, + 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, + 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, + 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x01, 0x31, 0x40, 0x4c, 0x50, 0x13, 0x14, 0x04, 0xc5, 0x01, + 0x31, 0x40, 0x4c, 0x50, 0x13, 0x14, 0x04, 0xc5, 0x01, 0x31, 0x40, 0x4c, + 0x50, 0x13, 0x14, 0x04, 0xc5, 0x01, 0x31, 0x40, 0x4c, 0x50, 0x13, 0x14, + 0x04, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x23, 0x05, 0x68, 0xc1, 0x5a, 0x30, 0x56, 0x8c, 0x15, 0xa3, 0x05, + 0x68, 0xc1, 0x5a, 0x30, 0x56, 0x8c, 0x15, 0xa3, 0x05, 0x68, 0xc1, 0x5a, + 0x30, 0x56, 0x8c, 0x15, 0xa3, 0x05, 0x68, 0xc1, 0x5a, 0x30, 0x56, 0x8c, + 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, + 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x44, 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, 0x11, 0x88, 0x44, + 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, 0x11, 0x88, 0x44, 0x62, 0x11, 0x18, + 0x84, 0x46, 0x21, 0x11, 0x88, 0x44, 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, + 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x45, 0x50, 0x11, 0x54, 0x04, 0x55, 0x01, 0x15, 0x40, 0x45, + 0x50, 0x11, 0x54, 0x04, 0x55, 0x01, 0x15, 0x40, 0x45, 0x50, 0x11, 0x54, + 0x04, 0x55, 0x01, 0x15, 0x40, 0x45, 0x50, 0x11, 0x54, 0x04, 0x55, 0x01, + 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x21, 0x42, 0x08, 0x50, 0x82, 0x14, 0x20, 0x85, 0x08, 0x21, + 0x42, 0x08, 0x50, 0x82, 0x14, 0x20, 0x85, 0x08, 0x21, 0x42, 0x08, 0x50, + 0x82, 0x14, 0x20, 0x85, 0x08, 0x21, 0x42, 0x08, 0x50, 0x82, 0x14, 0x20, + 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x01, 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, + 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, 0x02, 0x80, 0x40, + 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x03, 0x53, 0x00, 0xd4, 0xc0, 0x35, 0x30, 0x0d, 0x4c, 0x03, + 0x53, 0x00, 0xd4, 0xc0, 0x35, 0x30, 0x0d, 0x4c, 0x03, 0x53, 0x00, 0xd4, + 0xc0, 0x35, 0x30, 0x0d, 0x4c, 0x03, 0x53, 0x00, 0xd4, 0xc0, 0x35, 0x30, + 0x0d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x05, 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, + 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, 0x72, 0x01, 0x5c, + 0x80, 0x57, 0x20, 0x15, 0xc8, 0x05, 0x72, 0x01, 0x5c, 0x80, 0x57, 0x20, + 0x15, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x23, 0x18, 0x48, 0xc6, 0x12, 0x31, 0x84, 0x8c, 0x61, 0x23, 0x18, + 0x48, 0xc6, 0x12, 0x31, 0x84, 0x8c, 0x61, 0x23, 0x18, 0x48, 0xc6, 0x12, + 0x31, 0x84, 0x8c, 0x61, 0x23, 0x18, 0x48, 0xc6, 0x12, 0x31, 0x84, 0x8c, + 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3b, 0x7e, 0x4e, 0xdf, 0x93, 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, + 0x4e, 0xdf, 0x93, 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, 0x4e, 0xdf, 0x93, + 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, 0x4e, 0xdf, 0x93, 0xb7, 0xe4, 0xed, + 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x70, 0x40, 0x9c, 0x10, 0x27, 0x1c, 0x09, 0xc1, 0x02, + 0x70, 0x40, 0x9c, 0x10, 0x27, 0x04, 0x09, 0xc1, 0x02, 0x70, 0x40, 0x1c, + 0x10, 0x27, 0x04, 0x01, 0xc1, 0x02, 0x70, 0x40, 0x1c, 0x50, 0x67, 0x14, + 0x49, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x05, 0x71, 0x01, 0x5c, 0x40, 0x57, 0x10, 0x15, 0xc4, 0x05, + 0x71, 0x01, 0x5c, 0x40, 0x57, 0x10, 0x15, 0xc4, 0x05, 0x71, 0x00, 0x5c, + 0x40, 0x57, 0x10, 0x05, 0xc4, 0x05, 0x71, 0x01, 0x5c, 0x40, 0x77, 0x10, + 0x15, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, + 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, + 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, + 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x18, 0x00, 0x06, 0x10, 0x81, 0x80, 0x00, + 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x18, + 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x09, 0x18, 0x42, 0x06, 0x18, + 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x04, 0x72, 0x01, 0x1c, 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, + 0x72, 0x01, 0x1c, 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, 0x72, 0x01, 0x1c, + 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, 0x72, 0x01, 0x1c, 0x80, 0x07, 0x21, + 0x11, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, + 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x18, + 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x18, 0x00, 0x06, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x04, 0x22, 0x01, 0x08, 0x80, 0x42, 0x60, 0x10, 0x88, 0x04, + 0x22, 0x01, 0x08, 0x80, 0x42, 0x20, 0x10, 0x88, 0x04, 0x22, 0x01, 0x08, + 0x80, 0x42, 0x20, 0x10, 0x88, 0x04, 0x24, 0x01, 0x09, 0xa0, 0x02, 0x60, + 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x2a, 0x04, 0x4a, 0x81, 0x12, 0xa0, 0x44, 0xa8, 0x11, 0x2a, 0x04, + 0x4a, 0x81, 0x12, 0xa0, 0x44, 0xa8, 0x11, 0x2a, 0x04, 0x4a, 0x81, 0x12, + 0xa0, 0x44, 0xa8, 0x11, 0x2a, 0x04, 0x48, 0x80, 0x12, 0xa1, 0x04, 0xac, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0xc0, 0x0c, 0x00, 0x53, 0x00, 0x14, 0xc0, 0x05, 0x30, 0x01, 0x4c, 0x00, + 0x53, 0x00, 0x14, 0xc0, 0x05, 0x30, 0x01, 0x4c, 0x00, 0x53, 0x00, 0x14, + 0xc0, 0x05, 0x30, 0x01, 0x4c, 0x00, 0x53, 0x00, 0x14, 0xc0, 0x05, 0x30, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, + 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, + 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x46, 0x00, 0x19, 0x01, 0x04, 0x40, + 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0xc0, 0x40, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x88, 0x00, 0x02, + 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x80, 0x02, 0x20, 0x00, + 0x88, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0xc0, 0x40, 0x04, 0x60, 0x01, 0x18, 0x00, 0x46, 0x00, 0x11, 0x80, 0x04, + 0x60, 0x01, 0x18, 0x00, 0x46, 0x00, 0x11, 0x80, 0x00, 0x60, 0x01, 0x98, + 0x00, 0x46, 0x00, 0x11, 0x80, 0x04, 0x60, 0x01, 0x98, 0x00, 0x46, 0x00, + 0x11, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x40, 0x02, 0x60, 0x00, 0x98, 0x00, 0x26, 0x00, 0x09, 0x80, 0x02, + 0x40, 0x00, 0x98, 0x00, 0x26, 0x00, 0x09, 0x80, 0x02, 0x60, 0x00, 0x98, + 0x00, 0x26, 0x00, 0x09, 0x80, 0x02, 0x62, 0x00, 0x18, 0x00, 0x26, 0x00, + 0x09, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x42, 0x04, 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, + 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, 0x30, 0x81, 0x0c, + 0x20, 0x43, 0x08, 0x10, 0xc2, 0x04, 0x30, 0x81, 0x0c, 0x20, 0x43, 0x08, + 0x90, 0xc0, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, + 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, + 0x00, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x02, 0x00, 0x30, 0x80, 0x0c, 0x20, 0x03, 0x08, 0x00, 0xc2, 0x00, + 0x30, 0x80, 0x0c, 0x20, 0x03, 0x08, 0x00, 0xc2, 0x00, 0x30, 0x80, 0x0c, + 0x20, 0x03, 0x08, 0x00, 0xc2, 0x00, 0x30, 0xc1, 0x0c, 0x20, 0x03, 0x08, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x42, 0x04, 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, + 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0x81, 0x18, + 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0xc1, 0x18, 0x20, 0x46, 0x08, + 0x11, 0x80, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x42, 0x00, 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, + 0x20, 0x80, 0x08, 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x08, + 0x20, 0x02, 0x08, 0x00, 0x82, 0x00, 0x20, 0x80, 0x0c, 0x20, 0x02, 0x08, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x01, 0x42, 0x04, 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, + 0x60, 0x81, 0x18, 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0x81, 0x18, + 0x20, 0x46, 0x08, 0x11, 0x82, 0x04, 0x60, 0x81, 0x0c, 0x20, 0x46, 0x08, + 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x40, 0x04, 0x50, 0x01, 0x14, 0x00, 0x45, 0x00, 0x11, 0x40, 0x04, + 0x50, 0x01, 0x14, 0x00, 0x45, 0x00, 0x11, 0x40, 0x04, 0x50, 0x01, 0x14, + 0x00, 0x45, 0x00, 0x11, 0x40, 0x04, 0x50, 0x00, 0x04, 0x00, 0x45, 0x00, + 0x11, 0x42, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x06, 0x00, 0x41, 0x80, 0x10, 0x60, 0x04, 0x18, 0x01, 0x06, 0x00, + 0x41, 0x80, 0x10, 0x60, 0x04, 0x18, 0x01, 0x06, 0x00, 0x41, 0x80, 0x10, + 0x60, 0x04, 0x18, 0x01, 0x06, 0x00, 0x41, 0x80, 0x10, 0x60, 0x04, 0x18, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, + 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x46, 0x03, 0x51, 0x80, 0xd4, 0x60, 0x35, 0x19, 0x0d, 0x46, 0x03, + 0x51, 0x80, 0xd4, 0x60, 0x35, 0x18, 0x0d, 0x46, 0x03, 0x51, 0x80, 0xd4, + 0x60, 0x35, 0x18, 0x0d, 0x46, 0x03, 0x51, 0x90, 0xd4, 0x64, 0x35, 0x19, + 0x0d, 0x40, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x46, 0x04, 0x71, 0x81, 0x1c, 0x60, 0x47, 0x18, 0x11, 0xc6, 0x04, + 0x71, 0x81, 0x1c, 0x60, 0x47, 0x18, 0x11, 0xc6, 0x04, 0x71, 0x81, 0x1c, + 0x60, 0x47, 0x18, 0x11, 0xc6, 0x04, 0x71, 0x81, 0x9c, 0x60, 0x47, 0x18, + 0x91, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x46, 0x02, 0x71, 0x80, 0x9c, 0x60, 0x27, 0x18, 0x09, 0xc6, 0x02, + 0x71, 0x80, 0x9c, 0x60, 0x27, 0x18, 0x09, 0xc6, 0x02, 0x71, 0x80, 0x9c, + 0x60, 0x67, 0x18, 0x09, 0xc6, 0x02, 0x71, 0x80, 0x1c, 0x60, 0x27, 0x18, + 0x09, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x45, 0x46, 0x05, 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, + 0x71, 0x81, 0x5c, 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x5c, + 0x60, 0x57, 0x18, 0x15, 0xc6, 0x05, 0x71, 0x81, 0x0c, 0x60, 0x57, 0x18, + 0x15, 0xc2, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x02, 0x01, 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, + 0x20, 0x80, 0x48, 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x48, + 0x20, 0x12, 0x08, 0x04, 0x82, 0x01, 0x20, 0x80, 0x5c, 0x20, 0x12, 0x48, + 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x06, 0x00, 0x61, 0x80, 0x18, 0x60, 0x06, 0x18, 0x01, 0x86, 0x10, + 0x61, 0x80, 0x18, 0x60, 0x06, 0x18, 0x01, 0x86, 0x00, 0x61, 0x80, 0x18, + 0x60, 0x06, 0x18, 0x01, 0x86, 0x00, 0x61, 0x81, 0x18, 0x60, 0x06, 0x18, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x60, 0x04, 0x78, 0x01, 0x1e, 0x00, 0x47, 0x80, 0x11, 0xe0, 0x04, + 0x78, 0x01, 0x1e, 0x00, 0x47, 0x80, 0x11, 0xe0, 0x04, 0x78, 0x01, 0x1e, + 0x00, 0x07, 0x80, 0x11, 0xe0, 0x04, 0x78, 0x01, 0x1e, 0x00, 0x47, 0x80, + 0x11, 0xc0, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x42, 0x00, 0x60, 0x80, 0x18, 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, + 0x60, 0x80, 0x18, 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, 0x60, 0x80, 0x18, + 0x20, 0x06, 0x08, 0x01, 0x82, 0x00, 0x60, 0x80, 0x18, 0x20, 0x06, 0x48, + 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x42, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, + 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, 0x20, 0x81, 0x08, + 0x20, 0x02, 0x08, 0x10, 0x82, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, + 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x42, 0x04, 0x40, 0x81, 0x10, 0x20, 0x44, 0x08, 0x11, 0x02, 0x04, + 0x40, 0x81, 0x10, 0x20, 0x44, 0x08, 0x11, 0x02, 0x04, 0x40, 0x81, 0x10, + 0x20, 0x44, 0x08, 0x11, 0x02, 0x04, 0x40, 0x80, 0x10, 0x20, 0x44, 0x08, + 0x11, 0x00, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x03, 0x00, 0x50, 0xc0, 0x14, 0x30, 0x05, 0x0c, 0x01, 0x43, 0x00, + 0x50, 0xc0, 0x14, 0x30, 0x05, 0x0c, 0x01, 0x43, 0x00, 0x50, 0xc0, 0x14, + 0x30, 0x05, 0x0c, 0x01, 0x43, 0x00, 0x50, 0xc0, 0x14, 0x30, 0x05, 0x08, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x08, 0x00, 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, + 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, 0x42, 0x00, 0x10, + 0x80, 0x04, 0x20, 0x01, 0x08, 0x00, 0x42, 0x00, 0x10, 0x80, 0x04, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x42, 0x02, 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, + 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, 0x00, 0x80, 0x80, + 0x20, 0x20, 0x08, 0x08, 0x02, 0x02, 0x00, 0x80, 0x80, 0x20, 0x20, 0x08, + 0x08, 0x80, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x40, 0x04, 0x60, 0x01, 0x18, 0x00, 0x46, 0x00, 0x11, 0x80, 0x00, + 0x60, 0x01, 0x18, 0x00, 0x46, 0x00, 0x11, 0x80, 0x04, 0x60, 0x01, 0x18, + 0x00, 0x06, 0x00, 0x11, 0x80, 0x04, 0x60, 0x01, 0x98, 0x00, 0x46, 0x00, + 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x40, 0x02, 0x60, 0x00, 0x98, 0x00, 0x26, 0x00, 0x09, 0x80, 0x02, + 0x60, 0x00, 0x98, 0x00, 0x26, 0x00, 0x19, 0x80, 0x02, 0x60, 0x00, 0x98, + 0x00, 0x26, 0x00, 0x09, 0x80, 0x02, 0x60, 0x00, 0x1c, 0x00, 0x26, 0x00, + 0x09, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x60, 0x04, 0x38, 0x01, 0x0e, 0x00, 0x43, 0x80, 0x10, 0xe0, 0x04, + 0x38, 0x01, 0x0e, 0x00, 0x43, 0x80, 0x10, 0xe0, 0x04, 0x38, 0x01, 0x0e, + 0x00, 0x43, 0x80, 0x10, 0xe0, 0x04, 0x38, 0x01, 0x1a, 0x00, 0x43, 0x80, + 0x10, 0xc0, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x01, 0x00, 0x30, 0x40, 0x0c, 0x10, 0x03, 0x04, 0x00, 0xc1, 0x00, + 0x30, 0x40, 0x0c, 0x10, 0x03, 0x04, 0x00, 0xc1, 0x00, 0x30, 0x40, 0x0c, + 0x10, 0x03, 0x04, 0x00, 0xc1, 0x00, 0x30, 0x40, 0x08, 0x10, 0x03, 0x04, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x05, 0x00, 0x31, 0x44, 0x0c, 0x50, 0x03, 0x14, 0x00, 0xc5, 0x00, + 0x31, 0x40, 0x0c, 0x50, 0x03, 0x14, 0x10, 0xc5, 0x00, 0x31, 0x40, 0x0c, + 0x50, 0x03, 0x14, 0x00, 0xc5, 0x00, 0x31, 0x41, 0x0c, 0x50, 0x03, 0x10, + 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x43, 0x04, 0x60, 0xc1, 0x18, 0x30, 0x46, 0x0c, 0x11, 0x83, 0x04, + 0x60, 0xc1, 0x18, 0x30, 0x46, 0x0c, 0x01, 0x83, 0x04, 0x60, 0xc1, 0x18, + 0x30, 0x46, 0x0c, 0x11, 0x83, 0x04, 0x60, 0xc1, 0x18, 0x30, 0x46, 0x0c, + 0x11, 0x80, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x40, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, + 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x48, 0x44, 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, 0x11, 0x88, 0x44, + 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, 0x01, 0x88, 0x44, 0x62, 0x11, 0x18, + 0x84, 0x46, 0x21, 0x11, 0x88, 0x44, 0x62, 0x11, 0x18, 0x84, 0x46, 0x21, + 0x11, 0x80, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x40, 0x44, 0x50, 0x11, 0x14, 0x04, 0x45, 0x01, 0x11, 0x40, 0x44, + 0x50, 0x11, 0x14, 0x04, 0x45, 0x01, 0x01, 0x40, 0x44, 0x50, 0x11, 0x14, + 0x04, 0x45, 0x01, 0x11, 0x40, 0x44, 0x50, 0x10, 0x14, 0x04, 0x45, 0x01, + 0x11, 0x40, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x08, 0x20, 0x42, 0x08, 0x10, 0x82, 0x04, 0x20, 0x01, 0x08, 0x20, + 0x42, 0x08, 0x10, 0x82, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, + 0x82, 0x04, 0x20, 0x81, 0x08, 0x20, 0x42, 0x08, 0x10, 0x80, 0x04, 0x20, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x01, 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, + 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, 0x02, 0x80, 0x40, + 0xa0, 0x10, 0x28, 0x04, 0x0a, 0x01, 0x02, 0x80, 0x40, 0xa0, 0x10, 0x28, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x45, 0x4d, 0x03, 0x53, 0x40, 0xd4, 0xd0, 0x35, 0x34, 0x0d, 0x4d, 0x03, + 0x53, 0x40, 0xd4, 0xd0, 0x35, 0x34, 0x0d, 0x4d, 0x03, 0x53, 0x40, 0xd4, + 0xd0, 0x35, 0x34, 0x0d, 0x4d, 0x03, 0x53, 0x40, 0xd4, 0xd0, 0x35, 0x34, + 0x0d, 0x40, 0x11, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x48, 0x04, 0x72, 0x00, 0x1c, 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, + 0x72, 0x01, 0x1c, 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, 0x72, 0x01, 0x1c, + 0x80, 0x47, 0x20, 0x11, 0xc8, 0x04, 0x72, 0x01, 0x9c, 0x80, 0x47, 0x20, + 0x11, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x23, 0x18, 0x48, 0xc6, 0x12, 0x31, 0x84, 0x8c, 0x41, 0x23, 0x18, + 0x48, 0xc6, 0x12, 0x31, 0x84, 0x8c, 0x61, 0x23, 0x18, 0x48, 0xc6, 0x12, + 0x31, 0x84, 0x8c, 0x61, 0x23, 0x18, 0x48, 0xc4, 0x12, 0x31, 0x04, 0x8c, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, + 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, + 0xff, 0xf4, 0xff, 0xfd, 0x3f, 0xff, 0x4f, 0xff, 0xd3, 0xff, 0xf4, 0xff, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3b, 0x7e, 0x4e, 0xdf, 0x93, 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, + 0x4e, 0xdf, 0x93, 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, 0x4e, 0xdf, 0x93, + 0xb7, 0xe4, 0xed, 0xf9, 0x3b, 0x7e, 0x4e, 0xde, 0x13, 0xb7, 0xe4, 0xec, + 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x02, 0x84, 0x00, 0xa1, 0x00, 0x28, 0x40, 0x0a, 0x10, 0x02, 0x84, + 0x00, 0xa1, 0x00, 0x28, 0x40, 0x0a, 0x10, 0x02, 0x84, 0x00, 0xa1, 0x00, + 0x28, 0x40, 0x0a, 0x10, 0x02, 0x84, 0x00, 0xa1, 0x00, 0x28, 0x40, 0x0a, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x84, 0x00, 0x21, 0x00, 0x88, 0x40, 0x02, 0x10, 0x00, 0x84, + 0x00, 0x21, 0x00, 0x88, 0x40, 0x22, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, + 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, + 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, + 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x08, 0x80, 0x02, 0x20, 0x00, 0x88, 0x00, 0x22, 0x00, 0x08, 0x80, + 0x02, 0x20, 0x00, 0x88, 0x00, 0x22, 0x00, 0x08, 0x80, 0x02, 0x20, 0x00, + 0x88, 0x00, 0x22, 0x00, 0x08, 0x80, 0x02, 0x20, 0x00, 0x88, 0x00, 0x22, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, + 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, + 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x0a, 0x84, 0x02, 0xa1, 0x00, 0xa8, 0x40, 0x2a, 0x10, 0x0a, 0x84, + 0x02, 0xa1, 0x00, 0xa8, 0x40, 0x2a, 0x10, 0x0a, 0x84, 0x02, 0xa1, 0x00, + 0xa8, 0x40, 0x2a, 0x10, 0x0a, 0x84, 0x02, 0xa1, 0x00, 0xa8, 0x40, 0x2a, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, + 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x84, 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, + 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, + 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x07, 0x30, 0x01, 0xcc, 0x00, 0x73, 0x00, 0x1c, 0xc0, 0x07, + 0x30, 0x01, 0xcc, 0x00, 0x73, 0x00, 0x1c, 0xc0, 0x07, 0x30, 0x01, 0xcc, + 0x00, 0x73, 0x00, 0x1c, 0xc0, 0x07, 0x30, 0x01, 0xcc, 0x00, 0x73, 0x00, + 0x1c, 0xc0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x84, 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, + 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, + 0x08, 0x40, 0x02, 0x10, 0x00, 0x84, 0x00, 0x21, 0x00, 0x08, 0x40, 0x02, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, + 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, + 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x02, 0x84, 0x04, 0xa1, 0xcd, 0x28, 0x41, 0x0a, 0x10, 0xc2, 0x84, + 0x00, 0xa1, 0x0a, 0x28, 0x40, 0x0a, 0x10, 0xc2, 0x04, 0x00, 0xa1, 0x02, + 0x28, 0x40, 0x0a, 0x10, 0x02, 0x84, 0x24, 0xa1, 0x09, 0x28, 0x40, 0x0a, + 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x05, 0x10, 0x01, 0x06, 0x00, 0x42, 0x00, 0x10, 0x80, 0x04, + 0x18, 0x01, 0x00, 0x00, 0x43, 0x00, 0x10, 0xc0, 0x44, 0x08, 0x01, 0x00, + 0x00, 0x40, 0x00, 0x10, 0x00, 0x04, 0x10, 0x01, 0x06, 0x80, 0x42, 0x00, + 0x10, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x08, 0xc6, 0x26, 0x21, 0x08, 0x08, 0x41, 0x42, 0x10, 0xc8, 0xc4, + 0x26, 0x31, 0x0a, 0x88, 0x43, 0x62, 0x10, 0x88, 0xc4, 0x06, 0x21, 0x02, + 0x88, 0x40, 0x62, 0x10, 0x00, 0x84, 0x26, 0x21, 0x08, 0x88, 0x40, 0x62, + 0x10, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x30, 0x04, 0x24, 0x01, 0xc7, 0x00, 0x41, 0x40, 0x10, 0xf0, 0x04, + 0x00, 0x01, 0x08, 0x00, 0x41, 0x40, 0x10, 0xf0, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x40, 0x40, 0x10, 0x30, 0x04, 0x04, 0x01, 0x03, 0x00, 0x41, 0x40, + 0x10, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x24, 0x20, 0x00, 0x08, 0x20, 0x02, 0x00, 0x80, 0x02, + 0x20, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, + 0x08, 0x20, 0x02, 0x00, 0x00, 0x80, 0x04, 0x20, 0x00, 0x04, 0x22, 0x02, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x02, 0x00, 0x10, 0x80, 0x44, 0x20, 0x10, 0x08, 0x00, 0x42, 0x41, + 0x10, 0x90, 0x00, 0x20, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x80, 0x04, + 0x20, 0x10, 0x08, 0x00, 0x02, 0x01, 0x10, 0x80, 0x00, 0x20, 0x11, 0x08, + 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x08, 0xc0, 0x2e, 0x20, 0x08, 0x88, 0x02, 0x22, 0x00, 0xa8, 0xc2, + 0x26, 0x30, 0x03, 0x88, 0x00, 0x22, 0x00, 0x28, 0xc0, 0x06, 0x20, 0x0b, + 0x88, 0x20, 0x22, 0x00, 0x08, 0x82, 0x2e, 0x20, 0x00, 0x88, 0x22, 0x22, + 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x18, 0x00, 0x0a, 0x00, 0x89, 0x80, 0x22, 0x20, 0x00, 0x88, 0x02, + 0x02, 0x00, 0x02, 0x80, 0x00, 0x60, 0x00, 0x08, 0x00, 0x02, 0x00, 0x02, + 0x80, 0x00, 0x60, 0x00, 0x18, 0x00, 0x2a, 0x00, 0x01, 0x80, 0x20, 0x20, + 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x2a, 0x84, 0x12, 0xa1, 0x82, 0xa8, 0x61, 0x6a, 0x10, 0xca, 0x84, + 0x3e, 0xa1, 0x04, 0xa8, 0x50, 0xaa, 0x10, 0x4a, 0x84, 0x0e, 0xa1, 0x00, + 0xa8, 0x60, 0xaa, 0x10, 0x2a, 0x84, 0x22, 0xa1, 0x0e, 0xa8, 0x60, 0x6a, + 0x10, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x04, 0x22, 0x81, 0x48, 0x80, 0x52, 0x20, 0x10, 0xc8, 0x04, + 0x36, 0x01, 0x0d, 0x80, 0x61, 0x20, 0x10, 0x88, 0x04, 0x06, 0x01, 0x01, + 0x80, 0x52, 0x20, 0x10, 0x08, 0x04, 0x32, 0x01, 0x0c, 0x80, 0x51, 0x20, + 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x84, 0x30, 0x31, 0x0c, 0x08, 0x43, 0x42, 0x10, 0xe0, 0x84, + 0x20, 0x31, 0x0c, 0x08, 0x52, 0x02, 0x10, 0xe0, 0x04, 0x00, 0x21, 0x00, + 0x08, 0x61, 0x02, 0x10, 0x00, 0x84, 0x30, 0x21, 0x08, 0x08, 0x62, 0x42, + 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x30, 0x04, 0x20, 0x01, 0x8e, 0x00, 0x63, 0x40, 0x1c, 0x50, 0x07, + 0x30, 0x01, 0xc0, 0x00, 0x73, 0x00, 0x10, 0xd0, 0x07, 0x30, 0x01, 0xcc, + 0x00, 0x53, 0x00, 0x1c, 0xf0, 0x07, 0x10, 0x01, 0xc2, 0x00, 0x51, 0x40, + 0x1c, 0xc0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x84, 0x08, 0x21, 0x08, 0x08, 0x41, 0x02, 0x10, 0x40, 0x86, + 0x04, 0x01, 0x04, 0x08, 0x40, 0x42, 0x10, 0x40, 0x84, 0x04, 0x21, 0x00, + 0x08, 0x40, 0x42, 0x10, 0x20, 0x86, 0x18, 0x21, 0x00, 0x04, 0x41, 0x02, + 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, 0x24, 0x00, 0x0e, 0x20, 0x02, 0xc8, 0x00, 0x82, 0x01, + 0x38, 0x90, 0x09, 0x20, 0x01, 0x08, 0x00, 0xc2, 0x00, 0x08, 0x80, 0x01, + 0x20, 0x02, 0x08, 0x00, 0x02, 0x01, 0x24, 0x80, 0x0e, 0x20, 0x02, 0xc8, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x82, 0x10, 0x30, 0x08, 0x08, 0x01, 0x42, 0x00, 0x70, 0x80, + 0x20, 0x30, 0x0c, 0x08, 0x02, 0x42, 0x00, 0xf0, 0xc0, 0x00, 0x20, 0x00, + 0x08, 0x01, 0x42, 0x00, 0x10, 0x82, 0x10, 0x20, 0x08, 0x08, 0x01, 0x42, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x80, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, + 0x30, 0x00, 0x0e, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x3c, 0x30, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x00, 0x10, 0xf0, 0x80, + 0x80, 0x80, 0x00, 0x00, 0x10, 0x00, 0x10, 0xf0, 0x80, 0x80, 0x80, 0x00, + 0x00, 0x10, 0x00, 0x10, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x00, + 0x10, 0xcf, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x59, 0x80, 0x40, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, + 0x09, 0x80, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x30, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x22, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3e, 0x6f, 0xfe, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xfd, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3e, 0x6f, 0xbe, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x7f, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfb, + 0xff, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x37, 0x3f, 0x3d, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xef, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xbf, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x20, 0x01, 0x02, 0x02, 0x00, 0x00, 0x30, 0x00, 0x43, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x19, 0xaf, 0x30, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x03, 0x30, 0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x05, 0x30, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x01, 0x00, 0x00, 0xe1, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/kernel/drv/oss_envy24/oss_envy24.c b/kernel/drv/oss_envy24/oss_envy24.c new file mode 100644 index 0000000..b3b82bd --- /dev/null +++ b/kernel/drv/oss_envy24/oss_envy24.c @@ -0,0 +1,4043 @@ +/* + * Purpose: Driver for IC Ensemble ENVY24 based audio cards. + * + * The audio input and output devices implemented by this driver use additional + * layer of buffering for channel re-interleaving. The device itself uses + * 10/12 channel interleaved 32 bit format in hardware level. The + * re-interleaving engine splits these multi channel devices to several + * "stereo" devices. + */ +/* + * + * 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_envy24_cfg.h" +#include <ac97.h> +#include <oss_pci.h> + +#include "envy24.h" + +extern int envy24_skipdevs; +extern int envy24_force_mono; +extern int envy24_gain_sliders; +int envy24_virtualout = 0; /* This used to be an config option */ + +extern int envy24_devmask; +#define DMASK_ANALOGOUT 1 +#define DMASK_ANALOGIN 2 +#define DMASK_SPDIFOUT 4 +#define DMASK_SPDIFIN 8 +#define DMASK_MONITORIN 16 +#define DMASK_RAWDEVS 32 + +extern envy24_auxdrv_t default_auxdrv; +extern envy24_auxdrv_t ap2496_auxdrv; +extern envy24_auxdrv_t d410_auxdrv; +extern envy24_auxdrv_t d1010lt_auxdrv; +extern envy24_auxdrv_t tdif_auxdrv; +extern envy24_auxdrv_t ewx2496_auxdrv; +extern envy24_auxdrv_t ews88d_auxdrv; +extern envy24_auxdrv_t dmx6fire_auxdrv; + +static card_spec models[] = { + {0xd6301412, "M Audio Delta 1010", 8, 8, + MF_MAUDIO | MF_MIDI1 | MF_SPDIF | MF_WCLOCK | MF_MEEPROM}, + {0xd6311412, "M Audio Delta DiO 2496", 2, 0, + MF_MAUDIO | MF_SPDIF | MF_SPDSELECT | MF_MEEPROM}, + {0xd6321412, "M Audio Delta 66", 4, 4, + MF_MAUDIO | MF_SPDIF | MF_AKMCODEC | MF_MEEPROM}, + {0xd6331412, "M Audio Delta 44", 4, 4, + MF_MAUDIO | MF_AKMCODEC | MF_MEEPROM}, + {0xd6341412, "M Audio Audiophile 2496", 2, 2, + MF_AP | MF_SPDIF | MF_MIDI1 | MF_MEEPROM, &ap2496_auxdrv}, + {0xd6381412, "M Audio Delta 410", 8, 2, MF_D410 | MF_SPDIF | MF_MEEPROM, + &d410_auxdrv}, + + /* Delta 1010 rev E is based on 1010LT instead of the original 1010 design */ + {0xd63014ff, "M Audio Delta 1010 rev E", 8, 8, + MF_MIDI1 | MF_SPDIF | MF_MEEPROM | MF_WCLOCK, &d1010lt_auxdrv}, + + {0xd63b1412, "M Audio Delta 1010LT", 8, 8, + MF_MIDI1 | MF_SPDIF | MF_MEEPROM | MF_WCLOCK, &d1010lt_auxdrv}, + {0xd6351412, "M Audio Delta TDIF", 8, 8, MF_SPDIF | MF_MEEPROM | MF_WCLOCK, + &tdif_auxdrv}, + {0x1115153b, "Terratec EWS88MT", 8, 8, + MF_MIDI1 | MF_SPDIF | MF_EWS88 | MF_AC97}, + {0x112b153b, "Terratec EWS88D", 8, 8, + MF_MIDI1 | MF_MIDI2 | MF_SPDIF | MF_AC97 | MF_WCLOCK, &ews88d_auxdrv}, + {0x1130153b, "Terratec EWX 24/96", 2, 2, MF_SPDIF | MF_EWX2496, + &ewx2496_auxdrv}, + {0x1138153b, "Terratec DMX6fire 24/96", 6, 6, + MF_MIDI1 | MF_MIDI2 | MF_SPDIF, &dmx6fire_auxdrv}, + {0x17121412, "Generic Envy24 based card", 8, 8, + MF_SPDIF | MF_MIDI1 | MF_CONSUMER | MF_HOONTECH}, + {0} +}; + +static struct speed_sel speed_tab[] = { + { + 8000, 0x06} + , + { + 9600, 0x03} + , + { + 11025, 0x0a} + , + { + 12000, 0x02} + , + { + 16000, 0x05} + , + { + 22050, 0x09} + , + { + 24000, 0x01} + , + { + 32000, 0x04} + , + { + 44100, 0x08} + , + { + 48000, 0x00} + , + /* {64000, 0x0f}, doesn't work */ + { + 88200, 0x0b} + , + { + 96000, 0x07} + , + { + -1, 0x10} + , +}; + +int +envy24_read_cci (envy24_devc * devc, int pos) +{ + OUTB (devc->osdev, pos, devc->ccs_base + 0x03); + return INB (devc->osdev, devc->ccs_base + 0x04); +} + +void +envy24_write_cci (envy24_devc * devc, int pos, int data) +{ + OUTB (devc->osdev, pos, devc->ccs_base + 0x03); + OUTB (devc->osdev, data, devc->ccs_base + 0x04); +} + +static int +eeprom_read (envy24_devc * devc, int pos) +{ + int i, status; + + for (i = 0; i < 0x10000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + OUTB (devc->osdev, 0xa0, devc->ccs_base + 0x10); /* EEPROM read */ + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + + for (i = 0; i < 2000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + oss_udelay (1); + return INB (devc->osdev, devc->ccs_base + 0x12); +} + +static int +load_eeprom (envy24_devc * devc, int subid) +{ + int status, i, check; + + status = INB (devc->osdev, devc->ccs_base + 0x13); + + if (!(status & 0x80)) + return 0; /* No EEPROM */ + + for (i = 0; i < 32; i++) + { + devc->eeprom[i] = eeprom_read (devc, i); + devc->eeprom[i] = eeprom_read (devc, i); + } + DDB (cmn_err (CE_CONT, "EEPROM=")); + for (i = 0; i < 10; i++) + DDB (cmn_err (CE_CONT, "0x%02x, ", devc->eeprom[i])); + DDB (cmn_err (CE_CONT, "\n")); + + check = 0; + for (i = 0; i < 4; i++) + { + check <<= 8; + check |= devc->eeprom[i]; + } + + if (check != subid) + cmn_err (CE_CONT, + "Envy24 WARNING: Possible EEPROM read error %08x != %08x\n", + check, subid); + + return 1; +} + +static void +handle_playdev (envy24_devc * devc, envy24_portc * portc, int this_frag) +{ + int sample, nsamples, nbytes, ch; + dmap_t *dmap = audio_engines[portc->dev]->dmap_out; + + if (!(portc->trigger_bits & PCM_ENABLE_OUTPUT) && devc->playback_started) + return; + + nsamples = devc->hw_fragsamples; /* Number of 32 bit samples */ + + nbytes = nsamples * portc->channels; + + if (audio_engines[portc->dev]->dmap_out->flags & DMAP_POST) + { + if (portc->pcm_qlen > 0) + portc->pcm_qlen--; + } + else + { + if (portc->pcm_qlen < devc->writeahead) + portc->pcm_qlen++; + } + + if (portc->bits & (AFMT_S16_LE | AFMT_S16_BE | AFMT_AC3)) + nbytes *= 2; + else if (portc-> + bits & (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE)) + nbytes *= 4; + + if (nbytes != dmap->fragment_size) + return; /* Fragment size mismatch */ + + switch (portc->bits) + { + case AFMT_U8: + { + unsigned char *ip; + int *op; + + ip = audio_engines[portc->dev]->dmap_out->dmabuf; + ip += (dmap_get_qhead (dmap) * dmap->fragment_size); + op = (int *) (devc->playbuf + devc->hw_pfragsize * this_frag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 10 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *p++ = (*ip++ ^ 0x80) << 24; + } + } + } + break; + + case AFMT_AC3: + case AFMT_S16_LE: + { + short *ip; + int *op; +#ifdef DO_TIMINGS + oss_timing_printf ("Envy24: Copy out %d, %d", + dmap_get_qhead (dmap) * dmap->fragment_size, nbytes); +#endif + + ip = (short *) (dmap->dmabuf + + (dmap_get_qhead (dmap) * dmap->fragment_size)); + op = (int *) (devc->playbuf + devc->hw_pfragsize * this_frag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 10 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *p++ = *ip++ << 16; + } + } + } + break; + + case AFMT_S16_BE: + { + short *ip; + int *op; + + ip = (short *) (audio_engines[portc->dev]->dmap_out->dmabuf + + (dmap_get_qhead (dmap) * dmap->fragment_size)); + op = (int *) (devc->playbuf + devc->hw_pfragsize * this_frag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 10 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + short s = (short) (((*(unsigned short *) ip & 0xff) << 8) | + ((*(unsigned short *) ip & 0xff00) >> + 8)); + ip++; + *p++ = s << 16; + } + } + } + break; + + case AFMT_S24_LE: + { + int *ip; + int *op; + + ip = (int *) (audio_engines[portc->dev]->dmap_out->dmabuf + + (dmap_get_qhead (dmap) * dmap->fragment_size)); + op = (int *) (devc->playbuf + devc->hw_pfragsize * this_frag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 10 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *p++ = *ip++ << 8; + } + } + } + break; + + case AFMT_S32_LE: + { + int *ip; + int *op; + + ip = (int *) (audio_engines[portc->dev]->dmap_out->dmabuf + + (dmap_get_qhead (dmap) * dmap->fragment_size)); + op = (int *) (devc->playbuf + devc->hw_pfragsize * this_frag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 10 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *p++ = *ip++; + } + } + } + break; + } + + oss_audio_outputintr (portc->dev, 1); +} + +#ifdef DO_RIAA +static __inline__ int32_t +_riaa_sat31 (register int32_t a, register int32_t b) +{ + register int64_t v = (((int64_t) a) * b) + (1 << 30); + return (int32_t) (v >> 31); +} +#endif + +static void +handle_recdev (envy24_devc * devc, envy24_portc * portc) +{ + int sample, nsamples, nbytes, ch; + dmap_t *dmap = audio_engines[portc->dev]->dmap_in; + + if (portc->trigger_bits == 0 && devc->recording_started) + return; + + nsamples = devc->hw_fragsamples; /* Number of 32 bit samples */ + + nbytes = nsamples * portc->channels; + + if (portc->bits & (AFMT_S16_LE | AFMT_S16_BE | AFMT_AC3)) + nbytes *= 2; + else if (portc->bits & (AFMT_S32_LE | AFMT_S24_LE)) + nbytes *= 4; + + if (nbytes != dmap->fragment_size) + { + return; /* Fragment size mismatch */ + } + + switch (portc->bits) + { + case AFMT_U8: + { + unsigned char *ip; + int *op; + + ip = audio_engines[portc->dev]->dmap_in->dmabuf; + ip += (dmap_get_qtail (dmap) * dmap->fragment_size); + op = (int *) (devc->recbuf + devc->hw_rfragsize * devc->hw_recfrag); + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 12 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *ip++ = ((*p++) >> 24) ^ 0x80; + } + } + } + break; + + case AFMT_S16_LE: +#ifdef DO_RIAA + if (portc->riaa_filter) + { + /* RIAA filtered version */ + short *ip; + int *op; + + ip = (short *) (audio_engines[portc->dev]->dmap_in->dmabuf + + (dmap_get_qtail (dmap) * dmap->fragment_size)); + op = (int *) (devc->recbuf + devc->hw_rfragsize * devc->hw_recfrag); + + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + + for (ch = 0; ch < portc->channels; ch++) + { + int *p = &op[portc->chnum + ch]; + short *p2 = &ip[ch]; + riaa_t *ff = &portc->riaa_parms[ch]; + + int32_t x1 = ff->x1, x2 = ff->x2, x3 = ff->x3, + y1 = ff->y1, y2 = ff->y2, y3 = ff->y3, x0, y0; + + for (sample = 0; sample < nsamples; sample++) + { + int tmp = *p; + p += 12; + + x0 = _riaa_sat31 (tmp, 0x4C30C30C); + + y0 = _riaa_sat31 (x0, 0xF38FB92F) + + _riaa_sat31 (x1, 0xF2492994) + + _riaa_sat31 (x2, 0x1AB82385) + + _riaa_sat31 (x3, 0x023FB0F8) + + (_riaa_sat31 (y1, 0x574DB88C) << 1) + + _riaa_sat31 (y2, 0xF650F27D) + + _riaa_sat31 (y3, 0xDACB84B9); + + x3 = x2; + x2 = x1; + x1 = x0; + y3 = y2; + y2 = y1; + y1 = y0; + + tmp = -y0; + + *p2 = tmp >> 16; + p2 += portc->channels; + } + + ff->x1 = x1; + ff->x2 = x2; + ff->x3 = x3; + ff->y1 = y1; + ff->y2 = y2; + ff->y3 = y3; + } + /* RIAA filtered version */ + } + else +#endif + { + short *ip; + int *op; + + ip = (short *) (audio_engines[portc->dev]->dmap_in->dmabuf + + (dmap_get_qtail (dmap) * dmap->fragment_size)); + op = (int *) (devc->recbuf + devc->hw_rfragsize * devc->hw_recfrag); + + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 12 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *ip++ = (*p++) >> 16; + } + } + } + break; + + case AFMT_S32_LE: + { + int *ip; + int *op; + + ip = (int *) (audio_engines[portc->dev]->dmap_in->dmabuf + + (dmap_get_qtail (dmap) * dmap->fragment_size)); + op = (int *) (devc->recbuf + devc->hw_rfragsize * devc->hw_recfrag); + + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 12 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *ip++ = *p++; + } + } + } + break; + + case AFMT_S24_LE: + { + int *ip; + int *op; + + ip = (int *) (audio_engines[portc->dev]->dmap_in->dmabuf + + (dmap_get_qtail (dmap) * dmap->fragment_size)); + op = (int *) (devc->recbuf + devc->hw_rfragsize * devc->hw_recfrag); + + VMEM_CHECK (ip, nsamples * sizeof (*ip)); + VMEM_CHECK (op, nsamples * sizeof (*op)); + for (sample = 0; sample < nsamples; sample++) + { + int *p = &op[sample * 12 + portc->chnum]; + + for (ch = 0; ch < portc->channels; ch++) + { + *ip++ = *p++ >> 8; + } + } + } + break; + } + + oss_audio_inputintr (portc->dev, 0); +} + +static void +tank_playback_data (envy24_devc * devc) +{ + int i, nc = devc->nr_outdevs; + envy24_portc *portc; + unsigned char *p; + + p = devc->playbuf + devc->hw_playfrag * devc->hw_pfragsize; + VMEM_CHECK (p, devc->hw_pfragsize); + memset (p, 0, devc->hw_pfragsize); /* Cleanup the fragment */ + + for (i = 0; i < nc; i++) + { + portc = &devc->play_portc[i]; + + if (!portc->open_mode) /* Not opened */ + continue; + handle_playdev (devc, portc, devc->hw_playfrag); + } + + devc->hw_playfrag = (devc->hw_playfrag + 1) % devc->hw_nfrags; +} + +static void +handle_recording (envy24_devc * devc) +{ + int i; + envy24_portc *portc; + /* oss_native_word flags; */ + + /* + * TODO: Fix mutexes and move the inputintr/outputintr calls outside the + * mutex block. + */ + /* MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); */ + for (i = 0; i < devc->nr_indevs; i++) + { + portc = &devc->rec_portc[i]; + + if (!portc->open_mode) /* Not opened */ + continue; + handle_recdev (devc, portc); + } + + devc->hw_recfrag = (devc->hw_recfrag + 1) % devc->hw_nfrags; + /* MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); */ +} + +extern int envy24d_get_buffer_pointer (int dev, dmap_t * dmap, int direction); + +static void +mt_audio_intr (envy24_devc * devc) +{ + int status; + +#ifdef DO_TIMINGS + oss_timing_enter (DF_INTERRUPT); + oss_do_timing2 (DFLAG_PROFILE, "Envy24_audio_intr"); +#endif + status = INB (devc->osdev, devc->mt_base + 0x00); + if (devc->playback_started && (status & 0x01)) /* Playback interrupt */ + { +/* cmn_err(CE_CONT, "%d\n", GET_JIFFIES()); */ + if (devc->direct_audio_opened & OPEN_WRITE) + { + envy24d_playintr (devc); + } + else + { + int ptr, qlen, i; + + ptr = INW (devc->osdev, devc->mt_base + 0x14); + ptr = (devc->playbuffsize - ((ptr + 1) * 4)) / devc->hw_pfragsize; + + /* Find the number of current fragments in the hardware level buffer */ + qlen = 0; + i = devc->hw_playfrag; + + while (qlen < 15 && i != ptr) + { + qlen++; + i = (i + 1) % devc->hw_nfrags; + } + + if (qlen != devc->writeahead) + { + tank_playback_data (devc); + } + + if (devc->hw_playfrag == ptr) /* Out of sync */ + { + tank_playback_data (devc); /* Try to catch the hardware pointer */ + } + + + tank_playback_data (devc); + } + } + + if (devc->recording_started && (status & 0x02)) /* Record interrupt */ + { + if (devc->direct_audio_opened & OPEN_READ) + envy24d_recintr (devc); + else + handle_recording (devc); + } + + OUTB (devc->osdev, status, devc->mt_base + 0x00); +#ifdef DO_TIMINGS + oss_timing_leave (DF_INTERRUPT); + oss_do_timing2 (DFLAG_PROFILE, "Envy24_audio_intr done"); +#endif +} + +static int +envy24intr (oss_device_t * osdev) +{ + int status; + envy24_devc *devc; + + devc = osdev->devc; + + status = INB (devc->osdev, devc->ccs_base + 0x02); + if (status == 0) + return 0; + + if (status & 0x80) /* MIDI UART 1 */ + if (devc->model_data->flags & MF_MIDI1) + uart401_irq (&devc->uart401devc1); + + if (status & 0x20) /* MIDI UART 2 */ + if (devc->model_data->flags & MF_MIDI2) + uart401_irq (&devc->uart401devc2); + + if (status & 0x10) + { +/*cmn_err(CE_CONT, "%d/%d.", GET_JIFFIES(), envy24d_get_buffer_pointer(11, audio_engines[11]->dmap_out, DMODE_OUTPUT)); */ + mt_audio_intr (devc); + } + + OUTB (devc->osdev, status, devc->ccs_base + 0x02); /* ACK */ + + return 1; +} + +static void envy24_setup_pro_speed (envy24_devc * devc); +static void envy24_setup_consumer_speed (envy24_devc * devc); + +void +envy24_prepare_play_engine (envy24_devc * devc) +{ + int tmp, fragsize, buffsize; + + if (devc->playback_prepared) + return; + + /* Set S/PDIF sample rate indication */ + + if (devc->spdif_cbits[0] & 0x01) + envy24_setup_pro_speed (devc); + else + envy24_setup_consumer_speed (devc); + + if (devc->model_data->flags & MF_SPDIF) + { + tmp = 0x80; + + if (devc->ac3_mode) + tmp |= 0x40; /* Audio mode off */ + + switch (devc->speed) + { + case 48000: + tmp |= 0x01; + break; + case 44100: + tmp |= 0x02; + break; + case 32000: + tmp |= 0x03; + break; + } + + if (devc->model_data->auxdrv->spdif_set) + devc->model_data->auxdrv->spdif_set (devc, tmp); + + } + + if (devc->model_data->auxdrv->set_rate) + devc->model_data->auxdrv->set_rate (devc); + else + { + tmp = devc->speedbits; + if (devc->syncsource != SYNC_INTERNAL) + { + tmp |= 0x10; /* S/PDIF input clock select */ + if (devc->model_data->flags & MF_WCLOCK) /* Has world clock too */ + { + int cmd = envy24_read_cci (devc, 0x20); + cmd |= 0x10; /* S/PDIF */ + if (devc->syncsource == SYNC_WCLOCK) + cmd &= ~0x10; /* World clock */ + envy24_write_cci (devc, 0x20, cmd); + } + } + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + } + + fragsize = devc->hw_pfragsize; + buffsize = devc->playbuffsize / 4 - 1; + + PMEM_CHECK (devc->playbuf_phys, devc->playbuffsize); + + OUTL (devc->osdev, devc->playbuf_phys, devc->mt_base + 0x10); /* Base */ + OUTW (devc->osdev, buffsize, devc->mt_base + 0x14); /* Count */ + OUTL (devc->osdev, devc->playbuf_phys, devc->mt_base + 0x10); /* Base */ + OUTW (devc->osdev, buffsize, devc->mt_base + 0x14); /* Count */ + OUTL (devc->osdev, devc->playbuf_phys, devc->mt_base + 0x10); /* Base */ + OUTW (devc->osdev, fragsize / 4 - 1, devc->mt_base + 0x16); /* Interrupt rate */ + OUTL (devc->osdev, devc->playbuf_phys, devc->mt_base + 0x10); /* Base */ + + devc->playback_prepared = 1; + mixer_devs[devc->mixer_dev]->modify_counter++; +} + +void +envy24_launch_play_engine (envy24_devc * devc) +{ + /* Unmask playback interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->mt_base + 0x00) & ~0x40, + devc->mt_base + 0x00); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x00) & ~0x40, + devc->mt_base + 0x00); + /* Kick it */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) | 0x01, + devc->mt_base + 0x18); + devc->playback_started = 1; + + if (devc->model_data->auxdrv->set_rate) + devc->model_data->auxdrv->set_rate (devc); +} + +static void +start_playback (envy24_devc * devc) +{ + devc->hw_playfrag = 0; + +#ifdef DO_TIMINGS + oss_do_timing ("Envy24: Start playback"); +#endif + tank_playback_data (devc); + tank_playback_data (devc); + if (devc->writeahead == 2) + tank_playback_data (devc); + + envy24_prepare_play_engine (devc); + envy24_launch_play_engine (devc); +} + +void +envy24_stop_playback (envy24_devc * devc) +{ +#ifdef DO_TIMINGS + oss_do_timing ("Envy24: Stop playback"); +#endif + memset (devc->playbuf, 0, devc->playbuffsize); + /* + * Give the engine time to eat some silent samples + * This makes the corresponding digital mixer inputs to drop to 0 + * which decreases noise in the monitor outputs. + */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + + /* Mask playback interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->mt_base + 0x00) | 0x40, devc->mt_base + 0x00); + devc->playback_started = 0; + devc->playback_prepared = 0; +} + +void +envy24_start_recording (envy24_devc * devc) +{ + int tmp; + + devc->hw_recfrag = 0; + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + oss_udelay (20); + + if (devc->model_data->flags & MF_SPDIF) + { + tmp = 0x80; + + switch (devc->speed) + { + case 48000: + tmp |= 0x01; + break; + case 44100: + tmp |= 0x02; + break; + case 32000: + tmp |= 0x03; + break; + } + + if (devc->model_data->auxdrv->spdif_set) + devc->model_data->auxdrv->spdif_set (devc, tmp); + + } + + tmp = devc->speedbits; + if (devc->syncsource != SYNC_INTERNAL) + { + tmp |= 0x10; /* S/PDIF input clock select */ + if (devc->model_data->flags & MF_WCLOCK) /* Has world clock too */ + { + int cmd = envy24_read_cci (devc, 0x20); + cmd |= 0x10; /* S/PDIF */ + if (devc->syncsource == SYNC_WCLOCK) + cmd &= ~0x10; /* World clock */ + envy24_write_cci (devc, 0x20, cmd); + } + } + + OUTB (devc->osdev, tmp, devc->mt_base + 0x01); + + if (devc->model_data->auxdrv->set_rate) + devc->model_data->auxdrv->set_rate (devc); + + PMEM_CHECK (devc->recbuf_phys, devc->recbuffsize); + + OUTL (devc->osdev, devc->recbuf_phys, devc->mt_base + 0x20); /* Base */ + oss_udelay (20); + OUTL (devc->osdev, devc->recbuf_phys, devc->mt_base + 0x20); /* Base */ + oss_udelay (20); + OUTW (devc->osdev, devc->recbuffsize / 4 - 1, devc->mt_base + 0x24); /* Count */ + OUTL (devc->osdev, devc->recbuf_phys, devc->mt_base + 0x20); /* Base */ + oss_udelay (60); + OUTW (devc->osdev, devc->hw_rfragsize / 4 - 1, devc->mt_base + 0x26); /* Interrupt rate */ + + oss_udelay (60); +} + +void +envy24_launch_recording (envy24_devc * devc) +{ + +#if 1 + /* Unmask recording interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->mt_base + 0x00) & ~0x80, + devc->mt_base + 0x00); + +#endif + /* Kick it */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) | 0x04, + devc->mt_base + 0x18); + devc->recording_started = 1; + mixer_devs[devc->mixer_dev]->modify_counter++; + +} + +void +envy24_stop_recording (envy24_devc * devc) +{ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + + /* Mask recording interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->mt_base + 0x00) | 0x80, devc->mt_base + 0x00); + devc->recording_started = 0; + memset (devc->recbuf, 0, devc->recbuffsize); +} + +/* + * Audio entrypoint routines + */ + +int +envy24_audio_set_rate (int dev, int arg) +{ + envy24_devc *devc = audio_engines[dev]->devc; +#if 1 + int i = 0, ix = -1, df, best = 0x7fffffff; + oss_native_word flags; + + if (arg <= 0) + return devc->speed; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->recording_started || devc->playback_started) + { + DDB (cmn_err (CE_CONT, + "Requested sampling rate(1) on device %d was %d, got %d\n", + dev, arg, devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; + } + + if ((devc->open_inputs + devc->open_outputs) > 1) + { + DDB (cmn_err (CE_CONT, + "Requested sampling rate(2) on device %d was %d, got %d\n", + dev, arg, devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; + } + + if (devc->ratelock) + { + DDB (cmn_err (CE_CONT, + "Requested sampling rate(3) on device %d was %d, got %d\n", + dev, arg, devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; + } + +/* This is the only open device file so change the speed */ + + i = 0; + + while (speed_tab[i].speed != -1) + { + df = arg - speed_tab[i].speed; + if (df < 0) + df = -df; + + if (df < best) + { + best = df; + ix = i; + if (df == 0) + break; + } + + i++; + } + + if (ix == -1) /* No matching rate */ + { + DDB (cmn_err (CE_CONT, + "Requested sampling rate(4) on device %d was %d, got %d\n", + dev, arg, devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; + } + + devc->speed = speed_tab[ix].speed; + devc->speedbits = speed_tab[ix].speedbits; +#endif + if (devc->speed != arg) + { + DDB (cmn_err (CE_CONT, + "Requested sampling rate(5) on device %d was %d, got %d\n", + dev, arg, devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; + } + DDB (cmn_err (CE_CONT, "Sampling rate set to %d\n", devc->speed)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->speed; +} + +static void +update_fragments (envy24_portc * portc) +{ + int nsamples, nbytes, dev = portc->dev; + envy24_devc *devc = audio_engines[dev]->devc; + + nsamples = devc->hw_fragsamples; /* Number of 32 bit samples */ + + nbytes = nsamples * portc->channels; + + if (portc->bits & (AFMT_S16_LE | AFMT_S16_BE | AFMT_AC3)) + { + nbytes *= 2; + } + else if (portc->bits & (AFMT_S32_LE | AFMT_S24_LE)) + nbytes *= 4; + + audio_engines[dev]->min_block = nbytes; + audio_engines[dev]->max_block = nbytes; +} + +static short +envy24_audio_set_channels (int dev, short arg) +{ + envy24_portc *portc = audio_engines[dev]->portc; + envy24_devc *devc = audio_engines[dev]->devc; + int i, nc = devc->nr_play_channels; + oss_native_word flags; + + if (envy24_virtualout) + nc = 10; + + if (arg <= portc->channels) + return portc->channels; + + /* Force mono->stereo conversion if in skip=2 mode */ + if (devc->skipdevs == 2 && arg < 2) + arg = 2; + + if (envy24_force_mono) + arg = 1; + + if (portc->direction == DIR_INPUT) + { + if ((portc->chnum + arg) > devc->nr_rec_channels) + return portc->channels; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (i = portc->channels; i < arg; i++) + if (devc->rec_channel_mask & (1 << (portc->chnum + i))) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->channels; + } + for (i = portc->channels; i < arg; i++) + devc->rec_channel_mask |= (1 << (portc->chnum + i)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + } + else + { + if ((portc->chnum + arg) > nc) + return portc->channels; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (i = portc->channels; i < arg; i++) + if (devc->play_channel_mask & (1 << (portc->chnum + i))) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->channels; + } + for (i = portc->channels; i < arg; i++) + devc->play_channel_mask |= (1 << (portc->chnum + i)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + } + + portc->channels = arg; + update_fragments (portc); + + return portc->channels; +} + +static unsigned int +envy24_audio_set_format (int dev, unsigned int arg) +{ + envy24_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & audio_engines[dev]->oformat_mask)) + return portc->bits = AFMT_S16_LE; + + portc->bits = arg; + + if (arg == AFMT_AC3) + { + envy24_audio_set_channels (dev, 2); + } + + update_fragments (portc); + + return portc->bits; +} + +static int +envy24_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + int rt; + + if (arg == NULL) + return OSS_EINVAL; + + switch (cmd) + { + case SNDCTL_DSP_GET_RECSRC: + case SNDCTL_DSP_SET_RECSRC: + case SNDCTL_DSP_GET_PLAYTGT: + case SNDCTL_DSP_SET_PLAYTGT: + return *arg = 0; + break; + + case SNDCTL_DSP_GET_RECSRC_NAMES: + return oss_encode_enum ((oss_mixer_enuminfo *) arg, portc->name, 0); + break; + + case SNDCTL_DSP_GET_PLAYTGT_NAMES: + return oss_encode_enum ((oss_mixer_enuminfo *) arg, portc->name, 0); + break; + + case SNDCTL_DSP_GET_CHNORDER: + *(oss_uint64_t *) arg = CHNORDER_UNDEF; + return 0; + } + + if (devc->model_data->auxdrv->spdif_ioctl == NULL) + return OSS_EINVAL; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + rt = devc->model_data->auxdrv->spdif_ioctl (devc, dev, cmd, arg); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return rt; +} + +static void envy24_audio_trigger (int dev, int state); + +static void +envy24_audio_reset (int dev) +{ +#ifdef DO_TIMINGS + oss_do_timing ("Envy24: Reset audio"); +#endif + envy24_audio_trigger (dev, 0); +} + +#define WriteCsByte(devc, b, v) (devc)->spdif_cbits[b]=(v) +#define ReadCsByte(devc, b) (devc)->spdif_cbits[b] + +static __inline__ void +WriteCsField (envy24_devc * devc, unsigned char bByteNum, + unsigned short bMask, unsigned short bBits) +{ + /* Get current reg value. */ + unsigned char bTemp = ReadCsByte (devc, bByteNum); + + /* Clear field to be written. */ + bTemp &= ~(bMask); + + /* Set new values. */ + WriteCsByte (devc, bByteNum, (unsigned char) (bTemp | (bBits & bMask))); +} + +static void +envy24_setup_pro_speed (envy24_devc * devc) +{ + + switch (devc->speed) + { + case 32000: + WriteCsField (devc, 0, 0xc0, 0xc0); + break; + + case 44100: + WriteCsField (devc, 0, 0xc0, 0x40); + break; + + case 48000: + WriteCsField (devc, 0, 0xc0, 0x80); + break; + + default: + WriteCsField (devc, 0, 0xc0, 0x00); + break; + } +} + +static void +setup_pro_mode (envy24_devc * devc) +{ + devc->spdif_cbits[0] |= 0x01; /* Pro mode */ + devc->spdif_cbits[2] |= 0x2c; /* 24-bit data word */ + + envy24_setup_pro_speed (devc); +} + +static void +envy24_setup_consumer_speed (envy24_devc * devc) +{ + + /* + * Set the sampling rate indication + */ + if (devc->ac3_mode) + WriteCsField (devc, 0, 0x02, 0x02); /* 1:1 = 1 */ + else + WriteCsField (devc, 0, 0x02, 0x00); /* 1:1 = 0 */ + + switch (devc->speed) + { + case 22050L: + WriteCsField (devc, 0, 0xC0, 0x00); /* 7:6 = 00 */ + WriteCsField (devc, 3, 0x0F, 0x00); /* 3:0 = 0000 */ + WriteCsField (devc, 4, 0x0F, 0x09); /* 3:0 = 1001 */ + break; + case 32000L: + WriteCsField (devc, 0, 0xC0, 0xC0); /* 7:6 = 11 */ + WriteCsField (devc, 3, 0x0F, 0x03); /* 3:0 = 0011 */ + WriteCsField (devc, 4, 0x0F, 0x00); /* 3:0 = 0000 */ + break; + case 44100L: + WriteCsField (devc, 0, 0xC0, 0x40); /* 7:6 = 01 */ + WriteCsField (devc, 3, 0x0F, 0x00); /* 3:0 = 0000 */ + WriteCsField (devc, 4, 0x0F, 0x00); /* 3:0 = 0000 */ + break; + case 48000L: + WriteCsField (devc, 0, 0xC0, 0x80); /* 7:6 = 10 */ + WriteCsField (devc, 3, 0x0F, 0x02); /* 3:0 = 0010 */ + WriteCsField (devc, 4, 0x0F, 0x00); /* 3:0 = 0000 */ + break; + case 88200L: + WriteCsField (devc, 0, 0xC0, 0x00); /* 7:6 = 00 */ + WriteCsField (devc, 3, 0x0F, 0x00); /* 3:0 = 0000 */ + WriteCsField (devc, 4, 0x0F, 0x05); /* 3:0 = 0101 */ + break; + case 96000L: + WriteCsField (devc, 0, 0xC0, 0x00); /* 7:6 = 00 */ + WriteCsField (devc, 3, 0x0F, 0x00); /* 3:0 = 0000 */ + WriteCsField (devc, 4, 0x0F, 0x04); /* 3:0 = 0100 */ + break; + default: + WriteCsField (devc, 0, 0xC0, 0x00); /* 7:6 = 00 */ + WriteCsField (devc, 3, 0x0F, 0x00); /* 3:0 = 0000 */ + WriteCsField (devc, 4, 0x0F, 0x00); /* 3:0 = 0000 */ + break; + } +} + +static void +setup_consumer_mode (envy24_devc * devc) +{ + WriteCsByte (devc, 0, ReadCsByte (devc, 0) & ~(0x02)); /* Set audio mode */ + WriteCsByte (devc, 0, ReadCsByte (devc, 0) & ~(0x38)); /* Set no emphasis */ + + WriteCsByte (devc, 0, ReadCsByte (devc, 0) & ~(0x04)); /* Set "original" */ + WriteCsByte (devc, 1, ReadCsByte (devc, 1) | (0x80)); /* Set "original" */ + + envy24_setup_consumer_speed (devc); +} + +static void +setup_spdif_control (envy24_devc * devc) +{ +/* unsigned char *cbits; */ + + memset (devc->spdif_cbits, 0, sizeof (devc->spdif_cbits)); + +/* cbits = devc->spdif_cbits; */ + + if (devc->spdif_pro_mode) + { + setup_pro_mode (devc); + } + else + { + setup_consumer_mode (devc); + } +} + +/*ARGSUSED*/ +static int +envy24_audio_open (int dev, int mode, int open_flags) +{ + envy24_portc *portc = audio_engines[dev]->portc; + envy24_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + mode |= ADEV_NOVIRTUAL; + + if (devc->playbuf == NULL || devc->recbuf == NULL) + { + cmn_err (CE_WARN, "No DMA buffer\n"); + return OSS_ENOSPC; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode != 0 || devc->direct_audio_opened != 0) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + if (portc->direction == DIR_INPUT) + { + if (devc->rec_channel_mask & (1 << portc->chnum)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + devc->rec_channel_mask |= (1 << portc->chnum); + } + else + { + if (devc->play_channel_mask & (1 << portc->chnum)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + devc->play_channel_mask |= (1 << portc->chnum); + } + + portc->open_mode = mode; + portc->channels = 1; + if (devc->skipdevs == 2) + portc->channels = 2; + portc->pcm_qlen = 0; + if (portc->direction == DIR_INPUT) + { + if (devc->open_inputs++ == 0 && devc->open_outputs == 0) + { + devc->speed = speed_tab[devc->pending_speed_sel].speed; + devc->speedbits = speed_tab[devc->pending_speed_sel].speedbits; + } + } + else + { + if (devc->open_inputs == 0 && devc->open_outputs++ == 0) + { + if (portc->flags & PORTC_SPDOUT) + { + setup_spdif_control (devc); + } + + devc->speed = speed_tab[devc->pending_speed_sel].speed; + devc->speedbits = speed_tab[devc->pending_speed_sel].speedbits; + } + } +#if 1 + if (devc->use_src) + { + /* SRC stuff */ + audio_engines[dev]->flags |= ADEV_FIXEDRATE; + audio_engines[dev]->fixed_rate = devc->speed; + audio_engines[dev]->min_rate = devc->speed; + audio_engines[dev]->max_rate = devc->speed; + } + else + { + audio_engines[dev]->flags &= ~ADEV_FIXEDRATE; + audio_engines[dev]->fixed_rate = 0; + audio_engines[dev]->min_rate = 8000; + audio_engines[dev]->max_rate = 96000; + } +#endif + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static void +envy24_audio_close (int dev, int mode) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + int i; + + envy24_audio_reset (dev); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + if (portc->flags & PORTC_SPDOUT) + devc->ac3_mode = 0; + if (portc->direction == DIR_INPUT) + { + devc->open_inputs--; + for (i = 0; i < portc->channels; i++) + devc->rec_channel_mask &= ~(1 << (portc->chnum + i)); + } + else + { + devc->open_outputs--; + for (i = 0; i < portc->channels; i++) + devc->play_channel_mask &= ~(1 << (portc->chnum + i)); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +envy24_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ +} + +/*ARGSUSED*/ +static void +envy24_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ +} + +static int +envy24_sync_control (int dev, int event, int mode) +{ + envy24_devc *devc = audio_engines[dev]->devc; + envy24_portc *portc = audio_engines[dev]->portc; + + if (event == SYNC_PREPARE) + { + if (mode & PCM_ENABLE_OUTPUT) + { + if (!devc->playback_prepared) + devc->hw_playfrag = 0; + handle_playdev (devc, portc, devc->hw_playfrag); + handle_playdev (devc, portc, devc->hw_playfrag + 1); + if (devc->writeahead == 2) + handle_playdev (devc, portc, devc->hw_playfrag + 2); + envy24_prepare_play_engine (devc); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + + if (mode & PCM_ENABLE_INPUT) + { + if (devc->active_inputs == 0) + { + envy24_start_recording (devc); + } + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + return 0; + } + + if (event == SYNC_TRIGGER) + { + if (mode & PCM_ENABLE_OUTPUT) + { + envy24_prepare_play_engine (devc); /* Just to make sure */ + devc->hw_playfrag = 1 + devc->writeahead; + if (devc->active_outputs++ == 0) + envy24_launch_play_engine (devc); + } + + if (mode & PCM_ENABLE_INPUT) + { + if (devc->active_inputs++ == 0) + { + devc->hw_recfrag = 0; + envy24_launch_recording (devc); + } + } + return 0; + } + + return OSS_EIO; +} + +static void +envy24_audio_trigger (int dev, int state) +{ + int changed; + oss_native_word flags; + + envy24_portc *portc = audio_engines[dev]->portc; + envy24_devc *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + changed = state ^ portc->trigger_bits; + + if (portc->direction == DIR_OUTPUT && (changed & PCM_ENABLE_OUTPUT)) + { + if (state & PCM_ENABLE_OUTPUT) + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24: Trigger start output"); +#endif + portc->trigger_bits = state; + if (devc->active_outputs++ == 0) + start_playback (devc); + } + else + { +#ifdef DO_TIMINGS + oss_do_timing ("Envy24: Trigger stop output"); +#endif + portc->trigger_bits = state; + if (--devc->active_outputs == 0) + envy24_stop_playback (devc); + } + } + + if (portc->direction == DIR_INPUT && (changed & PCM_ENABLE_INPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + portc->trigger_bits = state; + if (devc->active_inputs++ == 0) + { + envy24_start_recording (devc); + envy24_launch_recording (devc); + } + } + else + { + if (--devc->active_inputs == 0) + envy24_stop_recording (devc); + portc->trigger_bits = state; + } + } + + portc->trigger_bits = state; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +envy24_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + int nsamples, nbytes; + + envy24_portc *portc = audio_engines[dev]->portc; + envy24_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + if (audio_engines[dev]->flags & ADEV_NOINPUT) + return OSS_EACCES; + + nsamples = devc->hw_fragsamples; /* Number of 32 bit samples */ + + nbytes = nsamples * portc->channels; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); +#ifdef DO_RIAA + memset (portc->riaa_parms, 0, sizeof (portc->riaa_parms)); + if (portc->riaa_filter) + cmn_err (CE_CONT, "oss: RIAA filter activated for /dev/dsp%d\n", dev); +#endif + + if (portc->bits & (AFMT_S16_LE | AFMT_S16_BE | AFMT_AC3)) + { + nbytes *= 2; + } + else if (portc->bits & (AFMT_S32_LE | AFMT_S24_LE)) + nbytes *= 4; + + if (nbytes != bsize) + { + dmap_p dmap = audio_engines[dev]->dmap_in; + dmap->fragment_size = bsize = nbytes; + dmap->bytes_in_use = dmap->fragment_size * dmap->nfrags; + if (dmap->bytes_in_use > dmap->buffsize) + { + dmap->nfrags = dmap->buffsize / dmap->fragment_size; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +envy24_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + int nsamples, nbytes; + oss_native_word flags; + + envy24_portc *portc = audio_engines[dev]->portc; + envy24_devc *devc = audio_engines[dev]->devc; + + if (audio_engines[dev]->flags & ADEV_NOOUTPUT) + return OSS_EACCES; + + nsamples = devc->hw_fragsamples; /* Number of 32 bit samples */ + + nbytes = nsamples * portc->channels; + + if (portc->flags & PORTC_SPDOUT) + if (portc->bits == AFMT_AC3) + devc->ac3_mode = 1; + + if (portc->bits & (AFMT_S16_LE | AFMT_S16_BE | AFMT_AC3)) + { + nbytes *= 2; + } + else if (portc->bits & (AFMT_S32_LE | AFMT_S32_BE)) + nbytes *= 4; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (nbytes != bsize) + { + dmap_p dmap = audio_engines[dev]->dmap_out; + cmn_err (CE_CONT, "Fragment size mismatch: hw=%d, sw=%d\n", + nbytes, bsize); + cmn_err (CE_NOTE, + "Application bug detected. Fix ioctl() calling order\n"); + + oss_audio_set_error (dev, E_PLAY, + OSSERR (1012, "Wrong ioctl call order"), 0); + /* + * Errordesc: The envy24 driver requires that number of channels, sample format and + * sampling rate are set before calling any ioctl call that may lock + * the fragment size prematurely. In such case the driver cannot change the + * fragment size to value that is suitable for the device. + * + * Please use the recommended ioctl call order defined in + * http://manuals.opensound.com/developer/callorder.html. + */ + dmap->fragment_size = bsize = nbytes; + dmap->bytes_in_use = dmap->fragment_size * dmap->nfrags; + if (dmap->bytes_in_use > dmap->buffsize) + { + dmap->nfrags = dmap->buffsize / dmap->fragment_size; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EIO; + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +envy24_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + envy24_devc *devc = audio_engines[dev]->devc; + + if (dmap->dmabuf != NULL) + return 0; + +#if 0 +/* + * Ignore the direction parameter since it's missleading. Instead use the + * ADEV_NOINPUT/ADEV_NOOUTPUT flag. + */ + + if (audio_engines[dev]->flags & ADEV_NOINPUT) + direction = OPEN_WRITE; + else + direction = OPEN_READ; +#endif + + dmap->buffsize = devc->skipdevs * DEV_BUFSIZE; + dmap->dmabuf_phys = 0; + dmap->dmabuf = KERNEL_MALLOC (dmap->buffsize); + + if (dmap->dmabuf == NULL) + { + cmn_err (CE_WARN, "Failed to allocate a DMA buffer\n"); + return OSS_ENOSPC; + } + memset (dmap->dmabuf, 0, dmap->buffsize); + return 0; +} + +/*ARGSUSED*/ +static int +envy24_free_buffer (int dev, dmap_t * dmap, int direction) +{ + if (dmap->dmabuf == NULL) + return 0; +#if 1 + KERNEL_FREE (dmap->dmabuf); +#endif + dmap->dmabuf = NULL; + return 0; +} + +static int +envy24_check_input (int dev) +{ + envy24_devc *devc = audio_engines[dev]->devc; + + if (!devc->recording_started) + return 0; + + cmn_err (CE_NOTE, "Input timed out.\n"); + return OSS_EIO; +} + +static int +envy24_check_output (int dev) +{ + envy24_devc *devc = audio_engines[dev]->devc; + + if (!devc->playback_started) + return 0; + + cmn_err (CE_NOTE, "Output timed out\n"); + return OSS_EIO; +} + +static int +envy24_local_qlen (int dev) +{ + envy24_portc *portc = audio_engines[dev]->portc; + + return portc->pcm_qlen * audio_engines[dev]->dmap_out->fragment_size; +} + +static const audiodrv_t envy24_audio_driver = { + envy24_audio_open, + envy24_audio_close, + envy24_audio_output_block, + envy24_audio_start_input, + envy24_audio_ioctl, + envy24_audio_prepare_for_input, + envy24_audio_prepare_for_output, + envy24_audio_reset, + envy24_local_qlen, + NULL, + NULL, + NULL, + envy24_audio_trigger, + envy24_audio_set_rate, + envy24_audio_set_format, + envy24_audio_set_channels, + NULL, + NULL, + envy24_check_input, + envy24_check_output, + envy24_alloc_buffer, + envy24_free_buffer, + NULL, + NULL, + NULL, /* envy24_get_buffer_pointer */ + NULL, /* calibrate_speed */ + envy24_sync_control +}; + +/*ARGSUSED*/ +static int +envy24_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + extern int envy24_realencoder_hack; + + if (!envy24_realencoder_hack) + { + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC || + cmd == SOUND_MIXER_READ_STEREODEVS) + return *arg = 0; + } + + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC || + cmd == SOUND_MIXER_READ_STEREODEVS) + return *arg = + SOUND_MASK_LINE | SOUND_MASK_PCM | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | SOUND_MASK_CD; + + if (cmd == SOUND_MIXER_READ_VOLUME || cmd == SOUND_MIXER_READ_PCM || + cmd == SOUND_MIXER_READ_LINE || cmd == SOUND_MIXER_READ_MIC || + cmd == SOUND_MIXER_READ_CD || cmd == MIXER_READ (SOUND_MIXER_DIGITAL1)) + return *arg = 100 | (100 << 8); + if (cmd == SOUND_MIXER_WRITE_VOLUME || cmd == SOUND_MIXER_WRITE_PCM || + cmd == SOUND_MIXER_WRITE_LINE || cmd == SOUND_MIXER_READ_MIC || + cmd == SOUND_MIXER_WRITE_CD || + cmd == MIXER_WRITE (SOUND_MIXER_DIGITAL1)) + return *arg = 100 | (100 << 8); + if (cmd == SOUND_MIXER_READ_CAPS) + return *arg = SOUND_CAP_EXCL_INPUT; + if (cmd == SOUND_MIXER_PRIVATE1) + return *arg = 0; + return OSS_EINVAL; +} + +static int +envy24_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 1: + return devc->pending_speed_sel; + break; + + case 2: + return devc->syncsource; + break; + + case 3: + return devc->use_src; + break; + + case 4: + { + int tmp = envy24_read_cci (devc, 0x20); + return !!(tmp & 0x10); + } + break; + + case 5: + return devc->ratelock; + break; + + case 6: + return devc->speed; + break; + + case 7: + return devc->sync_locked = + devc->model_data->auxdrv->get_locked_status (devc); + + default: + return OSS_EIO; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 1: + if (value < 0 || value > 12) + return OSS_EIO; + + if (value != devc->pending_speed_sel) + { + if (devc->open_inputs == 0 && devc->open_outputs == 0) /* IDDLE */ + OUTB (devc->osdev, value, devc->mt_base + 0x01); /* Make the change now */ + } + + return devc->pending_speed_sel = value; + break; + + case 2: + if (value < 0 || value > 2) + return OSS_EIO; + return devc->syncsource = value; + break; + + case 3: + return devc->use_src = value; + break; + + case 4: + { + int tmp = envy24_read_cci (devc, 0x20) & ~0x10; + if (value) + tmp |= 0x10; /* Optical */ + envy24_write_cci (devc, 0x20, tmp); + return !!(tmp & 0x10); + } + break; + + case 5: + return devc->ratelock = value; + break; + + case 6: + return devc->speed; + break; + + case 7: + return devc->sync_locked = + devc->model_data->auxdrv->get_locked_status (devc); + break; + + default: + return OSS_EIO; + } + + return OSS_EINVAL; +} + +static int +read_mon (envy24_devc * devc, int ch, int is_right) +{ + int tmp; + + if (ch >= 20) + return 0; + + OUTB (devc->osdev, ch, devc->mt_base + 0x3a); + tmp = INW (devc->osdev, devc->mt_base + 0x38); + + if (is_right) + tmp >>= 8; + tmp &= 0x7f; + if (tmp > 0x60) /* Mute? */ + return 0; + + tmp = (tmp * 15) / 10; + return 144 - tmp; +} + +static int +mon_scale (int v) +{ + if (v == 0) + return 0x7f; /* Mute */ + + v = 144 - v; + + v = (10 * v) / 15; + if (v > 0x60) + v = 0x7f; + return v; +} + +static void +mon_set (envy24_devc * devc, int ch, int left, int right) +{ + + left = mon_scale (left); + right = mon_scale (right); + + OUTB (devc->osdev, 1, devc->mt_base + 0x3b); /* Volume change rate */ + OUTB (devc->osdev, ch, devc->mt_base + 0x3a); + OUTW (devc->osdev, left | (right << 8), devc->mt_base + 0x38); +} + +static int +read_peak (envy24_devc * devc, int ch) +{ + int tmp; + + if (ch >= 22) + return 0; + + OUTB (devc->osdev, ch, devc->mt_base + 0x3e); + tmp = INB (devc->osdev, devc->mt_base + 0x3f); + + return tmp; +} + +/*ARGSUSED*/ +static int +envy24_get_peak (int dev, int ctrl, unsigned int cmd, int value) +{ + static const unsigned char peak_cnv[256] = { + 0, 18, 29, 36, 42, 47, 51, 54, 57, 60, 62, 65, 67, 69, 71, 72, + 74, 75, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, + 91, 92, 93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, + 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, + 108, + 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, + 114, + 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, + 119, + 119, 119, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, + 123, + 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, + 126, + 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, + 130, + 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, + 132, + 132, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 135, + 135, + 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, + 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, + 141, + 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, + 143, + 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, + }; + + envy24_devc *devc = mixer_devs[dev]->devc; + + int i, orign, n = -1, left = 0, right = 0; + + for (i = 0; i < 12 && n == -1; i++) + if (ctrl & (1 << i)) + n = i; + + if (n == -1) + return OSS_EINVAL; + + orign = n; + if (ctrl & 0x80000000) + n += 10; /* Recording stream */ + + if (cmd == SNDCTL_MIX_READ) + { + left = read_peak (devc, n); + if (ctrl & (1 << (orign + 1))) /* Stereo mode? */ + right = read_peak (devc, n + 1); + else + right = left; + + left = peak_cnv[left]; + right = peak_cnv[right]; + return left | (right << 8); + } + + return OSS_EINVAL; +} + +static int +envy24_set_mon (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + int i, orign, n = -1, left = 0, right = 0; + + for (i = 0; i < 10 && n == -1; i++) + if (ctrl & (1 << i)) + n = i; + + if (n == -1) + return OSS_EINVAL; + + orign = n; + if (ctrl & 0x80000000) + n += 10; /* Recording stream */ + + if (cmd == SNDCTL_MIX_READ) + { + left = read_mon (devc, n, 0) * 10; + if (ctrl & (1 << (orign + 1))) /* Stereo mode? */ + right = read_mon (devc, n + 1, 1) * 10; + else + right = read_mon (devc, n, 1) * 10; + + return left | (right << 16); + } + else if (cmd == SNDCTL_MIX_WRITE) + { + left = value & 0xffff; + right = (value >> 16) & 0xffff; + + if (right > 1440) + right = 1440; + if (left > 1440) + left = 1440; + + if (ctrl & (1 << (orign + 1))) /* Stereo mode? */ + { + mon_set (devc, n, left / 10, 0); + mon_set (devc, n + 1, 0, right / 10); + } + else + { + mon_set (devc, n, left / 10, right / 10); + } + return left | (right << 16); + } + return OSS_EINVAL; +} + +static int +get_loopback (envy24_devc * devc, int ch) +{ + int tmp; + + tmp = INL (devc->osdev, devc->mt_base + 0x34); + return (tmp >> (4 * ch)) & 0x07; +} + +static int +get_spdif_loopback (envy24_devc * devc, int ch) +{ + int tmp; + + tmp = INL (devc->osdev, devc->mt_base + 0x34); + return (tmp >> ((4 * ch) + 3)) & 0x01; +} + +static void +set_loopback (envy24_devc * devc, int ch, int val) +{ + int tmp = INL (devc->osdev, devc->mt_base + 0x34); + tmp &= ~(0x07 << (4 * ch)); + tmp |= (val & 0x07) << (4 * ch); + OUTL (devc->osdev, tmp, devc->mt_base + 0x34); +} + +static void +set_spdif_loopback (envy24_devc * devc, int ch, int val) +{ + int tmp = INL (devc->osdev, devc->mt_base + 0x34); + tmp &= ~(0x08 << (4 * ch)); + tmp |= (val & 0x01) << ((4 * ch) + 3); + OUTL (devc->osdev, tmp, devc->mt_base + 0x34); +} + +static int +envy24_set_outrout (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int tmp, i; + + if (cmd == SNDCTL_MIX_READ) + { + tmp = INW (devc->osdev, devc->mt_base + 0x30); + + for (i = 0; i < 8; i++) + if (ctrl & (1 << i)) + { + tmp = (tmp >> (2 * i)) & 0x03; + switch (tmp) + { + case 0: /* DMA */ + return 0; + break; + + case 1: /* Monitor */ + return 1; + break; + + case 2: /* Analog input loopback */ + return 2 + get_loopback (devc, i); + break; + + case 3: /* S/PDIF input loopback */ + return 10 + get_spdif_loopback (devc, i); + break; + } + } + + return OSS_EINVAL; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + tmp = INW (devc->osdev, devc->mt_base + 0x30); + for (i = 0; i < 8; i++) + if (ctrl & (1 << i)) + { + int ch; + ch = i / 2; + if (i & 1) + ch += 4; + + tmp &= ~(0x03 << (ch * 2)); /* Cleanup */ + + if (value == 0) /* DMA */ + continue; + + if (value == 1) /* Monitor */ + { + tmp |= 1 << (ch * 2); + continue; + } + + if (value < 10) /* Analog inputs */ + { + tmp |= 2 << (ch * 2); + set_loopback (devc, i, value - 2); + continue; + } + + tmp |= 3 << (ch * 2); + set_spdif_loopback (devc, i, value - 10); + } + + OUTW (devc->osdev, tmp, devc->mt_base + 0x30); + return value; + } + return OSS_EINVAL; +} + +static int +envy24_set_stereo_outrout (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int tmp, i; + + if (cmd == SNDCTL_MIX_READ) + { + tmp = INW (devc->osdev, devc->mt_base + 0x30); + + for (i = 0; i < 8; i++) + if (ctrl & (1 << i)) + { + int ch; + ch = i / 2; + if (i & 1) + ch += 4; + tmp = (tmp >> (2 * ch)) & 0x03; + switch (tmp) + { + case 0: /* DMA */ + return 0; + break; + + case 1: /* Monitor */ + return 1; + break; + + case 2: /* Analog input loopback */ + return 2 + get_loopback (devc, i) / 2; + break; + + case 3: /* S/PDIF input loopback */ + return 6; + break; + } + } + + return OSS_EINVAL; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + tmp = INW (devc->osdev, devc->mt_base + 0x30); + for (i = 0; i < 8; i++) + if (ctrl & (1 << i)) + { + int ch; + ch = i / 2; + if (i & 1) + ch += 4; + + tmp &= ~(0x03 << (ch * 2)); /* Cleanup */ + + if (value == 0) /* DMA */ + { + continue; + } + + if (value == 1) /* Monitor */ + { + tmp |= 1 << (ch * 2); + continue; + } + + if (value < 6) /* Analog inputs */ + { + tmp |= 2 << (ch * 2); + set_loopback (devc, i, (value - 2) * 2 + (i & 1)); + continue; + } + + tmp |= 3 << (ch * 2); /* S/PDIF */ + set_spdif_loopback (devc, i, (value - 10) + (i & 1)); + continue; + } + + OUTW (devc->osdev, tmp, devc->mt_base + 0x30); + return value; + } + return OSS_EINVAL; +} + +static int +read_spdif_stereo (envy24_devc * devc) +{ + int tmp; + tmp = INL (devc->osdev, devc->mt_base + 0x32); + +/* + * Look only at the left channel. Assume the same settings on right. + */ + + switch (tmp & 0x03) + { + case 0: /* From DMA */ + return 0; + break; + + case 1: /* From digital mixer */ + return 1; + break; + + case 2: /* Analog input # loopback */ + return 2 + ((tmp >> 9) & 0x03); + break; + + case 3: /* S/PDIF input loopback */ + return 6; + break; + } + + return 0; +} + +static int +read_spdif_mono (envy24_devc * devc, int ch) +{ + int tmp, v; + tmp = INL (devc->osdev, devc->mt_base + 0x32); + + if (ch == 0) /* Left channel ? */ + v = (tmp) & 0x03; + else + v = (tmp >> 2) & 0x03; + + switch (v) + { + case 0: /* DMA */ + return 0; + break; + + case 1: /* Monitor */ + return 1; + break; + + case 2: /* Analog input */ + if (ch == 0) /* Left or right */ + v = (tmp >> 8) & 0x07; + else + v = (tmp >> 12) & 0x07; + + return 2 + v; + break; + + case 3: + if (ch == 0) /* Left or right */ + v = (tmp >> 11) & 0x01; + else + v = (tmp >> 15) & 0x01; + return 10 + v; + break; + + } + + return 0; +} + +static int +write_spdif_mono (envy24_devc * devc, int ch, int val) +{ + int tmp = 0, v; + tmp = INW (devc->osdev, devc->mt_base + 0x32); + + if (val == 0) /* DMA */ + { + if (ch == 0) /* Left */ + tmp &= ~0x0003; + else + tmp &= ~0x000c; + goto do_ne; + } + + if (val == 1) /* Monitor */ + { + if (ch == 0) /* Left */ + { + tmp &= ~0x0003; + tmp |= 0x0001; + } + else + { + tmp &= ~0x000c; + tmp |= 0x0004; + } + goto do_ne; + } + + if (val < 10) /* Analog inputs */ + { + v = (val - 2) & 0x07; + + if (ch == 0) /* Left */ + { + tmp &= ~(0x0003 | (0x07 << 8)); + tmp |= 0x02 | (v << 8); + } + else + { + tmp &= ~(0x000c | (0x07 << 12)); + tmp |= 0x08 | (v << 12); + } + goto do_ne; + } + + /* Else S/PDIF */ + + if (ch == 0) /* Left */ + { + tmp &= ~(1 << 11); + tmp |= 0x0003; + + if (val == 11) + tmp |= 1 << 11; + } + else + { + tmp &= ~(1 << 15); + tmp |= 0x000c; + + if (val == 11) + tmp |= 1 << 15; + } + +do_ne: + OUTW (devc->osdev, tmp, devc->mt_base + 0x32); + return val; +} + +static int +write_spdif_stereo (envy24_devc * devc, int val) +{ + int tmp = 0, v; + + if (val == 0) /* DMA */ + { + tmp = 0x0000; + goto do_ne; + } + + if (val == 1) /* Monitor */ + { + tmp = 0x0005; + goto do_ne; + } + + if (val < 6) /* Analog inputs */ + { + tmp = 0x000a; + + v = (val - 2) * 2; + tmp |= (v << 8); + tmp |= ((v + 1) << 12); + goto do_ne; + } + + /* Else S/PDIF */ + + tmp = 0x800f; + +do_ne: + OUTW (devc->osdev, tmp, devc->mt_base + 0x32); + return val; +} + +static int +envy24_set_spdifrout (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl == 3) + return read_spdif_stereo (devc); + else + return read_spdif_mono (devc, ctrl - 1); + } + else if (cmd == SNDCTL_MIX_WRITE) + { + if (ctrl == 3) + return write_spdif_stereo (devc, value); + else + return write_spdif_mono (devc, ctrl - 1, value); + } + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +create_output_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, num, skip; + char tmp[64]; + + int nc = devc->nr_play_channels; + + if (envy24_virtualout) + { + mask = 0; + nc = 10; + for (i = 0; i < nc; i++) + mask |= (1 << i); + } + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_OUTPUT")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + for (i = 0; i < nc; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + sprintf (tmp, "@pcm%d", devc->play_portc[i / 2].dev); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL)) < + 0) + return err; + if ((err = mixer_ext_create_control (dev, group, + num, envy24_get_peak, + MIXT_STEREOPEAK, + "-", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_input_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->inportmask, group, err, num, skip; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_INPUT")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + for (i = 0; i < devc->nr_rec_channels && i < 10; i += skip) + { + + num = (1 << i); + if (!(mask & num)) + continue; /* Not present */ + + num |= 0x80000000; /* Input flag */ + + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + num |= (1 << (i + 1)); + + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL)) < + 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + num, envy24_get_peak, + MIXT_STEREOPEAK, + "-", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + } + + num = (1 << 11); + + if ((err = mixer_ext_create_control (dev, group, + num, envy24_get_peak, + MIXT_STEREOPEAK, + "MONITOR", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + return 0; +} + +/*ARGSUSED*/ +static int +create_mon_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, num, skip; + char tmp[64]; + + int nc = devc->nr_play_channels; + + if (envy24_virtualout) + { + mask = 0; + nc = 10; + for (i = 0; i < nc; i++) + mask |= (1 << i); + } + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_MON")) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + for (i = 0; i < nc; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUTL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDOUTR"); + else + sprintf (tmp, "ENVY24_OUT%d", i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < devc->nr_rec_channels && i < 10; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + num |= 0x80000000; /* Input flag */ + + if (devc->skipdevs == 2) + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + else + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDINL"); + else if (i == 9) + strcpy (tmp, "ENVY24_SPDINR"); + else + sprintf (tmp, "ENVY24_IN%d", i + 1); + + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_MONVOL | + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_peak_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, num, skip; + int nc = devc->nr_play_channels; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_PEAK")) < 0) + return group; + + skip = 2; + + for (i = 0; i < nc; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDOUT"); + else + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_get_peak, + MIXT_STEREOPEAK, + tmp, 144, + MIXF_READABLE | MIXF_DECIBEL)) < + 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < devc->nr_rec_channels; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + num |= 0x80000000; /* Input flag */ + + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIN"); + else if (i == 10) + strcpy (tmp, "ENVY24_MAIN"); + else + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_get_peak, + MIXT_STEREOPEAK, + tmp, 144, + MIXF_READABLE | MIXF_DECIBEL)) < + 0) + return err; + } + } + + return 0; +} + +void +envy24_set_enum_mask (int dev, int ctl, oss_native_word mask) +{ + oss_mixext *ext; + int i; + + ext = mixer_find_ext (dev, ctl); + + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension\n"); + return; + } + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < 32; i++) + if (mask & (1 << i)) + ext->enum_present[i / 8] |= (1 << (i % 8)); +} + +/*ARGSUSED*/ +static int +create_rout_mixer (int dev, envy24_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, skip, num, chnum; + char tmp[64]; + + if ((group = + mixer_ext_create_group_flags (dev, 0, "ENVY24_ROUTE", MIXF_FLAT)) < 0) + return group; + + skip = devc->skipdevs; + if (skip != 2) + skip = 1; + + for (i = 0; i < 8; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + if (devc->skipdevs == 2) + { + oss_native_word tmpmask = 0x00000001; + int j; + + if (i < 2) + tmpmask |= 0x00000002; + for (j = 0; j < 8; j++) + if (mask & (1 << j)) + tmpmask |= 1 << ((j / 2) + 2); + if (devc->model_data->flags & MF_SPDIF) + tmpmask |= 0x00000040; + + sprintf (tmp, "ENVY24_OUT%d/%d", i + 1, i + 2); + chnum = i; + num = (1 << chnum) | (1 << (chnum + 1)); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_stereo_outrout, + MIXT_ENUM, + tmp, 7, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + envy24_set_enum_mask (dev, err, tmpmask); + } + else + { + oss_native_word tmpmask = 0x00000001; + int j; + + sprintf (tmp, "ENVY24_OUT%d", i + 1); + chnum = i; + num = 1 << chnum; + + if (i < 2) + tmpmask |= (1 << 1); + for (j = 0; j < 8; j++) + if (mask & (1 << j)) + tmpmask |= 1 << (j + 2); + if (devc->model_data->flags & MF_SPDIF) + tmpmask |= (3 << 10); + + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_outrout, + MIXT_ENUM, + tmp, 12, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + envy24_set_enum_mask (dev, err, tmpmask); + } + } + + mask = devc->inportmask; + + if (devc->model_data->flags & MF_SPDIF) + { + if (devc->skipdevs == 2) + { + oss_native_word tmpmask = 0x00000043; + int j; + for (j = 0; j < 8; j++) + if (mask & (1 << j)) + tmpmask |= (1 << ((j / 2) + 2)); + + if ((err = mixer_ext_create_control (dev, group, + 3, envy24_set_spdifrout, + MIXT_ENUM, + "ENVY24_SPDIF", 7, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + envy24_set_enum_mask (dev, err, tmpmask); + } + else + { + oss_native_word tmpmask = 0x00000c03; + int j; + for (j = 0; j < 8; j++) + if (mask & (1 << j)) + tmpmask |= (1 << (j + 2)); + + if ((err = mixer_ext_create_control (dev, group, + 1, envy24_set_spdifrout, + MIXT_ENUM, + "ENVY24_SPDIFL", 12, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + envy24_set_enum_mask (dev, err, tmpmask); + + if ((err = mixer_ext_create_control (dev, group, + 2, envy24_set_spdifrout, + MIXT_ENUM, + "ENVY24_SPDIFR", 12, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return err; + envy24_set_enum_mask (dev, err, tmpmask); + } + } + +#if 0 + for (i = 0; i < devc->nr_rec_channels && i < 10; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + num |= 0x80000000; /* Input flag */ + + if (devc->skipdevs == 2) + { + sprintf (tmp, "ENVY24_IN%d/%d", i + 1, i + 2); + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + else + { + sprintf (tmp, "ENVY24_IN%d", i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24_set_mon, + MIXT_STEREOSLIDER16, + tmp, 1440, + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return err; + } + } +#endif + + return 0; +} + +static int +envy24_mix_init (int dev) +{ + envy24_devc *devc = mixer_devs[dev]->devc; + int group, err, ctl; + int n; + + extern int envy24_mixerstyle; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24")) < 0) + return group; + + if (envy24_skipdevs == 2) + switch (envy24_mixerstyle) + { + case 2: + /* New style input and output mixer sections */ + if ((err = create_output_mixer (dev, devc, group)) < 0) + return err; + if ((err = create_input_mixer (dev, devc, group)) < 0) + return err; + break; + + default: + /* Traditional mixer (peak meters and montor gains separated) */ + if ((err = create_peak_mixer (dev, devc, group)) < 0) + return err; + if ((err = create_mon_mixer (dev, devc, group)) < 0) + return err; + break; + } + + if ((err = create_rout_mixer (dev, devc, group)) < 0) + return err; + + if (devc->model_data->auxdrv->mixer_init) + if ((err = devc->model_data->auxdrv->mixer_init (devc, dev, group)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, envy24_set_control, + MIXT_ENUM, + "ENVY24_RATE", 12, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + mixer_ext_set_strings (dev, err, + "8000 9600 11025 12000 16000 22050 24000 32000 44100 48000 88200 96000", 0); + + if (devc->model_data->flags & (MF_SPDIF | MF_WCLOCK)) + { + n = 2; + if (devc->model_data->flags & MF_WCLOCK) + n = 3; + if ((err = mixer_ext_create_control (dev, group, + 2, envy24_set_control, + MIXT_ENUM, + "ENVY24_SYNC", n, + MIXF_READABLE | MIXF_WRITEABLE)) < + 0) + return err; + } + + if (devc->model_data->flags & MF_SPDSELECT) + { + if ((err = mixer_ext_create_control (dev, group, + 4, envy24_set_control, + MIXT_ENUM, + "ENVY24_SPDIN", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < + 0) + return err; + } + +#if 0 +/* Always on */ + if ((err = mixer_ext_create_control (dev, group, + 3, envy24_set_control, + MIXT_ONOFF, + "ENVY24_SRC", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; +#endif + + if ((err = mixer_ext_create_control (dev, group, + 5, envy24_set_control, + MIXT_ONOFF, + "ENVY24_RATELOCK", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((ctl = mixer_ext_create_control (dev, group, + 6, envy24_set_control, + MIXT_VALUE, + "ENVY24_ACTRATE", 96000, + MIXF_READABLE)) < 0) + return ctl; + mixer_ext_set_description(dev, ctl, "Sample rate currently used by the device"); + +#if 1 + if (devc->model_data->auxdrv->get_locked_status) + { + devc->sync_locked = devc->model_data->auxdrv->get_locked_status (devc); + + if ((err = mixer_ext_create_control (dev, group, + 7, envy24_set_control, + MIXT_ONOFF, + "ENVY24_LOCKED", 1, + MIXF_READABLE)) < 0) + return err; + } +#endif + + if (devc->model_data->auxdrv->spdif_mixer_init) + if ((err = + devc->model_data->auxdrv->spdif_mixer_init (devc, dev, group)) < 0) + return err; + return 0; +} + +static mixer_driver_t envy24_mixer_driver = { + envy24_mixer_ioctl +}; + +static int +install_adev (envy24_devc * devc, char *name, int flags, int skip, + int portc_flags, char *port_id, char *devfile_name) +{ + int dev, i; + adev_p adev; + int fmts = 0, last; + extern int envy24_realencoder_hack; + + if (portc_flags & PORTC_SPDOUT) + fmts |= AFMT_AC3; + + if ((dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + name, + &envy24_audio_driver, + sizeof (audiodrv_t), + ADEV_AUTOMODE | ADEV_NOMMAP | + flags | ADEV_NOVIRTUAL, + fmts | AFMT_S16_LE | AFMT_S32_LE | + AFMT_S24_LE, devc, -1, + devfile_name)) < 0) + { + dev = -1; + return 0; + } + else + { + envy24_portc *portc; + adev = audio_engines[dev]; + + if (devc->first_dev == -1) + devc->first_dev = dev; + for (i = 0; speed_tab[i].speed != -1; i++) + adev->rates[adev->nrates++] = speed_tab[i].speed; + + adev->vmix_flags = 0; + + if (flags == DIR_OUTPUT) + { + last = 10; + audio_engines[dev]->port_number = devc->curr_outch; + audio_engines[dev]->min_rate = 8000; + audio_engines[dev]->max_rate = 96000; + portc = &devc->play_portc[devc->nr_outdevs++]; + portc->chnum = devc->curr_outch; + strncpy (portc->name, port_id, sizeof (portc->name) - 1); + portc->name[sizeof (portc->name) - 1] = 0; + devc->curr_outch += skip; + if (portc_flags & PORTC_SPDOUT) + audio_engines[dev]->caps |= PCM_CAP_DIGITALOUT; + if (portc_flags & PORTC_SPDIN) + audio_engines[dev]->caps |= PCM_CAP_DIGITALIN; + + } + else + { + last = 12; + portc = &devc->rec_portc[devc->nr_indevs++]; + audio_engines[dev]->port_number = devc->curr_inch + 10; + portc->chnum = devc->curr_inch; + strncpy (portc->name, port_id, sizeof (portc->name) - 1); + portc->name[sizeof (portc->name) - 1] = 0; + devc->curr_inch += skip; +#ifdef DO_RIAA + portc->riaa_filter = 0; +#endif + } + + portc->flags = portc_flags; + audio_engines[dev]->devc = devc; + audio_engines[dev]->portc = portc; + audio_engines[dev]->rate_source = devc->first_dev; + + switch (skip) + { + case 1: + audio_engines[dev]->caps |= DSP_CH_MONO; + audio_engines[dev]->min_channels = 1; + audio_engines[dev]->max_channels = + (envy24_force_mono) ? 1 : last - portc->chnum; + break; + + case 2: + audio_engines[dev]->caps |= DSP_CH_STEREO; + audio_engines[dev]->min_channels = 1; + audio_engines[dev]->max_channels = last - portc->chnum; + break; + + default: + audio_engines[dev]->caps |= DSP_CH_MULTI; + audio_engines[dev]->min_channels = 1; + audio_engines[dev]->max_channels = last - portc->chnum; + } + + audio_engines[dev]->mixer_dev = devc->mixer_dev; + portc->dev = dev; + portc->open_mode = 0; + portc->is_active = 0; + portc->direction = flags; + portc->trigger_bits = 0; + + if (envy24_realencoder_hack && flags == DIR_INPUT + && devc->nr_indevs > 1) + if (oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "Dummy mixer", + &envy24_mixer_driver, + sizeof (mixer_driver_t), devc) >= 0) + { + mixer_devs[devc->mixer_dev]->priority = -1; /* Don't use as the default mixer */ + } + } + + return 1; +} + +static int +install_output_devices (envy24_devc * devc, int mask) +{ + char tmp[512], id[32]; + int i, nc, portc_flags = 0; + + char *lr = "", *kind; + + nc = devc->nr_play_channels = MAX_ODEV; + devc->nr_rec_channels = MAX_IDEV; + + if (devc->skipdevs < 1) + devc->skipdevs = 1; + + for (i = 0; i < nc; i += devc->skipdevs) + { + char *devfile_name = ""; + + if (devc->skipdevs != 2) + lr = (i & 1) ? "R" : "L"; + kind = ""; + + if (!(mask & (1 << devc->curr_outch))) + kind = "(virtual) "; + + switch (devc->curr_outch) + { + case 8: + case 9: + portc_flags = PORTC_SPDOUT; + sprintf (tmp, "%s %sS/PDIF out %s", devc->model_data->product, kind, + lr); + sprintf (id, "SPDIF%s", lr); + devfile_name = "spdout"; + break; + + default: + if (devc->skipdevs > 1) + { + sprintf (tmp, "%s %sout%d/%d", devc->model_data->product, kind, + i + 1, i + devc->skipdevs); + sprintf (id, "OUT%d/%d", i + 1, i + devc->skipdevs); + } + else + { + sprintf (tmp, "%s %sout%d", devc->model_data->product, kind, + i + 1); + sprintf (id, "OUT%d", i + 1); + } + } + + if (mask & (1 << devc->curr_outch)) + install_adev (devc, tmp, ADEV_NOINPUT, devc->skipdevs, portc_flags, + id, devfile_name); + else + devc->curr_outch += devc->skipdevs; + } + + return 1; +} + +/*ARGSUSED*/ +static int +install_virtual_output_devices (envy24_devc * devc, int mask) +{ +#if 0 + char tmp[512]; + int i, nc; + + char *lr = ""; + nc = devc->nr_play_channels = MAX_ODEV; + devc->nr_rec_channels = MAX_IDEV; + + if (envy24_virtualout) + { + nc = 10; + } + + if (devc->skipdevs < 1) + devc->skipdevs = 1; + + for (i = 0; i < nc; i += devc->skipdevs) + { + + if (devc->skipdevs != 2) + lr = (i & 1) ? "R" : "L"; + + switch (devc->curr_outch) + { + case 8: + case 9: + sprintf (tmp, "%s virtual out %s", devc->model_data->product, lr); + break; + + default: + if (devc->skipdevs > 1) + sprintf (tmp, "%s virtual out%d/%d", devc->model_data->product, + i + 1, i + devc->skipdevs); + else + sprintf (tmp, "%s virtual out%d", devc->model_data->product, + i + 1); + } + + if (!(mask & (1 << devc->curr_outch))) /* Not done yet */ + install_adev (devc, tmp, ADEV_NOINPUT, devc->skipdevs, 0, "virtual", ""); // TODO: Find better device file name + else + devc->curr_outch += devc->skipdevs; + } +#endif + return 1; +} + +static int +install_input_devices (envy24_devc * devc, int mask) +{ + char tmp[512], id[32]; + int i, portc_flags = 0; + + char *lr = ""; + + devc->nr_play_channels = MAX_ODEV; + devc->nr_rec_channels = MAX_IDEV; + + if (devc->skipdevs < 1) + devc->skipdevs = 1; + + for (i = 0; i < devc->nr_rec_channels; i += devc->skipdevs) + { + char *devfile_name = ""; + + if (devc->skipdevs != 2) + lr = (i & 1) ? "R" : "L"; + + switch (devc->curr_inch) + { + case 8: + case 9: + portc_flags = PORTC_SPDIN; + sprintf (tmp, "%s S/PDIF in %s", devc->model_data->product, lr); + sprintf (id, "SPDIF%s", lr); + devfile_name = "spdin"; + break; + + case 10: + case 11: + sprintf (tmp, "%s input from mon. mixer %s", + devc->model_data->product, lr); + sprintf (id, "MON%s", lr); + devfile_name = "mon"; + break; + + default: + if (devc->skipdevs > 1) + { + sprintf (tmp, "%s in%d/%d", devc->model_data->product, i + 1, + i + devc->skipdevs); + sprintf (id, "IN%d/%d", i + 1, i + devc->skipdevs); + } + else + { + sprintf (tmp, "%s in%d", devc->model_data->product, i + 1); + sprintf (id, "IN%d", i + 1); + } + } + + if (mask & (1 << devc->curr_inch)) + install_adev (devc, tmp, ADEV_NOOUTPUT, devc->skipdevs, portc_flags, + id, devfile_name); + else + devc->curr_inch += devc->skipdevs; + } + + OUTL (devc->osdev, 0x00224466, devc->mt_base + 0x34); /* 1 to 1 input routing */ + + return 1; +} + +static int +install_audio_devices (envy24_devc * devc) +{ + extern int envy24_swapdevs; + int maskout, maskin, i; +#define setmask(m, b) m|=(1<<(b)) + + maskout = maskin = 0; + + if (envy24_devmask == 0) + envy24_devmask = 65535; + + if (envy24_devmask & DMASK_MONITORIN) + { + setmask (maskin, 10); /* Monitor input left */ + setmask (maskin, 11); /* Monitor input right */ + } + + if (devc->model_data->flags & MF_SPDIF) + { + if (envy24_devmask & DMASK_SPDIFIN) + { + setmask (maskin, 8); /* S/PDIF left */ + setmask (maskin, 9); /* S/PDIF right */ + } + + if (envy24_devmask & DMASK_SPDIFOUT) + { + setmask (maskout, 8); /* S/PDIF left */ + setmask (maskout, 9); /* S/PDIF right */ + } + if (devc->model_data->auxdrv->spdif_set) + devc->model_data->auxdrv->spdif_set (devc, 0x20); + } + + if (envy24_devmask & DMASK_ANALOGOUT) + for (i = 0; i < devc->model_data->nr_outs; i++) + setmask (maskout, i); + + if (envy24_devmask & DMASK_ANALOGIN) + for (i = 0; i < devc->model_data->nr_ins; i++) + setmask (maskin, i); + + devc->inportmask = maskin; + devc->outportmask = maskout; + + if (envy24_swapdevs) + { + install_input_devices (devc, maskin); + install_output_devices (devc, maskout); + install_virtual_output_devices (devc, maskout); + } + else + { + install_output_devices (devc, maskout); + install_input_devices (devc, maskin); + install_virtual_output_devices (devc, maskout); + } + + for (i = 0; i < 10; i += devc->skipdevs) + { + int num = 1 << i; + if (devc->skipdevs == 2) + num |= 1 << (i + 1); + + if (maskout & num) + envy24_set_mon (devc->mixer_dev, num, SNDCTL_MIX_WRITE, + 1340 | (1340 << 16)); + if (maskin & num) + envy24_set_mon (devc->mixer_dev, 0x80000000 | num, SNDCTL_MIX_WRITE, + 1340 | (1340 << 16)); + } + + if (envy24_devmask & DMASK_RAWDEVS) + envy24d_install (devc); + return 1; +} + +static int +ac97_read (void *devc_, int reg) +{ + envy24_devc *devc = devc_; + int i, status; + + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, 0x10, devc->ccs_base + 0x09); + + for (i = 0; i < 1000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x09); + if (!(status & 0x10)) + { + status = INW (devc->osdev, devc->ccs_base + 0x0a); + return status; + } + } + + return 0xffff; +} + +static int +ac97_writereg (void *devc_, int reg, int data) +{ + envy24_devc *devc = devc_; + int i, status; + + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, reg, devc->ccs_base + 0x08); + OUTB (devc->osdev, 0x20, devc->ccs_base + 0x09); + + for (i = 0; i < 1000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x09); + if (!(status & 0x20)) + { + OUTW (devc->osdev, data & 0xffff, devc->ccs_base + 0x0a); + return 1; + } + } + + return 0; +} + +static int +ac97_write (void *devc, int reg, int data) +{ + int ret; + + ac97_writereg (devc, reg, data); + ac97_writereg (devc, reg, data); + ret = ac97_writereg (devc, reg, data); + return ret; +} + +static void +install_consumer_devices (envy24_devc * devc) +{ +#if 1 + int i, status; + + OUTB (devc->osdev, 0x80, devc->ccs_base + 0x09); /* Cold reset mixer */ + oss_udelay (200); + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x09); /* Release reset */ + oss_udelay (200); + + for (i = 0; i < 1000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x09); + + if (status & 0x80) + break; + + oss_udelay (1000); + } + + if (i >= 1000) + { + } +#endif + + devc->consumer_mixer_dev = + ac97_install (&devc->ac97devc, "Envy24 consumer mixer", ac97_read, + ac97_write, devc, devc->osdev); + + /* Route monitor output to consumer AC97 */ + OUTB (devc->osdev, 0x01, devc->mt_base + 0x3c); + + /* Set consumer volumes to full */ + envy24_write_cci (devc, 3, 0); + envy24_write_cci (devc, 4, 0); +} + +static int +maudio_load_eeprom (envy24_devc * devc) +{ + int status; + + status = INB (devc->osdev, devc->ccs_base + 0x13); + + if (!(status & 0x80)) + return 0; /* No EEPROM */ + + envy24_write_cci (devc, 0x22, devc->eeprom[0xc]); /* GPIO direction */ + envy24_write_cci (devc, 0x21, devc->eeprom[0xa]); /* GPIO write mask */ + envy24_write_cci (devc, 0x20, devc->eeprom[0xb]); /* GPIO data */ + + return 1; +} + + +static int +envy24_init (envy24_devc * devc) +{ + extern int envy24_nfrags; + oss_native_word phaddr; + int err; + + /* Disable all interrupts */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x01); + OUTB (devc->osdev, 0xff, devc->mt_base + 0x00); + + if ((err = oss_register_interrupts (devc->osdev, 0, envy24intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + if (envy24_skipdevs < 1) + envy24_skipdevs = 1; + if (envy24_skipdevs > 2) + envy24_skipdevs = 2; + + devc->skipdevs = envy24_skipdevs; + + if (envy24_skipdevs != 1) + envy24_force_mono = 0; + + if (devc->model_data->flags & MF_MIDI1) + { + char name[128]; + oss_native_word flags; + sprintf (name, "%s #1", devc->model_data->product); + + MUTEX_ENTER (devc->mutex, flags); + uart401_init (&devc->uart401devc1, devc->osdev, devc->ccs_base + 0x0c, + name); + MUTEX_EXIT (devc->mutex, flags); + + /* Enable UART1 interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->ccs_base + 0x01) & ~0x80, + devc->ccs_base + 0x01); + } + + if (devc->model_data->flags & MF_MIDI2) + { + char name[128]; + oss_native_word flags; + sprintf (name, "%s #2", devc->model_data->product); + + MUTEX_ENTER (devc->mutex, flags); + uart401_init (&devc->uart401devc2, devc->osdev, devc->ccs_base + 0x1c, + name); + MUTEX_EXIT (devc->mutex, flags); + /* Enable UART2 interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->ccs_base + 0x01) & ~0x20, + devc->ccs_base + 0x01); + } + + devc->speedbits = 0; + devc->speed = 48000; + devc->pending_speed_sel = 9; + + if (devc->model_data->flags & (MF_MEEPROM)) + maudio_load_eeprom (devc); + + if (devc->model_data->auxdrv->card_init) + devc->model_data->auxdrv->card_init (devc); + if (devc->model_data->auxdrv->spdif_init) + devc->model_data->auxdrv->spdif_init (devc); + + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + devc->model_data->product, + &envy24_mixer_driver, + sizeof (mixer_driver_t), + devc)) >= 0) + { + int n = 50; + + if (devc->skipdevs == 1) + n += 30; + mixer_ext_set_init_fn (devc->mixer_dev, envy24_mix_init, n); + } + + if (envy24_nfrags != 2 && envy24_nfrags != 4 && envy24_nfrags != 8 && + envy24_nfrags != 16 && envy24_nfrags != 32 && envy24_nfrags != 64) + envy24_nfrags = 16; + + devc->playbuffsize = HW_PLAYBUFFSIZE; + devc->recbuffsize = HW_RECBUFFSIZE; + + devc->hw_nfrags = envy24_nfrags; + devc->hw_pfragsize = devc->playbuffsize / devc->hw_nfrags; + devc->hw_rfragsize = devc->recbuffsize / devc->hw_nfrags; + devc->hw_fragsamples = devc->hw_pfragsize / 40; /* # of 32 bit samples/fragment/channel */ + + if (devc->hw_pfragsize % 40) + cmn_err (CE_WARN, "Error! Bad per channel fragment size\n"); + devc->hw_playfrag = 0; + devc->hw_recfrag = 0; + + devc->playbuf = + CONTIG_MALLOC (devc->osdev, HW_ALLOCSIZE, MEMLIMIT_28BITS, &phaddr, devc->playbuf_dma_handle); + if (devc->playbuf == NULL) + { + cmn_err (CE_WARN, "Failed to allocate %d bytes of DMA buffer\n", + HW_ALLOCSIZE); + return 0; + } + + devc->playbuf_phys = phaddr; + if ((devc->playbuf_phys + HW_ALLOCSIZE) >= (256 * 1024 * 1024)) + { + cmn_err (CE_WARN, "Got DMA buffer beyond address 256M.\n"); + cmn_err (CE_CONT, "Reboot and try again\n"); + return 1; + } + + OUTL (devc->osdev, devc->playbuf_phys, devc->mt_base + 0x10); /* Play base */ + + devc->recbuf = + CONTIG_MALLOC (devc->osdev, HW_ALLOCSIZE, MEMLIMIT_28BITS, &phaddr, devc->recbuf_dma_handle); + if (devc->recbuf == NULL) + { + cmn_err (CE_WARN, "Failed to allocate %d bytes of DMA buffer\n", + HW_ALLOCSIZE); + return 0; + } + + devc->recbuf_phys = phaddr; + if ((devc->recbuf_phys + HW_ALLOCSIZE) >= (256 * 1024 * 1024)) + { + cmn_err (CE_WARN, "Got DMA buffer beyond address 256M.\n"); + cmn_err (CE_CONT, "Reboot and try again\n"); + return 1; + } + + OUTL (devc->osdev, devc->recbuf_phys, devc->mt_base + 0x20); /* Rec base */ + + devc->playback_started = 0; + devc->recording_started = 0; + devc->playback_prepared = 0; + devc->recording_prepared = 0; + devc->writeahead = 1; +#ifdef __VXWORKS__ + devc->ratelock = 0; +#else + devc->ratelock = 1; +#endif + memset (devc->playbuf, 0, HW_ALLOCSIZE); + memset (devc->recbuf, 0, HW_ALLOCSIZE); + + install_audio_devices (devc); + + if (devc->consumer_ac97_present || (devc->model_data->flags & MF_CONSUMER)) + install_consumer_devices (devc); + /* Enable professional rec/play interrupts */ + OUTB (devc->osdev, + INB (devc->osdev, devc->ccs_base + 0x01) & ~0x10, + devc->ccs_base + 0x01); + + setup_spdif_control (devc); + + if (devc->model_data->auxdrv->spdif_set) + devc->model_data->auxdrv->spdif_set (devc, 0x20); + +#if 1 + /* Make sure everything is initialized */ + envy24_prepare_play_engine (devc); + envy24_launch_play_engine (devc); + oss_udelay (10000); + envy24_stop_playback (devc); +#endif + +#if 0 + { + char line[200], *s = line; + *line = 0; + + for (i = 0; i < 0x20; i++) + { + if (!(i % 16)) + { + if (*line != 0) + cmn_err (CE_CONT, "%s\n", line); + + s = line; + sprintf (s, "CCS%02x: ", i); + s = line + strlen (line); + } + sprintf (s, "%02x ", INB (devc->osdev, devc->ccs_base + i)); + s = line + strlen (line); + } + *line = 0; + + for (i = 0; i < 0x40; i++) + { + if (!(i % 16)) + { + if (*line != 0) + cmn_err (CE_CONT, "%s\n", line); + + s = line; + sprintf (s, "MT%02x: ", i); + s = line + strlen (line); + } + sprintf (s, "%02x ", INB (devc->osdev, devc->mt_base + i)); + s = line + strlen (line); + } + + cmn_err (CE_CONT, "%s\n", line); + } +#endif + + return 1; +} + +int +oss_envy24_attach (oss_device_t * osdev) +{ + envy24_devc *devc; + static int status; + unsigned char pci_irq_line; + unsigned short pci_command, vendor, device; + unsigned int subvendor; + unsigned int pci_ioaddr, pci_ioaddr3; + int i; + + char *name = "Generic ENVY24"; + + DDB (cmn_err (CE_CONT, "Entered Envy24 probe routine\n")); + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + + devc->osdev = osdev; + osdev->devc = devc; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != ICENSEMBLE_VENDOR_ID || device != ICENSEMBLE_ENVY24_ID) + return 0; + + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + DDB (cmn_err (CE_CONT, "Device found at I/O %x\n", pci_ioaddr)); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_3, &pci_ioaddr3); + + devc->active_inputs = 0; + devc->active_outputs = 0; + devc->sync_locked = 1; + devc->first_dev = -1; + + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, 0x2c, &subvendor); + devc->ccs_base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr) & ~0x3; + DDB (cmn_err (CE_CONT, "CCS base %x/%lx\n", pci_ioaddr, devc->ccs_base)); + + devc->mt_base = MAP_PCI_IOADDR (devc->osdev, 3, pci_ioaddr3) & ~0x3; + DDB (cmn_err (CE_CONT, "MT base %x/%lx\n", pci_ioaddr3, devc->mt_base)); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + + /* Reset the chip */ + OUTB (devc->osdev, 0x81, devc->ccs_base + 0x00); + oss_udelay (200); + /* Release reset */ + OUTB (devc->osdev, 0x01, devc->ccs_base + 0x00); + oss_udelay (200); + + devc->nr_outdevs = devc->nr_indevs = 0; + devc->curr_outch = devc->curr_inch = 0; + devc->playbuffsize = 0; + devc->recbuffsize = 0; + devc->playbuf = devc->recbuf = NULL; + + status = INB (devc->osdev, devc->ccs_base + 0x13); + if (status & 0x80) /* EEPROM present */ + { + static char resol_tab[] = { 16, 18, 20, 24 }; + unsigned char tmpbyte; + + load_eeprom (devc, subvendor); + + /* Fix bit 0x80 of EEPROM location 0x07. */ + pci_read_config_byte (osdev, 0x61, &tmpbyte); + tmpbyte &= 0x80; + devc->eeprom[0x07] &= ~0x80; + devc->eeprom[0x07] |= tmpbyte; + +#if 1 + devc->eeprom[0x07] |= 0x80; +#endif + + pci_write_config_byte (osdev, 0x60, devc->eeprom[0x06]); + pci_write_config_byte (osdev, 0x61, devc->eeprom[0x07]); + pci_write_config_byte (osdev, 0x62, devc->eeprom[0x08]); + pci_write_config_byte (osdev, 0x63, devc->eeprom[0x09]); + +#if 1 + if (devc->eeprom[0x06] & 0x20) + DDB (cmn_err (CE_CONT, "Two MPU401 UARTs present.\n")); + if (devc->eeprom[0x06] & 0x10) + { + DDB (cmn_err (CE_CONT, "Consumer AC97 not present.\n")); + } + else + { + DDB (cmn_err (CE_CONT, "Consumer AC97 present.\n")); + } + DDB (cmn_err (CE_CONT, "%d stereo ADC(s) available\n", + ((devc->eeprom[0x06] >> 2) & 0x03) + 1)); + DDB (cmn_err (CE_CONT, "%d stereo DAC(s) available\n", + ((devc->eeprom[0x06] >> 0) & 0x03) + 1)); + + DDB (cmn_err (CE_CONT, "MT converter type %s\n", + (devc->eeprom[0x07] & 0x80) ? "I2S" : "AC97")); + + if (devc->eeprom[0x08] & 0x80) + { + DDB (cmn_err (CE_CONT, "Has I2S volume control and mute\n")); + } + else + { + DDB (cmn_err (CE_CONT, "No I2S volume control and mute\n")); + } + if (devc->eeprom[0x08] & 0x20) + DDB (cmn_err (CE_CONT, "Has 96kHz support\n")); + + DDB (cmn_err (CE_CONT, "Converter resolution %d bits\n", + resol_tab[(devc->eeprom[0x08] >> 4) & 0x03])); + + if (devc->eeprom[0x09] & 0x02) + DDB (cmn_err (CE_CONT, "Has S/PDIF in support\n")); + if (devc->eeprom[0x09] & 0x01) + DDB (cmn_err (CE_CONT, "Has S/PDIF out support\n")); + +#endif + + if (subvendor == 0xd6301412) /* Delta 1010 */ + if (devc->eeprom[0xc] == 0x7b) /* Looks like Delta 1010 rev E */ + subvendor = 0xd63014ff; /* Delta 1010E */ + + +#if 1 + if (!(devc->eeprom[0x07] & 0x80)) + { + cmn_err (CE_WARN, "Cards with AC97 codecs are not supported\n"); + return 0; + } +#endif + } + + i = 0; + while (models[i].svid != 0) + { + if (models[i].svid == subvendor) + { + name = models[i].product; + devc->model_data = &models[i]; + if (devc->model_data->auxdrv == NULL) + devc->model_data->auxdrv = &default_auxdrv; + DDB (cmn_err (CE_CONT, "Card id '%s'\n", name)); + + break; + } + + i++; + } + + if (devc->model_data->flags & MF_AC97) + devc->consumer_ac97_present = 1; + + if (models[i].svid == 0) + { + cmn_err (CE_NOTE, "Unknown device ID (%08x).\n", subvendor); + cmn_err (CE_NOTE, "This card is not supported (yet).\n"); + return 0; + } + + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + oss_register_device (osdev, name); + devc->irq = pci_irq_line; + return envy24_init (devc); /* Detected */ +} + + +int +oss_envy24_detach (oss_device_t * osdev) +{ + envy24_devc *devc; + + devc = osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + /* Disable all interrupts */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x01); + + /* Stop playback */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + oss_udelay (100); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + + /* Stop recording */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + oss_udelay (100); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + + if (devc->model_data->flags & MF_MIDI1) + uart401_disable (&devc->uart401devc1); + if (devc->model_data->flags & MF_MIDI2) + uart401_disable (&devc->uart401devc2); + + oss_unregister_interrupts (osdev); + MUTEX_CLEANUP (devc->mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + UNMAP_PCI_IOADDR (devc->osdev, 3); + + if (devc->playbuf != NULL) + CONTIG_FREE (devc->osdev, devc->playbuf, HW_ALLOCSIZE, devc->playbuf_dma_handle); + + if (devc->recbuf != NULL) + CONTIG_FREE (devc->osdev, devc->recbuf, HW_ALLOCSIZE, devc->recbuf_dma_handle); + devc->playbuf = devc->recbuf = NULL; + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_envy24/oss_envy24.man b/kernel/drv/oss_envy24/oss_envy24.man new file mode 100644 index 0000000..d9943a9 --- /dev/null +++ b/kernel/drv/oss_envy24/oss_envy24.man @@ -0,0 +1,334 @@ +NAME +oss_envy24 - ICE Envy24 audio device driver. + +DESCRIPTION +Open Sound System driver for Envy24 based audio cards such as the +M-Audio Delta Series, Terratec EWS88 Series, Hoontech DSP24. + + ENVY24 device characteristics: + +o 8/16 bit playback/record +o mono/stereo/4ch/5.1ch/7.1ch playback +o mono/sterero recording +o 8KHz to 192Khz sample rate. + + ENVY24 AUDIO DEVICES + + Audio devices: + 0: M Audio Delta 1010 out1/2 + 1: M Audio Delta 1010 out3/4 + 2: M Audio Delta 1010 out5/6 + 3: M Audio Delta 1010 out7/8 + 4: M Audio Delta 1010 S/PDIF out + 5: M Audio Delta 1010 in1/2 + 6: M Audio Delta 1010 in3/4 + 7: M Audio Delta 1010 in5/6 + 8: M Audio Delta 1010 in7/8 + 9: M Audio Delta 1010 S/PDIF in + 10: M Audio Delta 1010 input from mon. mixer + 11: M Audio Delta 1010 (all outputs) + 12: M Audio Delta 1010 (all inputs) + + Synth devices: + + Midi devices: + 0: M Audio Delta 1010 + + Timers: + 0: System clock + + Mixers: + 0: M Audio Delta 1010 + + +The actual /dev/dsp# numbers may be different on your system. Check the right +ones by looking at the output procuced by "ossinfo -a" command. With the +above configuration you can use /dev/dsp0 to /dev/dsp4 for playback of stereo +streams. If you play mono files the signal will be output only from the left +channel. /dev/dsp0 to /dev/dsp3 are connected to the analog outputs while +/dev/dsp4 is the S/PDIF output. + +The /dev/dsp5 to /dev/dsp10 device files can be used for recording. /dev/dsp5 +to /dev/dsp8 are the analog inputs. /dev/dsp11 and /dev/dsp12 are raw +input/output device files. They will be described in detail in the "Raw I/O +devices" section below. + +It's also possible to make OSS to create individual device files for every +channel this creates twice as many device files than the default setting. To +do this just append envy24_skipdevs=1 to the oss_envy24.conf file. This is useful +only if you are working on mono rather than stereo signals. However please +note that setting envy24_skipdevs=1 does _NOT_ lock the device files to one +channel mode, the application can still set them to stereo or multi channel +mode if it likes. + +It is possible to set all device files to mono only mode by setting +envy24_skipdevs=1 and envy24_force_mono=1. However this mode disables stereo +and multi channel usage for all devices so in general it should not be used. + +By default the driver will create output devices before the input ones. By +setting envy24_swapdevs=1 in oss_envy24.conf you can ask OSS to create the device +files in opposite order i.e. input device files before the output ones. This +may be useful when using RealProducer. + +As a workaround to a bug in RealProducer you also need to create some dummy +mixer devices by defining envy24_realencoder_hack=1 in oss_envy24.conf. Without +these extra mixer devices RealProducer will not be able to access other than +the first input device. + + + DEVICE MANAGEMENT + +By default OSS creates a large number of device files for each envy24 card. +This may be a problem when multiple cards need to be used in the same system. +Adding the envy24_devmask option to oss_envy24.conf should help +in most cases because it removes the devices that are actually not needed in +the system. + +The envy24_devmask number is the SUM of the following values: + + 1: Create primary (analog/ADAT/TDIF) outputs. + 2: Create primary (analog/ADAT/TDIF) inputs. + 4: Create S/PDIF outputs. + 8: Create S/PDIF inputs. + 16: Create monitor input device. + 32: Create the raw input and output devices. + +For example envy24_devmask=12 (4+8) creates only the S/PDIF devices. +To enable all possible (current or future) device files set envy24_devmask +to 65535 (default). + +If possible make your application to open the right device file +(/dev/dsp0 to /dev/dsp10) explicitly. It's also possible to use the +default devicefile (/dev/dsp) since OSS now supports automatic device +allocation (it opens the first available input or output devicefile +depending on the open mode). + +The channel allocation mechanism between device files is very flexible. +Even there is a device file for every stereo pair (or a mono channel) +it's possible to use any of the device file to access multiple channels. +For example an application can open /dev/dsp0 and set the number of +channels to 10. In this way the application can play all 10 channels +(or any number between 1 and 10) simultaneously (the samples will be +interleaved). + +There is simple automatic syncstart feature when using multiple +applications at the same time. Playback will not start before all +currently open devices files have started the playback operation. +The same mechanism works for recording (recording and playback +operations are fully independent). + +The Envy24 driver supports 8, 16 and 24/32 bit sample formats. + + + SAMPLING RATE + +Envy24 based cards are multi channel devices and all the channels share the +same sampling rate. For this reason the sampling rate is normally locked to the +value selected using ossmix. However OSS supports some other methods for +changing the sampling rate. There are four ways to change the sampling rate. + + BASIC METHOD: + +Since all input and output channels of Envy24 work at the same sampling rate +it's not possible for the applications to select the rate themselves. Instead +the sampling rate is always locked to the currently selected rate. This rate +selection can be changed using the ossmix program shipped with OSS. + +For example: + + ossmix envy24.rate 48000 + +sets the sampling rate to 48000 Hz (default). The possible alternatives are +- 8000 +- 9600 +- 11025 +- 12000 +- 16000 +- 22050 +- 24000 +- 32000 +- 44100 +- 48000 +- 88200 +- 96000 + +When using S/PDIF inputs/outputs only the sampling rates 32000, 44100, 48000, 88200 or 96000 should be used. + + EXTERNAL SYNC +It's possible to lock the sampling rate to the S/PDIF or world clock inputs +by setting the envy24.sync setting in ossmix to SPDIF or WCLOCK. However +the envy24.rate setting should be set manually to match the rate being used +(there is no autodetection for that). + + NONLOCKED METHOD +It's also possible to turn the envy24.ratelock setting to OFF using ossmix. +After that the first application that opens the device can change the sampling +rate. However great care should be taken that this application gets the +recording/playback process fully started before any of the other +applications open their devices. Otherwise all devices will be locked to 8Khz. +Also keep in mind that subsequent applications will be forced to use the +sampling rate set by the first one. + + SOFTWARE SRC +OSS contains a very high quality software based sample rate converter. +It can be enabled by setting envy24.src to ON using ossmix. + +After that OSS can do on-fly sample rate conversions between the actual +"hardware" sampling rate and the sampling rates used by the applications. In +this way every application may use different sampling rate. However there are +some drawbacks in this method: + +o The hardware rate needs to be 44100, 48000 or 96000 Hz. +o The software SRC algorithm consumes some CPU time (1% to 20% per audio +channel depending on the CPU speed and sampling rates). For this reason this +method may be useless in multi channel use with anything else but the fastest +high end CPUs. +o Only mono and stereo (1 or 2 channel) streams are supported. +o The SRC algorithm does cause minor artifacts to the sound (SNR is around 60 dB). + + + RAW IO DEVICES + +These device files provide an alternative way to access Envy24 based devices. +With these devices it's possible to bypass the dual buffering required by the +"normal" input-output device files described above. This means that also the +mmap() feature is available and that the latencies caused by dual buffering +are gone. So these device files work much like "ordinary" soundcards. However +due to multi channel professional nature of the Envy24 chip there are some very +fundamental differences. This means that these device files can only be used +with applications that are aware of them. + +The differences from normal audio device files are: + +1. The sample format will always be 32 bit msb aligned (AFMT_S32_LE). Trying to +use any other sample format will cause unexpected results. +2. Number of channels is fixed and cannot be changed. The output device has +always 10 channels (0 to 7 are analog outputs and 8 to 9 are the digital +outputs). This assignment will be used even with cards that don't support +digital (or analog) outputs at all. If the actual hardware being used has +less channels the unused ones will be discarded (however they will be fed to +the on board monitor mixer). + +The input device is fixed to 12 channels. Channels 0 to 7 are analog inputs. +Channels 8 to 9 are digital inputs. Channels 10 and 11 are for the result +signal from the on board monitor mixer. + + + DIGITAL MONITOR MIXER + +All Envy24 based cards have a built in monitor mixer. It can be used to mix +allinput and output signals together. The result can be recorded from the +"input from mon mixer" device (device 10 in the /dev/sndstat example above). +The monitor mix signal can also be routed to any of the outputs (including +S/PDIF and the "consumer" AC97 output of Terratec EWS88MT/D and any other card +that support s it). + +The settings in the gain.* group of ossmix are used to change the levels of all +inputs and outputs in the digital monitor mixer. The possible values are +between 0 (minimum) and 144 (maximum). + +OSS permits using all 10 possible output channels of the monitor mixer even +with cards that have less physical outputs. These "virtual" outputs are only +sent to the monitor mixer and their signal is only present in the monitor mixer +output. To enable these "virtual" channels set the envy24_virtualout parameter +to 1 in oss_envy24.conf. This option has no effect with Delta1010, EWS88MT and +other cards that have 10 "real" outputs. + + + SYNC SOURCE + +On cards with S/PDIF and/or World Clock inputs it's possible to select the +sync source using + + ossmix envy24.sync + +The possible choices are: + +o INTERNAL: Use the internal sampling rate as defined by envy24.rate +o SPDIF: Use the S/PDIF input as the clock source. The envy24.rate setting +must be set manually to match the actual input sampling rate. +o WCLOCK: Like SPDIF but uses the world clock input signal (Delta 1010 only). + + + OUTPUT ROUTINGS + +Output routing of output ports can be changed by changing the route.* settings +using ossmix. The possible choices are: + +o DMA: Playback from the associated /dev/dsp# device. +o MONITOR: Output of the digital mixer (only out1/2 and S/PDIF). +o IN1/2 to IN9/10 or IN1 to IN10: Loopback from the analog inputs +o SPDIFL or SPDIFR or SPDIF: Loopback from the S/PDIF input. + + + PEAK METERS + +Envy24 based cards have peak meters for the input and output ports of the +digital monitor mixer. ossmix can show these values under the peak.* group +(these settings are read only). The values are between 0 (minimum) and 255 +(maximum). At this moment the only applications that supports these peak meters +are ossmix and ossxmix. + + + AUDIO LATENCY + +IDE disk and CD-ROM drives may cause some interrupt latency problems which +may cause dropouts in recording/playback with Envy24 based cards. For this +reason ensure that DMA is turned on for the disk drive. + +Another method to solve the dropout problems is making the fragment size used +by the driver longer. This can be done by adding envy24_nfrags=N to the +oss_envy24.conf file. By default N is 16. Values 2, 4 or 8 make the fragments +longer which should cure the dropout problems. However this may cause +latency problems with some applications. Values 32 and 64 decrease the +latencies but may cause dropouts with IDE. + + +OPTIONS + +o envy24_skipdevs: It's also possible to make OSS to create individual device +files for every channel. This creates twice as many device files than the +default setting. +Values: 1, 0 Default: 0 + +o envy24_swapdevs: By default the driver will create output devices before the +input ones. You can force the input devices to be configured before output +devices. +Values: 1, 0 Default: 0 + +o envy24_realencoder_hack: RealProducer wants to see a mixer device in +/dev/mixer. This option allows you to define a dummy /dev/mixer mixer device. +Envy24 Mixer device doesn't provide any consumer level soundcard compatibility +so this dummy mixer fools RealProducer into thinking it's running on a consumer +soundcard like SB Pro or SBLive. +Values: 1, 0 Default: 0 + +o envy24_gain_sliders: With some devices it's possible to change the gain +controllers to be continuous sliders instead of just enumerated ones. +Values: 1, 0 Default: 0 + +o envy24_nfrags: To solve the dropout problems make the fragment size used by +the driver longer. By default is 16. Values 2, 4 or 8 make the fragments longer +which should cure the dropout problems. However this may cause latency problems +with some applications. Values 32 and 64 decrease the latencies but may cause +dropouts with IDE drives. +Values: 2-64 Default: 16 + +o envy24_virtualout: OSS permits using all 10 possible output channels of the +monitor mixer even with cards that have less physical outputs. These "virtual" +outputs are only sent to the monitor mixer and their signal is only present in +the monitor mixer output. This has no effect for Delta1010 or Terratec EWS88MT. +Values: 1, 0 Default: 0 + +o envy24_force_mono: It is possible to set all device files to mono only mode +by setting envy24_skipdevs=1 and envy24_force_mono=1. However this mode +disables stereo and multi channel usage for all devices so in general it should +not be used. +Values: 1, 0 Default: 0 + +FILES +CONFIGFILEPATH/oss_envy24.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_envy24ht/.changelog b/kernel/drv/oss_envy24ht/.changelog new file mode 100644 index 0000000..972605e --- /dev/null +++ b/kernel/drv/oss_envy24ht/.changelog @@ -0,0 +1 @@ +800802xx by Artem Antonov: Added support for ESI Juli@ diff --git a/kernel/drv/oss_envy24ht/.devices b/kernel/drv/oss_envy24ht/.devices new file mode 100644 index 0000000..b90025d --- /dev/null +++ b/kernel/drv/oss_envy24ht/.devices @@ -0,0 +1,12 @@ +oss_envy24ht pci1412,1724 Generic ENVY24HT based sound card +oss_envy24ht pcs1412,3630 M Audio Revolution 7.1 +oss_envy24ht pcs1412,3631 M Audio Revolution 5.1 +oss_envy24ht pcs1412,6321 M Audio Audiophile 192 +oss_envy24ht pcs153b,1145 Terratec Aureon 7.1 Space +oss_envy24ht pcs153b,1147 Terratec Aureon 7.1 Sky +oss_envy24ht pcs153b,1149 Terratec PHASE 28 +oss_envy24ht pcs153b,1153 Terratec Aureon 7.1 Universe +oss_envy24ht pcs3031,4553 Ego Systems Juli@ *BETA* +oss_envy24ht pcs4933,4553 Audiotrak Prodigy 7.1 +oss_envy24ht pcs3137,4154 Audiotrak Prodigy HD2 +oss_envy24ht pcs1412,2401 Audiotrak Prodigy HD2 Advance DE diff --git a/kernel/drv/oss_envy24ht/.name b/kernel/drv/oss_envy24ht/.name new file mode 100644 index 0000000..77fd7c1 --- /dev/null +++ b/kernel/drv/oss_envy24ht/.name @@ -0,0 +1 @@ +VIA Envy24HT/PT (ICE1724) sound chipset diff --git a/kernel/drv/oss_envy24ht/.params b/kernel/drv/oss_envy24ht/.params new file mode 100644 index 0000000..4e6831b --- /dev/null +++ b/kernel/drv/oss_envy24ht/.params @@ -0,0 +1,5 @@ +int envy24ht_model = -1; +/* + * Select the Model number if the card isn't autodetected + * Values: 0 = Envy24ht 1=Envy24PT/HT-s compatible -1=Autodetect Default: -1 + */ diff --git a/kernel/drv/oss_envy24ht/envy24ht.h b/kernel/drv/oss_envy24ht/envy24ht.h new file mode 100644 index 0000000..f11029b --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht.h @@ -0,0 +1,230 @@ +/* + * Purpose: Common definitions for envy24ht driver files + */ +/* + * + * 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 "ac97.h" +#include "midi_core.h" + +/* + * Various subvendor device ID's + */ +#define SSID_AUREON_SPACE 0x1145153b +#define SSID_AUREON_SKY 0x1147153b +#define SSID_AUREON_UNIVERSE 0x1153153b +#define SSID_PHASE28 0x1149153b +#define SSID_PRODIGY71 0x45534933 +#define SSID_PRODIGYHD2 0x41543137 +#define SSID_PRODIGYHD2_ADE 0x24011412 +#define SSID_JULIA 0x45533031 +#define SSID_AP192 0x36321412 + +typedef struct +{ + unsigned int dwSubVendorID; /* PCI[2C-2F], in BIG ENDIAN format */ + unsigned char bSize; /* size of EEPROM image in bytes */ + unsigned char bVersion; /* version equal 1 for this structure. */ + unsigned char bCodecConfig; /* PCI[60] */ + unsigned char bACLinkConfig; /* PCI[61] */ + unsigned char bI2SID; /* PCI[62] */ + unsigned char bSpdifConfig; /* PCI[63] */ + unsigned char bGPIOInitMask0; /* Corresponding bits need to be inited */ + /* 0 means write bit and 1 means cannot write */ + unsigned char bGPIOInitState0; /* Initial state of GPIO pins */ + unsigned char bGPIODirection0; /* GPIO Direction State */ + unsigned char bGPIOInitMask1; + unsigned char bGPIOInitState1; + unsigned char bGPIODirection1; + unsigned char bGPIOInitMask2; + unsigned char bGPIOInitState2; + unsigned char bGPIODirection2; + unsigned char bAC97RecSrc; + unsigned char bDACID[4]; /* I2S IDs for DACs [0 ~ 3] */ + unsigned char bADCID[4]; /* I2S IDs for ADCs [0 ~ 3] */ + unsigned char bDACID4; /* I2S ID for DAC#4 */ + unsigned char Reserved[32]; +} eeprom_data_t; + +typedef struct envy24ht_auxdrv envy24ht_auxdrv_t; + +typedef struct +{ + unsigned int svid; + char *product; + int nr_outs, nr_ins; /* # of analog channels */ + int flags; +#define MF_MIDI 0x00000001 /* Has MIDI port */ +#define MF_192K 0x00000002 /* Supports 192kHz */ +#define MF_SPDIFIN 0x00000004 /* Has S/PDIF input */ +#define MF_SPDIFOUT 0x00000008 /* Has S/PDIF output */ +#define MF_ENVY24PT 0x00000010 /* Envy24PT chip (no EEPROM) */ +#define MF_NOAC97 0x00000020 /* Ignore AC97 codec */ + const envy24ht_auxdrv_t *auxdrv; + unsigned char *eeprom_data; +} +card_spec; + +#define ICENSEMBLE_VENDOR_ID 0x1412 +#define ICENSEMBLE_ENVY24HT_ID 0x1724 +#define MAX_ENVY24HT_CARD 8 + +#ifdef USE_LICENSING +extern int options_data; +#endif + +#define MAX_ODEV 5 +#define MAX_IDEV 2 + +typedef struct +{ + int dev; + int open_mode; + int direction; + int fmt; + char *name; + + int channels; + volatile int is_active; + volatile int trigger_bits; + oss_native_word base; + unsigned char mask; + int dev_flags; +#define DF_MULTICH 0x00000001 +#define DF_SPDIF 0x00000002 +#define DF_AC3 0x00000004 +#define DF_DUPLEX 0x00000008 + int chmask; + int used_chmask; + + int state_bits; +} +envy24ht_portc; + +typedef struct +{ + int dta, clk; +} oss_i2c_t; + +/*****************/ + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + const envy24ht_auxdrv_t *auxdrv; + int codec_type; +#define CODEC_I2S 0 +#define CODEC_AC97 1 + int mpu1_attached, mpu2_attached; + oss_native_word ccs_base, mt_base; + int irq; + card_spec *model_data; + unsigned int subvendor; + eeprom_data_t eeprom; + char channel_names[4][10]; + unsigned short gpio_shadow_L; + unsigned char gpio_shadow_H; + + oss_i2c_t i2c; +/* + * MT mixer + */ + + int mixer_dev; + ac97_devc ac97devc; + + int nr_outdevs, nr_indevs; + envy24ht_portc play_portc[MAX_ODEV]; + envy24ht_portc rec_portc[MAX_IDEV]; + + int outportmask, inportmask; + int nr_play_channels, nr_rec_channels; + int first_dev; + + int open_count; + int speed, pending_speed, pending_speed_sel, speedbits, configured_rate_sel; + int prev_speed; /* Strictly for use by low level modules */ + int max_ratesel; + int syncsource; + + int use_src; + int ratelock; + int external_sync; + int busy_play_channels; + int busy_rec_channels; + + spdif_devc spdc; + int gains[6]; + int monitor[5]; + int recsrc; + +/* + * MIDI + */ + int midi_opened; + int midi_attached; + oss_midi_inputbyte_t midi_input_intr; + oss_midi_outputintr_t midi_output_intr; + volatile unsigned char input_byte; + int midi_dev; + +/* + * Low level stuff + */ + unsigned char dac1val[5], dac2val[11]; /* M Audio Revo 7.1 */ + unsigned short m_AC97Volume[6]; /* Terratec Aureon */ + unsigned char m_fAC97Mute[6]; /* Terratec Aureon */ + int m_DigInSource; /* Aureon */ + int m_LineInSource; /* Aureon */ + int m_SPDIFSource; /* Aureon */ + int m_ADCIndex; /* Aureon */ + int m_f1724SPDIF; /* Aureon */ + int m_SPDIFConfig; /* Aureon */ + int m_Frontjack; /* Aureon */ + unsigned char m_fDACMute[12]; /* Aureon */ + unsigned char m_DACVolume[13]; /* Aureon & Juli@ */ + unsigned short m_ADCVolume[8]; /* Aureon */ + unsigned char m_ADCMux; /* Aureon */ + unsigned char m_fSPDIFRecord; /* Aureon */ + unsigned char m_AuxMux; /* Aureon */ + unsigned int m_ClockSource; /* Aureon */ + unsigned int m_Out0Source; /* Aureon */ + + int mute; + int reclevel; + timeout_id_t timeout_id; /* Juli@ */ + + unsigned char syncstart_mask; +} +envy24ht_devc; + +struct envy24ht_auxdrv +{ + void (*card_init) (envy24ht_devc * devc); + int (*mixer_init) (envy24ht_devc * devc, int dev, int group); + void (*set_rate) (envy24ht_devc * devc); + int (*get_locked_status) (envy24ht_devc * devc); + int (*spdif_mixer_init) (envy24ht_devc * devc, int dev, int group); + int (*private1) (envy24ht_devc * devc, int value); + int (*audio_ioctl) (envy24ht_devc * devc, envy24ht_portc * portc, unsigned int cmd, + ioctl_arg arg); + void (*card_uninit) (envy24ht_devc * devc); +}; + +struct speed_sel +{ + int speed, speedbits; +}; + +void envy24ht_write_cci (envy24ht_devc * devc, int pos, int data); +int envy24ht_read_cci (envy24ht_devc * devc, int pos); diff --git a/kernel/drv/oss_envy24ht/envy24ht_ac97.c b/kernel/drv/oss_envy24ht/envy24ht_ac97.c new file mode 100644 index 0000000..46d2382 --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_ac97.c @@ -0,0 +1,137 @@ +/* + * Purpose: Low level routines for AC97 based Envy24HT boards (mainly Envy24-PT). + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +#define AKM_ADDRESS 0x10 +#if 0 +# define PRT_STATUS(v) outb(v&0xff, 0x378) +#else +# define PRT_STATUS(v) +#endif + +#if 0 +static unsigned char +i2c_read (envy24ht_devc * devc, unsigned char addr, unsigned char pos) +{ + int i; + unsigned char data; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, addr << 1, devc->ccs_base + 0x10); /* Read address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + oss_udelay (1); + data = INB (devc->osdev, devc->ccs_base + 0x12); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return data; +} + +static void +i2c_write (envy24ht_devc * devc, unsigned char addr, unsigned char pos, + unsigned char data) +{ + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, data, devc->ccs_base + 0x12); /* Data */ + OUTB (devc->osdev, (addr << 1) | 1, devc->ccs_base + 0x10); /* Write address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} +#endif + +/*ARGSUSED*/ +static void +init_cs8415a (envy24ht_devc * devc) +{ +} + +/*ARGSUSED*/ +static void +init_wm8728 (envy24ht_devc * devc) +{ + +#if 0 + printk ("Regs="); + for (i = 0; i < 0x18; i++) + { + PRT_STATUS (2); + printk ("%02x ", i2c_read (devc, addr, i)); + PRT_STATUS (0); + } + printk ("\n"); +#endif +} + +static void +ac97_card_init (envy24ht_devc * devc) +{ + + PRT_STATUS (0); + PRT_STATUS (0x01); + PRT_STATUS (0); + + OUTW (devc->osdev, 0x000f, devc->ccs_base + 0x14); /* GPIO */ + + oss_udelay (1000); + + devc->recsrc = 0; + init_cs8415a (devc); + init_wm8728 (devc); +} + +/*ARGSUSED*/ +static int +ac97_mixer_init (envy24ht_devc * devc, int dev, int group) +{ + return 0; +} + +#if 0 +static int +ac97_private1 (envy24ht_devc * devc, int value) +{ + i2c_write (devc, AKM_ADDRESS, (value >> 8) & 0xff, value & 0xff); + return 0; +} +#endif + +envy24ht_auxdrv_t envy24ht_ac97_auxdrv = { + ac97_card_init, + ac97_mixer_init +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_ap192.c b/kernel/drv/oss_envy24ht/envy24ht_ap192.c new file mode 100644 index 0000000..9929c27 --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_ap192.c @@ -0,0 +1,617 @@ +/* + * Purpose: Low level routines for M Audio Audiophile 192 + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +static char channel_names[4][10] = { + "main", + "unused1", + "unused2", + "unused3" +}; + +#define BIT(x) (1<<(x)) +#define BIT3 BIT(3) + +/*----- SPI bus for CODEC communication. */ +/* */ +#define SPI_CLK 1 /* Clock output to CODEC's, rising edge clocks data. */ +#define SPI_DIN 2 /* Data input from the CODEC. */ +#define SPI_DOUT 3 /* Data output to the CODEC. */ +#define SPI_CS0n (1<<4) /* Selects first chip. */ +#define SPI_CS1n (1<<5) /* Selects second chip. */ + +#define SPI_CC_AK4358 0x02 /* C1:C0 for ak4358. */ +#define SPI_CC_AK4114 0x02 /* C1:C0 for ak4114. */ +#define WRITEMASK 0xffff +/*----- Revolution defines. */ +/* */ +#define ap192_AK4114 (1) /* iDevice value for AK4114 DIR. */ +#define ap192_AK4358 (2) /* iDevice value for AK4358 D/A. */ + +static unsigned int +GpioReadAll (envy24ht_devc * devc) +{ + return INW (devc->osdev, devc->ccs_base + 0x14); +} + +static void +GPIOWriteAll (envy24ht_devc * devc, unsigned int data) +{ + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, 0x0000, devc->ccs_base + 0x16); /* GPIO write mask */ + + OUTW (devc->osdev, data, devc->ccs_base + 0x14); +} + +static void +GPIOWrite (envy24ht_devc * devc, int pos, int bit) +{ + int data = GpioReadAll (devc); + + bit = (bit != 0); + + data &= ~(1 << pos); + data |= (bit << pos); + + GPIOWriteAll (devc, data); +} + +void +ap192_Assert_CS (envy24ht_devc * devc, int iDevice) +/* +***************************************************************************** +* Assert chip select to specified GPIO-connected device. +* iDevice: ap192_AK4114=DIG, ap192_AK4358=DAC. +****************************************************************************/ +{ + unsigned int dwGPIO; /* Current GPIO's. */ + dwGPIO = GpioReadAll (devc); /* Read current GPIO's. */ + dwGPIO |= (SPI_CS0n | SPI_CS1n); /* Reset CS bits. */ + switch (iDevice) /* Select CS#. */ + { + case ap192_AK4358: + dwGPIO &= ~SPI_CS0n; + break; /* DAC */ + case ap192_AK4114: + dwGPIO &= ~SPI_CS1n; + break; /* DIG */ + default: + break; + } + GPIOWriteAll (devc, dwGPIO); /* Write hardware. */ +} + +void +ap192_DeAssert_CS (envy24ht_devc * devc) +/* +***************************************************************************** +* De-Assert all chip selects. +****************************************************************************/ +{ + unsigned int dwGPIO = GpioReadAll (devc); /* Current GPIO's. */ + dwGPIO |= (SPI_CS0n | SPI_CS1n); /* Clear CS bits. */ + GPIOWriteAll (devc, dwGPIO); /* Write back to hardware. */ +} + +/*#define _delay() oss_udelay(1) */ +#define _delay() {} + +void +ap192_WriteSpiAddr (envy24ht_devc * devc, int iDevice, unsigned char bReg) +/* +***************************************************************************** +* Write the address byte part of the SPI serial stream. +* iDevice: ap192_AK4358=DAC, ap192_AK4114=DIG, etc. +****************************************************************************/ +{ + unsigned char bHdr; + unsigned char bNum; +/* Built 8-bit packet header: C1,C0,R/W,A4,A3,A2,A1,A0. */ +/* */ + switch (iDevice) + { + case ap192_AK4358: + bHdr = SPI_CC_AK4358 << 6; + break; + case ap192_AK4114: + bHdr = SPI_CC_AK4114 << 6; + break; + default: + bHdr = 0; + break; + } + bHdr = bHdr | 0x20 | (bReg & 0x1F); /* "write" + address. */ +/* Write header to SPI. */ +/* */ + for (bNum = 0; bNum < 8; bNum++) + { + GPIOWrite (devc, SPI_CLK, 0); /* Drop clock low. */ + _delay (); + GPIOWrite (devc, SPI_DOUT, 0x080 & bHdr); /* Write data bit. */ + _delay (); + GPIOWrite (devc, SPI_CLK, 1); /* Raise clock. */ + _delay (); + bHdr <<= 1; /* Next bit. */ + } +} + +void +ap192_WriteSpiReg (envy24ht_devc * devc, int iDevice, unsigned char bReg, + unsigned char bData) +/* +***************************************************************************** +* Writes one register in specified CHIP. +* devc = PCI slot code of specific board. +* iDevice: ap192_AK4358=DAC, ap192_AK4114=DIG, etc. +****************************************************************************/ +{ + unsigned char bNum; + GPIOWrite (devc, SPI_DOUT, 0); /* Init SPI signals. */ + GPIOWrite (devc, SPI_CLK, 1); /* */ +/* Drop the chip select low. */ +/* Wait at least 150 nS. */ +/* */ + ap192_Assert_CS (devc, iDevice); + _delay (); +/* Write the address byte. */ +/* */ + ap192_WriteSpiAddr (devc, iDevice, bReg); +/* Write the data byte. */ +/* */ + for (bNum = 0; bNum < 8; bNum++) + { + GPIOWrite (devc, SPI_CLK, 0); /* Drop clock low. */ + _delay (); + GPIOWrite (devc, SPI_DOUT, 0x080 & bData); /* Write data bit. */ + _delay (); + GPIOWrite (devc, SPI_CLK, 1); /* Raise clock. */ + _delay (); + bData <<= 1; /* Next bit. */ + } +/* De-assert chip selects. */ +/* */ + ap192_DeAssert_CS (devc); + _delay (); +} + + +#define GPIO_MUTEn 22 /* Converter mute signal. */ +void +ap192_Mute (envy24ht_devc * devc, int bMute) +/* +***************************************************************************** +* Mutes all outputs if bMute=TRUE. +****************************************************************************/ +{ + if (bMute) + { +/* Soft-mute. Delay currently unspecified, try ½ second. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 1, 0x03); + _delay (); +/* Switch mute transistors on. */ + GPIOWrite (devc, GPIO_MUTEn, 0); + } + else + { +/* Switch mute transistors off. Delay currently unspecified, try ½ second. */ + GPIOWrite (devc, GPIO_MUTEn, 1); + _delay (); +/* Release Soft-mute. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 1, 0x01); + } + + devc->mute = bMute; +} + + +void +ap192_Set_OutAttn (envy24ht_devc * devc, unsigned char bChan, int iAttn) +/* +***************************************************************************** +* Sets the attenuation on one output channel. +* bChan = Channel number (0..7). +* Channel 0:1 = front, 2:3 = center/sub, 4:5 = rear, 6:7 = headphones. +* Registers are 0x04, 05, 06, 07, 08, 09, 0B, 0C respectively +* iAttn = Number of steps to attenuate CODEC. +* Each step equals .5dB (-127..0) +****************************************************************************/ +{ + unsigned char bIndex; + unsigned char bAttn; + if (bChan > 7 || iAttn > 0 || iAttn < -127) /* parameter test */ + { + cmn_err (CE_CONT, "Dnvalid data! %d=bChan, %d=iAttn", bChan, iAttn); + return; + } + if (bChan < 6) + bIndex = 0x04 + bChan; /* for registers 0x04..0x09 */ + else + bIndex = 0x05 + bChan; /* for registers 0x0B..0x0C */ + bAttn = (0x80 + (unsigned char) (iAttn + 127)); /* 7F is max volume. */ +/* MSB enables attenuation. */ + ap192_WriteSpiReg (devc, ap192_AK4358, bIndex, bAttn); +} + +static void +ap192_Set_48K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets Chip and Envy24 for 8kHz-48kHz sample rates. +****************************************************************************/ +{ +/* ICE MCLK = 256x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) & ~BIT3, + devc->mt_base + 2); +/* DFS=normal, RESET. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x4E); +/* DFS=normal, NORMAL OPERATION. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x4F); + + /* Set ADC modes */ + GPIOWrite (devc, 8, 0); /* CKS0 = 0. MCLK = 256x */ + GPIOWrite (devc, 9, 0); /* DFS0 = 0. */ + GPIOWrite (devc, 10, 0); /* DFS1 = 0. Single speed mode. */ + + /* Reset ADC timing */ + GPIOWrite (devc, 11, 0); + _delay (); + GPIOWrite (devc, 11, 1); +} + +static void +ap192_Set_96K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets CODEC and Envy24 for 60kHz-96kHz sample rates. +****************************************************************************/ +{ +/* ICE MCLK = 256x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) & ~BIT3, + devc->mt_base + 2); +/* DFS=double-speed, RESET. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x5E); +/* DFS=double-speed, NORMAL OPERATION. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x5F); + + /* Set ADC modes */ + GPIOWrite (devc, 8, 0); /* CKS0 = 0. MCLK = 256x */ + GPIOWrite (devc, 9, 1); /* DFS0 = 0. */ + GPIOWrite (devc, 10, 0); /* DFS1 = 0. Single speed mode. */ + + /* Reset ADC timing */ + GPIOWrite (devc, 11, 0); + _delay (); + GPIOWrite (devc, 11, 1); +} + +static void +ap192_Set_192K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets CODEC and Envy24 for 120kHz-192kHz sample rate. +****************************************************************************/ +{ +/* ICE MCLK = 128x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) | BIT3, + devc->mt_base + 2); + _delay (); +/*----- SET THE D/A. */ +/* DFS=quad-speed, RESET. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x6E); + _delay (); +/* DFS=quad-speed, NORMAL OPERATION. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x6F); + + /* SPDIF */ + ap192_WriteSpiReg (devc, ap192_AK4114, 0x00, 0x0d); + ap192_WriteSpiReg (devc, ap192_AK4114, 0x00, 0x0f); + + /* Set ADC modes */ + GPIOWrite (devc, 8, 1); /* CKS0 = 0. MCLK = 256x */ + GPIOWrite (devc, 9, 0); /* DFS0 = 0. */ + GPIOWrite (devc, 10, 1); /* DFS1 = 0. Single speed mode. */ + + /* Reset ADC timing */ + GPIOWrite (devc, 11, 0); + _delay (); + GPIOWrite (devc, 11, 1); +} + +static int +set_dac (envy24ht_devc * devc, int reg, int level) +{ + if (level < 0) + level = 0; + if (level > 0x7f) + level = 0x7f; + + ap192_WriteSpiReg (devc, ap192_AK4358, reg, level | 0x80); + + return level; +} + +static void +AK4358_Init (envy24ht_devc * devc) +{ +/*===== AK4358 D/A initialization. Leave soft-muted. */ +/* */ +/* Power down, reset, normal mode. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x00); +/* Power up, reset, normal mode */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x4E); +/* Reset timing, Mode 3(I2S), disable auto clock detect, sharp roll off. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 0, 0x06); +/* Soft mute, reset timing. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 1, 0x02); +/* De-emphasis off. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 3, 0x01); +/* Max volume on all 8 channels. */ + set_dac (devc, 0x04, 0x7f); + set_dac (devc, 0x05, 0x7f); + set_dac (devc, 0x06, 0x7f); + set_dac (devc, 0x07, 0x7f); + set_dac (devc, 0x08, 0x7f); + set_dac (devc, 0x09, 0x7f); + set_dac (devc, 0x0b, 0x7f); + set_dac (devc, 0x0c, 0x7f); + +/* Datt mode 0, DZF non-invert, DCLK polarity 0, PCM mode, DCKS 512fs, TDM normal. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 0xA, 0x00); +/* DZF control disabled. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 0xD, 0x00); + ap192_WriteSpiReg (devc, ap192_AK4358, 0xE, 0x00); + ap192_WriteSpiReg (devc, ap192_AK4358, 0xF, 0x00); +/* Power up, normal operation. */ + ap192_WriteSpiReg (devc, ap192_AK4358, 2, 0x4F); +} + +static void +ap192_set_rate (envy24ht_devc * devc) +{ + int tmp; + + tmp = INB (devc->osdev, devc->mt_base + 0x02); + if (devc->speed <= 48000) + { + ap192_Set_48K_Mode (devc); + OUTB (devc->osdev, tmp & ~BIT (3), devc->mt_base + 0x02); + return; + } + + if (devc->speed <= 96000) + { + ap192_Set_96K_Mode (devc); + + return; + } + + ap192_Set_192K_Mode (devc); + OUTB (devc->osdev, tmp | BIT (3), devc->mt_base + 0x02); +} + +static int +ap192_audio_ioctl (envy24ht_devc * devc, envy24ht_portc * portc, unsigned int cmd, + ioctl_arg arg) +{ + int left, right, value; + + switch (cmd) + { + case SNDCTL_DSP_GETPLAYVOL: + if (portc != &devc->play_portc[0]) + return OSS_EINVAL; + left = (devc->gains[0] & 0xff) * 100 / 0x7f; + right = ((devc->gains[0] >> 8) & 0xff) * 100 / 0x7f; + return *arg = (left | (right << 8)); + break; + + case SNDCTL_DSP_SETPLAYVOL: + if (portc != &devc->play_portc[0]) + return OSS_EINVAL; + value = *arg; + left = value & 0xff; + right = (value >> 8) & 0xff; + + left = (left * 0x7f) / 100; + right = (right * 0x7f) / 100; + left = set_dac (devc, 0x04, left); + right = set_dac (devc, 0x05, right); + devc->gains[0] = left | (right << 8); + mixer_devs[devc->mixer_dev]->modify_counter++; + return 0; + break; + } + return OSS_EINVAL; +} + +static int +ap192_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 0: + return devc->mute; + + default: + return OSS_EINVAL; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 0: + value = !!value; + ap192_Mute (devc, value); + return devc->mute; + + default: + return OSS_EINVAL; + } + + return OSS_EINVAL; +} + +static int +ap192_set_ak4358 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EIO; + + return devc->gains[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + switch (ctrl) + { + case 0: /* PCM */ + left = set_dac (devc, 0x04, left); + right = set_dac (devc, 0x05, right); + break; + + case 1: /* Line IN */ + /* Line IN monitor permits panning but we don't support it */ + left = set_dac (devc, 0x06, left); + set_dac (devc, 0x07, 0); + set_dac (devc, 0x08, 0); + right = set_dac (devc, 0x09, right); + break; + + case 2: /* S/PDIF */ + left = set_dac (devc, 0x0b, left); + left = set_dac (devc, 0x0c, right); + break; + + default: + return OSS_EINVAL; + } + + value = left | (right << 8); + return devc->gains[ctrl] = value; + } + + return OSS_EINVAL; +} + +#if 0 +/*ARGSUSED*/ +static int +set_mongain (envy24ht_devc * devc, int reg, int value) +{ + if (value < 0) + value = 0; + if (value > 79) + value = 79; + + return value; +} +#endif + +/*ARGSUSED*/ +static int +ap192_mixer_init (envy24ht_devc * devc, int dev, int g) +{ + int group = g; + int err; + + if ((group = mixer_ext_create_group (dev, g, "VOL")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 0, ap192_set_control, + MIXT_ONOFF, + "ENVY24_MUTE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 0, ap192_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_PCM", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, ap192_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_IN", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, ap192_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_SPDIF", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +static void +ap192_card_init (envy24ht_devc * devc) +{ + + int i; + +#if 1 + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, 0x0000, devc->ccs_base + 0x16); /* GPIO write mask */ + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x14); /* Initial bit state */ + + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1a); /* GPIO direction for bits 16:22 */ + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x1f); /* GPIO mask for bits 16:22 */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1e); /* GPIO data for bits 16:22 */ +#endif + + memcpy (devc->channel_names, channel_names, sizeof (channel_names)); + AK4358_Init (devc); + ap192_Set_48K_Mode (devc); + + for (i = 0; i < 5; i++) + devc->gains[i] = 0x7f7f; + + ap192_Mute (devc, 0); + + GPIOWrite (devc, 5, 0); /* Select S/PDIF output mux */ + GPIOWrite (devc, 5, 0); /* Select S/PDIF output mux */ + +} + +envy24ht_auxdrv_t envy24ht_ap192_auxdrv = { + ap192_card_init, + ap192_mixer_init, + ap192_set_rate, + NULL, + NULL, + NULL, /* ap192_private1 */ + ap192_audio_ioctl +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_aureon.c b/kernel/drv/oss_envy24ht/envy24ht_aureon.c new file mode 100644 index 0000000..98c8d72 --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_aureon.c @@ -0,0 +1,2536 @@ +/* + * Purpose: Low level routines for Terrate Aureon 7.1 family + */ +/* + * + * 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_envy24ht_cfg.h" + +#define IN +#define OUT +#define UCHAR unsigned char +#define PUCHAR UCHAR* +#define BYTE unsigned char +#define PBYTE BYTE* +#define BOOLEAN unsigned char +#define ULONG unsigned int +#define PULONG ULONG* +#define USHORT unsigned short +#define PUSHORT USHORT* + +#define WORD USHORT +#define PWORD PUSHORT + +/* + * Default levels + */ +#define WM_OUT_DEFAULT 0x7F +#define WM_OUT_MAX 0x7F +#define WM_INP_DEFAULT 0x0C /* for 0dB */ +#define AC97_INP_DEFAULT 0x1f1f +#define AC97_INP_MAX 0x1f + +#define REG_CCS 1 +#define REG_MT 2 + +#define WM_MASTER_MODE_CNTRL 0 + +/* List of the WKN CCS Control Registers. */ +#define WKN_CONTROL_REG 0x00 +#define WKN_INT_MASK_REG 0x01 +#define WKN_INT_STAT_REG 0x02 +#define WKN_DMA_INT 0x10 +#define WKN_UART_RECV 0x80 +#define WKN_UART_TRAN 0x20 + +/* #define WKN_INDEX_REG 0x03 */ + +#define WKN_SYS_CONFIG 0x04 +#define WKN_49MHZ 0x40 +#define WKN_ACLINK_CONFIG 0x05 +#define CODEC_AKM 0x80 + +#define WKN_I2S_CONFIG 0x06 +#define WKN_SPDIF_CONFIG 0x07 + +#define SPDIF_ENABLE_MASK 0x00010000 + +/* #define WKN_AC97_INDEX 0x08 */ +/* #define WKN_AC97_CMDSTAT 0x09 */ +#define WKN_TX_QUE 0x0A +#define WKN_RX_QUE 0x0B + +#define WKN_MIDI_PORT1_DATA_REG 0x0C +#define WKN_MIDI_PORT1_CMD_REG 0x0D +#define WKN_NMI_EXTSTAT_REG 0x0E + +#define WKN_I2C_DEVADDR 0x10 +#define WKN_I2C_AKM 0x20 +#define WKN_I2C_WRITE 0x01 +#define WKN_I2C_READ 0x00 +#define WKN_I2C_BYTEADDR 0x11 +#define WKN_I2C_DATA 0x12 +#define WKN_I2C_STATUS 0x13 +#define WKN_I2C_BUSY 0x01 +#define WKN_GPIO_DATA0 0x14 +#define WKN_GPIO_DATA1 0x15 +#define WKN_GPIO_DATA2 0x1E +#define WKN_GPIO_WRT_MASK0 0x16 +#define WKN_GPIO_WRT_MASK1 0x17 +#define WKN_GPIO_WRT_MASK2 0x1F +#define WKN_GPIO_DIR0 0x18 +#define WKN_GPIO_DIR1 0x19 +#define WKN_GPIO_DIR2 0x1A +#define WKN_GPIO_DATA16 0x1E +#define WKN_GPIO_WRT_MASK16 0x1F + +#define GPIO_DATA_ADR_MASK 0x000000FF +#define GPIO_LD_DATA_H_MASK 0x00000100 +#define GPIO_LD_DATA_L_MASK 0x00000200 +#define GPIO_LD_ADR_MASK 0x00000400 +#define GPIO_GO_MASK 0x00000800 +#define GPIO_WM8770_CS_MASK 0x00001000 +#define GPIO_INT_REST_MASK 0x00002000 +#define GPIO_REMOTE_MASK 0x00004000 +#define GPIO_HEADPHONE_MASK 0x00004000 +#define GPIO_DIGITAL_SEL 0x00008000 +#define GPIO_AC97_RESET_MASK 0x00010000 +#define GPIO_SDA_TX_MASK 0x00020000 +#define GPIO_SDA_MASK 0x00040000 +#define GPIO_SCL_MASK 0x00080000 +#define GPIO_WM8770_RS_MASK 0x00100000 +#define GPIO_CS8415_CDTO_MASK 0x00200000 +#define GPIO_CS8415_CS_MASK 0x00400000 + +#define WM_DAC1_VOL_CNTRL 0x00 +#define WM_DAC2_VOL_CNTRL 0x02 +#define WM_DAC3_VOL_CNTRL 0x04 +#define WM_DAC4_VOL_CNTRL 0x06 +#define WM_MASTER_VOL_CNTRL 0x08 +#define WM_POWER_CNTRL 0x18 +#define WM_ADC_GAIN_CNTRL 0x19 +#define WM_ADC_INPUT_MX 0x1B +#define WM_OUT12_SELECT 0x1C +#define WM_OUT34_SELECT 0x1D + +#define CS_CONTROL_1 0x01 +#define CS_CONTROL_2 0x02 +#define CS_CLK_SRC_CNTRL 0x04 +#define CS_SER_OUT_FORMAT 0x06 + +#define MT_SAMPLE_RATE_REG 0x01 +#define MT_48KHZ 0x0 +#define MT_24KHZ 0x01 +#define MT_12KHZ 0x02 +#define MT_9p6KHZ 0x03 +#define MT_32KHZ 0x04 +#define MT_16KHZ 0x05 +#define MT_8KHZ 0x06 +#define MT_96KHZ 0x07 +#define MT_192KHZ 0x0E +#define MT_64KHZ 0x0F +#define MT_44p1KHZ 0x08 +#define MT_22p05KHZ 0x09 +#define MT_11p025KHZ 0x0A +#define MT_88p2KHZ 0x0B +#define MT_176p4KHZ 0x0C + +#define MT_DATA_FORMAT_REG 0x02 +#define MT_128X 0x08 +#define MT_INTR_MASK_REG 0x03 + +#define SRC_PDMA 0x00 +#define SRC_PSDIN0_L 0x02 +#define SRC_PSDIN0_R 0x03 +#define SRC_SPDIN_L 0x06 +#define SRC_SPDIN_R 0x07 +#define SRC_MASK 0x07 + +static const UCHAR gWMRegister[] = { WM_DAC1_VOL_CNTRL, + WM_DAC1_VOL_CNTRL + 1, + WM_DAC2_VOL_CNTRL, + WM_DAC2_VOL_CNTRL + 1, + WM_DAC3_VOL_CNTRL, + WM_DAC3_VOL_CNTRL + 1, + WM_DAC4_VOL_CNTRL, + WM_DAC4_VOL_CNTRL + 1, + WM_MASTER_VOL_CNTRL, + WM_MASTER_VOL_CNTRL + 1, + WM_ADC_GAIN_CNTRL, + WM_ADC_GAIN_CNTRL + 1 +}; + +#define AC97_IDXREG_RESET 0x00 +#define AC97_IDXREG_STEREO_OUT 0x02 +#define AC97_IDXREG_MONO_OUT 0x06 +#define AC97_IDXREG_PCBEEP 0x0A +#define AC97_IDXREG_PHONE 0x0C +#define AC97_IDXREG_MIC_IN 0x0E +#define AC97_IDXREG_LINE_IN 0x10 +#define AC97_IDXREG_CD_IN 0x12 +#define AC97_IDXREG_VIDEO_IN 0x14 +#define AC97_IDXREG_AUX_IN 0x16 +#define AC97_IDXREG_PCM_OUT 0x18 +#define AC97_IDXREG_RECORD_SELECT 0x1A +#define AC97_IDXREG_RECORD_GAIN 0x1C +#define AC97_IDXREG_GEN_PURPOSE 0x20 +#define AC97_IDXREG_POWER_DOWN 0x26 +#define AC97_IDXREG_TEST_CONTROL 0x5A +#define AC97_IDXREG_VENDOR_RESV 0x7A +#define AC97_IDXREG_VENDOR_ID1 0x7C +#define AC97_IDXREG_VENDOR_ID2 0x7E +/* AC97 register - AC97_IDXREG_RECORD_SELECT */ +#define AC97_REC_SELECT_MIC 0x0000 +#define AC97_REC_SELECT_LINEIN 0x0404 +#define AC97_REC_SELECT_ST_MIX 0x0505 + +/* + * List of the Channel IDs + */ +#define CH_MASTER_LEFT ((OUT_MASTER<<16)|CH_LEFT) +#define CH_MASTER_RIGHT ((OUT_MASTER<<16)|CH_RIGHT) +#define CH_MASTER_BOTH ((OUT_MASTER<<16)|CH_BOTH) + +#define CH_OUT12_LEFT ((OUT_12<<16)|CH_LEFT) +#define CH_OUT12_RIGHT ((OUT_12<<16)|CH_RIGHT) +#define CH_OUT12_BOTH ((OUT_12<<16)|CH_BOTH) +#define CH_OUT34_LEFT ((OUT_34<<16)|CH_LEFT) +#define CH_OUT34_RIGHT ((OUT_34<<16)|CH_RIGHT) +#define CH_OUT34_BOTH ((OUT_34<<16)|CH_BOTH) +#define CH_OUT56_LEFT ((OUT_56<<16)|CH_LEFT) +#define CH_OUT56_RIGHT ((OUT_56<<16)|CH_RIGHT) +#define CH_OUT56_BOTH ((OUT_56<<16)|CH_BOTH) +#define CH_OUT78_LEFT ((OUT_78<<16)|CH_LEFT) +#define CH_OUT78_RIGHT ((OUT_78<<16)|CH_RIGHT) +#define CH_OUT78_BOTH ((OUT_78<<16)|CH_BOTH) + +#define CH_IN12_LEFT ((IN_12<<16)|CH_LEFT) +#define CH_IN12_RIGHT ((IN_12<<16)|CH_RIGHT) +#define CH_IN12_BOTH ((IN_12<<16)|CH_BOTH) + +#define CH_FRONT_BOTH CH_OUT12_BOTH +#define CH_REAR_BOTH CH_OUT34_BOTH +#define CH_CENTER CH_OUT56_LEFT +#define CH_LFE CH_OUT56_RIGHT +#define CH_BS_BOTH CH_OUT78_BOTH + +#define MAX_VOLUME 0x7F +#define MIN_VOLUME 0x00 + +#define MAX_GAIN 0x1F + +#define MT_PLAY_REC_UNDOVR 0x01A +#define MT_INTR_STATUS_REG 0x00 +#define MT_INTR_MASK_REG 0x03 +#define MT_SPDIF_REG 0x3C + +/* List of AC97 inputs */ +#define AC97_CD 0 +#define AC97_AUX 1 +#define AC97_LINE 2 +#define AC97_MIC 3 +#define AC97_PHONO 4 +#define AC97_LINE2 5 +#define AC97_COUNT 6 /* Must match devc->m_AC97Volume definition in envy24ht.h */ + +/* Channel def */ +#define CH_LEFT 0x00000001 +#define CH_RIGHT 0x00000002 +#define CH_BOTH (CH_LEFT|CH_RIGHT) +#define CH_NOP 0xFFFFFFFF + +/* + * List of inputs + */ +#define ADC_CD 0 +#define ADC_AUX 1 +#define ADC_LINE 2 +#define ADC_MIC 3 +#define ADC_PHONO 4 +#define ADC_WTL 5 +#define ADC_LINE_REAR 6 +#define ADC_STEREO_MIX 7 +#define ADC_COUNT 8 /* Must match the size of m_ADCVolume */ + +/* + * List of Lines + */ +#define LINE_OUT_1L 0x00000000 +#define LINE_OUT_1R 0x00000001 +#define LINE_OUT_2L 0x00000002 +#define LINE_OUT_2R 0x00000003 +#define LINE_OUT_3L 0x00000004 +#define LINE_OUT_3R 0x00000005 +#define LINE_OUT_4L 0x00000006 +#define LINE_OUT_4R 0x00000007 +#define LINE_MASTER 0x00000008 +#define LINE_MASTER_ 0x00000009 +#define LINE_GAIN_L 0x0000000a +#define LINE_GAIN_R 0x0000000b +#define LINE_S_NUM 0x0000000c /* 12 - Should match devc->m_fDACMute size */ + +/* + * List of Stereo Lines + */ +#define OUT_12 0x00000000 +#define OUT_34 0x00000001 +#define OUT_56 0x00000002 +#define OUT_78 0x00000003 +#define OUT_MASTER 0x00000004 +#define IN_12 0x00000005 +#define NUM_LINES 0x00000006 + +/* + * SPDIF Out Source + */ +enum +{ + DIGOUT_DIG_IN = 0, + DIGOUT_ANA_IN, + DIGOUT_WAVE +}; +/* + * Digital IN Source + */ +enum +{ + DIGIN_OPTICAL = 0, + DIGIN_COAX, + DIGIN_CD_IN +}; +/* + * Out-0 Source + */ +enum +{ + SRC_DMA1 = 0, + SRC_PSDIN0, + SRC_SPDIN +}; + +/* + * Line IN Source (Aureon 7.1 Universe only) + */ +#define SRC_AUX 0 +#define SRC_WTL 1 +#define SRC_LINE_REAR 2 +#define SRC_GROUND 3 + +/* + * Clock Source + */ +enum +{ + ICE_INTERNAL_CLOCK = 0, + ICE_SPDIF_CLOCK +}; +/* + * Function of Frontjack + */ +enum +{ + FRONT_JACK_LINEIN = 0, + FRONT_JACK_HEADPHONE +}; + +enum MUX_TP_PIN +{ + CD_IN_MUX_TP_PIN = 1, + LINE_IN_MUX_TP_PIN, + AUX_IN_MUX_TP_PIN, + PHONO_IN_MUX_PIN, + LINE2_IN_MUX_PIN, + MIC_IN_MUX_TP_PIN, + DIG_IN_MUX_TP_PIN, + STEREO_MIX_MUX_TP_PIN +}; + +#define AUREON_REMOTE_CNTRL 0x32 +/* #define AUREON_REMOTE_ID 0x0016 */ +#define AUREON_REMOTE_ID 0x6B86 +#define AUREON_PCA_BASEBOARD 0x40 + +#define MT_LOOPBK_CONTROL 0x02C +#define MT_LOOPBK_CONTROL_DAC_REG 0x030 +#define MT_LOOPBK_CONTROL_SPDIF_OUT_REG 0x032 + +#define WIDTH_BYTE 1 +#define WIDTH_WORD 2 +#define WIDTH_DWORD 4 + +#define BITS_ON 0x10 +#define BITS_OFF 0x00 +#define TOGGLE_ON 0x20 + +#define CRITSEC_ON 0x00000001 + +#define WIDTH_MASK 0x0f + +#include "spdif.h" +#include "envy24ht.h" + +/*! \fn ======================================================================= + Function : WritePort +------------------------------------------------------------------------------- + Description : + Parameters : dwRegType -> + : dwIndex -> + : dwValue -> + : dwWidth -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void WritePort + (envy24ht_devc * devc, + IN ULONG dwRegType, IN ULONG dwIndex, IN ULONG dwValue, IN ULONG dwWidth) +{ + oss_native_word pPort = devc->ccs_base; + + switch (dwRegType) + { + case REG_CCS: + pPort = devc->ccs_base; + break; + + case REG_MT: + pPort = devc->mt_base; + break; + } + + /* registers are addressible in byte, word or dword */ + switch (dwWidth) + { + case WIDTH_BYTE: + OUTB (devc->osdev, dwValue, pPort + dwIndex); + break; + case WIDTH_WORD: + OUTW (devc->osdev, dwValue, pPort + dwIndex); + + break; + case WIDTH_DWORD: + OUTL (devc->osdev, dwValue, pPort + dwIndex); + break; + } +} + + +/*! \fn ======================================================================= + Function : ReadPort +------------------------------------------------------------------------------- + Description : + Returns : -> + Parameters : IN ULONG dwWidth -> + IN ULONG dwWidth +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static ULONG ReadPort + (envy24ht_devc * devc, + IN ULONG dwRegType, IN ULONG dwIndex, IN ULONG dwWidth) +{ + oss_native_word pPort = devc->ccs_base; + ULONG dwData = 0; + + switch (dwRegType) + { + case REG_CCS: + pPort = devc->ccs_base; + break; + + case REG_MT: + pPort = devc->mt_base; + break; + } + + /* all other registers are addressible in byte, word or dword */ + switch (dwWidth) + { + case WIDTH_BYTE: + dwData = INB (devc->osdev, pPort + dwIndex); + break; + case WIDTH_WORD: + dwData = INW (devc->osdev, pPort + dwIndex); + break; + case WIDTH_DWORD: + dwData = INL (devc->osdev, pPort + dwIndex); + break; + } + + + return dwData; +} + +/*! \fn ======================================================================= + Function : ReadModifyWritePort +------------------------------------------------------------------------------- + Description : + Returns : VOID -> + Parameters : wRegType -> + : dwMask -> + : dwControl -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void ReadModifyWritePort + (envy24ht_devc * devc, + IN ULONG dwRegType, IN ULONG dwIndex, IN ULONG dwMask, IN ULONG dwControl + /* dwControl: */ + /* bit[3:0] : data width, 1 => byte, 2 => word, 4 => dword */ + /* bit[4] : 1 => turn on bit(s); 0 => turn off bit(s) */ + /* bit[5] : 1 => toggle bit(s) */ + /* bit[6] : 1 => turn on Hw access critical section */ + ) +{ + ULONG dwValue; + ULONG dwWidth; + oss_native_word flags; + + dwWidth = dwControl & WIDTH_MASK; + + if (dwControl & CRITSEC_ON) + { + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + } + + dwValue = ReadPort (devc, dwRegType, dwIndex, dwWidth); + + /* see whether we should turn on or off the bit(s) */ + if (dwControl & BITS_ON) + dwValue |= dwMask; + else + dwValue &= ~dwMask; + + WritePort (devc, dwRegType, dwIndex, dwValue, dwWidth); + + /* see if we need to toggle the bit(s) */ + if (dwControl & TOGGLE_ON) + { + dwValue ^= dwMask; + WritePort (devc, dwRegType, dwIndex, dwValue, dwWidth); + } + + if (dwControl & CRITSEC_ON) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + } + +} + +/*! \fn ======================================================================= + Function : WriteGPIO +------------------------------------------------------------------------------- + Description : Writes masked Data to GPIO Port + Parameters : IN ULONG Data -> + : IN ULONG Mask -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +WriteGPIO (envy24ht_devc * devc, IN ULONG Data, IN ULONG Mask) +{ + USHORT MaskL; + UCHAR MaskH; + USHORT DataL; + UCHAR DataH; + + /* Do the masking. */ + MaskL = (USHORT) Mask; + MaskH = (UCHAR) (Mask >> 16); + DataL = (USHORT) Data; + DataH = (UCHAR) (Data >> 16); + devc->gpio_shadow_L &= ~MaskL; + devc->gpio_shadow_H &= ~MaskH; + devc->gpio_shadow_L |= (MaskL & DataL); + devc->gpio_shadow_H |= (MaskH & DataH); + + /* Write Data */ + WritePort (devc, REG_CCS, WKN_GPIO_DATA0, devc->gpio_shadow_L, WIDTH_WORD); + WritePort (devc, REG_CCS, WKN_GPIO_DATA2, devc->gpio_shadow_H, WIDTH_BYTE); +} + +/*! \fn ======================================================================= + Function : SetSDADir +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : IN BOOLEAN fOut -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetSDADir (envy24ht_devc * devc, IN BOOLEAN fOut) +{ + if (fOut) + { + /* Set GPIO 18 direction to output */ + WritePort (devc, REG_CCS, WKN_GPIO_DIR2, 0xDF, WIDTH_BYTE); + /* Turn IIC logic to SDA write */ + WriteGPIO (devc, GPIO_SDA_TX_MASK, GPIO_SDA_TX_MASK); + } + else + { + WriteGPIO (devc, 0, GPIO_SDA_TX_MASK); + /* Direction "Read" for GPIO 18 (SDA) */ + WritePort (devc, REG_CCS, WKN_GPIO_DIR2, 0xDB, WIDTH_BYTE); + } +} + +/*! \fn ======================================================================= + Function : SetSDA +------------------------------------------------------------------------------- + Description : + Parameters : BOOLEAN fSet +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetSDA (envy24ht_devc * devc, BOOLEAN fSet) +{ + /* Set GPIO 18 direction to output */ + SetSDADir (devc, 1); + /* Write SDA */ + WriteGPIO (devc, fSet ? GPIO_SDA_MASK : 0, GPIO_SDA_MASK); +} + +/*! \fn ======================================================================= + Function : GetSDA +------------------------------------------------------------------------------- + Description : + Returns : +UCHAR -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR +GetSDA (envy24ht_devc * devc) +{ + UCHAR ulData; + + /* Turn IIC logic to SDA read */ + SetSDADir (devc, 0); + ulData = + ((ReadPort (devc, REG_CCS, WKN_GPIO_DATA2, WIDTH_BYTE) & 0x04) == 0x04); + return ulData; +} + +/*! \fn ======================================================================= + Function : SetIIC +------------------------------------------------------------------------------- + Description : + Parameters : IN BOOLEAN fSDA -> + : IN BOOLEAN fCLK -> + : IN ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void SetIIC + (envy24ht_devc * devc, IN BOOLEAN fSDA, IN BOOLEAN fCLK, IN ULONG ulSleep) +{ + SetSDA (devc, fSDA); + if (fCLK) + WriteGPIO (devc, GPIO_SCL_MASK, GPIO_SCL_MASK); + else + WriteGPIO (devc, 0, GPIO_SCL_MASK); + if (ulSleep) + oss_udelay (ulSleep); +} + +/*! \fn ======================================================================= + Function : IICStart +------------------------------------------------------------------------------- + Description : + Parameters : ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +IICStart (envy24ht_devc * devc, ULONG ulSleep) +{ + /* falling edge of SDA while SCL is HIGH */ + SetIIC (devc, 1, 1, ulSleep); + SetIIC (devc, 0, 1, ulSleep); +} + +/*! \fn ======================================================================= + Function : IICStop +------------------------------------------------------------------------------- + Description : + Parameters : ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +IICStop (envy24ht_devc * devc, ULONG ulSleep) +{ + /* rising edge of SDA while SCL is HIGH */ + SetIIC (devc, 0, 1, ulSleep); + SetIIC (devc, 1, 1, ulSleep); + /* Reset Lines (No IIC requirement, but for prevent conflicts with SPI) */ + /*SetIIC(0,0,ulSleep); */ +} + +/*! \fn ======================================================================= + Function : IICSendByte +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : CHAR bByte -> + : ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR IICSendByte + (envy24ht_devc * devc, IN UCHAR bByte, IN ULONG ulSleep) +{ + UCHAR bDataBit, bAck; + int i; + for (i = 7; i >= 0; i--) /* send byte (MSB first) */ + { + bDataBit = (bByte >> i) & 0x01; + + SetIIC (devc, bDataBit, 0, ulSleep); + SetIIC (devc, bDataBit, 1, ulSleep); + SetIIC (devc, bDataBit, 0, ulSleep); + } /* end for i */ + + SetIIC (devc, 1, 0, ulSleep); + + /* This is neccesary for PLC */ + SetSDADir (devc, 0); + /* Get acknowledge */ + SetIIC (devc, 1, 1, ulSleep); + bAck = GetSDA (devc); + /*if (fAddress) */ + /* SetIIC(devc, 1,0,ulSleep); */ + /* else */ + /* this is a start condition but never mind */ + SetIIC (devc, 0, 0, ulSleep); + return (!bAck); /* bAck = 0 --> success */ +} + +#if 0 +/*! \fn ======================================================================= + Function : IICReceiveByte +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : CHAR fLastByte -> + : ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR IICReceiveByte + (envy24ht_devc * devc, UCHAR fLastByte, ULONG ulSleep) +{ + UCHAR bRead = 0; + int i; + + for (i = 7; i >= 0; i--) + { + SetIIC (devc, 1, 0, ulSleep); + SetIIC (devc, 1, 1, ulSleep); + bRead <<= 1; + bRead += GetSDA (devc); + } + + /* -> no acknowledge for last received byte */ + SetIIC (devc, fLastByte, 0, ulSleep); /* SDA = HIGH for last byte */ + SetIIC (devc, fLastByte, 1, ulSleep); + SetIIC (devc, fLastByte, 0, ulSleep); /* clock -> LOW */ + + return bRead; +} +#endif + +/*! \fn ======================================================================= + Function : IICWriteBuffer +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : CHAR bIicAddress -> + : PUCHAR pbByte -> + : USHORT nNoBytes -> + : ULONG ulSleep -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR IICWriteBuffer + (envy24ht_devc * devc, + UCHAR bIicAddress, PUCHAR pbByte, USHORT nNoBytes, ULONG ulSleep) +{ + IICStart (devc, ulSleep); + + /* send IIC address and data byte */ + if (!IICSendByte (devc, bIicAddress, ulSleep)) + goto FAILED; + /* send buffer */ + do + { + if (!IICSendByte (devc, *pbByte, ulSleep)) + goto FAILED; /* got no acknowledge */ + pbByte++; + nNoBytes--; + } + while (nNoBytes); + + IICStop (devc, ulSleep); + return 1; + +FAILED: + IICStop (devc, ulSleep); + return 0; +} + +/*! \fn ======================================================================= + Function : WriteCS8415 +------------------------------------------------------------------------------- + Description : + Parameters : IN UCHAR Register -> + : IN UCHAR Value -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void WriteCS8415 + (envy24ht_devc * devc, IN UCHAR Register, IN UCHAR Value) +{ + ULONG i; + BOOLEAN fData; + ULONG ulCmd; + ULONG ulCount; + + /* m_pAdapter->HwEnter(); *//* TODO */ + + /* Clock low to prevent IIC Startcondition */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + + SetSDA (devc, 0); + /* Chip select (CS low) */ + WriteGPIO (devc, 0, GPIO_CS8415_CS_MASK); + + /* format buffer */ + ulCmd = 0x200000 + /* chip address + R/W */ + (((ULONG) Register) << 8) + /* register address */ + Value; /* Value */ + ulCmd <<= 8; + ulCount = 24; /* (AddressOnly) ? 16:24; */ + for (i = 0; i < ulCount; i++) + { + fData = (ulCmd & 0x80000000) ? 1 : 0; + /* CCLK -> low */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + oss_udelay (3); + /* CDTI -> Set data */ + SetSDA (devc, fData); + oss_udelay (3); + /* CCLK -> high */ + WriteGPIO (devc, GPIO_SCL_MASK, GPIO_SCL_MASK); + ulCmd <<= 1; + } + WriteGPIO (devc, 0, GPIO_SCL_MASK); /* CCLK -> low */ + + /* Chip deselect (CS high) */ + WriteGPIO (devc, GPIO_CS8415_CS_MASK, GPIO_CS8415_CS_MASK); + /* m_pAdapter->HwLeave(); *//* TODO */ +} + +#if 0 +/*! \fn ======================================================================= + Function : ReadCS8415 +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : IN UCHAR Register -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ + /*ARGSUSED*/ static UCHAR +ReadCS8415 (envy24ht_devc * devc, IN UCHAR Register) +{ + ULONG i; + BOOLEAN fData; + UCHAR cValue = 0; + USHORT wCmd; + + /* m_pAdapter->HwEnter(); *//* TODO */ + + /* Clock low to prevent IIC Startcondition */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + + SetSDA (devc, 0); + + /* Chip select (CS low) */ + WriteGPIO (devc, 0, GPIO_CS8415_CS_MASK); + /* Set GPIO21 to read direction */ + WritePort (devc, REG_CCS, WKN_GPIO_DIR2, 0xDF, WIDTH_BYTE); + + wCmd = 0x2100; /* + *//* chip address + R/W */ + /*(((USHORT)Register) << 8); *//* register address */ + for (i = 0; i < 16; i++) + { + fData = (wCmd & 0x8000) ? 1 : 0; + /* CCLK -> low */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + /* CDTI -> Set data */ + SetSDA (devc, fData); + oss_udelay (3); + /* CCLK -> high */ + WriteGPIO (devc, GPIO_SCL_MASK, GPIO_SCL_MASK); + wCmd <<= 1; + if (i > 7) + { + /* Read CDTO */ + cValue <<= 1; + cValue += + ((ReadPort (devc, REG_CCS, WKN_GPIO_DATA2, WIDTH_BYTE) & 0x20) == + 0x20); + } + } + + WriteGPIO (devc, 0, GPIO_SCL_MASK); /* CCLK -> low */ + + /* Chip deselect (CS high) */ + WriteGPIO (devc, GPIO_CS8415_CS_MASK, GPIO_CS8415_CS_MASK); + + /* m_pAdapter->HwLeave(); *//* TODO */ + return cValue; +} +#endif + +/* + * Definition of PCA I/Os + */ +typedef union tagPCA_CFG +{ + unsigned char cReg; + struct + { + unsigned char P00_SourceSel:2; /* LineIN Selector */ + /* 00 -> Aux */ + /* 01 -> Wavetable */ + /* 11 -> LineIN Rear */ + unsigned char P02_DigSel:1; /* DigitalIN Selector */ + /* 0 -> Coax */ + /* 1 -> Optical */ + + unsigned char P03_LineLED:1; /* LineLED */ + /* 0 -> Off */ + /* 1 -> On */ + unsigned char P04_unused:4; /* unused */ + } Bits; +} PCA_CFG; + +/*! \fn ======================================================================= + Function : WritePCA +------------------------------------------------------------------------------- + Description : + Returns : NTSTATUS -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +WritePCA (envy24ht_devc * devc) +{ + PCA_CFG tCFG; + BYTE bByte[2]; + + tCFG.cReg = 0; + + switch (devc->m_LineInSource) + { + case SRC_AUX: + tCFG.Bits.P00_SourceSel = 0; + break; + case SRC_WTL: + tCFG.Bits.P00_SourceSel = 1; + break; + case SRC_LINE_REAR: + tCFG.Bits.P00_SourceSel = 2; + break; + case SRC_GROUND: + tCFG.Bits.P00_SourceSel = 3; + break; + + } + + /* Switch LineLED when Line is selected for record */ + if (devc->m_ADCIndex == ADC_LINE) + tCFG.Bits.P03_LineLED = 1; + if (devc->m_DigInSource == DIGIN_OPTICAL) + tCFG.Bits.P02_DigSel = 1; + /* Set all I/Os to Output */ + bByte[0] = 3; + bByte[1] = 0; + IICWriteBuffer (devc, AUREON_PCA_BASEBOARD, bByte, 2, 30); + /* Write config */ + bByte[0] = 0x01; + bByte[1] = tCFG.cReg; + IICWriteBuffer (devc, AUREON_PCA_BASEBOARD, bByte, 2, 30); +} + +/*! \fn ======================================================================= + Function : SetDigInSource +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : IN ULONG Source -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetDigInSource (envy24ht_devc * devc, IN ULONG Source) +{ + switch (Source) + { + case DIGIN_OPTICAL: + case DIGIN_COAX: + WriteCS8415 (devc, CS_CONTROL_2, 0x01); + break; + case DIGIN_CD_IN: + WriteCS8415 (devc, CS_CONTROL_2, 0x00); + break; + } + devc->m_DigInSource = Source; + WritePCA (devc); +} + +/*! \fn ======================================================================= + Function : SetOUT0Source +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : IN ULONG Source -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetOUT0Source (envy24ht_devc * devc, IN ULONG Source) +{ + ULONG ulShiftL, ulShiftR; + ULONG aulShiftL[] = { 0, 8, 11, 14, 17 }; + ULONG aulShiftR[] = { 3, 20, 23, 26, 29 }; + ULONG ulSourceL, ulSourceR; + int i; + + /* No DigMonitor when Clock is internal */ + if ((devc->m_ClockSource == ICE_INTERNAL_CLOCK) && (Source == SRC_SPDIN)) + return; + for (i = 0; i < 5; i++) + { + ulShiftL = aulShiftL[i]; + ulShiftR = aulShiftR[i]; + switch (Source) + { + case SRC_DMA1: + ulSourceL = SRC_PDMA; + ulSourceR = SRC_PDMA; + break; + case SRC_PSDIN0: + ulSourceL = SRC_PSDIN0_L; + ulSourceR = SRC_PSDIN0_R; + break; + case SRC_SPDIN: + ulSourceL = SRC_SPDIN_L; + ulSourceR = SRC_SPDIN_R; + break; + default: /* Do nothing */ + return; + } + /* First reset all relevant bits */ + ReadModifyWritePort (devc, REG_MT, MT_LOOPBK_CONTROL, + SRC_MASK << ulShiftL, WIDTH_DWORD | BITS_OFF); + ReadModifyWritePort (devc, REG_MT, MT_LOOPBK_CONTROL, + SRC_MASK << ulShiftR, WIDTH_DWORD | BITS_OFF); + /* ..and set routing mask */ + ReadModifyWritePort (devc, REG_MT, MT_LOOPBK_CONTROL, + ulSourceL << ulShiftL, WIDTH_DWORD | BITS_ON); + ReadModifyWritePort (devc, REG_MT, MT_LOOPBK_CONTROL, + ulSourceR << ulShiftR, WIDTH_DWORD | BITS_ON); + } + devc->m_Out0Source = Source; +} +static void SetADCMux (envy24ht_devc * devc, IN ULONG Value); + +/*! \fn ======================================================================= + Function : SetLineSource +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG Source -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetLineSource (envy24ht_devc * devc, IN ULONG Source) +{ + switch (Source) + { + case SRC_AUX: + devc->m_AuxMux = 0x00; + break; + case SRC_WTL: + devc->m_AuxMux = 0x44; + break; + case SRC_LINE_REAR: + devc->m_AuxMux = 0x66; + break; + + } + /* Update ADCMux */ + SetADCMux (devc, devc->m_ADCMux); + devc->m_LineInSource = Source; + WritePCA (devc); +} + +/*! \fn ======================================================================= + Function : SetClockSource +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG ClockSource -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetClockSource (envy24ht_devc * devc, IN ULONG ClockSource) +{ + + if (ClockSource == ICE_INTERNAL_CLOCK) + { + ReadModifyWritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, 0x10, + WIDTH_BYTE | BITS_OFF); + /* Disable DigMonitor to avoid noisy output */ + if (devc->m_Out0Source == SRC_SPDIN) + SetOUT0Source (devc, SRC_DMA1); + } + else + { + ReadModifyWritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, 0x10, + WIDTH_BYTE | BITS_ON); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + } + devc->m_ClockSource = ClockSource; +} + +/*! \fn ======================================================================= + Function : ResetGPIO +------------------------------------------------------------------------------- + Description : + Returns : void -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +ResetGPIO (envy24ht_devc * devc) +{ + + /* Enable all lower GPIOs */ + WritePort (devc, REG_CCS, WKN_GPIO_WRT_MASK0, 0x0, WIDTH_WORD); + /* Enable all upper GPIOs */ + WritePort (devc, REG_CCS, WKN_GPIO_WRT_MASK2, 0x0, WIDTH_BYTE); + /* Set GPIO direction */ + if (devc->subvendor == SSID_AUREON_UNIVERSE) + { + /* -> all output except GPIO_CS8415_CDTO_MASK */ + /* and GPIO_REMOTE_MASK */ + WritePort (devc, REG_CCS, WKN_GPIO_DIR0, + ~(GPIO_CS8415_CDTO_MASK | GPIO_REMOTE_MASK), WIDTH_DWORD); + } + else + { + /* All output except GPIO_CS8415_CDTO_MASK */ + WritePort (devc, REG_CCS, WKN_GPIO_DIR0, ~GPIO_CS8415_CDTO_MASK, + WIDTH_DWORD); + } + + oss_udelay (100); + + /*---------------------------------------------------------------------------- + Reset AC97 Interface + -----------------------------------------------------------------------------*/ + + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, 0, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + + /*---------------------------------------------------------------------------- + Enable Remote-Control Interrupts + -----------------------------------------------------------------------------*/ + WriteGPIO (devc, GPIO_INT_REST_MASK, GPIO_INT_REST_MASK); + + /* Select optical input */ + /* WriteGPIO(devc, GPIO_DIGITAL_SEL, 0); */ +} + +/*! \fn ======================================================================= + Function : SetSPDIFConfig +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : IN ULONG Config -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetSPDIFConfig (envy24ht_devc * devc, IN ULONG Config) +{ + ReadModifyWritePort (devc, REG_CCS, WKN_SPDIF_CONFIG, 0x80, + WIDTH_BYTE | BITS_OFF); + if (Config & SPDIF_ENABLE_MASK) + { + devc->m_f1724SPDIF = 1; + } + else + { + devc->m_f1724SPDIF = 0; + } + /* Reset SPDIF Config */ + ReadModifyWritePort (devc, REG_MT, MT_SPDIF_REG, 0x000F, + WIDTH_WORD | BITS_OFF); + /* Set new Config */ + ReadModifyWritePort (devc, REG_MT, MT_SPDIF_REG, Config & 0xFFFF, + WIDTH_WORD | BITS_ON); + devc->m_SPDIFConfig = Config; + if (devc->m_f1724SPDIF) + ReadModifyWritePort (devc, REG_CCS, WKN_SPDIF_CONFIG, 0x80, + WIDTH_BYTE | BITS_ON); + /* Force saving of registers */ + /* devc->m_pAdapter->SetDirty(); *//* TODO */ +} + +/*! \fn ======================================================================= + Function : SetFrontjack +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG Frontjack -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetFrontjack (envy24ht_devc * devc, IN ULONG Frontjack) +{ + + switch (Frontjack) + { + case FRONT_JACK_LINEIN: + WriteGPIO (devc, 0, GPIO_HEADPHONE_MASK); + break; + case FRONT_JACK_HEADPHONE: + WriteGPIO (devc, GPIO_HEADPHONE_MASK, GPIO_HEADPHONE_MASK); + break; + } + devc->m_Frontjack = Frontjack; + /* Force saving of registers */ + /* devc->m_pAdapter->SetDirty(); *//* TODO */ + +} + +/*! \fn ======================================================================= + Function : Init1724 +------------------------------------------------------------------------------- + Description : + Returns : void -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +Init1724 (envy24ht_devc * devc) +{ + /* System Config: 4 DACs, one ADC & SPDIF, MPU enabled, 24,576Mhz crystal */ + /* WritePort(REG_CCS, WKN_SYS_CONFIG, 0x2B, WIDTH_BYTE); */ + /* CL_NOTE: New Setings */ + /* System Config: 4 DACs, one ADC & SPDIF, MPU disabled, 24,576Mhz crystal */ + WritePort (devc, REG_CCS, WKN_SYS_CONFIG, 0x0B, WIDTH_BYTE); + + /* Config I2S Interface */ + WritePort (devc, REG_CCS, WKN_ACLINK_CONFIG, 0x80, WIDTH_BYTE); + WritePort (devc, REG_CCS, WKN_I2S_CONFIG, 0xF9, WIDTH_BYTE); + WritePort (devc, REG_CCS, WKN_SPDIF_CONFIG, 0x83, WIDTH_BYTE); + + /* Config Interrupt behaviour */ + WritePort (devc, REG_MT, MT_PLAY_REC_UNDOVR, 0, WIDTH_BYTE); + WritePort (devc, REG_MT, MT_INTR_STATUS_REG, 0, WIDTH_BYTE); + WritePort (devc, REG_MT, MT_INTR_MASK_REG, 0xFF, WIDTH_BYTE); + WritePort (devc, REG_CCS, WKN_INT_STAT_REG, 0, WIDTH_BYTE); + WritePort (devc, REG_CCS, WKN_INT_MASK_REG, 0xFE, WIDTH_BYTE); + + SetSPDIFConfig (devc, 0); + /* SetSDPIFSource(devc, DIGOUT_WAVE); */ + SetDigInSource (devc, DIGIN_OPTICAL); + SetFrontjack (devc, FRONT_JACK_LINEIN); +} + +/*! \fn ======================================================================= + Function : WriteWM8770 +------------------------------------------------------------------------------- + Description : + Parameters : IN UCHAR Register -> + : IN UCHAR Value -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +void +WriteWM8770 (envy24ht_devc * devc, IN UCHAR Register, IN USHORT Value) +{ + int i; + BOOLEAN fData; + USHORT wCmd; +/* KIRQL OldIrql; */ + + /* m_pAdapter->HwEnter(); */ + + /* KeAcquireSpinLock (&m_SPILock,&OldIrql); */ + + + /* Clock low to prevent IIC Startcondition */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + + SetSDA (devc, 0); + + /* Chip select (CS low) */ + WriteGPIO (devc, 0, GPIO_WM8770_CS_MASK); + + /* format buffer */ + wCmd = (((USHORT) Register) << 9) + Value; + + + for (i = 0; i < 16; i++) + { + fData = (wCmd & 0x8000) ? 1 : 0; + /* CCLK -> low */ + WriteGPIO (devc, 0, GPIO_SCL_MASK); + oss_udelay (3); + /* CDTI -> Set data */ + SetSDA (devc, fData); + oss_udelay (3); + /* CCLK -> high */ + WriteGPIO (devc, GPIO_SCL_MASK, GPIO_SCL_MASK); + wCmd <<= 1; + } + WriteGPIO (devc, 0, GPIO_SCL_MASK); /* CCLK -> low */ + + /* Chip deselect */ + WriteGPIO (devc, GPIO_WM8770_CS_MASK, GPIO_WM8770_CS_MASK); +} + +/*! \fn ======================================================================= + Function : SetVolReg +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG LineIdx -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetVolReg (envy24ht_devc * devc, IN ULONG LineIdx) +{ + int iVol, ChnlVol; + + ChnlVol = devc->m_DACVolume[LineIdx]; + + /* See if we want to mute anything */ + if (devc->m_fDACMute[LineIdx] || devc->m_fDACMute[LINE_MASTER]) + { + WriteWM8770 (devc, gWMRegister[LineIdx], 0x100); + return; + } + + /* Since master volume is virtualized, we add the attenuations for both */ + /* master volume and channel volume to obtain the overall attenuation */ + + /* Get total attenuation */ + iVol = ChnlVol + devc->m_DACVolume[LINE_MASTER] - MAX_VOLUME; + /* Check against bounds */ + iVol = (iVol < MAX_VOLUME) ? iVol : MAX_VOLUME; + if (iVol < MIN_VOLUME) + iVol = MIN_VOLUME; + WriteWM8770 (devc, gWMRegister[LineIdx], iVol | 0x180); +} + + +/*! \fn ======================================================================= + Function : SetMute +------------------------------------------------------------------------------- + Description : + Returns : VOID -> + Parameters : IN ULONG ChannelID -> + : IN BOOLEAN Mute -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void SetDACMute + (envy24ht_devc * devc, IN ULONG ChannelID, IN BOOLEAN Mute) +{ + ULONG LineIndex; + + /* Convert ChannelID to line index */ + /* If it is for left channel, we will need to add one */ + LineIndex = ChannelID >> 15; + + /* See if this is for master volume */ + if (LineIndex == LINE_MASTER) + { + /* if current setting is not the same as previous setting */ + if (devc->m_fDACMute[LINE_MASTER] != Mute) + { + int i; + + devc->m_fDACMute[LINE_MASTER] = Mute; + + /* Need to do it for every single line (excluding Master and Gain) */ + for (i = 0; i <= LINE_OUT_4R; i++) + { + SetVolReg (devc, i); + } + return; + } + } + + /* See if this is for left channel */ + if (ChannelID & CH_LEFT) + { + /* if current setting is not the same as previous setting */ + if (devc->m_fDACMute[LineIndex] != Mute) + { + devc->m_fDACMute[LineIndex] = Mute; + if (LineIndex == LINE_GAIN_L) + { + WriteWM8770 (devc, gWMRegister[LINE_GAIN_L], + devc-> + m_DACVolume[LINE_GAIN_L] | ((Mute) ? 0x20 : 0x00)); + } + else + { + SetVolReg (devc, LineIndex); + } + } + } + + /* See if this is for right channel */ + if (ChannelID & CH_RIGHT) + { + LineIndex++; + /* if current setting is not the same as previous setting */ + if (devc->m_fDACMute[LineIndex] != Mute) + { + devc->m_fDACMute[LineIndex] = Mute; + if (LineIndex == LINE_GAIN_R) + { + WriteWM8770 (devc, gWMRegister[LINE_GAIN_R], + devc-> + m_DACVolume[LINE_GAIN_R] | ((Mute) ? 0x20 : 0x00)); + } + else + { + SetVolReg (devc, LineIndex); + } + } + } + /* m_pAdapter->SetDirty(); *//* TODO */ +} + + + +/*============================================================================= + Function : SetVolume +------------------------------------------------------------------------------- + Description : + Returns : VOID -> + Parameters : IN ICE_HW_PARAM* HwParm -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void SetDACVolume + (envy24ht_devc * devc, IN ULONG ChannelID, IN UCHAR Volume) +{ + ULONG LineIndex; + WORD LeftRight; + BOOLEAN VolChnged = 0; + + /* Convert ChannelID to line index */ + LineIndex = ChannelID >> 15; + /* Get the left/right side */ + LeftRight = (WORD) (ChannelID & 0xffff); + + /* Check if left volume is changed */ + if (LeftRight & CH_LEFT) + { + if (devc->m_DACVolume[LineIndex] != Volume) + { + devc->m_DACVolume[LineIndex] = Volume; + VolChnged = 1; + } + } + + /* Check if right volume is changed */ + if (LeftRight & CH_RIGHT) + { + if (devc->m_DACVolume[LineIndex + 1] != Volume) + { + devc->m_DACVolume[LineIndex + 1] = Volume; + VolChnged = 1; + } + } + + /* If any volume is changed, need to touch hardware */ + if (VolChnged) + { + /* check if this is for input gain */ + if ((ChannelID >> 16) == IN_12) + { + USHORT WMValue = (USHORT) Volume; +#ifdef NULL_DB + WMValue = 0x0C; +#endif + if (LeftRight & CH_LEFT) + WriteWM8770 (devc, gWMRegister[LineIndex], WMValue); + if (LeftRight & CH_RIGHT) + WriteWM8770 (devc, gWMRegister[LineIndex + 1], WMValue); + } + else + /* Yap, now check if this is for master volume */ + if ((ChannelID >> 16) == OUT_MASTER) + { + int i; + /* Need to do it for every single line (excluding Master and Gain) */ + for (i = 0; i <= LINE_OUT_4R; i++) + { + SetVolReg (devc, i); + } + } + else + { + if (LeftRight & CH_LEFT) + SetVolReg (devc, LineIndex); + if (LeftRight & CH_RIGHT) + SetVolReg (devc, LineIndex + 1); + } + } + /* m_pAdapter->SetDirty(); TODO */ +} + + +/*! \fn ======================================================================= + Function : GetVolume +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : IN ULONG ChannelID -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR +GetDACVolume (envy24ht_devc * devc, IN ULONG ChannelID) +{ + UCHAR Value; + USHORT LeftRight; + ULONG LineIndex; + + /* Convert ChannelID to line index */ + LineIndex = ChannelID >> 15; + /* Get the left/right side */ + LeftRight = (USHORT) (ChannelID & 0xffff); + + if (LeftRight == CH_LEFT) + { + Value = devc->m_DACVolume[LineIndex]; + } + else + { + Value = devc->m_DACVolume[LineIndex + 1]; + } + return Value; +} + + +#if 0 +/*! \fn ======================================================================= + Function : GetMute +------------------------------------------------------------------------------- + Description : + Returns : BOOLEAN -> + Parameters : IN ULONG ChannelID -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static BOOLEAN +GetDACMute (envy24ht_devc * devc, IN ULONG ChannelID) +{ + BOOLEAN Value; + USHORT LeftRight; + ULONG LineIndex; + + /* Convert ChannelID to line index */ + LineIndex = ChannelID >> 15; + /* Get the left/right side */ + LeftRight = (USHORT) (ChannelID & 0xffff); + + if (LeftRight == CH_LEFT) + { + Value = devc->m_fDACMute[LineIndex]; + } + else + { + Value = devc->m_fDACMute[LineIndex + 1]; + } + return Value; +} +#endif + +/*! \fn ======================================================================= + Function : SetADCGain +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG Index -> + : IN ULONG Value -> + : IN ULONG Channel -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void SetADCGain + (envy24ht_devc * devc, IN ULONG Index, IN USHORT Value, IN ULONG Channel) +{ + UCHAR WMReg = 0x19; + USHORT WMValue; + + /* Set only selected Line */ + if (Index != devc->m_ADCIndex) + return; + + switch (Channel) + { + case CH_LEFT: + devc->m_ADCVolume[Index] = + (Value << 8) | (devc->m_ADCVolume[Index] & 0x00FF); + break; + case CH_BOTH: + devc->m_ADCVolume[Index] = (Value << 8) | Value; + break; + case CH_NOP: + /* Hold Value */ + break; + case CH_RIGHT: + default: + devc->m_ADCVolume[Index] = Value | (devc->m_ADCVolume[Index] & 0xFF00); + + } + WMValue = + ((devc->m_ADCVolume[Index] & 0x00FF) < + 0x1F) ? (devc->m_ADCVolume[Index] & 0x00FF) : 0x1F; +#ifdef NULL_DB + WMValue = 0x0C; +#endif + WriteWM8770 (devc, WMReg, WMValue); + WMValue = (((devc->m_ADCVolume[Index] >> 8) & 0x00FF) < 0x1F) ? + ((devc->m_ADCVolume[Index] >> 8) & 0x00FF) : 0x1F; +#ifdef NULL_DB + WMValue = 0x0C; +#endif + WriteWM8770 (devc, WMReg + 1, WMValue); + /* Force saving of registers */ + /* devc->m_pAdapter->SetDirty(); TODO */ +} + +#if 0 +/*! \fn ======================================================================= + Function : GetADCGain +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : IN ULONG Index -> + : IN ULONG Channel -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static UCHAR GetADCGain + (envy24ht_devc * devc, IN ULONG Index, IN ULONG Channel) +{ + UCHAR Value; + + if (Channel == CH_LEFT) + { + Value = (UCHAR) ((devc->m_ADCVolume[Index] >> 8) & 0xFF); + } + else + { + Value = (UCHAR) (devc->m_ADCVolume[Index] & 0xFF); + } + return Value; +} +#endif + +/*! \fn ======================================================================= + Function : SetADCMux +------------------------------------------------------------------------------- + Description : + Parameters : IN Value -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetADCMux (envy24ht_devc * devc, IN ULONG Value) +{ + UCHAR MuxVal = 0; + BOOLEAN fAU; + + /* Store to shadow register */ + devc->m_ADCMux = Value; + devc->m_fSPDIFRecord = 0; + fAU = (devc->subvendor == SSID_AUREON_UNIVERSE); + switch (Value) + { + case CD_IN_MUX_TP_PIN: + devc->m_ADCIndex = ADC_CD; + MuxVal = (fAU) ? 0x11 : 0x00; + break; + case LINE_IN_MUX_TP_PIN: + devc->m_ADCIndex = ADC_LINE; + MuxVal = (fAU) ? 0x33 : 0x22; + break; + case AUX_IN_MUX_TP_PIN: + devc->m_ADCIndex = ADC_AUX; + MuxVal = (fAU) ? devc->m_AuxMux : 0x11; + break; + case MIC_IN_MUX_TP_PIN: + devc->m_ADCIndex = ADC_MIC; + MuxVal = (fAU) ? 0x55 : 0x33; + break; + case DIG_IN_MUX_TP_PIN: + /* Use SPDIF DMA channel */ + devc->m_fSPDIFRecord = 1; + break; + case PHONO_IN_MUX_PIN: + devc->m_ADCIndex = ADC_PHONO; + MuxVal = 0x22; + break; + case STEREO_MIX_MUX_TP_PIN: + devc->m_ADCIndex = ADC_STEREO_MIX; + MuxVal = (fAU) ? 0x77 : 0x44; + break; + + default: + devc->m_ADCIndex = ADC_LINE; + MuxVal = 0x22; + + } + WriteWM8770 (devc, WM_ADC_INPUT_MX, (UCHAR) MuxVal); + /* Reset GAIN */ + SetADCGain (devc, devc->m_ADCIndex, 0, CH_NOP); + /* Update PCA config */ + WritePCA (devc); + /* Force saving of registers */ + /*devc->m_pAdapter->SetDirty(); TODO */ +} + +/*! \fn ======================================================================= + Function : InitWM8770 +------------------------------------------------------------------------------- + Description : +------------------------------------------------------------------------------- + Notes : Call before Registry Read +=============================================================================*/ +static void +InitWM8770 (envy24ht_devc * devc) +{ + /*---------------------------------------------------------------------------- + Reset WM8770 + -----------------------------------------------------------------------------*/ + /* Set SPI Mode */ + WriteGPIO (devc, 0, GPIO_WM8770_RS_MASK); + oss_udelay (3); + WriteGPIO (devc, GPIO_WM8770_CS_MASK, GPIO_WM8770_CS_MASK); + oss_udelay (3); + WriteGPIO (devc, GPIO_WM8770_RS_MASK, GPIO_WM8770_RS_MASK); + oss_udelay (100); + + /*---------------------------------------------------------------------------- + Set defaults + -----------------------------------------------------------------------------*/ + + /* Output defaults */ + SetDACVolume (devc, CH_MASTER_BOTH, WM_OUT_DEFAULT); + SetDACVolume (devc, CH_FRONT_BOTH, WM_OUT_DEFAULT); + SetDACVolume (devc, CH_REAR_BOTH, WM_OUT_DEFAULT); + SetDACVolume (devc, CH_CENTER, WM_OUT_DEFAULT); + SetDACVolume (devc, CH_LFE, WM_OUT_DEFAULT); + SetDACVolume (devc, CH_BS_BOTH, WM_OUT_DEFAULT); + SetDACMute (devc, CH_MASTER_BOTH, 0); + SetDACMute (devc, CH_FRONT_BOTH, 0); + SetDACMute (devc, CH_REAR_BOTH, 0); + SetDACMute (devc, CH_CENTER, 0); + SetDACMute (devc, CH_LFE, 0); + SetDACMute (devc, CH_BS_BOTH, 0); + /* Input */ + SetADCGain (devc, ADC_CD, WM_INP_DEFAULT, CH_BOTH); + SetADCGain (devc, ADC_AUX, WM_INP_DEFAULT, CH_BOTH); + SetADCGain (devc, ADC_LINE, WM_INP_DEFAULT, CH_BOTH); + SetADCGain (devc, ADC_MIC, WM_INP_DEFAULT, CH_BOTH); + /* Mux */ + SetADCMux (devc, STEREO_MIX_MUX_TP_PIN); + + /* At least Power DAC & ADC */ + WriteWM8770 (devc, WM_POWER_CNTRL, 0x0000); + /* Power ADC Input Mux */ + WriteWM8770 (devc, WM_ADC_INPUT_MX, 0x0000); + /* Enable Aux-Output */ + + if (devc->subvendor == SSID_PHASE28) + { + WriteWM8770 (devc, WM_OUT12_SELECT, 0x0009); + WriteWM8770 (devc, WM_OUT34_SELECT, 0x0009); + } + else + { + WriteWM8770 (devc, WM_OUT12_SELECT, 0x000b); + WriteWM8770 (devc, WM_OUT34_SELECT, 0x0009); + } + /* Init Master Mode Register */ + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x0012); + +} + +/*! \fn ======================================================================= + Function : InitCS8415 +------------------------------------------------------------------------------- + Description : + Returns : void -> +------------------------------------------------------------------------------- + Notes : Has to be called after InitWM8770 since RST must be "high" +=============================================================================*/ +static void +InitCS8415 (envy24ht_devc * devc) +{ + + /* Init Remote-Controller */ + if (devc->subvendor == SSID_AUREON_UNIVERSE) + { + UCHAR bByte[2]; + bByte[0] = (UCHAR) ((AUREON_REMOTE_ID >> 8) & 0xFF); + bByte[1] = (UCHAR) AUREON_REMOTE_ID; + IICWriteBuffer (devc, AUREON_REMOTE_CNTRL, bByte, 2, 200); + } + /*---------------------------------------------------------------------------- + Reset CS8415 + -----------------------------------------------------------------------------*/ + /* Set SPI Mode */ + WriteGPIO (devc, GPIO_CS8415_CS_MASK, GPIO_CS8415_CS_MASK); + oss_udelay (3); + WriteGPIO (devc, 0, GPIO_CS8415_CS_MASK); + oss_udelay (100); + + /* Set defaults */ + WriteCS8415 (devc, CS_CONTROL_1, 0x80); + /* SPDIF mux to RXP1 */ + WriteCS8415 (devc, CS_CONTROL_2, 0x01); + WriteCS8415 (devc, CS_CLK_SRC_CNTRL, 0x41); + WriteCS8415 (devc, CS_SER_OUT_FORMAT, 0x05); + + /* all other register remain to their defaults */ + +} + +#define GPIO_WAIT 10 + +/*! \fn ======================================================================= + Function : WriteAC97Codec +------------------------------------------------------------------------------- + Description : Writes to TT-AC97 Interface + Parameters : IN ULONG Register -> + : IN ULONG Data -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void WriteAC97Codec + (envy24ht_devc * devc, IN ULONG Register, IN ULONG Data) +{ + UCHAR TTData; + +#ifdef TTTT + /* CL_TEST */ + /* Reset AC97 */ + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, 0, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + oss_udelay (3); + /* Unmute Master */ + WriteAC97Codec (devc, 0x02, 0x00); +#endif + + /* m_pAdapter->HwEnter(); TODO */ + + oss_udelay (GPIO_WAIT); + + /* Reset all LD Pins and GO Pin */ + WriteGPIO (devc, 0, + GPIO_LD_DATA_H_MASK | GPIO_LD_DATA_L_MASK | GPIO_LD_ADR_MASK | + GPIO_GO_MASK); + + + /* apply address to TT-AC97 Interface */ + WriteGPIO (devc, Register, GPIO_DATA_ADR_MASK); + + /* Set "Load Address" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, GPIO_LD_ADR_MASK, GPIO_LD_ADR_MASK); + + /* Reset "Load Address" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, 0, GPIO_LD_ADR_MASK); + + /* apply data low to TT-AC97 Interface */ + oss_udelay (GPIO_WAIT); + TTData = (UCHAR) (Data & 0x000000FF); + WriteGPIO (devc, TTData, GPIO_DATA_ADR_MASK); + + /* Set "Load Data low" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, GPIO_LD_DATA_L_MASK, GPIO_LD_DATA_L_MASK); + + /* Reset "Load Data low" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, 0, GPIO_LD_DATA_L_MASK); + + /* apply data high to TT-AC97 Interface */ + oss_udelay (GPIO_WAIT); + TTData = (UCHAR) ((Data >> 8) & 0x000000FF); + WriteGPIO (devc, TTData, GPIO_DATA_ADR_MASK); + + /* Set "Load Data high" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, GPIO_LD_DATA_H_MASK, GPIO_LD_DATA_H_MASK); + + /* Reset "Load Data high" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, 0, GPIO_LD_DATA_H_MASK); + + /* Set and immediately reset "GO" Pin */ + oss_udelay (GPIO_WAIT); + WriteGPIO (devc, GPIO_GO_MASK, GPIO_GO_MASK); + WriteGPIO (devc, 0, GPIO_GO_MASK); + /* m_pAdapter->HwLeave(); *//* TODO */ + +} + +/*! \fn ======================================================================= + Function : SetAC97Volume +------------------------------------------------------------------------------- + Description : + Parameters : IN ULONG Index -> + : IN UHSORT Value -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void SetAC97Volume + (envy24ht_devc * devc, IN ULONG Index, IN USHORT left, IN USHORT right) +{ + int AC97Reg = 0, value; + + devc->m_AC97Volume[Index] = left | (right << 8); + + left = AC97_INP_MAX - left; + right = AC97_INP_MAX - right; + + value = (left << 8) | right; + + switch (devc->subvendor) + { + case SSID_AUREON_SKY: + case SSID_PRODIGY71: + case SSID_AUREON_SPACE: + switch (Index) + { + case AC97_MIC: + AC97Reg = AC97_IDXREG_MIC_IN; + break; + case AC97_LINE: + AC97Reg = AC97_IDXREG_LINE_IN; + break; + case AC97_CD: + AC97Reg = AC97_IDXREG_CD_IN; + break; + case AC97_AUX: + AC97Reg = AC97_IDXREG_AUX_IN; + break; + default: + cmn_err (CE_CONT, "Aureon: Bad index %d\n", Index); + return; + } + break; + case SSID_AUREON_UNIVERSE: + switch (Index) + { + case AC97_MIC: + AC97Reg = AC97_IDXREG_MIC_IN; + break; + case AC97_LINE: + AC97Reg = AC97_IDXREG_LINE_IN; + break; + case AC97_CD: + AC97Reg = AC97_IDXREG_AUX_IN; + break; + case AC97_PHONO: + AC97Reg = AC97_IDXREG_CD_IN; + break; + case AC97_AUX: + case AC97_LINE2: + AC97Reg = AC97_IDXREG_VIDEO_IN; + break; + default: + cmn_err (CE_CONT, "Aureon: Bad index %d\n", Index); + return; + + } + break; + } + if (!devc->m_fAC97Mute[Index]) + { + WriteAC97Codec (devc, AC97Reg, value); + } + /* Force saving of registers */ + /* m_pAdapter->SetDirty(); TODO */ +} + + +/*! \fn ======================================================================= + Function : GetAC97Volume +------------------------------------------------------------------------------- + Description : + Returns : UCHAR -> + Parameters : IN ULONG Index -> + : IN ULONG Channel -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static USHORT +GetAC97Volume (envy24ht_devc * devc, IN ULONG Index) +{ + return devc->m_AC97Volume[Index]; +} + +/*! \fn ======================================================================= + Function : SetAC97Mute +------------------------------------------------------------------------------- + Description : + Returns : void -> + Parameters : IN ULONG Index -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetAC97Mute (envy24ht_devc * devc, IN ULONG Index, BOOLEAN OnOff) +{ + UCHAR AC97Reg = 0; + devc->m_fAC97Mute[Index] = OnOff; + switch (devc->subvendor) + { + case SSID_AUREON_SKY: + case SSID_PRODIGY71: + case SSID_AUREON_SPACE: + switch (Index) + { + case AC97_MIC: + AC97Reg = AC97_IDXREG_MIC_IN; + break; + case AC97_LINE: + AC97Reg = AC97_IDXREG_LINE_IN; + break; + case AC97_CD: + AC97Reg = AC97_IDXREG_CD_IN; + break; + case AC97_AUX: + AC97Reg = AC97_IDXREG_AUX_IN; + break; + default: + cmn_err (CE_CONT, "Aureon: Bad index %d\n", Index); + return; + } + break; + case SSID_AUREON_UNIVERSE: + switch (Index) + { + case AC97_MIC: + AC97Reg = AC97_IDXREG_MIC_IN; + break; + case AC97_LINE: + AC97Reg = AC97_IDXREG_LINE_IN; + break; + case AC97_CD: + AC97Reg = AC97_IDXREG_AUX_IN; + break; + case AC97_PHONO: + AC97Reg = AC97_IDXREG_CD_IN; + break; + case AC97_AUX: + case AC97_LINE2: + AC97Reg = AC97_IDXREG_VIDEO_IN; + break; + default: + cmn_err (CE_CONT, "Aureon: Bad index %d\n", Index); + return; + } + break; + } +#ifdef AC97_MUTE + WriteAC97Codec (devc, AC97Reg, 0x8000); +#else + WriteAC97Codec (devc, AC97Reg, + (OnOff) ? 0x8000 : devc->m_AC97Volume[Index]); +#endif + + /* Force saving of registers */ + /* m_pAdapter->SetDirty(); *//* TODO */ +} + +/*! \fn ======================================================================= + Function : InitAC97 +------------------------------------------------------------------------------- + Description : + Returns : void -> +------------------------------------------------------------------------------- + Notes : Call before Registry Read +=============================================================================*/ +static void +InitAC97 (envy24ht_devc * devc) +{ + /* Reset AC97 */ + oss_udelay (30); + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, 0, GPIO_AC97_RESET_MASK); + oss_udelay (3); + WriteGPIO (devc, GPIO_AC97_RESET_MASK, GPIO_AC97_RESET_MASK); + oss_udelay (3); + + /* Unmute Master */ + WriteAC97Codec (devc, 0x02, 0x00); + + /*---------------------------------------------------------------------------- + Set defaults + -----------------------------------------------------------------------------*/ + /* Volume */ + SetAC97Volume (devc, AC97_MIC, AC97_INP_DEFAULT, AC97_INP_DEFAULT); + SetAC97Volume (devc, AC97_LINE, AC97_INP_DEFAULT, AC97_INP_DEFAULT); + SetAC97Volume (devc, AC97_AUX, AC97_INP_DEFAULT, AC97_INP_DEFAULT); + SetAC97Volume (devc, AC97_CD, AC97_INP_DEFAULT, AC97_INP_DEFAULT); + /* Mute */ + SetAC97Mute (devc, AC97_MIC, 0); + SetAC97Mute (devc, AC97_LINE, 0); + SetAC97Mute (devc, AC97_AUX, 0); + SetAC97Mute (devc, AC97_CD, 0); +} + +/*! \fn ======================================================================= + Function : SetSampleRate +------------------------------------------------------------------------------- + Description : + Returns : NTSTATUS -> + Parameters : IN ULONG SampleRate -> +------------------------------------------------------------------------------- + Notes : +=============================================================================*/ +static void +SetSampleRate (envy24ht_devc * devc, IN ULONG SampleRate) +{ + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x0012); + + switch (SampleRate) + { + case 48000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_48KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + /* WRITE_PORT_UCHAR(WKNMTBase + MT_DATA_FORMAT_REG,(~MT_128X)&READ_PORT_UCHAR(WKNMTBase + MT_DATA_FORMAT_REG)); */ + break; + case 24000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_24KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 12000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_12KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 9600: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_9p6KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 32000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_32KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 16000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_16KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 8000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_8KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 96000: + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x001A); + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_96KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 192000: + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x001A); + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_192KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_ON); + break; + case 64000: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_64KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 44100: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_44p1KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 22050: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_22p05KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 11025: + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_11p025KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 88200: + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x001A); + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_88p2KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + case 176400: + WriteWM8770 (devc, WM_MASTER_MODE_CNTRL, 0x001A); + WritePort (devc, REG_MT, MT_SAMPLE_RATE_REG, MT_176p4KHZ, WIDTH_BYTE); + ReadModifyWritePort (devc, REG_MT, MT_DATA_FORMAT_REG, MT_128X, + WIDTH_BYTE | BITS_OFF); + break; + default: + break; + + } +} + +static void +aureon_card_init (envy24ht_devc * devc) +{ + +/* Do not change the order of the following lines */ + Init1724 (devc); + ResetGPIO (devc); + + if (devc->subvendor != SSID_PHASE28) + InitAC97 (devc); + InitWM8770 (devc); + InitCS8415 (devc); +/* Do not change the order of the above lines */ + + SetSPDIFConfig (devc, 0); + /* SetSDPIFSource(devc, DIGOUT_WAVE); */ + SetDigInSource (devc, DIGIN_COAX); + SetFrontjack (devc, FRONT_JACK_HEADPHONE); + SetLineSource (devc, SRC_LINE_REAR); + SetClockSource (devc, ICE_INTERNAL_CLOCK); + +} + +static void +aureon_set_rate (envy24ht_devc * devc) +{ + SetSampleRate (devc, devc->speed); +} + +static int +aureon_set_ctl (int dev, int ctl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->devc; + + if (cmd == SNDCTL_MIX_READ) + { + switch (ctl) + { + case 1: + return devc->m_LineInSource; + case 3: + return devc->m_DigInSource; + case 4: + return devc->m_Frontjack; + } + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctl) + { + case 1: + SetLineSource (devc, value); + return devc->m_LineInSource; + case 3: + SetDigInSource (devc, value); + return devc->m_DigInSource; + case 4: + SetFrontjack (devc, value); + return devc->m_Frontjack; + } + } + + return OSS_EINVAL; +} + +static int +aureon_set_vol (int dev, int ChannelID, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->devc; + ULONG LineIndex; + WORD LeftRight; + int left, right; + + /* Convert ChannelID to line index */ + LineIndex = ChannelID >> 15; + /* Get the left/right side */ + LeftRight = (WORD) (ChannelID & 0xffff); + + if (cmd == SNDCTL_MIX_READ) + { + left = right = 0; + if (LeftRight & CH_LEFT) + left = GetDACVolume (devc, (LineIndex << 15) | CH_LEFT); + if (LeftRight & CH_RIGHT) + right = GetDACVolume (devc, (LineIndex << 15) | CH_RIGHT); + + if (left == 0) + left = right; + else if (right == 0) + right = left; + + return left | (right << 8); + } + + if (cmd == SNDCTL_MIX_WRITE) + { + left = (value & 0xff); + right = ((value >> 8) & 0xff); + + if (LeftRight != CH_BOTH) + right = left; + + if (LeftRight & CH_LEFT) + SetDACVolume (devc, (LineIndex << 15) | CH_LEFT, left); + + if (LeftRight & CH_RIGHT) + SetDACVolume (devc, (LineIndex << 15) | CH_RIGHT, right); + + return left | (right << 8); + } + + return OSS_EINVAL; +} + +static int +aureon_set_ac97 (int dev, int Index, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->devc; + int left, right; + + if (cmd == SNDCTL_MIX_READ) + { + return GetAC97Volume (devc, Index); + } + + if (cmd == SNDCTL_MIX_WRITE) + { + left = (value & 0xff); + right = ((value >> 8) & 0xff); + + SetAC97Volume (devc, Index, left, right); + + return left | (right << 8); + } + + return OSS_EINVAL; +} + + /*ARGSUSED*/ static int +aureon_mixer_init_common (envy24ht_devc * devc, int dev, int root) +{ + int ctl, group; + + if ((group = mixer_ext_create_group (dev, root, "VOL")) < 0) + return group; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_MASTER_BOTH, + aureon_set_vol, + MIXT_STEREOSLIDER, "MASTER", + WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_FRONT_BOTH, + aureon_set_vol, + MIXT_STEREOSLIDER, "FRONT", WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_REAR_BOTH, + aureon_set_vol, + MIXT_STEREOSLIDER, "SURROUND", + WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_CENTER, + aureon_set_vol, + MIXT_MONOSLIDER, "CENTER", WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_LFE, + aureon_set_vol, + MIXT_MONOSLIDER, "LFE", WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + CH_BS_BOTH, + aureon_set_vol, + MIXT_STEREOSLIDER, "REAR", WM_OUT_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((group = + mixer_ext_create_group_flags (dev, root, "TERRATEC", MIXF_FLAT)) < 0) + return group; + + if ((ctl = mixer_ext_create_control (dev, group, + 1, + aureon_set_ctl, + MIXT_ENUM, "LINESRC", 4, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "AUX WTL REAR GROUND", 0); + + if ((ctl = mixer_ext_create_control (dev, group, + 3, + aureon_set_ctl, + MIXT_ENUM, "DIGIN", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "OPTICAL COAX CD", 0); + + return 0; +} + + /*ARGSUSED*/ static int +aureon_mixer_init_universe (envy24ht_devc * devc, int dev, int group) +{ + int ctl; + + if ((group = mixer_ext_create_group (dev, group, "ENVY24_UNIVERSE")) < 0) + return group; + + if ((ctl = mixer_ext_create_control (dev, group, + 4, + aureon_set_ctl, + MIXT_ENUM, "FRONTJACK", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "LINEIN HEADPH", 0); + + return 0; +} + + /*ARGSUSED*/ static int +aureon_mixer_init_ac97 (envy24ht_devc * devc, int dev, int group) +{ + int ctl; + + if ((group = mixer_ext_create_group (dev, group, "ENVY24_AC97")) < 0) + return group; + + if ((ctl = mixer_ext_create_control (dev, group, + AC97_MIC, + aureon_set_ac97, + MIXT_STEREOSLIDER, "MIC", AC97_INP_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + AC97_LINE, + aureon_set_ac97, + MIXT_STEREOSLIDER, "LINE", + AC97_INP_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + AC97_CD, + aureon_set_ac97, + MIXT_STEREOSLIDER, "CD", AC97_INP_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + AC97_PHONO, + aureon_set_ac97, + MIXT_STEREOSLIDER, "PHONO", + AC97_INP_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, group, + AC97_AUX, + aureon_set_ac97, + MIXT_STEREOSLIDER, "AUX", AC97_INP_MAX, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + return 0; +} + +static int +aureon_mixer_init (envy24ht_devc * devc, int dev, int root) +{ + aureon_mixer_init_common (devc, dev, root); + + if (devc->subvendor == SSID_AUREON_UNIVERSE) + aureon_mixer_init_universe (devc, dev, root); + + if (devc->subvendor != SSID_PHASE28) + aureon_mixer_init_ac97 (devc, dev, root); + return 0; +} + +envy24ht_auxdrv_t envy24ht_aureon_auxdrv = { + aureon_card_init, + aureon_mixer_init, + aureon_set_rate, + NULL, + NULL, + NULL, /* aureon_private1 */ +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_julia.c b/kernel/drv/oss_envy24ht/envy24ht_julia.c new file mode 100644 index 0000000..544dd08 --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_julia.c @@ -0,0 +1,547 @@ +/* + * Purpose: Low level routines for the ESI (Egosys) Juli@ card + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +#define AK4358_ADDRESS 0x11 +#define AK4114_ADDRESS 0x10 + +static unsigned char +i2c_read (envy24ht_devc * devc, unsigned char addr, unsigned char pos) +{ + int i; + unsigned char data; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, addr << 1, devc->ccs_base + 0x10); /* Read address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + oss_udelay (1); + data = INB (devc->osdev, devc->ccs_base + 0x12); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return data; +} + +static void +i2c_write (envy24ht_devc * devc, unsigned char addr, unsigned char pos, + unsigned char data) +{ + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, data, devc->ccs_base + 0x12); /* Data */ + OUTB (devc->osdev, (addr << 1) | 1, devc->ccs_base + 0x10); /* Write address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + if ((addr == AK4358_ADDRESS) && (pos <= 0x0c)) + devc->m_DACVolume[pos] = data; +} + +static void +GPIOWrite (envy24ht_devc * devc, int pos, int bit) +{ + int data = INW (devc->osdev, devc->ccs_base + 0x14); + + bit = (bit != 0); + + data &= ~(1 << pos); + data |= (bit << pos); + + OUTW (devc->osdev, data, devc->ccs_base + 0x14); +} + +static int +set_dac (envy24ht_devc * devc, int reg, int level) +{ + if (level < 0) + level = 0; + if (level > 0x7f) + level = 0x7f; + + i2c_write (devc, AK4358_ADDRESS, reg, level | 0x80); + + return level; +} + +static struct { + int rate, spdifin, clks; +} rate_sel[] = { + {32000, 0x30, 0x08}, + {44100, 0x00, 0x09}, + {48000, 0x20, 0x0A}, + {88200, 0x80, 0x05}, + {96000, 0xA0, 0x06}, + {176400, 0xC0, 0x01}, + {192000, 0xE0, 0x02}, + {16000, -1, 0x0C}, + {22050, -1, 0x0D}, + {24000, -1, 0x0E}, + {64000, -1, 0x04}, + {128000, -1, 0x00}, + {-1, -1, -1} +}; + +static void +julia_set_deemph (envy24ht_devc * devc, int mode) +{ + int deemph = 0x01; /* OFF */ + + if (mode == 0) + i2c_write (devc, AK4358_ADDRESS, 0x03, deemph); + else { + + if (devc->speed == 44100) + deemph = 0x00; + else if (devc->speed == 48000) + deemph = 0x02; + else if (devc->speed == 32000) + deemph = 0x03; + + i2c_write (devc, AK4358_ADDRESS, 0x03, deemph); + } +} + +static void +julia_Monitor (envy24ht_devc * devc, int bMonitor, int num) +{ + switch (num) + { + case 0: /* MUTE */ + if (bMonitor) + { + i2c_write (devc, AK4358_ADDRESS, 1, 0x03); + GPIOWrite (devc, 15, 1); + } else { + i2c_write (devc, AK4358_ADDRESS, 1, 0x01); + GPIOWrite (devc, 15, 0); + } + break; + + case 1: /* LINEIN */ + if (bMonitor) + GPIOWrite (devc, 13, 1); + else + GPIOWrite (devc, 13, 0); + break; + + case 2: /* SPDIFOUT */ + if (bMonitor) + GPIOWrite (devc, 11, 1); + else + GPIOWrite (devc, 11, 0); + break; + case 3: /* SPDIFIN */ + if (bMonitor) + GPIOWrite (devc, 12, 1); + else + GPIOWrite (devc, 12, 0); + break; + case 4: /* De-emphasis */ + julia_set_deemph (devc, bMonitor); + break; + } + devc->monitor[num] = bMonitor; +} + +static void +ak4114_init (envy24ht_devc * devc) +{ + /* + * AK4114 S/PDIF interface initialization + */ + i2c_write (devc, AK4114_ADDRESS, 0x00, 0x0f); + i2c_write (devc, AK4114_ADDRESS, 0x01, 0x70); + i2c_write (devc, AK4114_ADDRESS, 0x02, 0x80); + i2c_write (devc, AK4114_ADDRESS, 0x03, 0x49); + i2c_write (devc, AK4114_ADDRESS, 0x04, 0x00); + i2c_write (devc, AK4114_ADDRESS, 0x05, 0x00); + + i2c_write (devc, AK4114_ADDRESS, 0x0d, 0x41); + i2c_write (devc, AK4114_ADDRESS, 0x0e, 0x02); + i2c_write (devc, AK4114_ADDRESS, 0x0f, 0x2c); + i2c_write (devc, AK4114_ADDRESS, 0x10, 0x00); + i2c_write (devc, AK4114_ADDRESS, 0x11, 0x00); +} + +static void +julia_set_rate (envy24ht_devc * devc) +{ + int i, data; + int adc = 0x00; + + if (devc->speed <= 48000) + devc->m_DACVolume[2] = 0x4f; /* DFS=normal-speed */ + else if (devc->speed <= 96000) + { + adc = 0x04; + devc->m_DACVolume[2] = 0x5f; /* DFS=double-speed */ + } + else + { + adc = 0x03; + devc->m_DACVolume[2] = 0x6f; /* DFS=quad-speed */ + } + + data = INW (devc->osdev, devc->ccs_base + 0x14); + data &= ~0x70f; + data |= adc << 8; + + for (i = 0; rate_sel[i].rate; i++) + if (rate_sel[i].rate == devc->speed) + data |= rate_sel[i].clks; + + OUTW (devc->osdev, data, devc->ccs_base + 0x14); + + OUTB (devc->osdev, 0x80, devc->mt_base + 0x05); /* RESET */ + OUTB (devc->osdev, 0x00, devc->mt_base + 0x05); + + if (devc->speed == 8000) + OUTB (devc->osdev, 0x06, devc->mt_base + 0x01); + else if (devc->speed == 9600) + OUTB (devc->osdev, 0x03, devc->mt_base + 0x01); + else if (devc->speed == 11025) + OUTB (devc->osdev, 0x0a, devc->mt_base + 0x01); + else if (devc->speed == 12000) + OUTB (devc->osdev, 0x02, devc->mt_base + 0x01); + else + OUTB (devc->osdev, 0x10, devc->mt_base + 0x01); + + /* Restore ak4358 regs and set DFS */ + for (i = 0; i <= 0x0c; i++) + i2c_write (devc, AK4358_ADDRESS, i, devc->m_DACVolume[i]); + /* Restore ak4114 */ + ak4114_init (devc); + if (devc->monitor[4] == 1) + julia_set_deemph (devc, 1); +} + +static void +julia_sync_ak4114 (void *arg) +{ + envy24ht_devc *devc = arg; + int i; + int spdifin = i2c_read (devc, AK4114_ADDRESS, 7); + + for (i = 0; rate_sel[i].rate; i++) + if (rate_sel[i].spdifin == spdifin) + { + if (devc->speed != rate_sel[i].rate) + { + devc->speed = rate_sel[i].rate; + mixer_devs[devc->mixer_dev]->modify_counter++; + julia_set_rate (devc); + } + break; + } + + if (devc->syncsource == 1) + devc->timeout_id = timeout (julia_sync_ak4114, devc, OSS_HZ); +} + +static int +julia_set_syncsource (envy24ht_devc * devc, int value) +{ + if (value == 1) + { + GPIOWrite (devc, 4, 0); + devc->timeout_id = timeout (julia_sync_ak4114, devc, OSS_HZ); + } else { + if (devc->timeout_id != 0) + untimeout (devc->timeout_id); + devc->timeout_id = 0; + + GPIOWrite (devc, 4, 1); + + if (devc->speed != devc->pending_speed) + { + devc->speed = devc->pending_speed; + mixer_devs[devc->mixer_dev]->modify_counter++; + julia_set_rate (devc); + } + } + + return 0; +} + +static int +julia_audio_ioctl (envy24ht_devc * devc, envy24ht_portc * portc, unsigned int cmd, + ioctl_arg arg) +{ + int left, right, value; + + switch (cmd) + { + case SNDCTL_DSP_GETPLAYVOL: + if (portc != &devc->play_portc[0]) + return OSS_EINVAL; + left = (devc->gains[0] & 0xff) * 100 / 0x7f; + right = ((devc->gains[0] >> 8) & 0xff) * 100 / 0x7f; + return *arg = (left | (right << 8)); + break; + + case SNDCTL_DSP_SETPLAYVOL: + if (portc != &devc->play_portc[0]) + return OSS_EINVAL; + value = *arg; + left = value & 0xff; + right = (value >> 8) & 0xff; + + left = (left * 0x7f) / 100; + right = (right * 0x7f) / 100; + left = set_dac (devc, 0x04, left); + right = set_dac (devc, 0x05, right); + devc->gains[0] = left | (right << 8); + mixer_devs[devc->mixer_dev]->modify_counter++; + return 0; + break; + } + return OSS_EINVAL; +} + +static int +julia_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EINVAL; + + return devc->monitor[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EINVAL; + + value = !!value; + julia_Monitor (devc, value, ctrl); + return devc->monitor[ctrl]; + } + + return OSS_EINVAL; +} + +static int +julia_set_ak4358 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EIO; + + return devc->gains[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + switch (ctrl) + { + case 0: /* PCM */ + left = set_dac (devc, 0x04, left); + right = set_dac (devc, 0x05, right); + break; + case 1: /* LINEIN */ + left = set_dac (devc, 0x06, left); + right = set_dac (devc, 0x07, right); + break; + case 2: /* SPDIFOUT */ + left = set_dac (devc, 0x08, left); + right = set_dac (devc, 0x09, right); + break; + case 3: /* SPDIFIN */ + left = set_dac (devc, 0x0B, left); + right = set_dac (devc, 0x0C, right); + break; + + default: + return OSS_EINVAL; + } + + value = left | (right << 8); + return devc->gains[ctrl] = value; + } + + return OSS_EINVAL; +} + + /*ARGSUSED*/ static int +julia_mixer_init (envy24ht_devc * devc, int dev, int g) +{ + int group = g; + int err, monitor; + + if ((group = mixer_ext_create_group (dev, g, "VOL")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 0, julia_set_control, + MIXT_ONOFF, + "ENVY24_MUTE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 0, julia_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_PCM", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, julia_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_LINEIN", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, julia_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_SPDIFOUT", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, julia_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_SPDIFIN", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((monitor = mixer_ext_create_group (dev, g, "MONITOR")) < 0) + return monitor; + + if ((err = mixer_ext_create_control (dev, monitor, + 1, julia_set_control, + MIXT_ONOFF, + "ENVY24_LINEIN", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, monitor, + 2, julia_set_control, + MIXT_ONOFF, + "ENVY24_SPDIFOUT", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, monitor, + 3, julia_set_control, + MIXT_ONOFF, + "ENVY24_SPDIFIN", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, monitor, + 4, julia_set_control, + MIXT_ENUM, + "ENVY24_DEEMPH", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + mixer_ext_set_strings (dev, err, "OFF 50/15usec", 0); + + return 0; +} + +static void +julia_card_init (envy24ht_devc * devc) +{ + ak4114_init (devc); +/* + * AK4358 DAC initialization + */ + i2c_write (devc, AK4358_ADDRESS, 2, 0x00); + i2c_write (devc, AK4358_ADDRESS, 2, 0x4E); + i2c_write (devc, AK4358_ADDRESS, 0, 0x06); + i2c_write (devc, AK4358_ADDRESS, 1, 0x02); + i2c_write (devc, AK4358_ADDRESS, 3, 0x01); + + set_dac (devc, 0x04, 0x7f); + set_dac (devc, 0x05, 0x7f); + set_dac (devc, 0x06, 0x7f); + set_dac (devc, 0x07, 0x7f); + set_dac (devc, 0x08, 0x7f); + set_dac (devc, 0x09, 0x7f); + set_dac (devc, 0x0b, 0x7f); + set_dac (devc, 0x0c, 0x7f); + + i2c_write (devc, AK4358_ADDRESS, 0xA, 0x00); + i2c_write (devc, AK4358_ADDRESS, 0xD, 0x00); + i2c_write (devc, AK4358_ADDRESS, 0xE, 0x00); + i2c_write (devc, AK4358_ADDRESS, 0xF, 0x00); + i2c_write (devc, AK4358_ADDRESS, 2, 0x4F); + + julia_Monitor (devc, 0, 0); /* Unmute */ +} + +static void +julia_card_uninit (envy24ht_devc * devc) +{ + if (devc->timeout_id != 0) + untimeout (devc->timeout_id); +} + +envy24ht_auxdrv_t envy24ht_julia_auxdrv = { + julia_card_init, + julia_mixer_init, + julia_set_rate, + NULL, + NULL, + julia_set_syncsource, + julia_audio_ioctl, + julia_card_uninit +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_revo51.c b/kernel/drv/oss_envy24ht/envy24ht_revo51.c new file mode 100644 index 0000000..e84cb6a --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_revo51.c @@ -0,0 +1,938 @@ +/* + * Purpose: Low level routines for M Audio Revolution 5.1 + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +static char channel_names[4][10] = { + "front", + "c/l", + "surround", + "headph" +}; + +#define BIT(x) (1<<(x)) +#define BIT3 BIT(3) + +/*----- SPI bus for CODEC communication. */ +/* */ +#define SPI_CLK 1 /* Clock output to CODEC's, rising edge clocks data. */ +#define SPI_DOUT 3 /* Data output to the CODEC. */ +#define SPI_CS0n (1<<4) /* Selects first chip. */ +#define SPI_CS1n (1<<5) /* Selects second chip. */ +#define SPI_CC_AK4358 0x02 /* C1:C0 for ak4358. */ +#define SPI_CC_AK5365 0x02 /* C1:C0 for ak5365. */ +#define WRITEMASK 0xffff +/*----- Revolution defines. */ +/* */ +#define REVO51_AK5365 (1) /* iDevice value for AK5365 A/D. */ +#define REVO51_AK4358 (2) /* iDevice value for AK4358 D/A. */ + +static unsigned int +GpioReadAll (envy24ht_devc * devc) +{ + return INW (devc->osdev, devc->ccs_base + 0x14); +} + +static void +GpioWriteAll (envy24ht_devc * devc, unsigned int data) +{ + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, 0x0000, devc->ccs_base + 0x16); /* GPIO write mask */ + + OUTW (devc->osdev, data, devc->ccs_base + 0x14); +} + +static void +GpioWrite (envy24ht_devc * devc, int pos, int bit) +{ + int data = GpioReadAll (devc); + + bit = (bit != 0); + + data &= ~(1 << pos); + data |= (bit << pos); + + GpioWriteAll (devc, data); +} + +void +REVO51_Assert_CS (envy24ht_devc * devc, int iDevice) +/* +***************************************************************************** +* Assert chip select to specified GPIO-connected device. +* iDevice: REVO51_AK5365=ADC, REVO51_AK4358=DAC. +****************************************************************************/ +{ + unsigned int dwGPIO; /* Current GPIO's. */ + dwGPIO = GpioReadAll (devc); /* Read current GPIO's. */ + dwGPIO |= (SPI_CS0n | SPI_CS1n); /* Reset CS bits. */ + switch (iDevice) /* Select CS#. */ + { + case REVO51_AK4358: + dwGPIO &= ~SPI_CS0n; + break; /* DAC */ + case REVO51_AK5365: + dwGPIO &= ~SPI_CS1n; + break; /* ADC */ + default: + break; + } + GpioWriteAll (devc, dwGPIO); /* Write hardware. */ +} + +void +REVO51_DeAssert_CS (envy24ht_devc * devc) +/* +***************************************************************************** +* De-Assert all chip selects. +****************************************************************************/ +{ + unsigned int dwGPIO = GpioReadAll (devc); /* Current GPIO's. */ + dwGPIO |= (SPI_CS0n | SPI_CS1n); /* Clear CS bits. */ + GpioWriteAll (devc, dwGPIO); /* Write back to hardware. */ +} + +/*#define _delay() oss_udelay(1) */ +#define _delay() {} + +void +REVO51_WriteSpiAddr (envy24ht_devc * devc, int iDevice, unsigned char bReg) +/* +***************************************************************************** +* Write the address byte part of the SPI serial stream. +* iDevice: REVO51_AK4358=DAC, REVO51_AK5365=ADC, etc. +****************************************************************************/ +{ + unsigned char bHdr; + unsigned char bNum; +/* Built 8-bit packet header: C1,C0,R/W,A4,A3,A2,A1,A0. */ +/* */ + switch (iDevice) + { + case REVO51_AK4358: + bHdr = SPI_CC_AK4358 << 6; + break; + case REVO51_AK5365: + bHdr = SPI_CC_AK5365 << 6; + break; + default: + bHdr = 0; + break; + } + bHdr = bHdr | 0x20 | (bReg & 0x1F); /* "write" + address. */ +/* Write header to SPI. */ +/* */ + for (bNum = 0; bNum < 8; bNum++) + { + GpioWrite (devc, SPI_CLK, 0); /* Drop clock low. */ + _delay (); + GpioWrite (devc, SPI_DOUT, 0x080 & bHdr); /* Write data bit. */ + _delay (); + GpioWrite (devc, SPI_CLK, 1); /* Raise clock. */ + _delay (); + bHdr <<= 1; /* Next bit. */ + } +} + +void +REVO51_WriteSpiReg (envy24ht_devc * devc, int iDevice, unsigned char bReg, + unsigned char bData) +/* +***************************************************************************** +* Writes one register in specified CHIP. +* devc = PCI slot code of specific board. +* iDevice: REVO51_AK4358=DAC, REVO51_AK5365=ADC, etc. +****************************************************************************/ +{ + unsigned char bNum; + GpioWrite (devc, SPI_DOUT, 0); /* Init SPI signals. */ + GpioWrite (devc, SPI_CLK, 1); /* */ +/* Drop the chip select low. */ +/* Wait at least 150 nS. */ +/* */ + REVO51_Assert_CS (devc, iDevice); + _delay (); +/* Write the address byte. */ +/* */ + REVO51_WriteSpiAddr (devc, iDevice, bReg); +/* Write the data byte. */ +/* */ + for (bNum = 0; bNum < 8; bNum++) + { + GpioWrite (devc, SPI_CLK, 0); /* Drop clock low. */ + _delay (); + GpioWrite (devc, SPI_DOUT, 0x080 & bData); /* Write data bit. */ + _delay (); + GpioWrite (devc, SPI_CLK, 1); /* Raise clock. */ + _delay (); + bData <<= 1; /* Next bit. */ + } +/* De-assert chip selects. */ +/* */ + REVO51_DeAssert_CS (devc); + _delay (); +} + + +#define GPIO_MUTEn 22 /* Converter mute signal. */ +void +REVO51_Mute (envy24ht_devc * devc, int bMute) +/* +***************************************************************************** +* Mutes all outputs if bMute=1. +****************************************************************************/ +{ + if (bMute) + { +/* Soft-mute. Delay currently unspecified, try ½ second. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 1, 0x03); + _delay (); +/* Switch mute transistors on. */ + GpioWrite (devc, GPIO_MUTEn, 0); + } + else + { +/* Switch mute transistors off. Delay currently unspecified, try ½ second. */ + GpioWrite (devc, GPIO_MUTEn, 1); + _delay (); +/* Release Soft-mute. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 1, 0x01); + } + + devc->mute = bMute; +} + + +void +REVO51_Set_OutAttn (envy24ht_devc * devc, unsigned char bChan, int iAttn) +/* +***************************************************************************** +* Sets the attenuation on one output channel. +* bChan = Channel number (0..7). +* Channel 0:1 = front, 2:3 = center/sub, 4:5 = rear, 6:7 = headphones. +* Registers are 0x04, 05, 06, 07, 08, 09, 0B, 0C respectively +* iAttn = Number of steps to attenuate CODEC. +* Each step equals .5dB (-127..0) +****************************************************************************/ +{ + unsigned char bIndex; + unsigned char bAttn; + if (bChan > 7 || iAttn > 0 || iAttn < -127) /* parameter test */ + { + cmn_err (CE_CONT, "\ninvalid data! %d=bChan, %d=iAttn", bChan, iAttn); + return; + } + if (bChan < 6) + bIndex = 0x04 + bChan; /* for registers 0x04..0x09 */ + else + bIndex = 0x05 + bChan; /* for registers 0x0B..0x0C */ + bAttn = (0x80 + (unsigned char) (iAttn + 127)); /* 7F is max volume. */ +/* MSB enables attenuation. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, bIndex, bAttn); +} + +static void +ADC_Set_Chan (envy24ht_devc * devc, int iChan) +/*************************************************************************** +* Makes input selection for ADC. +* 0=mic, 1=line, 2=aux +****************************************************************************/ +{ +/*Check param */ + if (2 < iChan) +#define GPIO_SDA 6 /* SDA pin */ + cmn_err (CE_CONT, "\nInvalid Input channel parameter"); + else + REVO51_WriteSpiReg (devc, REVO51_AK5365, 1, (unsigned char) iChan); +} + +#define GPIO_SCL 7 /* SCL pin */ +static void +start_bit (envy24ht_devc * devc) +/* +***************************************************************************** +* Send I2C Start Bit. +****************************************************************************/ +{ + GpioWrite (devc, GPIO_SDA, 1); /* Make sure DATA high. */ + _delay (); + GpioWrite (devc, GPIO_SCL, 1); /* Set clock high. */ + _delay (); + GpioWrite (devc, GPIO_SDA, 0); /* Falling edge indicates start bit. */ + _delay (); + GpioWrite (devc, GPIO_SCL, 0); /* Start clock train. */ +} + +static void +byte_out (envy24ht_devc * devc, unsigned char b8) +/* +***************************************************************************** +* Send current 8 input bits in B8. Msb is first written. +****************************************************************************/ +{ + int bnum; /* bit number */ + for (bnum = 7; bnum >= 0; bnum--) + { + GpioWrite (devc, GPIO_SDA, b8 & 0x80); /* Set bit. */ + _delay (); /* */ + GpioWrite (devc, GPIO_SCL, 1); /* Set clock high. */ + _delay (); /* */ + GpioWrite (devc, GPIO_SCL, 0); /* Return clock low. */ + b8 = b8 << 1; /* Next position. */ + } +/* No ACK, but we need to clock a false "9th" bit. */ + _delay (); /* */ + GpioWrite (devc, GPIO_SCL, 1); /* Set clock high. */ + _delay (); /* */ + GpioWrite (devc, GPIO_SCL, 0); /* Return clock low. */ +} + +static void +stop_bit (envy24ht_devc * devc) +/* +***************************************************************************** +* Send I2C Stop Bit. +****************************************************************************/ +{ + GpioWrite (devc, GPIO_SDA, 0); /* Make sure data is low. */ + _delay (); + GpioWrite (devc, GPIO_SCL, 1); /* Set clock high. */ + _delay (); + GpioWrite (devc, GPIO_SDA, 1); /* Rising edge indicates stop bit. */ +} +static void +PT2258S_Write_Data (envy24ht_devc * devc, int cnt, unsigned char *aData) +/* +************************************************************************ ***** +* Write an array of bytes (aData) to address VADDR in PT2258S. +* Assumes I2C Bus is inactive, i.e., SCL=1,SDA=1 and both are outputs. +* This routine waits for the byte to complete writing. +************************************************************************ ****/ +{ + int i; + start_bit (devc); /* Send start bit. */ + byte_out (devc, (unsigned char) 0x80); /* Set address to write data to. */ + for (i = 0; i < cnt; i++) + byte_out (devc, aData[i]); /* Write data to address. */ + stop_bit (devc); /* Stop bit ends operation. */ +} +static void +PT2258S_Write_Byte (envy24ht_devc * devc, unsigned char vdata) +/* +***************************************************************************** +* Write a byte VDATA to address VADDR in PT2258S. +* Assumes I2C Bus is inactive, i.e., SCL=1,SDA=1 and both are outputs. +* This routine waits for the byte to complete writing. +****************************************************************************/ +{ + start_bit (devc); /* Send start bit. */ + byte_out (devc, (unsigned char) 0x80); /* Set address to write data to. */ + byte_out (devc, vdata); /* Write data to address. */ + stop_bit (devc); /* Stop bit ends operation. */ +} + +static void +PT2258S_Set_Attn (envy24ht_devc * devc, unsigned char bChan, int iAttn) +/* +************************************************************************ ***** +* Set the attenuation of a specific channel. +* bChan = 0..5. +* iAttn = 0..-79. +************************************************************************ ****/ +{ + static unsigned char bXlat[] = { 0x90, 0x50, 0x10, 0x30, 0x70, 0xB0 }; + unsigned char aAttn[2]; + aAttn[1] = (-iAttn) % 10; /* 1's digit */ + aAttn[0] = (-iAttn) / 10; /* 10's digit */ +/* Check parameters. */ + if ((bChan > 5) || (iAttn < (-79) || iAttn > 0)) + { + cmn_err (CE_CONT, "\nPT2258S_Set_Attn() parameter out of range!"); + return; + } +/* Always set 10's digit, then 1's. */ + aAttn[0] += bXlat[bChan] - 0x10; + aAttn[1] += bXlat[bChan]; + PT2258S_Write_Data (devc, 2, aAttn); +} +static void +PT2258S_Mute (envy24ht_devc * devc, int bMute) +/* +***************************************************************************** +* Mute all 6 outputs of the monitoring volume control. +* Unmuting returns volume to previous levels. +****************************************************************************/ +{ + if (bMute) + PT2258S_Write_Byte (devc, (unsigned char) 0xF9); + else + PT2258S_Write_Byte (devc, (unsigned char) 0xF8); +} + + +static void +REVO51_Set_48K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets Chip and Envy24 for 8kHz-48kHz sample rates. +****************************************************************************/ +{ +/* ICE MCLK = 256x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) & ~BIT3, + devc->mt_base + 2); +/* DFS=normal, RESET. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x4E); +/* DFS=normal, NORMAL OPERATION. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x4F); +} + +static void +REVO51_Set_96K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets CODEC and Envy24 for 60kHz-96kHz sample rates. +****************************************************************************/ +{ +/* ICE MCLK = 256x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) & ~BIT3, + devc->mt_base + 2); +/* DFS=double-speed, RESET. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x5E); +/* DFS=double-speed, NORMAL OPERATION. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x5F); +} + +static void +REVO51_Set_192K_Mode (envy24ht_devc * devc) +/* +***************************************************************************** +* Sets CODEC and Envy24 for 120kHz-192kHz sample rate. +****************************************************************************/ +{ +/* ICE MCLK = 128x. */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 2) | BIT3, + devc->mt_base + 2); + _delay (); +/*----- SET THE D/A. */ +/* DFS=quad-speed, RESET. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x6E); + _delay (); +/* DFS=quad-speed, NORMAL OPERATION. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x6F); +/*------ POWER DOWN THE A/D -- doesn't support 192K. */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 0, 0x00); +} + +static int +set_dac (envy24ht_devc * devc, int reg, int level) +{ + if (level < 0) + level = 0; + if (level > 0x7f) + level = 0x7f; + + REVO51_WriteSpiReg (devc, REVO51_AK4358, reg, level | 0x80); + + return level; +} + +static void +AK4358_Init (envy24ht_devc * devc) +{ +/*===== AK4358 D/A initialization. Leave soft-muted. */ +/* */ +/* Power down, reset, normal mode. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x00); +/* Power up, reset, normal mode */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x4E); +/* Reset timing, Mode 3(I2S), disable auto clock detect, sharp roll off. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 0, 0x06); +/* Soft mute, reset timing. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 1, 0x02); +/* De-emphasis off. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 3, 0x01); +/* Max volume on all 8 channels. */ + set_dac (devc, 0x04, 0x7f); + set_dac (devc, 0x05, 0x7f); + set_dac (devc, 0x06, 0x7f); + set_dac (devc, 0x07, 0x7f); + set_dac (devc, 0x08, 0x7f); + set_dac (devc, 0x09, 0x7f); + set_dac (devc, 0x0b, 0x7f); + set_dac (devc, 0x0c, 0x7f); + +/* Datt mode 0, DZF non-invert, DCLK polarity 0, PCM mode, DCKS 512fs, TDM normal. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 0xA, 0x00); +/* DZF control disabled. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 0xD, 0x00); + REVO51_WriteSpiReg (devc, REVO51_AK4358, 0xE, 0x00); + REVO51_WriteSpiReg (devc, REVO51_AK4358, 0xF, 0x00); +/* Power up, normal operation. */ + REVO51_WriteSpiReg (devc, REVO51_AK4358, 2, 0x4F); +} + +static void +PT2258_init (envy24ht_devc * devc) +{ +/*===== PT2258 initialization. */ +/* */ +/* Initializes and clears register . */ + PT2258S_Write_Byte (devc, (unsigned char) 0xC0); +/*Example of 2-line command controlling all channels. */ +/*This sets all channels to max volume. */ +/*PT2258S_Write_Byte(devc, (unsigned char)0xE0); */ +/*PT2258S_Write_Byte(devc, (unsigned char)0xD0); */ +/* set volumes */ + PT2258S_Set_Attn (devc, 0, 0); + PT2258S_Set_Attn (devc, 1, 0); + PT2258S_Set_Attn (devc, 2, 0); + PT2258S_Set_Attn (devc, 3, 0); + PT2258S_Set_Attn (devc, 4, 0); + PT2258S_Set_Attn (devc, 5, 0); +/*mute, true or false */ + PT2258S_Mute (devc, 0); +} + +static void +REVO51_set_recsrc (envy24ht_devc * devc, int src) +{ + devc->recsrc = src; + + REVO51_WriteSpiReg (devc, REVO51_AK5365, 1, src); +} + +static void +AK5365_Init (envy24ht_devc * devc) +{ +/*===== AK5365 2-ch A/D initialization. Leave soft-muted. */ +/* */ +/* Power down. */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 0, 0x00); +/* Set input to (LINE IN). */ + REVO51_set_recsrc (devc, 0); +/* Clock freq 256fs, I2S mode, mute off. */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 2, 0x08); +/* ALC settings (ALC is disabled, so rewrite default values). */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 3, 0x2B); +/* Neutral analog and digital gain. */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 4, 0x7F); + REVO51_WriteSpiReg (devc, REVO51_AK5365, 5, 0x7F); +/* ALC settings (ALC is disabled, so rewrite default values). */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 6, 0x28); +/* ALC settings (ALC is disabled, so rewrite default values). */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 7, 0x89); +/* Power up. */ + REVO51_WriteSpiReg (devc, REVO51_AK5365, 0, 0x01); +} + +static void +revo51_set_rate (envy24ht_devc * devc) +{ + int tmp; + + tmp = INB (devc->osdev, devc->mt_base + 0x02); + if (devc->speed <= 48000) + { + REVO51_Set_48K_Mode (devc); + OUTB (devc->osdev, tmp & ~BIT (3), devc->mt_base + 0x02); + return; + } + + if (devc->speed <= 96000) + { + REVO51_Set_96K_Mode (devc); + + return; + } + + REVO51_Set_192K_Mode (devc); + OUTB (devc->osdev, tmp | BIT (3), devc->mt_base + 0x02); +} + +static int +revo51_audio_ioctl (envy24ht_devc * devc, envy24ht_portc * portc, unsigned int cmd, + ioctl_arg arg) +{ + int value; + + switch (cmd) + { + case SNDCTL_DSP_GET_RECSRC_NAMES: + return oss_encode_enum ((oss_mixer_enuminfo *) arg, "mic line aux", 0); + break; + + case SNDCTL_DSP_GET_RECSRC: + return *arg = devc->recsrc; + break; + + case SNDCTL_DSP_SET_RECSRC: + value = *arg; + if (value < 0 || value > 2) + return OSS_EINVAL; + REVO51_set_recsrc (devc, value); + return *arg = devc->recsrc; + break; + + case SNDCTL_DSP_GET_PLAYTGT: + case SNDCTL_DSP_SET_PLAYTGT: + return *arg = 0; + break; + + case SNDCTL_DSP_GET_PLAYTGT_NAMES: + return oss_encode_enum ((oss_mixer_enuminfo *) arg, portc->name, 0); + break; + + + default: + return OSS_EINVAL; + } +} + +static int +set_reclevel (envy24ht_devc * devc, int value) +{ + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + if (left > 0x98) + left = 0x98; + if (right > 0x98) + right = 0x98; + + value = left | (right << 8); + + devc->reclevel = value; + + REVO51_WriteSpiReg (devc, REVO51_AK5365, 4, left); + REVO51_WriteSpiReg (devc, REVO51_AK5365, 5, right); + + return value; +} + +static int +revo51_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 0: + return devc->mute; + + case 1: + return devc->recsrc; + + case 2: + return devc->reclevel; + + default: + return OSS_EINVAL; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 0: + value = !!value; + REVO51_Mute (devc, value); + return devc->mute; + + case 1: + if (value < 0 || value > 2) + return devc->recsrc; + REVO51_set_recsrc (devc, value); + return devc->recsrc; + + case 2: + return set_reclevel (devc, value); + + default: + return OSS_EINVAL; + } + + return OSS_EINVAL; +} + +static int +revo51_set_ak4358 (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EIO; + + return devc->gains[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + switch (ctrl) + { + case 0: /* Front */ + left = set_dac (devc, 0x04, left); + right = set_dac (devc, 0x05, right); + break; + + case 1: /* Center */ + left = set_dac (devc, 0x06, left); + right = left; + break; + + case 2: /* LFE */ + left = set_dac (devc, 0x07, left); + right = left; + break; + + case 3: /* Surround */ + left = set_dac (devc, 0x08, left); + left = set_dac (devc, 0x09, right); + break; + + case 4: /* Headphones */ + left = set_dac (devc, 0x0b, left); + left = set_dac (devc, 0x0c, right); + break; + + default: + return OSS_EINVAL; + } + + value = left | (right << 8); + return devc->gains[ctrl] = value; + } + + return OSS_EINVAL; +} + +static int +set_mongain (envy24ht_devc * devc, int reg, int value) +{ + if (value < 0) + value = 0; + if (value > 79) + value = 79; + + PT2258S_Set_Attn (devc, reg, value - 79); + return value; +} + +static int +revo51_set_monitor (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 3) + return OSS_EIO; + + return devc->monitor[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + switch (ctrl) + { + case 0: /* Mic */ + left = set_mongain (devc, 0, left); + right = set_mongain (devc, 1, right); + break; + + case 1: /* Line */ + left = set_mongain (devc, 2, left); + right = set_mongain (devc, 3, right); + break; + + case 2: /* Aux */ + left = set_mongain (devc, 4, left); + right = set_mongain (devc, 5, right); + break; + + case 3: /* Mute */ + value = !!value; + PT2258S_Mute (devc, value); + return devc->monitor[3] = value; + break; + + default: + return OSS_EINVAL; + } + + value = left | (right << 8); + return devc->monitor[ctrl] = value; + } + + return OSS_EINVAL; +} + + /*ARGSUSED*/ static int +revo51_mixer_init (envy24ht_devc * devc, int dev, int g) +{ + int group = 0; + int err; + + if ((err = mixer_ext_create_control (dev, group, + 0, revo51_set_control, + MIXT_ONOFF, + "ENVY24_MUTE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 0, revo51_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_FRONT", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, revo51_set_ak4358, + MIXT_SLIDER, + "ENVY24_CENTER", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, revo51_set_ak4358, + MIXT_SLIDER, + "ENVY24_LFE", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, revo51_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_SURROUND", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 4, revo51_set_ak4358, + MIXT_STEREOSLIDER, + "ENVY24_HEADPH", 0x7f, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, revo51_set_control, + MIXT_STEREOSLIDER, + "ENVY24_REC", 0x98, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, revo51_set_control, + MIXT_ENUM, + "ENVY24_RECSRC", 3, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + mixer_ext_set_strings (dev, err, "mic line aux", 0); + + if ((group = mixer_ext_create_group (dev, g, "MONITOR")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 3, revo51_set_monitor, + MIXT_ONOFF, + "MON_MUTE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 0, revo51_set_monitor, + MIXT_STEREOSLIDER, + "ENVY24_MIC", 79, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, revo51_set_monitor, + MIXT_STEREOSLIDER, + "ENVY24_LINE", 79, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, revo51_set_monitor, + MIXT_STEREOSLIDER, + "ENVY24_AUX", 79, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +static void +revo51_card_init (envy24ht_devc * devc) +{ + + int i; + +#if 1 + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, 0x0000, devc->ccs_base + 0x16); /* GPIO write mask */ + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x14); /* Initial bit state */ + + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1a); /* GPIO direction for bits 16:22 */ + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x1f); /* GPIO mask for bits 16:22 */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1e); /* GPIO data for bits 16:22 */ +#endif + + memcpy (devc->channel_names, channel_names, sizeof (channel_names)); + AK4358_Init (devc); + AK5365_Init (devc); + PT2258_init (devc); + ADC_Set_Chan (devc, 0); /* TODO */ + REVO51_Set_48K_Mode (devc); + + for (i = 0; i < 5; i++) + devc->gains[i] = 0x7f7f; + for (i = 0; i < 3; i++) + devc->monitor[i] = 79 | (79 << 8); + devc->monitor[3] = 0; /* Unmuted */ + + set_reclevel (devc, 0x7f7f); /* +0 dB */ + + REVO51_Mute (devc, 0); +} + +envy24ht_auxdrv_t envy24ht_revo51_auxdrv = { + revo51_card_init, + revo51_mixer_init, + revo51_set_rate, + NULL, + NULL, + NULL, /* revo51_private1 */ + revo51_audio_ioctl +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_revo71.c b/kernel/drv/oss_envy24ht/envy24ht_revo71.c new file mode 100644 index 0000000..fd3a9bb --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_revo71.c @@ -0,0 +1,338 @@ +/* + * Purpose: Low level routines for M Audio Revolution 7.1 + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +#define BIT(x) (1<<(x)) + +#define CCLK (1<<1) +#define CDIN (1<<2) /* Currently not connected */ +#define CDTI (1<<3) +#define CSDIG (1<<4) +#define CSN1 (1<<5) +#define CSN2 (1<<6) + +#define WRITEMASK (CSN1|CSN2|CDTI|CCLK) + +#define DAC1 0x01 /* 2ch Front DAC (AK4381) */ +#define DAC2 0x03 /* 6ch Surround DAC (AK4355) */ + + +static void +writereg (envy24ht_devc * devc, int csn, int chip, unsigned char reg, + unsigned char val) +{ + int i; + unsigned short v, tmp; + + tmp = INW (devc->osdev, devc->ccs_base + 0x14) & ~(csn | CCLK | CDTI); + OUTW (devc->osdev, tmp, devc->ccs_base + 0x14); + + reg = (reg & 0x1f) | 0x20 | (chip << 6); /* Chip address (variable), write */ + /* Address bits */ + + for (i = 7; i >= 0; i--) + { + v = (reg & (1 << i)) ? CDTI : 0; + OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14); /* Tack */ + OUTW (devc->osdev, v | CCLK | tmp, devc->ccs_base + 0x14); /* Tick */ + } + + /* Data bits */ + + for (i = 7; i >= 0; i--) + { + v = (val & (1 << i)) ? CDTI : 0; + OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14); /* Tack */ + OUTW (devc->osdev, v | CCLK | tmp, devc->ccs_base + 0x14); /* Tick */ + } + + OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14); /* Tack */ + OUTW (devc->osdev, tmp | csn | CDTI | CCLK, devc->ccs_base + 0x14); /* Release */ + +} + +static void +writedac1 (envy24ht_devc * devc, unsigned char reg, unsigned char data) +{ + writereg (devc, CSN1, DAC1, reg, data); + devc->dac1val[reg] = data; +} + +static void +writedac2 (envy24ht_devc * devc, unsigned char reg, unsigned char data) +{ + writereg (devc, CSN2, DAC2, reg, data); + devc->dac2val[reg] = data; +} + +static void +revo71_mute (envy24ht_devc * devc, int mute) +{ + if (mute) + { + writedac1 (devc, 1, devc->dac1val[1] | BIT (0)); + writedac2 (devc, 1, devc->dac2val[1] | BIT (1)); + oss_udelay (1000); +/* OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x1e) & ~BIT(22-16), */ +/* devc->ccs_base + 0x1e); */ + } + else + { +/* OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x1e) | ~BIT(22-16), */ +/* devc->ccs_base + 0x1e); */ + oss_udelay (1000); + writedac1 (devc, 1, devc->dac1val[1] & ~BIT (0)); + writedac2 (devc, 1, devc->dac2val[1] & ~BIT (1)); + } +} + +static void +revo71_card_init (envy24ht_devc * devc) +{ + int i; + + OUTL (devc->osdev, WRITEMASK | 0x400000, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, ~WRITEMASK, devc->ccs_base + 0x16); /* GPIO write mask */ + OUTB (devc->osdev, 0x40, devc->ccs_base + 0x1f); + OUTW (devc->osdev, WRITEMASK, devc->ccs_base + 0x14); /* Initial bit state */ + + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1a); /* GPIO direction for bits 16:22 */ + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x1f); /* GPIO mask for bits 16:22 */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1e); /* GPIO data for bits 16:22 */ + +#if 0 + for (i = 0; i < 7; i++) + { + OUTW (devc->osdev, 1 << i, devc->ccs_base + 0x14); /* Test bit */ + OUTW (devc->osdev, 0, devc->ccs_base + 0x14); /* Test bit */ + } +#endif + + OUTW (devc->osdev, WRITEMASK, devc->ccs_base + 0x14); /* Initial bit state */ + oss_udelay (10); + + revo71_mute (devc, 1); +/* + * Init front DAC (AK4381) + */ + writedac1 (devc, 0x00, 0x0c); + writedac1 (devc, 0x01, 0x03); + writedac1 (devc, 0x02, 0x00); + + writedac1 (devc, 0x03, 0xff); /* Initial volume */ + writedac1 (devc, 0x04, 0xff); /* Initial volume */ + + writedac1 (devc, 0x00, 0x0f); +/* + * Init surround DAC (AK4355) + */ + writedac2 (devc, 0x01, 0x02); + writedac2 (devc, 0x00, 0x06); + oss_udelay (10); + writedac2 (devc, 0x02, 0x0e); + writedac2 (devc, 0x03, 0x01); + + for (i = 4; i < 10; i++) + writedac2 (devc, i, 0xff); /* Initial volumes */ + writedac2 (devc, 0x0a, 0x00); + + writedac2 (devc, 0x01, 0x01); + revo71_mute (devc, 0); +} + +static void +revo71_set_rate (envy24ht_devc * devc) +{ + int rate = devc->speed, i; + unsigned char tmp; + + if (devc->speed == devc->prev_speed) + return; + devc->prev_speed = devc->speed; + + revo71_mute (devc, 1); + + /* Pulse the PRST# signal to reset converters */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x05) | 0x80, + devc->mt_base + 0x05); + oss_udelay (5000); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x05) & ~0x80, + devc->mt_base + 0x05); + oss_udelay (5000); + + tmp = 0x03; + if (rate <= 48000) + tmp |= 0x00; + else + { + if (rate <= 96000) + tmp |= 0x04; + else + tmp |= 0x08; + } + + /* Front DAC */ + + writedac1 (devc, 0, 0x0c); + writedac1 (devc, 1, tmp); + writedac1 (devc, 2, 0x00); + writedac1 (devc, 3, devc->dac1val[3]); + writedac1 (devc, 4, devc->dac1val[4]); + writedac1 (devc, 0, 0x0f); + + /* Surround DAC */ + writedac2 (devc, 1, 0x02); + writedac2 (devc, 0, 0x06); + + tmp = 0x0e; + + if (devc->speed > 60000) + { + if (devc->speed > 120000) + tmp |= 0x20; + else + tmp |= 0x10; + } + writedac2 (devc, 2, tmp); + writedac2 (devc, 3, 0x01); + + for (i = 4; i < 10; i++) + writedac2 (devc, i, devc->dac2val[i]); + + writedac2 (devc, 0xa, 0x00); + writedac2 (devc, 1, 0x03); + + revo71_mute (devc, 0); +} + +static int +revo71_set_akm (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl < 0 || ctrl > 4) + return OSS_EIO; + + return devc->gains[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + switch (ctrl) + { + case 0: /* Front */ + writedac1 (devc, 0x03, left); + writedac1 (devc, 0x04, right); + break; + + case 1: /* Rear */ + writedac2 (devc, 0x06, left); + writedac2 (devc, 0x07, right); + break; + + case 2: /* Center */ + writedac2 (devc, 0x04, left); + right = left; + break; + + case 3: /* LFE */ + writedac2 (devc, 0x05, left); + right = left; + break; + + case 4: /* Surround */ + writedac2 (devc, 0x08, left); + writedac2 (devc, 0x09, right); + break; + + default: + return OSS_EINVAL; + } + + value = left | (right << 8); + return devc->gains[ctrl] = value; + } + + return OSS_EINVAL; +} + +static int +revo71_mixer_init (envy24ht_devc * devc, int dev, int group) +{ + int i, err; + + for (i = 0; i < 6; i++) + devc->gains[i] = 0xffff; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24HT_GAIN")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 0, revo71_set_akm, + MIXT_STEREOSLIDER, + "GAIN_FRONT", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, revo71_set_akm, + MIXT_STEREOSLIDER, + "GAIN_REAR", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, revo71_set_akm, + MIXT_MONOSLIDER, + "GAIN_CENTER", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, revo71_set_akm, + MIXT_MONOSLIDER, + "GAIN_LFE", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 4, revo71_set_akm, + MIXT_STEREOSLIDER, + "GAIN_surround", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +envy24ht_auxdrv_t envy24ht_revo71_auxdrv = { + revo71_card_init, + revo71_mixer_init, + revo71_set_rate, + NULL, + NULL, + NULL, /* revo71_private1 */ +}; diff --git a/kernel/drv/oss_envy24ht/envy24ht_via.c.save b/kernel/drv/oss_envy24ht/envy24ht_via.c.save new file mode 100644 index 0000000..49d4199 --- /dev/null +++ b/kernel/drv/oss_envy24ht/envy24ht_via.c.save @@ -0,0 +1,324 @@ +/* + * Purpose: Low level routines for VIA's Envy24HT reference board (AKM codec) + * + * Notice: + * + * This driver is currently disabled because no known real world device + * is based on this design. To enable this driver againa just rename it to + * envy24ht_via.c and edit the models[] table in envy24ht.c. + */ +/* + * + * 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_envy24ht_cfg.h" + +#include "spdif.h" +#include "envy24ht.h" + +#define AKM_ADDRESS 0x10 + +static unsigned char +i2c_read (envy24ht_devc * devc, unsigned char addr, unsigned char pos) +{ + int i; + unsigned char data; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, addr << 1, devc->ccs_base + 0x10); /* Read address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + oss_udelay (1); + data = INB (devc->osdev, devc->ccs_base + 0x12); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return data; +} + +static void +i2c_write (envy24ht_devc * devc, unsigned char addr, unsigned char pos, + unsigned char data) +{ + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, data, devc->ccs_base + 0x12); /* Data */ + OUTB (devc->osdev, (addr << 1) | 1, devc->ccs_base + 0x10); /* Write address */ + + for (i = 0; i < 2000; i++) + { + unsigned char status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +static void +viaref_card_init (envy24ht_devc * devc) +{ + int addr = AKM_ADDRESS; + + if (devc->codec_type != CODEC_I2S) + return; + + OUTW (devc->osdev, 0x000f, devc->ccs_base + 0x14); /* GPIO */ + + oss_udelay (1000); + + i2c_write (devc, addr, 0, 0x00); + i2c_write (devc, addr, 0, 0x0f); + i2c_write (devc, addr, 1, 0x00); + i2c_write (devc, addr, 2, 0x01); + i2c_write (devc, addr, 5, 0x07); + i2c_write (devc, addr, 6, 0x00); + i2c_write (devc, addr, 7, 0x00); + + i2c_write (devc, addr, 6, 0x00); + i2c_write (devc, addr, 7, 0x00); + i2c_write (devc, addr, 8, 0x00); + i2c_write (devc, addr, 9, 0x00); + i2c_write (devc, addr, 10, 0x00); + i2c_write (devc, addr, 11, 0x00); + + devc->recsrc = 0; + +#if 0 + cmn_err(CE_CONT, "Regs="); + for (i = 0; i < 0x18; i++) + { + cmn_err(CE_CONT, "%02x ", i2c_read (devc, addr, i)); + } + cmn_err(CE_CONT, "\n"); +#endif +} + +static int +viaref_set_akm (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + int left, right, val; + unsigned char tmp, tmp2, old, old2; + + if (cmd == SNDCTL_MIX_READ) + { + switch (ctrl) + { + /* Output gain controls */ + case 0: + case 1: + case 2: + case 3: + return devc->gains[ctrl]; + + case 10: /* Loopback enable */ + return !!(i2c_read (devc, AKM_ADDRESS, 0x01) & 0x30); + + case 11: /* codec.recsrc (ANALOG OPTICAL COAX CD AUX) */ + return devc->recsrc; + break; + + default: + return OSS_EINVAL; + } + } + + if (cmd == SNDCTL_MIX_WRITE) + { + oss_native_word flags; + left = value & 0xff; + right = (value >> 8) & 0xff; + val = left | (right << 8); + + switch (ctrl) + { + case 0: + left = 0xff - left; + right = 0xff - right; + i2c_write (devc, AKM_ADDRESS, 0x06, left); + i2c_write (devc, AKM_ADDRESS, 0x07, right); + return devc->gains[ctrl] = val; + + case 1: + left = 0xff - left; + right = 0xff - right; + i2c_write (devc, AKM_ADDRESS, 0x08, left); + i2c_write (devc, AKM_ADDRESS, 0x09, right); + return devc->gains[ctrl] = val; + + case 2: + val = left | (left << 8); + left = 0xff - left; + i2c_write (devc, AKM_ADDRESS, 0x0a, left); + return devc->gains[ctrl] = val; + + case 3: + val = left | (left << 8); + left = 0xff - left; + i2c_write (devc, AKM_ADDRESS, 0x0b, left); + return devc->gains[ctrl] = val; + + case 10: /* Loopback enable */ + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + old = tmp = i2c_read (devc, AKM_ADDRESS, 0x01); + value = !!value; + if (value) + tmp |= 0x10; + else + tmp &= ~0x30; + + if (tmp != old) + { + i2c_write (devc, AKM_ADDRESS, 0x01, tmp); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return value; + + case 11: /* codec.recsrc (ANALOG OPTICAL COAX CD AUX) */ + if (value < 0 || value > 4) + return devc->recsrc; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + old = tmp = i2c_read (devc, AKM_ADDRESS, 0x01); + old2 = tmp2 = i2c_read (devc, AKM_ADDRESS, 0x02); + + tmp &= ~0x0c; + tmp2 &= ~0x03; + + switch (value) + { + case 0: /* Analog */ + tmp2 |= 0x01; + break; + + case 1: /* Optical (RX2) */ + tmp |= 0x04; + tmp2 |= 0x00; + break; + + case 2: /* Coax (RX1) */ + tmp |= 0x00; + tmp2 |= 0x00; + break; + + case 3: /* CD digital input (RX3) */ + tmp |= 0x08; + tmp2 |= 0x00; + break; + + case 4: /* Unused digital input (RX4) */ + tmp |= 0x08; + tmp2 |= 0x00; + break; + } + + if (tmp != old) + i2c_write (devc, AKM_ADDRESS, 0x01, tmp); + if (tmp2 != old2) + i2c_write (devc, AKM_ADDRESS, 0x02, tmp2); + + devc->recsrc = value; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->recsrc; + break; + + } + return OSS_EIO; + } + + return OSS_EIO; +} + +static int +viaref_mixer_init (envy24ht_devc * devc, int dev, int group) +{ + int i, err; + if (devc->codec_type != CODEC_I2S) + return 0; + + for (i = 0; i < 4; i++) + devc->gains[i] = 0xffff; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24HT_GAIN")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 0, viaref_set_akm, + MIXT_STEREOSLIDER, + "GAIN_FRONT", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 1, viaref_set_akm, + MIXT_STEREOSLIDER, + "GAIN_REAR", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 2, viaref_set_akm, + MIXT_MONOSLIDER, + "GAIN_CENTER", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, viaref_set_akm, + MIXT_MONOSLIDER, + "GAIN_LFE", 255, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24HT_CODEC")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, + 11, viaref_set_akm, + MIXT_ENUM, + "CODEC_RECSRC", 5, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 10, viaref_set_akm, + MIXT_ONOFF, + "CODEC_LOOPBACK", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + return 0; +} + +#if 0 +static int +viaref_private1 (envy24ht_devc * devc, int value) +{ + i2c_write (devc, AKM_ADDRESS, (value >> 8) & 0xff, value & 0xff); + return 0; +} +#endif + +envy24ht_auxdrv_t envy24ht_viaref_auxdrv = { + viaref_card_init, + viaref_mixer_init +}; diff --git a/kernel/drv/oss_envy24ht/oss_envy24ht.c b/kernel/drv/oss_envy24ht/oss_envy24ht.c new file mode 100644 index 0000000..11fb75b --- /dev/null +++ b/kernel/drv/oss_envy24ht/oss_envy24ht.c @@ -0,0 +1,2411 @@ +/* + * Purpose: VIA ENVY24HT chipset 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. + * + */ + +#include "oss_envy24ht_cfg.h" +#include <oss_pci.h> + +#define SUPPORTED_FORMAT AFMT_S32_LE + +#include <spdif.h> +#include "envy24ht.h" + +/* extern envy24ht_auxdrv_t envy24ht_viaref_auxdrv; */ +extern envy24ht_auxdrv_t envy24ht_ac97_auxdrv; +extern envy24ht_auxdrv_t envy24ht_revo51_auxdrv; +extern envy24ht_auxdrv_t envy24ht_revo71_auxdrv; +extern envy24ht_auxdrv_t envy24ht_aureon_auxdrv; +extern envy24ht_auxdrv_t envy24ht_julia_auxdrv; +extern envy24ht_auxdrv_t envy24ht_ap192_auxdrv; + +#define OUTCH_NAMES "front c/l side rear" +static char channel_names[4][10] = { + "front", + "c/l", + "side", + "rear" +}; + +static card_spec models[] = { + {0x17241412, "Generic Envy24PT motherboard audio", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + {0xf641270f, "Chaintech ZNF3-150", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + {0x2723270f, "Chaintech 9CJS", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + {0x50361297, "Shuttle SN25P", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + {0x020010b0, "Gainward Hollywood Envy24HT-S", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + {0x36311412, "M Audio Revolution 5.1", 6, 2, + MF_SPDIFOUT | MF_192K, &envy24ht_revo51_auxdrv}, + {0x36301412, "M Audio Revolution 7.1", 8, 2, + MF_SPDIFOUT | MF_192K, &envy24ht_revo71_auxdrv}, + {SSID_AUREON_SPACE, "Terratec Aureon 7.1 Space", 8, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_aureon_auxdrv}, + {SSID_AUREON_UNIVERSE, "Terratec Aureon 7.1 Universe", 8, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_aureon_auxdrv}, + {SSID_AUREON_SKY, "Terratec Aureon 7.1 Sky", 8, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_aureon_auxdrv}, + {SSID_PRODIGY71, "Audiotrak Prodigy 7.1", 8, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_aureon_auxdrv}, + {SSID_JULIA, "Ego Systems Juli@", 2, 2, + MF_SPDIFOUT | MF_SPDIFIN | MF_192K | MF_NOAC97 | MF_MIDI, + &envy24ht_julia_auxdrv}, + {SSID_PHASE28, "Terratec PHASE 28", 8, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97 | MF_MIDI, &envy24ht_aureon_auxdrv}, + {SSID_AP192, "M-Audio Audiophile 192", 2, 2, + MF_SPDIFOUT | MF_SPDIFIN | MF_192K | MF_NOAC97 | MF_MIDI, + &envy24ht_ap192_auxdrv}, + {0x24031412, "VIA Vinyl Tremor Audio", 6, 2, + MF_SPDIFOUT | MF_ENVY24PT, &envy24ht_ac97_auxdrv}, + /* XXX Do a separate auxdrv, to adjust for Envy24HT-S and other differences. */ + {SSID_PRODIGYHD2, "Audiotrak Prodigy HD2", 2, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_ap192_auxdrv}, + {SSID_PRODIGYHD2_ADE, "Audiotrak Prodigy HD2 Advance DE", 2, 2, + MF_SPDIFOUT | MF_192K | MF_NOAC97, &envy24ht_ap192_auxdrv}, + /* {0x17241412, "VIA Envy24HT reference design", 6, 2, */ + /* MF_SPDIFOUT | MF_MIDI, &envy24ht_viaref_auxdrv}, */ + {0} +}; + +static struct speed_sel speed_tab[] = { + { + 8000, 0x06} + , + { + 9600, 0x03} + , + { + 11025, 0x0a} + , + { + 12000, 0x02} + , + { + 16000, 0x05} + , + { + 22050, 0x09} + , + { + 24000, 0x01} + , + { + 32000, 0x04} + , + { + 44100, 0x08} + , + { + 48000, 0x00} + , + { + 64000, 0x0f} + , + { + 88200, 0x0b} + , + { + 96000, 0x07} + , + { + 176400, 0x0c} + , + { + 192000, 0x0e} + , + {-1, 0x10} + , +}; + +static const envy24ht_auxdrv_t dummy_auxdrv = { NULL }; + +static int +ac97_read (void *devc_, int wAddr) +{ + envy24ht_devc *devc = devc_; + oss_native_word flags; + int n = 0, dat; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + while (n++ < 10000 && INB (devc->osdev, devc->mt_base + 0x05) & 0x30); + OUTB (devc->osdev, wAddr, devc->mt_base + 0x04); + OUTB (devc->osdev, 0x10, devc->mt_base + 0x05); /* Codec read */ + + n = 0; + while (n++ < 10000 && INB (devc->osdev, devc->mt_base + 0x05) & 0x10); + dat = INW (devc->osdev, devc->mt_base + 0x06); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dat; +} + +static int +ac97_write (void *devc_, int wAddr, int wData) +{ + envy24ht_devc *devc = devc_; + oss_native_word flags; + int n = 0; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + while (n++ < 10000 && INB (devc->osdev, devc->mt_base + 0x05) & 0x30); + + OUTB (devc->osdev, wAddr, devc->mt_base + 0x04); + OUTW (devc->osdev, wData, devc->mt_base + 0x06); + OUTB (devc->osdev, 0x20, devc->mt_base + 0x05); /* Codec write */ + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + +static __inline__ int +input_avail (envy24ht_devc * devc) +{ + unsigned char status; + + status = INB (devc->osdev, devc->ccs_base + 0x0b); + return status & 0x1f; /* Number of bytes in RX queue */ +} + +static __inline__ int +output_ready (envy24ht_devc * devc) +{ + unsigned char status; + + status = INB (devc->osdev, devc->ccs_base + 0x0a); + return (31 - (status & 0x1f)) > 0; /* Number of free bytes in TX queue */ +} + +static __inline__ void +midi_cmd (envy24ht_devc * devc, unsigned char cmd) +{ + OUTB (devc->osdev, cmd, devc->ccs_base + 0x0d); +} + +static __inline__ int +midi_read (envy24ht_devc * devc) +{ + return INB (devc->osdev, devc->ccs_base + 0x0c); +} + +static __inline__ void +midi_write (envy24ht_devc * devc, unsigned char byte) +{ + OUTB (devc->osdev, byte, devc->ccs_base + 0x0c); +} + +static void reset_midi (envy24ht_devc * devc); +static void enter_uart_mode (envy24ht_devc * devc); + +static void +midi_input_loop (envy24ht_devc * devc) +{ + int n = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + while (input_avail (devc) && n++ < 33) + { + unsigned char c = midi_read (devc); + + devc->input_byte = c; + if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, c); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +midiintr (envy24ht_devc * devc) +{ + int status; + + status = INB (devc->osdev, devc->ccs_base + 0x02); + if (status & 0x80) + midi_input_loop (devc); + if ((status & 0x20)) + { + OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x01) | 0x20, + devc->ccs_base + 0x01); + +#if 0 + if (devc->midi_output_intr) + devc->midi_output_intr (devc->midi_dev); +#endif + } +} + +/*ARGSUSED*/ +static int +midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, oss_midi_outputintr_t outputintr) +{ + envy24ht_devc *devc = (envy24ht_devc *) midi_devs[dev]->devc; + int n = 0, tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (devc->midi_opened & mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + devc->midi_opened |= mode; + + if (mode & OPEN_READ) + { + while (n++ < 33 && input_avail (devc)) + midi_read (devc); + + devc->midi_input_intr = inputbyte; + devc->midi_output_intr = outputintr; + } + enter_uart_mode (devc); + tmp = INB (devc->osdev, devc->ccs_base + 0x01); + if (mode & OPEN_READ) + tmp &= ~0x80; + OUTB (devc->osdev, tmp, devc->ccs_base + 0x01); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +midi_close (int dev, int mode) +{ + envy24ht_devc *devc = (envy24ht_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + reset_midi (devc); + enter_uart_mode (devc); + reset_midi (devc); + OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x01) | 0xa0, + devc->ccs_base + 0x01); + devc->midi_opened &= ~mode; + devc->midi_input_intr = NULL; + devc->midi_output_intr = NULL; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +midi_out (int dev, unsigned char midi_byte) +{ + envy24ht_devc *devc = (envy24ht_devc *) midi_devs[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (!output_ready (devc)) + { + OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x01) & ~0x20, + devc->ccs_base + 0x01); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + midi_write (devc, midi_byte); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 1; +} + +/*ARGSUSED*/ +static int +midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t envy24ht_midi_driver = { + midi_open, + midi_close, + midi_ioctl, + midi_out +}; + +static void +enter_uart_mode (envy24ht_devc * devc) +{ + devc->input_byte = 0; + midi_cmd (devc, 1); +} + +void +attach_midi (envy24ht_devc * devc) +{ + char name[128]; + enter_uart_mode (devc); + + sprintf (name, "%s input", devc->model_data->product); + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "ENVY24HT", name, &envy24ht_midi_driver, sizeof (midi_driver_t), + MFLAG_INPUT, devc, devc->osdev); + sprintf (name, "%s output", devc->model_data->product); + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "ENVY24HT", name, &envy24ht_midi_driver, sizeof (midi_driver_t), + MFLAG_OUTPUT, devc, devc->osdev); + devc->midi_opened = 0; + devc->midi_attached = 1; +} + +static void +reset_midi (envy24ht_devc * devc) +{ + /* + * Send the RESET command. Try again if no success at the first time. + */ + + midi_cmd (devc, 0); +} + +void +unload_midi (envy24ht_devc * devc) +{ + if (devc->midi_attached) + reset_midi (devc); + devc->midi_attached = 0; +} + +static int +envy24htintr (oss_device_t * osdev) +{ + envy24ht_devc *devc = osdev->devc; + int port, status, mt_status, serviced = 0; + + status = INB (devc->osdev, devc->ccs_base + 0x02); + if (status != 0) + serviced = 1; + + if (status & 0xa0) + midiintr (devc); + +/* + * Handle audio interrupts + */ + mt_status = INB (devc->osdev, devc->mt_base + 0x00); + + if (mt_status & 0x08) /* FIFO underrun/overrun */ + { + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x1A), + devc->mt_base + 0x1A); + serviced = 1; + } + + if ((status & 0x10) || mt_status != 0) + { + + for (port = 0; port < devc->nr_outdevs; port++) + { + envy24ht_portc *portc = &devc->play_portc[port]; + + if (mt_status & portc->mask) + { + oss_audio_outputintr (portc->dev, 1); + } + } + + for (port = 0; port < devc->nr_indevs; port++) + { + envy24ht_portc *portc = &devc->rec_portc[port]; + + if (mt_status & portc->mask) + { + oss_audio_inputintr (portc->dev, 0); + } + } + } + OUTB (devc->osdev, mt_status, devc->mt_base + 0x00); + OUTB (devc->osdev, status, devc->ccs_base + 0x02); + + return serviced; +} + +/*ARGSUSED*/ +static int +envy24ht_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static mixer_driver_t envy24ht_mixer_driver = { + envy24ht_mixer_ioctl +}; + +static int +envy24ht_set_route (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + unsigned int tmp; + oss_native_word flags; + + if (ctrl < 0 || ctrl > 8) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + tmp = INL (devc->osdev, devc->mt_base + 0x2c); + + switch (ctrl) + { + case 0: + tmp >>= 8; + break; + case 2: + tmp >>= 11; + break; + case 4: + tmp >>= 14; + break; + case 6: + tmp >>= 17; + break; + } + + tmp = (tmp & 0x03) >> 1; + + if (tmp == 3) + return 2; + return tmp; + } + else if (cmd == SNDCTL_MIX_WRITE) + { + int left_shift = 0, right_shift = 0; + + static const unsigned char cnv_tab[3] = { 0x00, 0x02, 0x06 }; + if (value < 0 || value > 2) + return OSS_EINVAL; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + tmp = INL (devc->osdev, devc->mt_base + 0x2c); + + switch (ctrl) + { + case 0: + left_shift = 8; + right_shift = 20; + break; + case 2: + left_shift = 11; + right_shift = 23; + break; + case 4: + left_shift = 14; + right_shift = 26; + break; + case 6: + left_shift = 17; + right_shift = 29; + break; + case 8: + left_shift = 0; + right_shift = 3; + break; + } + + tmp &= ~(0x7 << left_shift); + tmp &= ~(0x7 << right_shift); + tmp |= cnv_tab[value] << left_shift; + if (ctrl != 8) + tmp |= (cnv_tab[value] + 1) << right_shift; + else + tmp |= cnv_tab[value] << right_shift; + + OUTL (devc->osdev, tmp, devc->mt_base + 0x2c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return value; + } + return OSS_EINVAL; +} + +static int +read_peak (envy24ht_devc * devc, int ch) +{ + int tmp; + + if (ch >= 22) + return 0; + + OUTB (devc->osdev, ch, devc->mt_base + 0x3e); + tmp = INB (devc->osdev, devc->mt_base + 0x3f); + + return tmp; +} + +/*ARGSUSED*/ +static int +envy24ht_get_peak (int dev, int ctrl, unsigned int cmd, int value) +{ + static const unsigned char peak_cnv[256] = { + 0, 18, 29, 36, 42, 47, 51, 54, 57, 60, 62, 65, 67, 69, 71, 72, + 74, 75, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, + 91, 92, 93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, + 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, + 108, + 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, + 114, + 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, + 119, + 119, 119, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, + 123, + 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, + 126, + 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, + 130, + 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, + 132, + 132, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 135, + 135, + 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, + 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, + 141, + 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, + 143, + 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, + }; + + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + + int i, orign, n = -1, left = 0, right = 0; + + for (i = 0; i < 12 && n == -1; i++) + if (ctrl & (1 << i)) + n = i; + + if (n == -1) + return OSS_EINVAL; + + orign = n; + if (ctrl & 0x80000000) + n += 10; /* Recording stream */ + + if (cmd == SNDCTL_MIX_READ) + { + left = read_peak (devc, n); + if (ctrl & (1 << (orign + 1))) /* Stereo mode? */ + right = read_peak (devc, n + 1); + else + right = left; + + left = peak_cnv[left]; + right = peak_cnv[right]; + return left | (right << 8); + } + + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +create_peak_mixer (int dev, envy24ht_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, err, num, skip; + int nc = devc->nr_play_channels; + char tmp[64]; + + if ((group = mixer_ext_create_group (dev, 0, "ENVY24_PEAK")) < 0) + return group; + + skip = 2; + + for (i = 0; i < nc; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIFOUT"); + else + sprintf (tmp, devc->channel_names[i / 2], i + 1, i + 2); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24ht_get_peak, + MIXT_STEREOPEAK, + tmp, 144, + MIXF_READABLE | MIXF_DECIBEL)) < + 0) + return err; + } + } + + mask = devc->inportmask; + for (i = 0; i < devc->nr_rec_channels; i += skip) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + num |= 0x80000000; /* Input flag */ + + { + if (i == 8) + strcpy (tmp, "ENVY24_SPDIFIN"); + else + strcpy (tmp, "ENVY24_IN"); + + num |= 1 << (i + 1); + if ((err = mixer_ext_create_control (dev, group, + num, envy24ht_get_peak, + MIXT_STEREOPEAK, + tmp, 144, + MIXF_READABLE | MIXF_DECIBEL)) < + 0) + return err; + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +create_rout_mixer (int dev, envy24ht_devc * devc, int root) +{ + int i, mask = devc->outportmask, group, ret, num; + char *name; + + if ((group = + mixer_ext_create_group_flags (dev, 0, "ENVY24_ROUTE", MIXF_FLAT)) < 0) + return group; + + for (i = 0; i < 8; i += 2) + { + + num = 1 << i; + if (!(mask & num)) + continue; /* Not present */ + + name = devc->channel_names[i / 2]; + + if ((ret = mixer_ext_create_control (dev, group, + i, + envy24ht_set_route, + MIXT_ENUM, name, 3, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return ret; + mixer_ext_set_strings (dev, ret, "DMA ANALOGIN DIGITALIN", 0); + } + + if (devc->model_data == NULL) + { + cmn_err (CE_CONT, "Internal error: No model data\n"); + return 0; + } + + mask = devc->inportmask; + + if (devc->model_data->flags & MF_SPDIFOUT) + { + if ((ret = mixer_ext_create_control (dev, group, + 8, envy24ht_set_route, + MIXT_ENUM, + "ENVY24_SPDIFOUT", 3, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return ret; + } + + return 0; +} + +/* + * S/PDIF lowlevel driver + */ +/*ARGSUSED*/ +static int +default_reprogram_device (void *_devc, void *_portc, + oss_digital_control * ctl, unsigned int mask) +{ + unsigned char c; + unsigned short cbits = 0; + envy24ht_devc *devc = _devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + cbits |= (ctl->rate_bits & 0x0f) << 12; /* Sample rate */ + + if (ctl->out_vbit == VBIT_ON) + cbits |= 0x8000; /* Turn on the V bit */ + + cbits |= ctl->cbitout[0] & 0x07; /* Consumer/pro, audio/data, copyright */ + cbits |= (!!(ctl->cbitout[1] & 0x80)) << 11; /* Generation level */ + cbits |= (ctl->cbitout[1] & 0x7f) << 4; /* Category code */ + cbits |= (ctl->emphasis_type & 1) << 3; /* Pre-emphasis */ + + if (cbits != INW (devc->osdev, devc->mt_base + 0x3c)) + { + c = INB (devc->osdev, devc->ccs_base + 0x07); + OUTB (devc->osdev, c & ~0x80, devc->ccs_base + 0x07); /* Disable S/PDIF transmitter */ + OUTW (devc->osdev, cbits, devc->mt_base + 0x3c); + OUTB (devc->osdev, c | 0x80, devc->ccs_base + 0x07); /* (Re)enable S/PDIF transmitter */ + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +spdif_driver_t default_spdif_driver = { +/* reprogram_device: */ default_reprogram_device, +}; + + +static void +setup_sample_rate (envy24ht_devc * devc) +{ + unsigned char bits; + int change = 0; + + devc->speedbits = bits = speed_tab[devc->pending_speed_sel].speedbits; + if (devc->speed != speed_tab[devc->pending_speed_sel].speed) + change = 1; + devc->speed = devc->pending_speed = + speed_tab[devc->pending_speed_sel].speed; + mixer_devs[devc->mixer_dev]->modify_counter++; + + if (change) + { + oss_spdif_setrate (&devc->spdc, devc->speed); + + if (devc->model_data->svid == SSID_JULIA) + goto JULIA; + + if (devc->syncsource != 0) /* External sync */ + bits |= 0x10; + + if (devc->speed > 120000) + { + OUTB (devc->osdev, 0x08, devc->mt_base + 0x02); /* 128x I2S setup */ + } + else + { + OUTB (devc->osdev, 0x00, devc->mt_base + 0x02); /* 256x I2S setup */ + } + + OUTB (devc->osdev, bits & 0x0f, devc->mt_base + 0x01); /* Sampling rate */ +JULIA: + if (devc->auxdrv->set_rate) + devc->auxdrv->set_rate (devc); + } +} + +static int +envy24ht_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + oss_native_word flags; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 1: + return devc->pending_speed_sel; + break; + + case 2: + return devc->syncsource; + break; + + case 3: + return devc->use_src; + break; + + case 5: + return devc->ratelock; + break; + + case 6: + return devc->speed; + break; + + case 7: + return 1; + + default: + return OSS_EIO; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 1: + if (value < 0 || value > devc->max_ratesel) + return OSS_EIO; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->configured_rate_sel != value) + { + devc->configured_rate_sel = value; + if (devc->open_count < 1) + { + devc->pending_speed_sel = devc->configured_rate_sel; + setup_sample_rate (devc); + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->configured_rate_sel; + break; + + case 2: + if (value < 0 || value > 2) + return OSS_EIO; + devc->syncsource = value; + if (devc->model_data->svid == SSID_JULIA) + devc->auxdrv->private1 (devc, value); + return devc->syncsource; + break; + + case 3: + devc->use_src = !!value; + return devc->use_src; + break; + + case 5: + return devc->ratelock = !!value; + break; + + case 6: + return devc->speed; + break; + + case 7: + return 1; + break; + + default: + return OSS_EIO; + } + + return OSS_EINVAL; +} + +static int +envy24ht_mix_init (int dev) +{ + envy24ht_devc *devc = mixer_devs[dev]->hw_devc; + int group, err, n; + + if ((group = + mixer_ext_create_group_flags (dev, 0, "ENVY24", MIXF_FLAT)) < 0) + return group; + + if ((err = create_peak_mixer (dev, devc, group)) < 0) + return err; + + if ((err = create_rout_mixer (dev, devc, group)) < 0) + return err; + + n = devc->max_ratesel + 1; + if ((err = mixer_ext_create_control (dev, group, + 1, envy24ht_set_control, + MIXT_ENUM, + "ENVY24_RATE", n, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + mixer_ext_set_strings (dev, err, + "8000 9600 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000 176400 192000", 0); + + if ((err = mixer_ext_create_control (dev, group, + 2, envy24ht_set_control, + MIXT_ENUM, + "ENVY24_SYNC", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 3, envy24ht_set_control, + MIXT_ONOFF, + "ENVY24_SRC", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 5, envy24ht_set_control, + MIXT_ONOFF, + "ENVY24_RATELOCK", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, + 6, envy24ht_set_control, + MIXT_VALUE, + "ENVY24_ACTRATE", 192000, + MIXF_READABLE)) < 0) + return err; + + if (devc->auxdrv->mixer_init) + if ((err = devc->auxdrv->mixer_init (devc, dev, 0)) < 0) + return err; + + if ((err = oss_spdif_mix_init (&devc->spdc)) < 0) + return err; + + return 0; +} + +static int +eeprom_read (envy24ht_devc * devc, int pos) +{ + int i, status; + + for (i = 0; i < 0x10000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + OUTB (devc->osdev, pos, devc->ccs_base + 0x11); /* Offset */ + OUTB (devc->osdev, 0xa0, devc->ccs_base + 0x10); /* EEPROM read */ + + for (i = 0; i < 0x10000; i++) + { + status = INB (devc->osdev, devc->ccs_base + 0x13); + if (!(status & 1)) + break; + + } + + oss_udelay (1); + return INB (devc->osdev, devc->ccs_base + 0x12); +} + +static void +envy24pt_init (envy24ht_devc * devc) +{ + int gpio; + + gpio = INW (devc->osdev, devc->ccs_base + 0x14); + gpio |= INB (devc->osdev, devc->ccs_base + 0x1e) << 16; + +#if 0 +#define GPBIT(nn) !!(1<<nn) + cmn_err (CE_CONT, "GPIO=%06x\n", gpio); + cmn_err (CE_CONT, "With SPDIF_IN 'optical' connector: %d\n", GPBIT (1)); + cmn_err (CE_CONT, "With SPDIF_IN 'coaxial' connector: %d\n", GPBIT (2)); + + cmn_err (CE_CONT, "AC97 with stereo DAC for 7.1: %d\n", !GPBIT (8)); + cmn_err (CE_CONT, "Extra ADC/DAC connected to S/PDIF pins: %d\n", + GPBIT (9)); + cmn_err (CE_CONT, "S/PDIF connected to RDMA1: %d\n", !GPBIT (10)); + cmn_err (CE_CONT, "Smart 5.1 function supported: %d\n", GPBIT (11)); + cmn_err (CE_CONT, "De-POP function supported: %d\n", !GPBIT (12)); + cmn_err (CE_CONT, "PDMA4 DAC: 0=cs4321 1=WM8728: %d\n", GPBIT (13)); +#endif + + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x04); /* System configuration */ + OUTB (devc->osdev, 0x02, devc->ccs_base + 0x05); /* AC-link configuration */ + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x06); /* I2S configuration */ + OUTB (devc->osdev, 0x83, devc->ccs_base + 0x07); /* S/PDIF configuration */ + + /* TODO: GPIO initialization */ +} + +static void +julia_eeprom_init (envy24ht_devc * devc) +{ + OUTB (devc->osdev, 0x39, devc->ccs_base + 0x04); /* System configuration */ + OUTB (devc->osdev, 0x80, devc->ccs_base + 0x05); /* AC-link configuration */ + OUTB (devc->osdev, 0x78, devc->ccs_base + 0x06); /* I2S configuration */ + OUTB (devc->osdev, 0xc3, devc->ccs_base + 0x07); /* S/PDIF configuration */ + + OUTW (devc->osdev, 0xffff, devc->ccs_base + 0x18); /* GPIO direction */ + OUTW (devc->osdev, 0x0000, devc->ccs_base + 0x16); /* GPIO write mask */ + OUTW (devc->osdev, 0x801A, devc->ccs_base + 0x14); /* Initital bit state */ +} + +static int +init_eeprom_v2 (envy24ht_devc * devc) +{ + unsigned char *eeprom = (unsigned char *) &devc->eeprom; + + OUTB (devc->osdev, eeprom[6], devc->ccs_base + 0x04); + OUTB (devc->osdev, eeprom[7], devc->ccs_base + 0x05); + OUTB (devc->osdev, eeprom[8], devc->ccs_base + 0x06); + OUTB (devc->osdev, eeprom[9], devc->ccs_base + 0x07); + + OUTB (devc->osdev, eeprom[10], devc->ccs_base + 0x18); + OUTB (devc->osdev, eeprom[11], devc->ccs_base + 0x19); + OUTB (devc->osdev, eeprom[12], devc->ccs_base + 0x1a); + + OUTB (devc->osdev, eeprom[13], devc->ccs_base + 0x16); + OUTB (devc->osdev, eeprom[14], devc->ccs_base + 0x17); + OUTB (devc->osdev, eeprom[15], devc->ccs_base + 0x1f); + + OUTB (devc->osdev, eeprom[16], devc->ccs_base + 0x14); + OUTB (devc->osdev, eeprom[17], devc->ccs_base + 0x15); + OUTB (devc->osdev, eeprom[18], devc->ccs_base + 0x1e); + return 1; +} + +static int +load_eeprom (envy24ht_devc * devc) +{ + int status, i, check; + unsigned char *eeprom = (unsigned char *) &devc->eeprom, c; + static const char resolutions[4] = { 16, 18, 20, 24 }; + + c = 0; + + status = INB (devc->osdev, devc->ccs_base + 0x13); + + if (!(status & 0x80)) + return 0; /* No EEPROM */ + + devc->eeprom.bSize = sizeof (devc->eeprom); /* Guess the size */ + + for (i = 0; i < devc->eeprom.bSize; i++) + { + eeprom[i] = eeprom_read (devc, i); + eeprom[i] = eeprom_read (devc, i); + + if (devc->eeprom.bSize > sizeof (devc->eeprom)) + devc->eeprom.bSize = sizeof (devc->eeprom); + } +#if 1 + DDB (cmn_err (CE_CONT, "EEPROM=")); + for (i = 0; i < devc->eeprom.bSize; i++) + DDB (cmn_err (CE_CONT, "0x%02x, ", eeprom[i])); + DDB (cmn_err (CE_CONT, "\n")); +#endif + + check = 0; + for (i = 0; i < 4; i++) + { + check <<= 8; + check |= eeprom[i]; + } + + if (check != devc->model_data->svid) + cmn_err (CE_CONT, + "Envy24 WARNING: Possible EEPROM read error %08x != %08x\n", + check, devc->model_data->svid); + + DDB (cmn_err (CE_CONT, "EEPROM version %d\n", devc->eeprom.bVersion)); + + if (devc->eeprom.bVersion == 2) + { + return init_eeprom_v2 (devc); + } + + /* Init the controller registers based on the EEPROM data */ + + OUTB (devc->osdev, devc->eeprom.bCodecConfig, devc->ccs_base + 0x04); + OUTB (devc->osdev, devc->eeprom.bACLinkConfig, devc->ccs_base + 0x05); + OUTB (devc->osdev, devc->eeprom.bI2SID, devc->ccs_base + 0x06); + OUTB (devc->osdev, devc->eeprom.bSpdifConfig, devc->ccs_base + 0x07); + + /* GPIO ports */ + + OUTB (devc->osdev, devc->eeprom.bGPIODirection2, devc->ccs_base + 0x18); + OUTB (devc->osdev, devc->eeprom.bGPIODirection1, devc->ccs_base + 0x19); + OUTB (devc->osdev, devc->eeprom.bGPIODirection0, devc->ccs_base + 0x1a); + + OUTB (devc->osdev, devc->eeprom.bGPIOInitMask2, devc->ccs_base + 0x14); + OUTB (devc->osdev, devc->eeprom.bGPIOInitMask1, devc->ccs_base + 0x15); + OUTB (devc->osdev, devc->eeprom.bGPIOInitMask0, devc->ccs_base + 0x1f); + + OUTB (devc->osdev, devc->eeprom.bGPIOInitState2, devc->ccs_base + 0x14); + OUTB (devc->osdev, devc->eeprom.bGPIOInitState1, devc->ccs_base + 0x15); + OUTB (devc->osdev, devc->eeprom.bGPIOInitState0, devc->ccs_base + 0x1e); + +#if 1 + DDB (cmn_err (CE_CONT, "GPIO=%02x%02x%02x (%02x%02x%02x, %02x%02x%02x)\n", + devc->eeprom.bGPIOInitState2, + devc->eeprom.bGPIOInitState1, + devc->eeprom.bGPIOInitState0, + devc->eeprom.bGPIODirection2, + devc->eeprom.bGPIODirection1, + devc->eeprom.bGPIODirection0, + devc->eeprom.bGPIOInitMask2, + devc->eeprom.bGPIOInitMask1, devc->eeprom.bGPIOInitMask0)); + + c = devc->eeprom.bCodecConfig; + switch ((c >> 6) % 0x03) + { + case 0: + DDB (cmn_err (CE_CONT, "24.576MHz crystal\n")); + break; + case 1: + DDB (cmn_err (CE_CONT, "49.152MHz crystal\n")); + break; + default: + DDB (cmn_err (CE_CONT, "Unknown crystal frequency\n")); + } + + if (c & 0x20) + { + DDB (cmn_err (CE_CONT, "Has MPU401 UART\n")); + } + else + { + DDB (cmn_err (CE_CONT, "No MPU401 UART\n")); + } + DDB (cmn_err + (CE_CONT, "%d stereo ADC pairs connected\n", ((c >> 2) & 0x03) + 1)); + DDB (cmn_err (CE_CONT, "%d stereo DAC pairs connected\n", (c & 0x03) + 1)); + + c = devc->eeprom.bACLinkConfig; + DDB (cmn_err + (CE_CONT, "Converter type: %s\n", (c & 0x80) ? "I2S" : "AC97")); + if (!(c & 0x80)) + { + if (!(devc->model_data->flags & MF_NOAC97)) + devc->codec_type = CODEC_AC97; + + DDB (cmn_err (CE_NOTE, + "AC link connection mode type: %s\n", + (c & 0x02) ? "packed" : "split")); + } + else + { + c = devc->eeprom.bI2SID; + + DDB (cmn_err (CE_CONT, "I2C codec has volume control/mute: %s\n", + (c % 0x80) ? "YES" : "NO")); + DDB (cmn_err (CE_CONT, "I2C codec has 96 KHz S/R support: %s\n", + (c % 0x40) ? "YES" : "NO")); + DDB (cmn_err (CE_CONT, "I2C codec has 192 KHz S/R support: %s\n", + (c % 0x08) ? "YES" : "NO")); + + DDB (cmn_err (CE_CONT, + "Converter resolution %d bits\n", + resolutions[(c >> 4) & 0x03])); + } + + c = INB (devc->osdev, devc->ccs_base + 0x07); + DDB (cmn_err (CE_CONT, + "Internal S/PDIF out implemented: %s\n", + (c & 0x40) ? "YES" : "NO")); + DDB (cmn_err + (CE_CONT, "Internal S/PDIF out enabled: %s\n", + (c & 0x80) ? "YES" : "NO")); + DDB (cmn_err + (CE_CONT, "External S/PDIF out implemented: %s\n", + (c & 0x01) ? "YES" : "NO")); + DDB (cmn_err + (CE_CONT, "S/PDIF input present: %s\n", (c & 0x02) ? "YES" : "NO")); + DDB (cmn_err (CE_CONT, "S/PDIF chip IDs %x\n", (c >> 2) & 0x0f)); +#endif + + return 1; +} + +/*ARGSUSED*/ +static void +dump_regs (envy24ht_devc * devc, char *lbl) +{ +#if 0 + int i; + + cmn_err (CE_CONT, "\nDump registers: %s\n", lbl); + + for (i = 0; i < 0x20; i += 4) + { + if (!(i % (8 * 4))) + cmn_err (CE_CONT, "\nCCS%02x: ", i); + cmn_err (CE_CONT, "%08x ", INL (devc->osdev, devc->ccs_base + i)); + } + cmn_err (CE_CONT, "\n"); + + for (i = 0; i < 0x80; i += 4) + { + if (!(i % (8 * 4))) + cmn_err (CE_CONT, "\nMT%02x: ", i); + cmn_err (CE_CONT, "%08x ", INL (devc->osdev, devc->mt_base + i)); + } + cmn_err (CE_CONT, "\n"); +#endif +} + +static int +verify_rate (envy24ht_devc * devc, int arg) +{ + if (devc->codec_type == CODEC_AC97 && arg > 48000) + arg = 48000; + if (arg > 96000 && !(devc->model_data->flags & MF_192K)) + arg = 96000; + + return arg; +} + +static int +envy24ht_set_rate (int dev, int arg) +{ + envy24ht_devc *devc = audio_engines[dev]->devc; + envy24ht_portc *portc = audio_engines[dev]->portc; + int i, ix, diff, bestdiff; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (arg == 0) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->pending_speed; + } + + arg = verify_rate (devc, arg); +/* + * Don't permit changing the sampling rate if we have multiple clients. + */ + if (devc->open_count != 1 || devc->ratelock) + { + DDB (cmn_err (CE_CONT, "Can't set speed: open_count %d, ratelock %d\n", + devc->open_count, devc->ratelock)); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + if (arg != devc->pending_speed) + { + audio_engines[dev]->fixed_rate = devc->speed; + audio_engines[dev]->min_rate = devc->speed; + audio_engines[dev]->max_rate = devc->speed; + audio_engines[dev]->flags |= ADEV_FIXEDRATE; + } + else + { + audio_engines[dev]->min_rate = 8000; + audio_engines[dev]->max_rate = 192000; + audio_engines[dev]->flags &= ~ADEV_FIXEDRATE; + } + return devc->pending_speed; + } + + if (portc->dev_flags & DF_SPDIF) + { + /* Allow only supported S/PDIF rates */ + if (arg < 32000) + arg = 32000; + if (arg > 96000) + arg = 96000; + } + + ix = 9; + bestdiff = 1000000; + i = 0; + audio_engines[dev]->flags &= ~ADEV_FIXEDRATE; + + while (speed_tab[i].speed != -1) + { + diff = speed_tab[i].speed - arg; + if (diff < 0) + diff = -diff; + if (diff < bestdiff) + { + ix = i; + bestdiff = diff; + } + i++; + } + + devc->pending_speed = speed_tab[ix].speed; + devc->pending_speed_sel = ix; + /*cmn_err(CE_CONT, "Requested sampling rate %d, got %d\n", arg, devc->pending_speed); */ + + //setup_sample_rate (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return devc->pending_speed; +} + +static short +envy24ht_set_channels (int dev, short arg) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + if (arg == 0) + return portc->channels; + + if (portc->dev_flags & DF_MULTICH) + { + int n = 2, ch, i, mask; + + if (arg < 2) + arg = 2; + + arg = ((arg + 1) / 2) * 2; /* Round to even number of channels */ + + if (arg > devc->model_data->nr_outs) + arg = devc->model_data->nr_outs; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + devc->busy_play_channels &= ~portc->used_chmask; + + for (ch = 2; ch <= arg; ch += 2) + { + mask = 0; + + for (i = 0; i < ch; i++) + mask |= (1 << i); + + if (devc->busy_play_channels & mask) + break; + n = ch; + } + + portc->channels = n; + portc->used_chmask = 0; + for (i = 0; i < n; i++) + portc->used_chmask |= (1 << i); + + devc->busy_play_channels |= portc->used_chmask; + /* MT19: Channel allocation */ + OUTB (devc->osdev, 4 - n / 2, devc->mt_base + 0x19); + /* cmn_err(CE_CONT, "%d channels: MT19=%02x\n", n, INB(devc->osdev, devc->mt_base+0x19)); */ + + if (portc->channels == 6) + { + /* The fragment size must be a multiple of 6 */ + audio_engines[dev]->min_block = 4 * 288; + audio_engines[dev]->max_block = 4 * 288; + + } + else + { + audio_engines[dev]->min_block = 0; + audio_engines[dev]->max_block = 0; + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->channels; + } + + return portc->channels = 2; +} + +/*ARGSUSED*/ +static int +ac3_write (adev_t * adev, + dmap_t * dmap, + void *frombuf, void *tobuf, int maxspace, int *fromlen, int *tolen) +{ +/* + * This routine takes AC3 input 16 bits at time and packs them to + * 32 bit words. + */ + int i, l; + unsigned short *ip; + unsigned int *op; + + l = *fromlen * 2; + if (l > maxspace) + { + l = maxspace; + } + + *tolen = l; + *fromlen = l / 2; + l /= 4; + + ip = frombuf; + op = tobuf; + + for (i = 0; i < l; i++) + { + *op++ = (*ip++) << 16; + } + + return 0; +} + +static unsigned int +envy24ht_set_format (int dev, unsigned int arg) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->fmt; + + if (arg == AFMT_AC3 && (portc->dev_flags & DF_AC3)) + { + audio_engines[dev]->dmap_out->device_write = ac3_write; + return portc->fmt = AFMT_AC3; + } + audio_engines[dev]->dmap_out->device_write = NULL; + return portc->fmt = SUPPORTED_FORMAT; +} + +static int +envy24ht_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc = audio_engines[dev]->devc; + + switch (cmd) + { + case SNDCTL_DSP_GET_CHNORDER: + *(oss_uint64_t *) arg = CHNORDER_NORMAL; + return 0; + } + + if (portc->dev_flags & DF_SPDIF) + { + int ret; + ret = oss_spdif_ioctl (&devc->spdc, portc->open_mode, cmd, arg); + if (ret != SPDIF_NOIOCTL) + return ret; + } + + if (devc->auxdrv->audio_ioctl) + return devc->auxdrv->audio_ioctl (devc, portc, cmd, arg); + return OSS_EINVAL; +} + +static void envy24ht_trigger (int dev, int state); + +static void +envy24ht_reset (int dev) +{ + envy24ht_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +envy24ht_open_input (int dev, int mode, int open_flags) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc = audio_engines[dev]->devc; + adev_p adev = audio_engines[dev]; + oss_native_word flags; + + if (mode & OPEN_WRITE) + { + cmn_err (CE_CONT, "Playback is not possible with %s\n", adev->devnode); + return OSS_ENOTSUP; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode || (devc->busy_rec_channels & portc->chmask)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + portc->open_mode = mode; + devc->open_count++; + if (devc->open_count == 1) + { + devc->pending_speed_sel = devc->configured_rate_sel; + } + + if (portc->dev_flags & DF_SPDIF) + oss_spdif_open (&devc->spdc, mode); + + portc->used_chmask = portc->chmask; + devc->busy_rec_channels |= portc->chmask; + + if (!devc->use_src) + adev->flags |= ADEV_NOSRC; + else + adev->flags &= ~ADEV_NOSRC; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +envy24ht_open_output (int dev, int mode, int open_flags) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + adev_p adev = audio_engines[dev]; + + if (mode & OPEN_READ) + { + cmn_err (CE_CONT, "Recording is not possible with %s\n", adev->devnode); + return OSS_ENOTSUP; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode || (devc->busy_play_channels & portc->chmask)) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + portc->used_chmask = portc->chmask; + devc->busy_play_channels |= portc->chmask; + audio_engines[dev]->dmap_out->device_write = NULL; + + devc->open_count++; + if (devc->open_count == 1) + { + devc->pending_speed_sel = devc->configured_rate_sel; + } + + if (portc->dev_flags & DF_SPDIF) + oss_spdif_open (&devc->spdc, mode); + + if (!devc->use_src) + adev->flags |= ADEV_NOSRC; + else + adev->flags &= ~ADEV_NOSRC; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +envy24ht_close (int dev, int mode) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_count--; + + if (portc->open_mode & OPEN_READ) + devc->busy_rec_channels &= ~portc->used_chmask; + if (portc->open_mode & OPEN_WRITE) + devc->busy_play_channels &= ~portc->used_chmask; + portc->open_mode = 0; + + if (portc->dev_flags & DF_MULTICH) + { + OUTB (devc->osdev, 0x03, devc->mt_base + 0x19); /* Channel allocation */ + portc->chmask = 0x003; /* Just the front channels */ + } + + if (portc->dev_flags & DF_SPDIF) + oss_spdif_close (&devc->spdc, mode); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +envy24ht_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +envy24ht_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +static void +envy24ht_trigger (int dev, int state) +{ + envy24ht_devc *devc = audio_engines[dev]->devc; + envy24ht_portc *portc = audio_engines[dev]->portc; + unsigned char enable, intrmask; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + enable = INB (devc->osdev, devc->mt_base + 0x18); + intrmask = INB (devc->osdev, devc->mt_base + 0x03); + + if (portc->state_bits == state) /* No change */ + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return; + } + portc->state_bits = state; + + if (portc->open_mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + { + enable |= portc->mask; + intrmask &= ~portc->mask; + } + else + { + enable &= ~portc->mask; + intrmask |= portc->mask; + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + enable |= portc->mask; + intrmask &= ~portc->mask; + } + else + { + enable &= ~portc->mask; + intrmask |= portc->mask; + } + } + OUTB (devc->osdev, enable, devc->mt_base + 0x18); + OUTB (devc->osdev, intrmask, devc->mt_base + 0x03); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (state) + dump_regs (devc, "trigger"); +} + +/*ARGSUSED*/ +static int +envy24ht_prepare_for_input (int dev, int bsize, int bcount) +{ + envy24ht_devc *devc = audio_engines[dev]->devc; + envy24ht_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_in; + int buffsize, fragsize; + oss_native_word flags; + + if (audio_engines[dev]->flags & ADEV_NOINPUT) + return OSS_EACCES; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + setup_sample_rate (devc); + buffsize = dmap->bytes_in_use / 4 - 1; + fragsize = dmap->fragment_size / 4 - 1; + + OUTL (devc->osdev, dmap->dmabuf_phys, portc->base + 0x00); + OUTW (devc->osdev, buffsize, portc->base + 0x04); + OUTW (devc->osdev, fragsize, portc->base + 0x06); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +envy24ht_prepare_for_output (int dev, int bsize, int bcount) +{ + envy24ht_devc *devc = audio_engines[dev]->devc; + envy24ht_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + int buffsize, fragsize; + oss_native_word flags; + + if (audio_engines[dev]->flags & ADEV_NOOUTPUT) + return OSS_EACCES; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + setup_sample_rate (devc); + buffsize = dmap->bytes_in_use / 4 - 1; + fragsize = dmap->fragment_size / 4 - 1; + + if (portc->dev_flags & DF_MULTICH) + { + /* Multi ch device */ + OUTL (devc->osdev, dmap->dmabuf_phys, devc->mt_base + 0x10); + OUTL (devc->osdev, buffsize, devc->mt_base + 0x14); + OUTL (devc->osdev, fragsize, devc->mt_base + 0x1c); + } + else + { + OUTL (devc->osdev, dmap->dmabuf_phys, portc->base + 0x00); + OUTW (devc->osdev, buffsize, portc->base + 0x04); + OUTW (devc->osdev, fragsize, portc->base + 0x06); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +envy24ht_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + envy24ht_portc *portc = audio_engines[dev]->portc; + envy24ht_devc *devc; + int pos; + + devc = audio_engines[dev]->devc; + pos = (INW (devc->osdev, portc->base + 0x04) + 1) * 4; + return dmap->bytes_in_use - pos; +} + +static int +envy24ht_sync_control(int dev, int event, int mode) +{ + envy24ht_devc *devc = audio_engines[dev]->devc; + envy24ht_portc *portc = audio_engines[dev]->portc; + unsigned char enable, intrmask; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE(devc->mutex, flags); + if(event == SYNC_PREPARE) + { + devc->syncstart_mask |= portc->mask; + portc->state_bits = mode; + } + else if(event == SYNC_TRIGGER) + { + if(devc->syncstart_mask) + { + enable = INB (devc->osdev, devc->mt_base + 0x18); + intrmask = INB (devc->osdev, devc->mt_base + 0x03); + enable |= devc->syncstart_mask; + intrmask &= ~devc->syncstart_mask; + OUTB (devc->osdev, enable, devc->mt_base + 0x18); + OUTB (devc->osdev, intrmask, devc->mt_base + 0x03); + devc->syncstart_mask = 0; + } + } + MUTEX_EXIT_IRQRESTORE(devc->mutex, flags); + return 0; +} + +#if 0 +static int +envy24ht_check_output (int dev) +{ + int pos; + envy24ht_devc *devc = audio_engines[dev]->devc; + + pos = envy24ht_get_buffer_pointer (dev, audio_engines[dev]->dmap_out, 0); + + cmn_err (CE_CONT, + "Envy24ht: Output timeout on device %d (%d, %02x, %02x)\n", dev, + pos, INB (devc->osdev, devc->ccs_base + 0x02), INB (devc->osdev, + devc-> + ccs_base + + 0x00)); + return OSS_EIO; +} +#endif + +static audiodrv_t envy24ht_output_driver = { + envy24ht_open_output, + envy24ht_close, + envy24ht_output_block, + envy24ht_start_input, + envy24ht_ioctl, + envy24ht_prepare_for_input, + envy24ht_prepare_for_output, + envy24ht_reset, + NULL, + NULL, + NULL, + NULL, + envy24ht_trigger, + envy24ht_set_rate, + envy24ht_set_format, + envy24ht_set_channels, + NULL, + NULL, + NULL, /* check input */ + NULL, /* envy24ht_check_output */ + NULL, /* envy24ht_alloc_buffer */ + NULL, /* envy24ht_free_buffer */ + NULL, + NULL, + envy24ht_get_buffer_pointer, + NULL, + envy24ht_sync_control +}; + + +static audiodrv_t envy24ht_input_driver = { + envy24ht_open_input, + envy24ht_close, + envy24ht_output_block, + envy24ht_start_input, + envy24ht_ioctl, + envy24ht_prepare_for_input, + envy24ht_prepare_for_output, + envy24ht_reset, + NULL, + NULL, + NULL, + NULL, + envy24ht_trigger, + envy24ht_set_rate, + envy24ht_set_format, + envy24ht_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* envy24ht_alloc_buffer */ + NULL, /* envy24ht_free_buffer */ + NULL, + NULL, + envy24ht_get_buffer_pointer, + NULL, + envy24ht_sync_control +}; + +static const int bindings[MAX_ODEV] = { + DSP_BIND_FRONT, + DSP_BIND_CENTER_LFE, + DSP_BIND_SURR, + DSP_BIND_REAR +}; + +static int +init_play_device (envy24ht_devc * devc, int chmask, int offset, + unsigned char mask, char *name, int dev_flags, + char *port_id, char *devfile_name) +{ + int opts, dev, formats; + char tmp[80]; + envy24ht_portc *portc = NULL; + int i; + adev_p adev; + + sprintf (tmp, "%s %s out", devc->model_data->product, name); + + if (devc->nr_outdevs >= MAX_ODEV) + { + cmn_err (CE_CONT, "Envy24ht: Too many audio devices\n"); + return OSS_ENXIO; + } + + opts = ADEV_AUTOMODE | ADEV_NOINPUT; + + if (dev_flags & DF_SPDIF) + opts |= ADEV_SPECIAL; + + formats = SUPPORTED_FORMAT; + if (dev_flags & DF_AC3) + formats |= AFMT_AC3; + + if (dev_flags & DF_MULTICH) + opts |= ADEV_COLD; + else + opts |= ADEV_SPECIAL; + + if ((dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &envy24ht_output_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + return dev; + } + + if (devc->first_dev == -1) + { + devc->first_dev = dev; + audio_engines[dev]->outch_names = OUTCH_NAMES; + } + adev = audio_engines[dev]; + + portc = &devc->play_portc[devc->nr_outdevs]; + for (i = 0; speed_tab[i].speed != -1; i++) + adev->rates[adev->nrates++] = speed_tab[i].speed; + + portc->name = port_id; + audio_engines[dev]->portc = portc; + audio_engines[dev]->mixer_dev = devc->mixer_dev; + audio_engines[dev]->rate_source = devc->first_dev; + audio_engines[dev]->min_rate = 8000; + audio_engines[dev]->max_rate = 192000; + audio_engines[dev]->binding = bindings[devc->nr_outdevs]; + if (dev_flags & DF_SPDIF) + audio_engines[dev]->binding = DSP_BIND_SPDIF; + + portc->dev = dev; + portc->open_mode = 0; + portc->fmt = SUPPORTED_FORMAT; + portc->base = devc->mt_base + offset; + portc->mask = mask; + portc->dev_flags = dev_flags; + portc->chmask = chmask; + portc->state_bits = 0; + portc->direction = PCM_ENABLE_OUTPUT; + + audio_engines[dev]->min_channels = 2; + audio_engines[dev]->max_channels = 2; + + if (dev_flags & DF_SPDIF) + audio_engines[dev]->caps |= PCM_CAP_DIGITALOUT | DSP_CH_STEREO; + else + { + if (dev_flags & DF_MULTICH) + { + audio_engines[dev]->caps |= PCM_CAP_ANALOGOUT; + audio_engines[dev]->caps |= DSP_CH_STEREO; + audio_engines[dev]->min_channels = 2; + audio_engines[dev]->max_channels = devc->model_data->nr_outs; + } + else + audio_engines[dev]->caps |= PCM_CAP_ANALOGOUT | DSP_CH_STEREO; + } + devc->nr_outdevs++; + + return dev; +} + +static int +init_rec_device (envy24ht_devc * devc, int chmask, int offset, + unsigned char mask, char *name, int dev_flags, char *devfile_name) +{ + int opts, dev, formats; + adev_p adev; + int i; + envy24ht_portc *portc = NULL; + char tmp[80]; + sprintf (tmp, "%s %s in", devc->model_data->product, name); + + if (devc->nr_indevs >= MAX_IDEV) + { + cmn_err (CE_CONT, "Envy24ht: Too many audio devices\n"); + return OSS_ENXIO; + } + + opts = ADEV_AUTOMODE | ADEV_NOOUTPUT | ADEV_COLD; + + if (dev_flags & DF_SPDIF) + opts |= ADEV_SPECIAL; + + formats = SUPPORTED_FORMAT; + if (dev_flags & DF_AC3) + formats |= AFMT_AC3; + + if ((dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &envy24ht_input_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + return dev; + } + + if (devc->first_dev == -1) + devc->first_dev = dev; + portc = &devc->rec_portc[devc->nr_indevs]; + adev = audio_engines[dev]; + + for (i = 0; speed_tab[i].speed != -1; i++) + adev->rates[adev->nrates++] = speed_tab[i].speed; + + audio_engines[dev]->portc = portc; + audio_engines[dev]->mixer_dev = devc->mixer_dev; + audio_engines[dev]->rate_source = devc->first_dev; + audio_engines[dev]->min_rate = 8000; + audio_engines[dev]->max_rate = 192000; + + portc->dev = dev; + portc->name = "rec"; + portc->open_mode = 0; + portc->base = devc->mt_base + offset; + portc->mask = mask; + portc->state_bits = 0; + portc->fmt = SUPPORTED_FORMAT; + portc->dev_flags = dev_flags; + portc->chmask = chmask; + portc->direction = PCM_ENABLE_INPUT; + if (dev_flags & DF_SPDIF) + audio_engines[dev]->caps |= PCM_CAP_DIGITALIN | DSP_CH_STEREO; + else + audio_engines[dev]->caps |= PCM_CAP_ANALOGIN | DSP_CH_STEREO; + devc->nr_indevs++; + + return dev; +} + +static void +init_devices (envy24ht_devc * devc) +{ + int front_engine, rec_engine; + + OUTB (devc->osdev, 0x03, devc->mt_base + 0x19); /* Channel allocation */ + OUTB (devc->osdev, 0x00, devc->mt_base + 0x1b); /* Unpause ALL channels */ + + devc->first_dev = -1; + + front_engine=init_play_device (devc, 0x003, 0x10, 0x01, devc->channel_names[0], + DF_MULTICH, "front", ""); + + if (devc->model_data->nr_outs > 2) + init_play_device (devc, 0x00c, 0x70, 0x10, devc->channel_names[1], 0, + "C/LFE", ""); + + if (devc->model_data->nr_outs > 4) + init_play_device (devc, 0x030, 0x60, 0x20, devc->channel_names[2], 0, + "side", ""); + + if (devc->model_data->nr_outs > 6) + init_play_device (devc, 0x0c0, 0x50, 0x40, devc->channel_names[3], 0, + "rear", ""); + + if (devc->model_data->flags & MF_SPDIFOUT) + { + init_play_device (devc, 0x300, 0x40, 0x80, "digital", + DF_SPDIF | DF_AC3, "spdif", "spdout"); + } + + rec_engine = init_rec_device (devc, 0x003, 0x20, 0x02, "analog", 0, ""); + + if (devc->model_data->flags & MF_SPDIFIN) + { + init_rec_device (devc, 0x00c, 0x30, 0x04, "digital", DF_SPDIF, "spdin"); + } + +#ifdef CONFIG_OSS_VMIX + if (rec_engine < 0) + rec_engine = -1; /* Not available */ + + if (front_engine >= 0) + vmix_attach_audiodev(devc->osdev, front_engine, rec_engine, 0); +#endif +} + +static void +install_ac97_mixer (envy24ht_devc * devc) +{ + int tmp; + tmp = 0; + + DDB (cmn_err (CE_CONT, "Installing AC97 mixer\n")); + + devc->mixer_dev = + ac97_install (&devc->ac97devc, devc->model_data->product, ac97_read, + ac97_write, devc, devc->osdev); + if (devc->mixer_dev < 0) + { + cmn_err (CE_CONT, "Envy24ht: Mixer install failed\n"); + return; + } + ac97_init_ext (devc->mixer_dev, &devc->ac97devc, envy24ht_mix_init, 50); + +#if 1 + /* AD1616 specific stuff. Check this if there is some other AC97 chip */ + /* Maybe this should be moved to ac97.c in a way or another */ + + /* Turn surround dacs ON */ + tmp = ac97_read (devc, 0x2a); + tmp &= ~0x3800; + ac97_write (devc, 0x2a, tmp); + + tmp = ac97_read (devc, 0x5a); + tmp &= ~0x8000; + tmp |= 0x1800; + ac97_write (devc, 0x5a, tmp); +#endif + +#if 0 + for (tmp = 0; tmp < 0x3f; tmp += 2) + cmn_err (CE_CONT, "%02x: %04x\n", tmp, ac97_read (devc, tmp)); + for (tmp = 0x5a; tmp < 0x5d; tmp += 2) + cmn_err (CE_CONT, "%02x: %04x\n", tmp, ac97_read (devc, tmp)); + for (tmp = 0x7a; tmp < 0x7f; tmp += 2) + cmn_err (CE_CONT, "%02x: %04x\n", tmp, ac97_read (devc, tmp)); +#endif +} + +int +oss_envy24ht_attach (oss_device_t * osdev) +{ + envy24ht_devc *devc; + extern int envy24ht_model; + unsigned char pci_irq_line; + unsigned short pci_command, vendor, device; + unsigned int subvendor; + unsigned int pci_ioaddr, pci_ioaddr1; + int i, err; + + char *name = "Generic ENVY24HT"; + + DDB (cmn_err (CE_CONT, "Entered Envy24HT probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != ICENSEMBLE_VENDOR_ID || device != ICENSEMBLE_ENVY24HT_ID) + 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; + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + MUTEX_INIT (osdev, devc->low_mutex, MH_DRV + 1); + + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, 0x2c, &subvendor); + + DDB (cmn_err (CE_CONT, + "Device found at I/O %x, %x\n", pci_ioaddr & ~3, + pci_ioaddr1 & ~3)); + + devc->subvendor = subvendor; + + devc->ccs_base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr) & ~0x3; + DDB (cmn_err (CE_CONT, "CCS base %x/%lx\n", pci_ioaddr, devc->ccs_base)); + + devc->mt_base = MAP_PCI_IOADDR (devc->osdev, 1, pci_ioaddr1) & ~0x3; + DDB (cmn_err (CE_CONT, "MT base %x/%lx\n", pci_ioaddr1, devc->mt_base)); + + /* Reset the chip */ + OUTB (devc->osdev, 0x81, devc->ccs_base + 0x00); + oss_udelay (1000); + + /* Release reset */ + OUTB (devc->osdev, 0x00, devc->ccs_base + 0x00); + oss_udelay (1000); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->nr_outdevs = devc->nr_indevs = 0; + i = 0; + + if ((envy24ht_model > -1) + && (envy24ht_model < (sizeof (models) / sizeof (card_spec)) - 1)) + i = envy24ht_model; + else + while (models[i].svid != 0) + { + if (models[i].svid == subvendor) + { + name = models[i].product; + devc->model_data = &models[i]; + DDB (cmn_err (CE_CONT, "Card id '%s'\n", name)); + + break; + } + + i++; + } + + if (models[i].svid == 0) + { + cmn_err (CE_CONT, "Unknown device ID (%08x).\n", subvendor); + cmn_err (CE_CONT, "This card may not be supported (yet).\n"); + i = 0; /* Assume AC97 based Envy23PT */ + } + + oss_register_device (osdev, name); + + if (devc->model_data == NULL) + { + cmn_err (CE_CONT, "Envy24ht: This card was not recognized: %08x\n", + subvendor); + return 0; + } + + /* Disable all interrupts */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x01); + OUTB (devc->osdev, 0xff, devc->mt_base + 0x03); + + if (devc->model_data->flags & MF_ENVY24PT) + { + devc->codec_type = CODEC_AC97; + envy24pt_init (devc); + } + else if (devc->model_data->svid == SSID_JULIA) + { + julia_eeprom_init (devc); + } + else + load_eeprom (devc); + + devc->irq = pci_irq_line; + if ((err = + oss_register_interrupts (devc->osdev, 0, envy24htintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + i = 0; + devc->max_ratesel = 0; + + while (speed_tab[i].speed != -1) + { + int rate = speed_tab[i].speed; + + if (verify_rate (devc, rate) == rate) + devc->max_ratesel = i; + + i++; + } + + OUTB (devc->osdev, ~0x10, devc->ccs_base + 0x01); /* Enable audio interrupts */ + + if (devc->model_data->flags & MF_MIDI) + { + attach_midi (devc); + } + i = 0; + devc->max_ratesel = 0; + + while (speed_tab[i].speed != -1) + { + int rate = speed_tab[i].speed; + + if (verify_rate (devc, rate) == rate) + devc->max_ratesel = i; + + i++; + } + + devc->syncstart_mask = 0; + devc->speedbits = 0; + devc->speed = 0; + devc->pending_speed = 0; + devc->prev_speed = 0; + devc->pending_speed_sel = 9; + devc->configured_rate_sel = devc->pending_speed_sel; + devc->open_count = 0; + memcpy (devc->channel_names, channel_names, sizeof (channel_names)); + + devc->nr_play_channels = 10; + devc->nr_rec_channels = 10; +#define setmask(m, b) m|=(1<<(b)) + + devc->inportmask = 0; + devc->outportmask = 0; + devc->busy_play_channels = 0; + devc->busy_rec_channels = 0; + + for (i = 0; i < devc->model_data->nr_outs; i++) + setmask (devc->outportmask, i); + if (devc->model_data->flags & MF_SPDIFOUT) + { + setmask (devc->outportmask, 8); /* SPDIF */ + setmask (devc->outportmask, 9); /* SPDIF */ + } + for (i = 0; i < devc->model_data->nr_ins; i++) + setmask (devc->inportmask, i); + if (devc->model_data->flags & MF_SPDIFIN) + { + setmask (devc->inportmask, 8); /* SPDIF */ + setmask (devc->inportmask, 9); /* SPDIF */ + } + + if (devc->model_data->auxdrv == NULL) + { + devc->auxdrv = &dummy_auxdrv; + } + else + { + devc->auxdrv = devc->model_data->auxdrv; + if (devc->auxdrv->card_init) + devc->auxdrv->card_init (devc); + } + + if (devc->codec_type == CODEC_AC97) + install_ac97_mixer (devc); + else + { + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + devc->model_data-> + product, + &envy24ht_mixer_driver, + sizeof (mixer_driver_t), + devc)) >= 0) + { + int n = 50; + + mixer_devs[devc->mixer_dev]->hw_devc = devc; + mixer_ext_set_init_fn (devc->mixer_dev, envy24ht_mix_init, n); + mixer_devs[devc->mixer_dev]->priority = 1; /* Possible default mixer candidate */ + } + } + + if (devc->model_data->flags & (MF_SPDIFOUT | MF_SPDIFIN)) + { + int err; + + if ((err = oss_spdif_install (&devc->spdc, devc->osdev, + &default_spdif_driver, + sizeof (spdif_driver_t), devc, NULL, + devc->mixer_dev, SPDF_OUT, + DIG_PASSTHROUGH | DIG_EXACT | + DIG_CBITOUT_LIMITED | DIG_VBITOUT | + DIG_PRO | DIG_CONSUMER)) != 0) + { + cmn_err (CE_CONT, + "S/PDIF driver install failed. error %d\n", err); + return 0; + } + } + OUTB (devc->osdev, ~0x10, devc->ccs_base + 0x01); /* Enable audio interrupts */ + init_devices (devc); + setup_sample_rate (devc); + + + return 1; +} + +int +oss_envy24ht_detach (oss_device_t * osdev) +{ + envy24ht_devc *devc = osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + /* Disable all interrupts */ + OUTB (devc->osdev, 0xff, devc->ccs_base + 0x01); + /* disable DMA interrupt mask */ + OUTB (devc->osdev, 0xff, devc->mt_base + 0x00); + + /* Stop playback */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + oss_udelay (100); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x01, + devc->mt_base + 0x18); + + /* Stop recording */ + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + oss_udelay (100); + OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x18) & ~0x04, + devc->mt_base + 0x18); + + unload_midi (devc); + + if (devc->auxdrv->card_uninit) + devc->auxdrv->card_uninit(devc); + + oss_unregister_interrupts (devc->osdev); + + if (devc->model_data->flags & (MF_SPDIFOUT | MF_SPDIFIN)) + { + oss_spdif_uninstall (&devc->spdc); + } + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + UNMAP_PCI_IOADDR (devc->osdev, 1); + + oss_unregister_device (osdev); + return 1; +} diff --git a/kernel/drv/oss_envy24ht/oss_envy24ht.man b/kernel/drv/oss_envy24ht/oss_envy24ht.man new file mode 100644 index 0000000..f87d928 --- /dev/null +++ b/kernel/drv/oss_envy24ht/oss_envy24ht.man @@ -0,0 +1,24 @@ +NAME +oss_envy24ht - VIA Envy24HT/PT audio driver. + +DESCRIPTION +Open Sound System driver for Envy24HT, Envy24HT-S, Envy24PT based sound +cards. + +Envy24HT device characteristics: + o 8/16 bit playback/record + o mono/stereo/4ch/5.1ch/7.1ch playback + o mono/sterero recording + o 8KHz to 192Khz sample rate. + +OPTIONS + o envy24ht_model = -1|0|1 + Select the Model number if the card isn't autodetected + Values: 0 = Envy24ht 1=Envy24PT/HT-s compatible -1=Autodetect Default: -1 + +FILES +CONFIGFILEPATH/oss_envy24ht.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_fmedia/.devices b/kernel/drv/oss_fmedia/.devices new file mode 100644 index 0000000..bccf58d --- /dev/null +++ b/kernel/drv/oss_fmedia/.devices @@ -0,0 +1,2 @@ +oss_fmedia pci1319,801 ForteMedia FM 801 +oss_fmedia pcs1489,7008 Genius Sound Maker Live diff --git a/kernel/drv/oss_fmedia/.name b/kernel/drv/oss_fmedia/.name new file mode 100644 index 0000000..5fdf20b --- /dev/null +++ b/kernel/drv/oss_fmedia/.name @@ -0,0 +1 @@ +ForteMedia FM 801 diff --git a/kernel/drv/oss_fmedia/.params b/kernel/drv/oss_fmedia/.params new file mode 100644 index 0000000..d756cde --- /dev/null +++ b/kernel/drv/oss_fmedia/.params @@ -0,0 +1,6 @@ +int fmedia_mpu_irq=0; +/* + * FM801 MPU IRQ + * Values: 5,7,9,10,11 Default: 0 + */ + diff --git a/kernel/drv/oss_fmedia/oss_fmedia.c b/kernel/drv/oss_fmedia/oss_fmedia.c new file mode 100644 index 0000000..fb5634a --- /dev/null +++ b/kernel/drv/oss_fmedia/oss_fmedia.c @@ -0,0 +1,1076 @@ +/* + * Purpose: Driver for FM801 FM801 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_fmedia_cfg.h" +#include "ac97.h" +#include "oss_pci.h" +#include "uart401.h" + + +#define FORTEMEDIA_VENDOR_ID 0x1319 +#define FORTEMEDIA_FM801 0x0801 + +/* Register Definitions */ +#define AC97_CMD 0x2A +#define AC97_DATA 0x2C +#define CODEC_CONTROL 0x22 +#define PCM_VOL 0x00 +#define FM_VOL 0x02 +#define I2S_VOL 0x04 +#define DIG_REC_SRC 0x06 +#define PLAY_CONTROL 0x08 +#define PLAY_SIZE 0x0A +#define PLAY_BUF1_ADDR 0x0C +#define PLAY_BUF2_ADDR 0x10 +#define REC_CONTROL 0x14 +#define REC_SIZE 0x16 +#define REC_BUF1_ADDR 0x18 +#define REC_BUF2_ADDR 0x1C +#define I2S_MODE 0x24 +#define HW_VOL_CONTROL 0x26 +#define I2S_CONTROL 0x29 +#define MPU_DATA 0x30 +#define MPU_COMMAND 0x31 +#define GPIO_CONTROL 0x52 +#define GENERAL_CONTROL 0x54 +#define IRQ_MASK 0x56 +#define IRQ_STATUS 0x5B + +/* playback and record control register bits */ +#define FM801_BUF1_LAST (1<<1) +#define FM801_BUF2_LAST (1<<2) +#define FM801_START (1<<5) +#define FM801_PAUSE (1<<6) +#define FM801_IMMED_STOP (1<<7) + +/* IRQ status bits */ +#define IRQ_PLAY (1<<8) +#define IRQ_REC (1<<9) +#define IRQ_HWVOL (1<<14) +#define IRQ_MPU (1<<15) + +#define MAX_PORTC 2 + +typedef struct fm801_portc +{ + int speed, bits, channels; + int open_mode; + int audio_enabled; + int trigger_bits; + int audiodev; +} fm801_portc; + +typedef struct fm801_devc +{ + oss_device_t *osdev; + oss_native_word base, mpu_base; + int mpu_attached, fm_attached; + int irq, mpu_irq; + int irq_allocated; + volatile unsigned char intr_mask; + int model; +#define MDL_FM801AS 1 +#define MDL_FM801AU 2 + char *chip_name; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + /* Audio parameters */ + int audio_initialized; + int open_mode; + fm801_portc portc[MAX_PORTC]; + int play_flag, play_count; + int rec_flag, rec_count; + /* Mixer parameters */ + ac97_devc ac97devc, ac97devc2; + int mixer_dev, mixer2_dev; +} fm801_devc; + +extern int fmedia_mpu_irq; + +static struct +{ + unsigned int rate; + unsigned int lower; + unsigned int upper; + unsigned char freq; +} rate_lookup[] = +{ + { + 5512, (0 + 5512) / 2, (5512 + 8000) / 2, 0x0}, + { + 8000, (5512 + 8000) / 2, (8000 + 9600) / 2, 0x1}, + { + 9600, (8000 + 9600) / 2, (9600 + 11025) / 2, 0x2}, + { + 11025, (9600 + 11025) / 2, (11025 + 16000) / 2, 0x3}, + { + 16000, (11025 + 16000) / 2, (16000 + 19200) / 2, 0x4}, + { + 19200, (16000 + 19200) / 2, (19200 + 22050) / 2, 0x5}, + { + 22050, (19200 + 22050) / 2, (22050 + 32000) / 2, 0x6}, + { + 32000, (22050 + 32000) / 2, (32000 + 38400) / 2, 0x7}, + { + 38400, (32000 + 38400) / 2, (38400 + 44100) / 2, 0x8}, + { + 44100, (38400 + 44100) / 2, (44100 + 48000) / 2, 0x9}, + { + 48000, (48000 + 44100) / 2, (48000 + 96000) / 2, 0xA} +}; + +static int +ac97_write (void *devc_, int index, int data) +{ + fm801_devc *devc = devc_; + int idx; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Wait until the codec interface is ready.. + */ + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "AC97 busy\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + /* write data and address */ + OUTW (devc->osdev, data, devc->base + AC97_DATA); + OUTW (devc->osdev, index | (0 << 10), devc->base + AC97_CMD); + /* + * Wait until the write command is completed.. + */ + for (idx = 0; idx < 1000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "AC97 busy (1)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static int +ac97_read (void *devc_, int index) +{ + fm801_devc *devc = devc_; + int idx; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Wait until the codec interface is not ready.. + */ + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "AC97 (read) not ready (1)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + /* read command */ + OUTW (devc->osdev, index | (0 << 10) | (1 << 7), devc->base + AC97_CMD); + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + /* + * Wait until the codec interface is not ready.. + */ + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "AC97 (read) not ready(2)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + for (idx = 0; idx < 10000; idx++) + { + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8)) + break; + oss_udelay (10); + } + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8))) + { + cmn_err (CE_WARN, "AC97 (read) data not valid (2)\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return INW (devc->osdev, devc->base + AC97_DATA); +} + +static int +ac97_write2 (void *devc_, int index, int data) +{ + fm801_devc *devc = devc_; + int idx; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Wait until the codec interface is ready.. + */ + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "Secondary AC97 busy\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + /* write data and address */ + OUTW (devc->osdev, data, devc->base + AC97_DATA); + OUTW (devc->osdev, index | (0x1 << 10), devc->base + AC97_CMD); + /* + * Wait until the write command is completed.. + */ + for (idx = 0; idx < 1000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "Secondary AC97 busy (1)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static int +ac97_read2 (void *devc_, int index) +{ + fm801_devc *devc = devc_; + int idx; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* + * Wait until the codec interface is not ready.. + */ + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready (1)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + /* read command */ + OUTW (devc->osdev, index | (0x1 << 10) | (1 << 7), devc->base + AC97_CMD); + for (idx = 0; idx < 10000; idx++) + { + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))) + break; + oss_udelay (10); + } + /* + * Wait until the codec interface is not ready.. + */ + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)) + { + DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready(2)\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + for (idx = 0; idx < 10000; idx++) + { + if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8)) + break; + oss_udelay (10); + } + if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8))) + { + cmn_err (CE_WARN, "Secondary AC97 (read) data not valid (2)\n"); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return INW (devc->osdev, devc->base + AC97_DATA); +} + +static int +fm801intr (oss_device_t * osdev) +{ + fm801_devc *devc = (fm801_devc *) osdev->devc; + unsigned int status; + int i; + int serviced = 0; + status = INB (devc->osdev, devc->base + IRQ_STATUS); + /* Playback interrupt */ + if (status & 0x01) + { + serviced = 1; + for (i = 0; i < MAX_PORTC; i++) + { + fm801_portc *portc = &devc->portc[i]; + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + { + dmap_t *dmapout = audio_engines[portc->audiodev]->dmap_out; + devc->play_count++; + if (devc->play_count == dmapout->nfrags) + devc->play_count = 0; + if (devc->play_flag) + { + OUTL (devc->osdev, dmapout->dmabuf_phys + + devc->play_count * dmapout->fragment_size, + devc->base + PLAY_BUF1_ADDR); + } + else + { + OUTL (devc->osdev, dmapout->dmabuf_phys + + devc->play_count * dmapout->fragment_size, + devc->base + PLAY_BUF2_ADDR); + } + devc->play_flag = !devc->play_flag; + oss_audio_outputintr (portc->audiodev, 1); + } + } + OUTB (devc->osdev, status | 0x01, devc->base + IRQ_STATUS); + } + /* Record Interrupt */ + if (status & 0x02) + { + serviced = 1; + for (i = 0; i < MAX_PORTC; i++) + { + fm801_portc *portc = &devc->portc[i]; + if (portc->trigger_bits & PCM_ENABLE_INPUT) + { + dmap_t *dmapin = audio_engines[portc->audiodev]->dmap_in; + devc->rec_count++; + if (devc->rec_count == dmapin->nfrags) + devc->rec_count = 0; + if (devc->rec_flag) + { + OUTL (devc->osdev, dmapin->dmabuf_phys + + devc->rec_count * dmapin->fragment_size, + devc->base + REC_BUF1_ADDR); + } + else + OUTL (devc->osdev, dmapin->dmabuf_phys + + devc->rec_count * dmapin->fragment_size, + devc->base + REC_BUF2_ADDR); + devc->rec_flag = !devc->rec_flag; + oss_audio_inputintr (portc->audiodev, 0); + } + } + OUTB (devc->osdev, status | 0x02, devc->base + IRQ_STATUS); + } + /* MIDI Interrupt */ + if (status & 0x80) + { + serviced = 1; + /* uart401intr (INT_HANDLER_CALL (devc->mpu_irq)); */ + OUTB (devc->osdev, status | 0x80, devc->base + IRQ_STATUS); + } + return serviced; +} + +static int +fm801_audio_set_rate (int dev, int arg) +{ + fm801_portc *portc = audio_engines[dev]->portc; + if (arg == 0) + return portc->speed; + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +fm801_audio_set_channels (int dev, short arg) +{ + fm801_portc *portc = audio_engines[dev]->portc; + if (arg>6) + arg=6; + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + portc->channels = arg; + return portc->channels; +} + +static unsigned int +fm801_audio_set_format (int dev, unsigned int arg) +{ + fm801_portc *portc = audio_engines[dev]->portc; + if (arg == 0) + return portc->bits; + if (!(arg & (AFMT_U8 | AFMT_S16_LE))) + return portc->bits; + portc->bits = arg; + return portc->bits; +} + +/*ARGSUSED*/ +static int +fm801_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void fm801_audio_trigger (int dev, int state); + +static void +fm801_audio_reset (int dev) +{ + fm801_audio_trigger (dev, 0); +} + +static void +fm801_audio_reset_input (int dev) +{ + fm801_portc *portc = audio_engines[dev]->portc; + fm801_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +fm801_audio_reset_output (int dev) +{ + fm801_portc *portc = audio_engines[dev]->portc; + fm801_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +fm801_audio_open (int dev, int mode, int open_flags) +{ + fm801_portc *portc = audio_engines[dev]->portc; + fm801_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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +fm801_audio_close (int dev, int mode) +{ + fm801_portc *portc = audio_engines[dev]->portc; + fm801_devc *devc = audio_engines[dev]->devc; + fm801_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +fm801_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + fm801_portc *portc = audio_engines[dev]->portc; + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +fm801_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + fm801_portc *portc = audio_engines[dev]->portc; + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +fm801_audio_trigger (int dev, int state) +{ + fm801_portc *portc = audio_engines[dev]->portc; + fm801_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + 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)) + { + OUTW (devc->osdev, + INW (devc->osdev, + devc->base + + PLAY_CONTROL) | FM801_START | FM801_IMMED_STOP, + devc->base + PLAY_CONTROL); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + OUTW (devc->osdev, + (INW (devc->osdev, devc->base + PLAY_CONTROL) & + (~FM801_START | FM801_IMMED_STOP)) | (FM801_BUF1_LAST | + FM801_BUF2_LAST), + devc->base + PLAY_CONTROL); + } + } + } + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + OUTW (devc->osdev, INW (devc->osdev, devc->base + REC_CONTROL) | + FM801_START | FM801_IMMED_STOP, devc->base + REC_CONTROL); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + OUTW (devc->osdev, + (INW (devc->osdev, devc->base + REC_CONTROL) & + (~FM801_START | FM801_IMMED_STOP)) | (FM801_BUF1_LAST | + FM801_BUF2_LAST), + devc->base + REC_CONTROL); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static unsigned char +sampling_rate (unsigned int rate) +{ + unsigned char freq = 1; + int i; + if (rate > 48000) + rate = 48000; + if (rate < 5512) + rate = 5512; + for (i = 0; i < sizeof (rate_lookup) / sizeof (rate_lookup[0]); i++) + { + if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) + { + rate = rate_lookup[i].rate; + freq = rate_lookup[i].freq; + break; + } + } + return (freq); +} + +/*ARGSUSED*/ +static int +fm801_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + fm801_devc *devc = audio_engines[dev]->devc; + fm801_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + unsigned short value; + unsigned char frequency; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + value = 0x0000; + if (portc->channels == 2) + value |= 0x8000; + if (portc->bits == 16) + value |= 0x4000; + frequency = sampling_rate (portc->speed); + value |= (frequency << 8); + OUTW (devc->osdev, value, devc->base + REC_CONTROL); + OUTW (devc->osdev, dmap->fragment_size - 1, devc->base + REC_SIZE); + OUTL (devc->osdev, dmap->dmabuf_phys, devc->base + REC_BUF1_ADDR); + OUTL (devc->osdev, dmap->dmabuf_phys + dmap->fragment_size, + devc->base + REC_BUF2_ADDR); + devc->rec_flag = 1; + devc->rec_count = 1; + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +fm801_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + fm801_devc *devc = audio_engines[dev]->devc; + fm801_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + unsigned short value; + unsigned char frequency; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + value = 0x0000; + if (portc->channels > 1) + value |= 0x8000; + if (portc->bits == 16) + value |= 0x4000; + frequency = sampling_rate (portc->speed); + value |= (frequency << 8); + if (portc->channels == 4) + value |= (1 << 12); /* 4channel output */ + if (portc->channels == 6) + value |= (1 << 13); /* 6channel output */ + OUTW (devc->osdev, value, devc->base + PLAY_CONTROL); + OUTW (devc->osdev, dmap->fragment_size - 1, devc->base + PLAY_SIZE); + OUTL (devc->osdev, dmap->dmabuf_phys, devc->base + PLAY_BUF1_ADDR); + OUTL (devc->osdev, dmap->dmabuf_phys + dmap->fragment_size, + devc->base + PLAY_BUF2_ADDR); + devc->play_flag = 1; + devc->play_count = 1; + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +fm801_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + fm801_devc *devc = audio_engines[dev]->devc; + int ptr = 0; + oss_native_word flags; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + if (devc->play_flag) + ptr = INL (devc->osdev, devc->base + PLAY_BUF1_ADDR); + else + ptr = INL (devc->osdev, devc->base + PLAY_BUF2_ADDR); + } + if (direction == PCM_ENABLE_INPUT) + { + if (devc->rec_flag) + ptr = INL (devc->osdev, devc->base + REC_BUF1_ADDR); + else + ptr = INL (devc->osdev, devc->base + REC_BUF2_ADDR); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr % dmap->bytes_in_use; +} + +static audiodrv_t fm801_audio_driver = { + fm801_audio_open, + fm801_audio_close, + fm801_audio_output_block, + fm801_audio_start_input, + fm801_audio_ioctl, + fm801_audio_prepare_for_input, + fm801_audio_prepare_for_output, + fm801_audio_reset, + NULL, + NULL, + fm801_audio_reset_input, + fm801_audio_reset_output, + fm801_audio_trigger, + fm801_audio_set_rate, + fm801_audio_set_format, + fm801_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* fm801_alloc_buffer */ + NULL, /* fm801_free_buffer */ + NULL, + NULL, + fm801_get_buffer_pointer +}; + +static void +init_audio (fm801_devc * devc) +{ + devc->audio_initialized = 1; +} + +static void +uninit_audio (fm801_devc * devc) +{ + unsigned int irqmask; + devc->audio_initialized = 0; +#ifndef _TRU64_UNIX + /* interrupt setup - mask MPU, PLAYBACK & CAPTURE */ + irqmask = INW (devc->osdev, devc->base + IRQ_MASK); + irqmask |= 0x00C3; + OUTW (devc->osdev, irqmask, devc->base + IRQ_MASK); + pci_write_config_word (devc->osdev, 0x40, 0x807F); +#endif +} + +#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 (fm801_devc * devc) +{ + if (!opl3_detect (devc->base + 0x68, devc->osdev)) + return; + opl3_init (devc->base + 0x68, devc->osdev); + devc->fm_attached = 1; +} + +static void +attach_mpu (fm801_devc * devc) +{ + struct address_info hw_config; + hw_config.io_base = devc->mpu_base; + hw_config.irq = devc->mpu_irq; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = "FM801 MPU-401"; + 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 (fm801_devc * devc) +{ + struct address_info hw_config; + hw_config.io_base = -devc->mpu_base; + hw_config.irq = devc->mpu_irq; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = "FM801 MPU-401"; + 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_fm801 (fm801_devc * devc) +{ + int my_mixer, my_mixer2; + int legacy; + int irqmask; + int adev; + int first_dev = 0; + int i; + + devc->mpu_attached = devc->fm_attached = 0; + + legacy = 0; + +#if !defined(__hpux) && !defined(sparc) && !defined(_TRU64) + /* Enable Legacy FM, MPU and Joystick ports */ + legacy = 0x001E; + switch (fmedia_mpu_irq) + { + case 5: + legacy |= 0x0000; + break; + case 7: + legacy |= 0x0800; + break; + case 9: + legacy |= 0x1000; + break; + case 10: + legacy |= 0x1800; + break; + case 11: + legacy |= 0x2000; + break; + } +#endif + + pci_write_config_word (devc->osdev, 0x40, legacy); + + /* codec cold reset + AC'97 warm reset */ + OUTW (devc->osdev, (1 << 5) | (1 << 6), devc->base + CODEC_CONTROL); + oss_udelay (10); + OUTW (devc->osdev, 0, devc->base + CODEC_CONTROL); + + if (devc->model == MDL_FM801AU) + { + OUTW (devc->osdev, (1 << 7), devc->base + CODEC_CONTROL); + oss_udelay (10); + } + + /* init volume */ + OUTW (devc->osdev, 0x0808, devc->base + PCM_VOL); + OUTW (devc->osdev, 0x0808, devc->base + FM_VOL); + OUTW (devc->osdev, 0x0808, devc->base + I2S_VOL); + /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */ + irqmask = INW (devc->osdev, devc->base + IRQ_MASK); + irqmask &= ~0x0083; + OUTW (devc->osdev, irqmask, devc->base + IRQ_MASK); + OUTW (devc->osdev, 0x280C, devc->base + GENERAL_CONTROL); + OUTW (devc->osdev, 0x0, devc->base + I2S_MODE); +#if !defined(__hpux) && !defined(sparc) && !defined(_TRU64_UNIX) + /* interrupt clear */ + /* + * TODO: Check this. Unaligned I/O access causes a crash onder non-x86 + */ + OUTW (devc->osdev, IRQ_PLAY | IRQ_REC | IRQ_MPU, devc->base + IRQ_STATUS); +#endif + /* + * Enable BusMasterMode and IOSpace Access + */ +#ifdef OBSOLETED_STUFF + attach_fm (devc); + attach_mpu (devc); +#endif + my_mixer = ac97_install (&devc->ac97devc, "FM801 AC97 Mixer", + ac97_read, ac97_write, devc, devc->osdev); + + if (my_mixer >= 0) + { + devc->mixer_dev = my_mixer; + if (devc->model == MDL_FM801AU) + { + my_mixer2 = ac97_install (&devc->ac97devc2, "FM801 AC97 Secondary", + ac97_read2, ac97_write2, devc, + devc->osdev); + if (my_mixer2 >= 0) + devc->mixer2_dev = my_mixer2; + } + } + else + return 0; + + for (i = 0; i < MAX_PORTC; i++) + { + char tmp_name[100]; + fm801_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX; + } + else + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX | ADEV_SHADOW; + } + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &fm801_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0) + { + adev = -1; + return 1; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + audio_engines[adev]->min_channels = 2; + audio_engines[adev]->max_channels = 6; + 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 + } + init_audio (devc); + } + return 1; +} + +int +oss_fmedia_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int err; + fm801_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered FM801 FM801 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != FORTEMEDIA_VENDOR_ID || device != FORTEMEDIA_FM801) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + DDB (cmn_err (CE_WARN, "FM801 I/O base %04x\n", pci_ioaddr)); + + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d). Can't continue\n", + pci_irq_line); + return 0; + } + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n"); + 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->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + + /* Remove I/O space marker in bit 0. */ + devc->base &= ~3; + devc->mpu_irq = fmedia_mpu_irq; + devc->mpu_base = devc->base + 0x30; + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + switch (pci_revision) + { + case 0xb1: + devc->model = MDL_FM801AS; + devc->chip_name = "ForteMedia FM801-AS"; + break; + case 0xb2: + devc->model = MDL_FM801AU; + devc->chip_name = "ForteMedia FM801-AU"; + break; + } + + oss_register_device (osdev, devc->chip_name); + if ((err = oss_register_interrupts (osdev, 0, fm801intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Error installing interrupt handler: %x\n", err); + return 0; + } + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + + return init_fm801 (devc); /* Detected */ +} + +int +oss_fmedia_detach (oss_device_t * osdev) +{ + fm801_devc *devc = (fm801_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + if (devc->audio_initialized) + { + uninit_audio (devc); + } + + devc->audio_initialized = 0; + +#ifdef OBSOLETED_STUFF + if (devc->mpu_attached) + { + unload_mpu (devc); + devc->mpu_attached = 0; + } +#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/kernel/drv/oss_fmedia/oss_fmedia.man b/kernel/drv/oss_fmedia/oss_fmedia.man new file mode 100644 index 0000000..58ed235 --- /dev/null +++ b/kernel/drv/oss_fmedia/oss_fmedia.man @@ -0,0 +1,23 @@ +NAME +oss_fmedia - Forte Media FM801 driver. + +DESCRIPTION +Open Sound System driver for Forte Media FM801/FM801-AU audio controllers. + +FM801 device characteristics: + o 8/16 bit playback/record + o mono/stereo/4ch/5.1ch playback + o mono/sterero recording + o 8KHz to 48Khz sample rate. + +OPTIONS +o fmedia_mpu_irq=<xx> +Set the IRQ for the UART401 MPU. Refer to device conf file (see below) for +valid IRQs. + +FILES +CONFIGFILEPATH/oss_fmedia.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_geode/.config b/kernel/drv/oss_geode/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_geode/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_geode/.devices b/kernel/drv/oss_geode/.devices new file mode 100644 index 0000000..fce8dd2 --- /dev/null +++ b/kernel/drv/oss_geode/.devices @@ -0,0 +1,3 @@ +oss_geode pci100b,503 National Semiconductor Geode SC1200 +oss_geode pci1078,103 National Semiconductor Geode CS5530 +oss_geode pci1022,2093 AMD Geode CS5536 diff --git a/kernel/drv/oss_geode/.name b/kernel/drv/oss_geode/.name new file mode 100644 index 0000000..02c7b76 --- /dev/null +++ b/kernel/drv/oss_geode/.name @@ -0,0 +1 @@ +National Semiconductor Geode SC1200/CS5530/CS5536 diff --git a/kernel/drv/oss_geode/oss_geode.c b/kernel/drv/oss_geode/oss_geode.c new file mode 100644 index 0000000..284aba3 --- /dev/null +++ b/kernel/drv/oss_geode/oss_geode.c @@ -0,0 +1,852 @@ +/* + * Purpose: Driver for the NS/Cyrix/AMD Geode AC97 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_geode_cfg.h" +#include "oss_pci.h" +#include "ac97.h" + +#define CYRIX_VENDOR_ID 0x1078 +#define CYRIX_GEODE 0x0103 +#define AMD_VENDOR_ID 0x1022 +#define AMD_CS5536_ID 0x2093 +#define NATIONAL_VENDOR_ID 0x100b +#define NATIONAL_SC1200 0x0503 + +#define CS_READL(devc,addr) INL((devc)->osdev, (unsigned int)((devc)->physaddr) + (addr)) +#define CS_READW(devc,addr) INW((devc)->osdev, (unsigned int)((devc)->physaddr) + (addr)) +#define CS_READB(devc,addr) INB((devc)->osdev, (unsigned int)((devc)->physaddr) + (addr)) +#define CS_WRITEL(devc,addr,val) OUTL((devc)->osdev, (val), (unsigned int)((devc)->physaddr) + (addr)) +#define CS_WRITEB(devc,addr,val) OUTB((devc)->osdev, (val), (unsigned int)((devc)->physaddr) + (addr)) + +#define MAX_PORTC 2 + +typedef struct +{ + unsigned int ptr; + unsigned int size; +#define PRD_EOT 0x80000000 +#define PRD_EOP 0x40000000 +#define PRD_JMP 0x20000000 +} +PRD_rec; + +typedef struct +{ + int open_mode; + int speed; + int bits; + int channels; + int trigger_bits; + int audio_enabled; + int audiodev; +} +geode_portc; + +typedef struct +{ + oss_device_t *osdev; + int physaddr; + void *linaddr; + int irq; + char *chip_name; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + int mixer_dev; + ac97_devc ac97devc; + + geode_portc portc[MAX_PORTC]; + int open_mode; + + PRD_rec *prdin, *prdout; + unsigned long prdin_phys, prdout_phys; + oss_dma_handle_t prdin_dma_handle, prdout_dma_handle; + + unsigned int chip; +} +geode_devc; + +static int +geodeintr_5530 (oss_device_t * osdev) +{ + + geode_devc *devc = osdev->devc; + geode_portc *portc; + int i, n, irqstat; + int serviced = 0; + unsigned int pos; + int ptr; + + irqstat = CS_READW (devc, 0x12); + if (irqstat & 3) /* either gpio or gpio wakeup */ + { + CS_READL (devc, 0x00); + serviced = 1; + } + + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && (irqstat & 4)) + { + dmap_t *dmap; + dmap = audio_engines[portc->audiodev]->dmap_out; + CS_READB (devc, 0x21); /* ack interrupt */ + pos = CS_READL (devc, 0x24); + pos = (pos - devc->prdout_phys) / 8; + ptr = pos; + ptr--; + + if (ptr < 0) + ptr = 0; + ptr %= dmap->nfrags; + + n = 0; + while (ptr != dmap_get_qhead (dmap) && n++ < dmap->nfrags) + oss_audio_outputintr (portc->audiodev, 0); + serviced = 1; + } + + + if ((portc->trigger_bits & PCM_ENABLE_INPUT) && (irqstat & 8)) + { + dmap_t *dmap; + + dmap = audio_engines[portc->audiodev]->dmap_in; + + pos = CS_READL (devc, 0x2c); + pos = (pos - devc->prdin_phys) / 8; + ptr = pos; + ptr--; + + if (ptr < 0) + ptr = 0; + ptr %= dmap->nfrags; + + n = 0; + while (ptr != dmap_get_qtail (dmap) && n++ < dmap->nfrags) + oss_audio_inputintr (portc->audiodev, 0); + + serviced = 1; + } + } + return serviced; +} + +static int +geodeintr_5536 (oss_device_t * osdev) +{ + + geode_devc *devc = osdev->devc; + geode_portc *portc; + int i; + int serviced = 0; + int irqstat; + + irqstat = CS_READW (devc, 0x12); + + if (irqstat & 3) /* either gpio or gpio wakeup */ + { + CS_READL (devc, 0x00); + serviced = 1; + } + + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && (irqstat & 4)) + if (CS_READB (devc, 0x21) & 1) + { + oss_audio_outputintr (portc->audiodev, 0); + serviced = 1; + + } + + + if ((portc->trigger_bits & PCM_ENABLE_INPUT) && (irqstat & 8)) + if (CS_READB (devc, 0x29) & 1) + { + oss_audio_inputintr (portc->audiodev, 0); + serviced = 1; + } + } + return serviced; +} + +static int +codec_valid_data (geode_devc * devc, int command, unsigned int *data) +{ + int y; + for (y = 0; y < 1000; y++) + { + *data = CS_READL (devc, 0x08); + + if ((*data & 0x7F000000) != (command & 0x7F000000)) + continue; + if (devc->chip == AMD_CS5536_ID) + { + if ((*data & 0x00020000) == 0x00020000) + return 1; + } + else + { + if ((*data & 0x00030000) == 0x00030000) + return 1; + } + } + return 0; +} + +static int +ac97_read (void *devc_, int wAddr) +{ + geode_devc *devc = devc_; + int i; + unsigned int x, y; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + for (i = 0; i < 10000; i++) + if (!(CS_READL (devc, 0x0c) & 0x10000)) + break; + + for (i = 0; i < 10000; i++) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + x = (wAddr << 24) | 0x80000000; + if (devc->chip == AMD_CS5536_ID) + x = x | 0x10000; /* this chip also need the NEW flag set */ + CS_WRITEL (devc, 0x0c, x); + + if (codec_valid_data (devc, x, &y)) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return y & 0xffff; + } + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; +} + +static int +ac97_write (void *devc_, int wAddr, int wData) +{ + geode_devc *devc = devc_; + unsigned int tmp, i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + tmp = (wAddr << 24) | wData; + if (devc->chip == AMD_CS5536_ID) + tmp = (tmp | 0x10000) & ~0x80000000; + CS_WRITEL (devc, 0x0c, tmp); + + /* wait for codec to be ready */ + for (i = 0; i <= 10000; i++) + if (!(CS_READL (devc, 0x0c) & 0x10000)) + break; + + if (i >= 10000) + { + cmn_err (CE_WARN, "AC97 write timeout\n"); + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + +static int +geode_audio_set_rate (int dev, int arg) +{ + geode_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 < 8000) + arg = 8000; + portc->speed = arg; + return portc->speed; +} + +static short +geode_audio_set_channels (int dev, short arg) +{ + geode_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 +geode_audio_set_format (int dev, unsigned int arg) +{ + geode_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 +geode_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void geode_audio_trigger (int dev, int state); + +static void +geode_audio_reset (int dev) +{ + geode_audio_trigger (dev, 0); +} + +static void +geode_audio_reset_input (int dev) +{ + geode_portc *portc = audio_engines[dev]->portc; + geode_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +geode_audio_reset_output (int dev) +{ + geode_portc *portc = audio_engines[dev]->portc; + geode_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +geode_audio_open (int dev, int mode, int open_flags) +{ + geode_portc *portc = audio_engines[dev]->portc; + geode_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; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +geode_audio_close (int dev, int mode) +{ + geode_portc *portc = audio_engines[dev]->portc; + geode_devc *devc = audio_engines[dev]->devc; + + geode_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +geode_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + geode_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +geode_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + geode_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +geode_audio_trigger (int dev, int state) +{ + geode_devc *devc = audio_engines[dev]->devc; + geode_portc *portc = audio_engines[dev]->portc; + int i; + oss_native_word flags; + + 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)) + { + CS_WRITEB (devc, 0x20, 0x01); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + CS_WRITEB (devc, 0x20, 0x00); + for (i = 0; i < 512; i++) + { + devc->prdout[i].size = PRD_EOT; /* Stop */ + } + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + CS_WRITEB (devc, 0x28, 0x09); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + CS_WRITEB (devc, 0x28, 0x00); + for (i = 0; i < 512; i++) + { + devc->prdin[i].size = PRD_EOT; /* Stop */ + } + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +geode_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + geode_devc *devc = audio_engines[dev]->devc; + geode_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ac97_recrate (&devc->ac97devc, portc->speed); + + + /* clear out the prd table */ + memset (devc->prdin, 0, 512 * sizeof (PRD_rec)); + + /* Initialize PRD entries */ + for (i = 0; i < dmap->nfrags; i++) + { + devc->prdin[i].ptr = dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->prdin[i].size = dmap->fragment_size | PRD_EOP; + } + + /* Initialize the JMP entry back to the beginning */ + devc->prdin[dmap->nfrags].ptr = devc->prdin_phys; + devc->prdin[dmap->nfrags].size = PRD_JMP | PRD_EOP; + + CS_WRITEL (devc, 0x2c, devc->prdin_phys); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +geode_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + geode_devc *devc = audio_engines[dev]->devc; + geode_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ac97_playrate (&devc->ac97devc, portc->speed); + + /* clear out the PRD table */ + memset (devc->prdout, 0, 512 * sizeof (PRD_rec)); + + + /* Initialize PRD entries */ + for (i = 0; i < dmap->nfrags; i++) + { + devc->prdout[i].ptr = dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->prdout[i].size = dmap->fragment_size | PRD_EOP; + } + + /* Initialize the JMP entry back to the beginning */ + devc->prdout[dmap->nfrags].ptr = devc->prdout_phys; + devc->prdout[dmap->nfrags].size = PRD_JMP | PRD_EOP; + + CS_WRITEL (devc, 0x24, devc->prdout_phys); + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static int +geode_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + geode_devc *devc = audio_engines[dev]->devc; + int ptr = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + if (devc->chip == AMD_CS5536_ID) + ptr = CS_READL (devc, 0x60); + else + ptr = CS_READL (devc, 0x24); + } + if (direction == PCM_ENABLE_INPUT) + { + if (devc->chip == AMD_CS5536_ID) + ptr = CS_READL (devc, 0x64); + else + ptr = CS_READL (devc, 0x2c); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr - dmap->dmabuf_phys; +} + +static const audiodrv_t geode_audio_driver = { + geode_audio_open, + geode_audio_close, + geode_audio_output_block, + geode_audio_start_input, + geode_audio_ioctl, + geode_audio_prepare_for_input, + geode_audio_prepare_for_output, + geode_audio_reset, + NULL, + NULL, + geode_audio_reset_input, + geode_audio_reset_output, + geode_audio_trigger, + geode_audio_set_rate, + geode_audio_set_format, + geode_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* geode_alloc_buffer */ + NULL, /* geode_free_buffer */ + NULL, + NULL, + geode_get_buffer_pointer +}; + +static int +init_geode (geode_devc * devc) +{ + int i, caps, opts; + int first_dev = 0; + oss_native_word phaddr; + + /* Allocate the buffers for the prdin/prdout tables */ + devc->prdin = + (PRD_rec *) CONTIG_MALLOC (devc->osdev, 512 * sizeof (PRD_rec), + MEMLIMIT_32BITS, &phaddr, devc->prdin_dma_handle); + if (devc->prdin == NULL) + { + cmn_err (CE_WARN, "Can't allocate memory for PRD input tables\n"); + return 0; + } + + devc->prdin_phys = phaddr; + + devc->prdout = + (PRD_rec *) CONTIG_MALLOC (devc->osdev, 512 * sizeof (PRD_rec), + MEMLIMIT_32BITS, &phaddr, devc->prdout_dma_handle); + if (devc->prdout == NULL) + { + cmn_err (CE_WARN, "Can't allocate memory for PRD output tables\n"); + return 0; + } + + devc->prdout_phys = phaddr; + + if (devc->chip != AMD_CS5536_ID) + { + /* VSA2 IRQ config method */ + OUTW (devc->osdev, 0xFC53, 0xAC1C); + OUTW (devc->osdev, 0x108, 0xAC1C); + OUTW (devc->osdev, devc->irq, 0xAC1E); + + /* VSA1 IRQ config method */ + OUTL (devc->osdev, 0x800090D0, 0x0CF8); + OUTL (devc->osdev, (devc->irq << 16) | 0xA00A, 0x0CFC); + oss_udelay (10000); + } + /* Now configure the OSS devices */ + + devc->mixer_dev = + ac97_install (&devc->ac97devc, "AC97 Mixer", ac97_read, ac97_write, devc, + devc->osdev); + + if (devc->mixer_dev < 0) + return 0; + + if (devc->chip == AMD_CS5536_ID) + { + /* remove controls that are backed by devices unsupported by the + chip, like s/pdif (cs5536 databook, page 89) */ + ac97_remove_control (&devc->ac97devc, + SOUND_MASK_VIDEO | SOUND_MASK_MONO | SOUND_MASK_CD | SOUND_MASK_PHONE, + 0); + } + + opts = ADEV_AUTOMODE | ADEV_STEREOONLY | ADEV_16BITONLY; + + if (!ac97_varrate (&devc->ac97devc)) + { + opts |= ADEV_FIXEDRATE; + } + + for (i = 0; i < MAX_PORTC; i++) + { + int adev; + geode_portc *portc = &devc->portc[i]; + char tmp_name[100]; + + if (i == 0) + { + if (devc->chip == AMD_CS5536_ID) + sprintf (tmp_name, "%s", "Geode CS5536"); + else + sprintf (tmp_name, "%s", "Geode CS5530"); + + caps = opts | ADEV_DUPLEX; + } + else + { + if (devc->chip == AMD_CS5536_ID) + sprintf (tmp_name, "%s", "Geode CS5536 (playback)"); + else + sprintf (tmp_name, "%s", "Geode CS5530 (playback"); + + caps = opts | ADEV_DUPLEX | ADEV_SHADOW; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &geode_audio_driver, + sizeof (audiodrv_t), + caps, 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]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = devc->mixer_dev; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + portc->open_mode = 0; + portc->audiodev = adev; + portc->audio_enabled = 0; + if (caps & ADEV_FIXEDRATE) + { + audio_engines[adev]->fixed_rate = 48000; + audio_engines[adev]->min_rate = 48000; + } +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + + } + return 1; +} + +int +oss_geode_attach (oss_device_t * osdev) +{ + unsigned char pci_revision, pci_irq_line /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int err; + geode_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered Geode probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + if (vendor != CYRIX_VENDOR_ID || device != CYRIX_GEODE) + if (vendor != NATIONAL_VENDOR_ID || device != NATIONAL_SC1200) + if (vendor != AMD_VENDOR_ID || device != AMD_CS5536_ID) + return 0; + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &pci_ioaddr); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "BAR0 not initialized by BIOS\n"); + 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->physaddr = pci_ioaddr & ~1UL; + devc->irq = pci_irq_line; + devc->chip = device; + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + if (devc->chip == AMD_CS5536_ID) + { + devc->chip_name = "AMD CS5536 AC97 Controller"; + + oss_register_device (osdev, devc->chip_name); + + if ((err = oss_register_interrupts (devc->osdev, 0, geodeintr_5536, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + } + else + { + devc->chip_name = "Geode/NS5530 AC97 Controller"; + + oss_register_device (osdev, devc->chip_name); + + if ((err = oss_register_interrupts (devc->osdev, 0, geodeintr_5530, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + } + + return init_geode (devc); /* Detected */ +} + + +int +oss_geode_detach (oss_device_t * osdev) +{ + geode_devc *devc = (geode_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + CS_WRITEB (devc, 0x20, 0); /* Disable output */ + CS_WRITEB (devc, 0x28, 0); /* Disable input */ + CS_WRITEL (devc, 0x24, 0); + CS_WRITEL (devc, 0x2c, 0); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + if (devc->prdin != NULL) + CONTIG_FREE (devc->osdev, devc->prdin, 512 * sizeof (PRD_rec), devc->prdin_dma_handle); + if (devc->prdout != NULL) + CONTIG_FREE (devc->osdev, devc->prdout, 512 * sizeof (PRD_rec), devc->prdout_dma_handle); + + devc->prdin = devc->prdout = NULL; + oss_unregister_device (devc->osdev); + + return 1; +} diff --git a/kernel/drv/oss_geode/oss_geode.man b/kernel/drv/oss_geode/oss_geode.man new file mode 100644 index 0000000..d833217 --- /dev/null +++ b/kernel/drv/oss_geode/oss_geode.man @@ -0,0 +1,25 @@ +NAME +oss_geode - National Semiconductor Geode audio driver. + +DESCRIPTION +Open Sound System driver for National Semiconductor Geode/CS5530/CS5536 audio +controllers. + +Geode device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +NOTES +Some old Geode CPUs are not able to handle heavy computational loads. +If your audio streams are use a lot of CPU, you can start getting garbled audio +since the OSS Sample Rate Convertor is CPU intensive. Setting vmix0-src to +OFF will allow you to play audio but only at a fixed rate set via vmixctl +(Default: 48Khz). + +FILES +CONFIGFILEPATH/oss_geode.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_hdaudio/.changelog b/kernel/drv/oss_hdaudio/.changelog new file mode 100644 index 0000000..d26ec7a --- /dev/null +++ b/kernel/drv/oss_hdaudio/.changelog @@ -0,0 +1,7 @@ +20080111 by Hannu: Fixed problem of several jack widgets getting named as "lineout" + +20080205 by Hannu: Improved support for systems with multiple codecs. + +20080221 by Hannu: Changed default volumes in hdaudio_generic.c to be louder. Earlier the volumes were 80% now 90%. + + diff --git a/kernel/drv/oss_hdaudio/.config b/kernel/drv/oss_hdaudio/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_hdaudio/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_hdaudio/.devices b/kernel/drv/oss_hdaudio/.devices new file mode 100644 index 0000000..7ee6bb3 --- /dev/null +++ b/kernel/drv/oss_hdaudio/.devices @@ -0,0 +1,27 @@ +oss_hdaudio pci8086,2668 Intel High Definition Audio (ICH6) +oss_hdaudio pci8086,27d8 Intel High Definition Audio (ICH7) +oss_hdaudio pci8086,269a Intel High Definition Audio (ESB2) +oss_hdaudio pci8086,284b Intel High Definition Audio (ICH8) +oss_hdaudio pci8086,293e Intel High Definition Audio (P35) +oss_hdaudio pci8086,293f Intel High Definition Audio (ICH9) +oss_hdaudio pci8086,3a3e Intel High Definition Audio (ICH10) +oss_hdaudio pci8086,3a6e Intel High Definition Audio (ICH10) +oss_hdaudio pci8086,3b56 Intel High Definition Audio (PCH) +oss_hdaudio pci8086,3b57 Intel High Definition Audio (PCH) +oss_hdaudio pci8086,1c20 Intel High Definition Audio (CPT) +oss_hdaudio pci8086,811b Intel High Definition Audio (SCH) +oss_hdaudio pci10de,26c Nvidia High Definition Audio (MCP51) +oss_hdaudio pci10de,371 Nvidia High Definition Audio (MCP55) +oss_hdaudio pci10de,3e4 Nvidia High Definition Audio (MCP61) +oss_hdaudio pci10de,3f0 Nvidia High Definition Audio (MCP61) +oss_hdaudio pci10de,44a Nvidia High Definition Audio (MCP65) +oss_hdaudio pci10de,55c Nvidia High Definition Audio (MCP67) +oss_hdaudio pci10de,7fc Nvidia High Definition Audio (MCP73) +oss_hdaudio pci10de,774 Nvidia High Definition Audio (MCP78S) +oss_hdaudio pci10de,ac0 Nvidia High Definition Audio (MCP79) +oss_hdaudio pci1002,437b ATI High Definition Audio (SB450) +oss_hdaudio pci1002,4383 ATI High Definition Audio (SB600) +oss_hdaudio pci1106,3288 VIA High Definition Audio +oss_hdaudio pci1039,7502 SiS High Definition Audio +oss_hdaudio pci10b9,5461 ULI High Definition Audio +oss_hdaudio pci1102,9 Creative Labs SB XFi Xtreme diff --git a/kernel/drv/oss_hdaudio/.name b/kernel/drv/oss_hdaudio/.name new file mode 100644 index 0000000..21af427 --- /dev/null +++ b/kernel/drv/oss_hdaudio/.name @@ -0,0 +1 @@ +High Definition Audio (Azalia) diff --git a/kernel/drv/oss_hdaudio/.params b/kernel/drv/oss_hdaudio/.params new file mode 100644 index 0000000..916648f --- /dev/null +++ b/kernel/drv/oss_hdaudio/.params @@ -0,0 +1,24 @@ +int hdaudio_snoopy=0; +/* + * hdaudio_snopy is reserved for diagnostic purposes and it must be 0 + * in all situations. Other values may make the driver vulnerable to + * DoS attacks. For security reasons only root can use this diagnostic + * interface. + */ +int hdaudio_jacksense=0; +/* + * Setting hdaudio_jacksense=1 enables jack sensing mode when the + * hdaudio driver is loaded. In this mode all I/O pin's that are not + * in use will be disabled as well as the mixer controls that are related + * with them. In this way the mixer/control panel will become more intuitive. + * However OSS will need to be restarted with soundoff;soundon every time + * new inputs or outputs are attached to the audio jacks. + * + * NOTE! hdaudio_jacksense=1 works only in some systems. Many laptops and + * motherboards don't support jack sensing. + */ +int hdaudio_noskip=0; +/* + * Disable checks to skip unconnected jack. Values: 0-7, where value is a + * bitmask - every bit disables another check. Can override hdaudio_jacksense. + */ diff --git a/kernel/drv/oss_hdaudio/hdaudio.h b/kernel/drv/oss_hdaudio/hdaudio.h new file mode 100644 index 0000000..964fd7f --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio.h @@ -0,0 +1,168 @@ +/* + * Purpose: Common definitions for the hdaudio driver files + */ +/* + * + * 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 HDA_GCAP 0x00 /* Global Capabilities */ +#define HDA_VMIN 0x02 /* Minor Version */ +#define HDA_VMAJ 0x03 /* Major Version */ +#define HDA_OUTPAY 0x04 /* Output Payload Capability */ +#define HDA_INPAY 0x06 /* Input Payload Capability */ +#define HDA_GCTL 0x08 /* Global Control */ +# define CRST 0x00000001 /* Controller reset */ +#define HDA_WAKEEN 0x0C /* Wake Enable */ +#define HDA_STATESTS 0x0E /* Wake Status */ +#define HDA_GSTST 0x10 /* Global Status */ +#define HDA_INTCTL 0x20 /* Interrupt Control */ +#define HDA_INTSTS 0x24 /* Interrupt Status */ +#define HDA_WCCNT 0x30 /* Wall Clock Counter */ +#define HDA_SSYNC 0x38 /* Stream Synchronization */ +#define HDA_CORBLBASE 0x40 /* CORB Lower Base Address */ +#define HDA_CORBUBASE 0x44 /* CORB Upper Base Address */ +#define HDA_CORBWP 0x48 /* CORB Write Pointer */ +#define HDA_CORBRP 0x4A /* CORB Read Pointer */ +#define HDA_CORBCTL 0x4C /* CORB Control */ +#define HDA_CORBSTS 0x4D /* CORB Status */ +#define HDA_CORBSIZE 0x4E /* CORB Size */ +#define HDA_RIRBLBASE 0x50 /* RIRB Lower Base Address */ +#define HDA_RIRBUBASE 0x54 /* RIRB Upper Base Address */ +#define HDA_RIRBWP 0x58 /* RIRB Write Pointer */ +#define HDA_RINTCNT 0x5A /* Response Interrupt Count */ +#define HDA_RIRBCTL 0x5C /* RIRB Control */ +#define HDA_RIRBSTS 0x5D /* RIRB Status */ +#define HDA_RIRBSIZE 0x5E /* RIRB Size */ +#define HDA_IC 0x60 /* Immediate Command Output Interface */ +#define HDA_IR 0x64 /* Immediate Command Input Interface */ +#define HDA_IRS 0x68 /* Immediate Command Status */ +#define HDA_DPLBASE 0x70 /* DMA Position Lower Base Address */ +#define HDA_DPUBASE 0x74 /* DMA Position Upper Base Address */ + +#define HDA_SD_CTL 0x0 +#define HDA_SD_STS 0x3 +#define HDA_SD_LPIB 0x4 +#define HDA_SD_CBL 0x8 +#define HDA_SD_LVI 0xC +#define HDA_SD_FIFOSIZE 0x10 +#define HDA_SD_FORMAT 0x12 +#define HDA_SD_BDLPL 0x18 +#define HDA_SD_BDLPU 0x1C +#define HDA_SD_LPIBA 0x2004 + +#define HDA_SDI0CTL 0x80 /* Stream Descriptor Control */ +#define HDA_SDI0STS 0x83 /* Stream Descriptor Status */ +#define HDA_SDI0LPIB 0x84 /* Link Position in Current Buffer */ +#define HDA_SDI0CBL 0x88 /* Cyclic Buffer Length */ +#define HDA_SDI0LVI 0x8C /* Last Valid Index */ +#define HDA_SDI0FIFOSIZE 0x90 /* FIFO Size */ +#define HDA_SDI0FORMAT 0x92 /* Format */ +#define HDA_SDI0BDLPL 0x98 /* List Pointer - Lower */ +#define HDA_SDI0BDLPU 0x9C /* List Pointer - Upper */ +#define HDA_SDI0LPIBA 0x2084 /* Link Position in Buffer n Alias */ + +#define HDA_SDI1CTL 0xA0 /* Stream Descriptor Control */ +#define HDA_SDI1STS 0xA3 /* Stream Descriptor Status */ +#define HDA_SDI1LPIB 0xA4 /* Link Position in Current Buffer */ +#define HDA_SDI1CBL 0xA8 /* Cyclic Buffer Length */ +#define HDA_SDI1LVI 0xAC /* Last Valid Index */ +#define HDA_SDI1FIFOSIZE 0xB0 /* FIFO Size */ +#define HDA_SDI1FORMAT 0xB2 /* Format */ +#define HDA_SDI1BDLPL 0xB8 /* List Pointer - Lower */ +#define HDA_SDI1BDLPU 0xBC /* List Pointer - Upper */ +#define HDA_SDI1LPIBA 0x20A4 /* Link Position in Buffer n Alias */ + +#define HDA_SDI2CTL 0xC0 /* Stream Descriptor Control */ +#define HDA_SDI2STS 0xC3 /* Stream Descriptor Status */ +#define HDA_SDI2LPIB 0xC4 /* Link Position in Current Buffer */ +#define HDA_SDI2CBL 0xC8 /* Cyclic Buffer Length */ +#define HDA_SDI2LVI 0xCC /* Last Valid Index */ +#define HDA_SDI2FIFOSIZ 0xD0 /* FIFO Size */ +#define HDA_SDI2FORMAT 0xD2 /* Format */ +#define HDA_SDI2BDLPL 0xD8 /* List Pointer - Lower */ +#define HDA_SDI2BDLPU 0xDC /* List Pointer - Upper */ +#define HDA_SDI2LPIBA 0x20D4 /* Link Position in Buffer n Alias */ + +#define HDA_SDI3CTL 0xE0 /* Stream Descriptor Control */ +#define HDA_SDI3STS 0xE3 /* Stream Descriptor Status */ +#define HDA_SDI3LPIB 0xE4 /* Link Position in Current Buffer */ +#define HDA_SDI3CBL 0xE8 /* Cyclic Buffer Length */ +#define HDA_SDI3LVI 0xEC /* Last Valid Index */ +#define HDA_SDI3FIFOSIZE 0xF0 /* FIFO Size */ +#define HDA_SDI3FORMAT 0xF2 /* Format */ +#define HDA_SDI3BDLPL 0xF8 /* List Pointer - Lower */ +#define HDA_SDI3BDLPU 0xFC /* List Pointer - Upper */ +#define HDA_SDI3LPIBA 0x20E4 /* Link Position in Buffer n Alias */ + +#define HDA_SDO0CTL 0x100 /* Stream Descriptor Control */ +#define HDA_SDO0STS 0x103 /* Stream Descriptor Status */ +#define HDA_SDO0LPIB 0x104 /* Link Position in Current Buffer */ +#define HDA_SDO0CBL 0x108 /* Cyclic Buffer Length */ +#define HDA_SDO0LVI 0x10C /* Last Valid Index */ +#define HDA_SDO0FIFOSIZE 0x110 /* FIFO Size */ +#define HDA_SDO0FORMAT 0x112 /* Format */ +#define HDA_SDO0BDLPL 0x118 /* List Pointer - Lower */ +#define HDA_SDO0BDLPU 0x11C /* List Pointer - Upper */ +#define HDA_SDO0LPIBA 0x2104 /* Link Position in Buffer n Alias */ + +#define HDA_SDO1CTL 0x120 /* Stream Descriptor Control */ +#define HDA_SDO1STS 0x123 /* Stream Descriptor Status */ +#define HDA_SDO1LPIB 0x124 /* Link Position in Current Buffer */ +#define HDA_SDO1CBL 0x128 /* Cyclic Buffer Length */ +#define HDA_SDO1LVI 0x12C /* Last Valid Index */ +#define HDA_SDO1FIFOSIZE 0x130 /* FIFO Size */ +#define HDA_SDO1FORMAT 0x132 /* Format */ +#define HDA_SDO1BDLPL 0x138 /* List Pointer - Lower */ +#define HDA_SDO1BDLPU 0x13C /* List Pointer - Upper */ +#define HDA_SDO1LPIBA 0x2124 /* Link Position in Buffer n Alias */ + +#define HDA_SDO2CTL 0x140 /* Stream Descriptor Control */ +#define HDA_SDO2STS 0x143 /* Stream Descriptor Status */ +#define HDA_SDO2LPIB 0x144 /* Link Position in Current Buffer */ +#define HDA_SDO2CBL 0x148 /* Cyclic Buffer Length */ +#define HDA_SDO2LVI 0x14C /* Last Valid Index */ +#define HDA_SDO2FIFOSIZE 0x150 /* FIFO Size */ +#define HDA_SDO2FORMAT 0x152 /* Format */ +#define HDA_SDO2BDLPL 0x158 /* List Pointer - Lower */ +#define HDA_SDO2BDLPU 0x15C /* List Pointer - Upper */ +#define HDA_SDO2LPIBA 0x2144 /* Link Position in Buffer n Alias */ + +#define HDA_SDO3CTL 0x160 /* Stream Descriptor Control */ +#define HDA_SDO3STS 0x163 /* Stream Descriptor Status */ +#define HDA_SDO3LPIB 0x164 /* Link Position in Current Buffer */ +#define HDA_SDO3CBL 0x168 /* Cyclic Buffer Length */ +#define HDA_SDO3LVI 0x16C /* Last Valid Index */ +#define HDA_SDO3FIFOSIZE 0x170 /* FIFO Size */ +#define HDA_SDO3FORMAT 0x172 /* Format */ +#define HDA_SDO3BDLPL 0x178 /* List Pointer - Lower */ +#define HDA_SDO3BDLPU 0x17C /* List Pointer - Upper */ + +#define HWINFO_SIZE 256 + +/* + * Debugging ioctl calls + */ + +typedef struct +{ + int cad, wid; + char name[32]; +} hda_name_t; + +typedef struct +{ + int cad, wid; + char info[4000]; +} hda_widget_info_t; + +#define HDA_IOCTL_WRITE __SIOWR('H', 0, int) +#define HDA_IOCTL_READ __SIOWR('H', 1, int) +#define HDA_IOCTL_NAME __SIOWR('H', 2, hda_name_t) +#define HDA_IOCTL_WIDGET __SIOWR('H', 3, hda_widget_info_t) diff --git a/kernel/drv/oss_hdaudio/hdaudio_abit_AA8.c b/kernel/drv/oss_hdaudio/hdaudio_abit_AA8.c new file mode 100644 index 0000000..6d7366d --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_abit_AA8.c @@ -0,0 +1,347 @@ +/* + * + * 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. + * + */ +/* Codec index is 0 */ +/* Codec vendor 10ec:0880 */ +/* HD codec revision 0.9 (5.0) (0x00090500) */ +/* Subsystem ID 08800000 */ +/* Default amplifier caps: in=00000000, out=00000000 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_abit_AA8_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, + int top_group) +{ + int ctl = 0; + + DDB (cmn_err (CE_CONT, "hdaudio_abit_AA8_mixer_init got called.\n")); + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n = 0; + + HDA_GROUP (pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP (0x14, group, pin_group, "green", n, "jack", 4)) /* Pin widget 0x14 */ + { + /* Src 0xc=front */ + if (HDA_PINSELECT (0x14, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "front input"); + HDA_OUTMUTE (0x14, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x15, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x15 */ + { + /* Src 0xd=rear */ + if (HDA_PINSELECT (0x15, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "rear input"); + HDA_OUTMUTE (0x15, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x16, group, pin_group, "C-L", n, "jack", 4)) /* Pin widget 0x16 */ + { + /* Src 0xe=center/LFE */ + if (HDA_PINSELECT (0x16, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "center/LFE input"); + HDA_OUTMUTE (0x16, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x17, group, pin_group, "surr", n, "jack", 4)) /* Pin widget 0x17 */ + { + /* Src 0xf=side */ + if (HDA_PINSELECT (0x17, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "side input"); + HDA_OUTMUTE (0x17, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x18, group, pin_group, "pink1", n, "jack", 4)) /* Pin widget 0x18 */ + { + /* Src 0x10=out-source */ + if (HDA_PINSELECT (0x18, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "out-source input"); + HDA_OUTMUTE (0x18, group, "mute", UNMUTE); + + /* Widget 0x10 (out-source) */ + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + if (HDA_SELECT (0x10, "out-source", ctl, group, -1)) + { + HDA_CHOICES (ctl, "front rear center/LFE side"); + } + } + + if (HDA_PIN_GROUP (0x19, group, pin_group, "pink2", n, "jack", 4)) /* Pin widget 0x19 */ + { + /* Src 0x11=out-source */ + if (HDA_PINSELECT (0x19, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "out-source input"); + HDA_OUTMUTE (0x19, group, "mute", UNMUTE); + + /* Widget 0x11 (out-source) */ + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + if (HDA_SELECT (0x11, "out-source", ctl, group, -1)) + { + HDA_CHOICES (ctl, "front rear center/LFE side"); + } + } + + if (HDA_PIN_GROUP (0x1a, group, pin_group, "blue1", n, "jack", 4)) /* Pin widget 0x1a */ + { + /* Src 0x12=out-source */ + if (HDA_PINSELECT (0x1a, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "out-source input"); + HDA_OUTMUTE (0x1a, group, "mute", UNMUTE); + + /* Widget 0x12 (out-source) */ + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + if (HDA_SELECT (0x12, "out-source", ctl, group, -1)) + { + HDA_CHOICES (ctl, "front rear center/LFE side"); + } + } + + if (HDA_PIN_GROUP (0x1b, group, pin_group, "blue2", n, "jack", 4)) /* Pin widget 0x1b */ + { + /* Src 0x13=out-source */ + if (HDA_PINSELECT (0x1b, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "out-source input"); + HDA_OUTMUTE (0x1b, group, "mute", UNMUTE); + + /* Widget 0x13 (out-source) */ + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + if (HDA_SELECT (0x13, "out-source", ctl, group, -1)) + { + HDA_CHOICES (ctl, "front rear center/LFE side"); + } + } + + if (HDA_PIN_GROUP (0x1c, group, pin_group, "cd", n, "jack", 4)) /* Pin widget 0x1c */ + { + if (HDA_PINSELECT (0x1c, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } + + if (HDA_PIN_GROUP (0x1d, group, pin_group, "beep", n, "jack", 4)) /* Pin widget 0x1d */ + { + if (HDA_PINSELECT (0x1d, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } + } + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n = 0; + + HDA_GROUP (rec_group, top_group, "record"); + + if (HDA_ADC_GROUP (0x07, group, rec_group, "rec1", n, "record", 2)) /* ADC widget 0x07 */ + { + /* Src 0x18=pink1 */ + /* Src 0x19=pink2 */ + /* Src 0x1a=blue1 */ + /* Src 0x1b=blue2 */ + /* Src 0x1c=cd */ + /* Src 0x14=green */ + /* Src 0x15=black */ + if (HDA_SELECT (0x07, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "pink1 pink2 blue1 blue2 cd green black"); + } + { + int amp_group; + + HDA_GROUP (amp_group, group, "vol"); + HDA_INAMP (0x07, 0, amp_group, "pink1", 90); /* From widget 0x18 */ + HDA_INAMP (0x07, 1, amp_group, "pink2", 90); /* From widget 0x19 */ + HDA_INAMP (0x07, 2, amp_group, "blue1", 90); /* From widget 0x1a */ + HDA_INAMP (0x07, 3, amp_group, "blue2", 90); /* From widget 0x1b */ + HDA_INAMP (0x07, 4, amp_group, "cd", 90); /* From widget 0x1c */ + HDA_INAMP (0x07, 5, amp_group, "green", 90); /* From widget 0x14 */ + HDA_INAMP (0x07, 6, amp_group, "black", 90); /* From widget 0x15 */ + } + } + + if (HDA_ADC_GROUP (0x08, group, rec_group, "rec2", n, "record", 2)) /* ADC widget 0x08 */ + { + /* Src 0x18=pink1 */ + /* Src 0x19=pink2 */ + /* Src 0x1a=blue1 */ + /* Src 0x1b=blue2 */ + /* Src 0x1c=cd */ + /* Src 0x14=green */ + /* Src 0x15=black */ + if (HDA_SELECT (0x08, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "pink1 pink2 blue1 blue2 cd green black"); + } + { + int amp_group; + + HDA_GROUP (amp_group, group, "vol"); + HDA_INAMP (0x08, 0, amp_group, "pink1", 90); /* From widget 0x18 */ + HDA_INAMP (0x08, 1, amp_group, "pink2", 90); /* From widget 0x19 */ + HDA_INAMP (0x08, 2, amp_group, "blue1", 90); /* From widget 0x1a */ + HDA_INAMP (0x08, 3, amp_group, "blue2", 90); /* From widget 0x1b */ + HDA_INAMP (0x08, 4, amp_group, "cd", 90); /* From widget 0x1c */ + HDA_INAMP (0x08, 5, amp_group, "green", 90); /* From widget 0x14 */ + HDA_INAMP (0x08, 6, amp_group, "black", 90); /* From widget 0x15 */ + } + } + + if (HDA_ADC_GROUP (0x09, group, rec_group, "rec3", n, "record", 2)) /* ADC widget 0x09 */ + { + /* Src 0x18=pink1 */ + /* Src 0x19=pink2 */ + /* Src 0x1a=blue1 */ + /* Src 0x1b=blue2 */ + /* Src 0x1c=cd */ + /* Src 0xb=inputmix */ + /* Src 0x14=green */ + /* Src 0x15=black */ + /* Src 0x16=C-L */ + /* Src 0x17=surr */ + if (HDA_SELECT (0x09, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, + "pink1 pink2 blue1 blue2 cd inputmix green black C-L surr"); + } + { + int amp_group; + + HDA_GROUP (amp_group, group, "vol"); + HDA_INAMP (0x09, 0, amp_group, "pink1", 90); /* From widget 0x18 */ + HDA_INAMP (0x09, 1, amp_group, "pink2", 90); /* From widget 0x19 */ + HDA_INAMP (0x09, 2, amp_group, "blue1", 90); /* From widget 0x1a */ + HDA_INAMP (0x09, 3, amp_group, "blue2", 90); /* From widget 0x1b */ + HDA_INAMP (0x09, 4, amp_group, "cd", 90); /* From widget 0x1c */ + HDA_INAMP (0x09, 5, amp_group, "inputmix", 90); /* From widget 0x0b */ + HDA_INAMP (0x09, 6, amp_group, "green", 90); /* From widget 0x14 */ + HDA_INAMP (0x09, 7, amp_group, "black", 90); /* From widget 0x15 */ + HDA_INAMP (0x09, 8, amp_group, "C-L", 90); /* From widget 0x16 */ + HDA_INAMP (0x09, 9, amp_group, "surr", 90); /* From widget 0x17 */ + } + } + +#if 0 + if (HDA_ADC_GROUP (0x0a, group, rec_group, "spdif-in", n, "record", 2)) /* ADC widget 0x0a */ + { + /* Src 0x1f=spdin */ + } +#endif + } + /* Handle misc widgets */ + { + int n, group, misc_group; + + n = 0; + + HDA_GROUP (misc_group, top_group, "misc"); + + if (HDA_MISC_GROUP (0x0c, group, misc_group, "front", n, "misc", 8)) /* Misc widget 0x0c */ + { + /* Src 0x2=front */ + /* Src 0xb=inputmix */ + HDA_OUTAMP (0x0c, group, "-", 90); + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE (0x0c, 0, amp_group, "front", UNMUTE); /* From widget 0x02 */ + HDA_INMUTE (0x0c, 1, amp_group, "inputmix", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP (0x0d, group, misc_group, "rear", n, "misc", 8)) /* Misc widget 0x0d */ + { + /* Src 0x3=rear */ + /* Src 0xb=inputmix */ + HDA_OUTAMP (0x0d, group, "-", 90); + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE (0x0d, 0, amp_group, "rear", UNMUTE); /* From widget 0x03 */ + HDA_INMUTE (0x0d, 1, amp_group, "inputmix", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP (0x0e, group, misc_group, "center/LFE", n, "misc", 8)) /* Misc widget 0x0e */ + { + /* Src 0x4=center/LFE */ + /* Src 0xb=inputmix */ + HDA_OUTAMP (0x0e, group, "-", 90); + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE (0x0e, 0, amp_group, "center/LFE", UNMUTE); /* From widget 0x04 */ + HDA_INMUTE (0x0e, 1, amp_group, "inputmix", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP (0x0f, group, misc_group, "side", n, "misc", 8)) /* Misc widget 0x0f */ + { + /* Src 0x5=side */ + /* Src 0xb=inputmix */ + HDA_OUTAMP (0x0f, group, "-", 90); + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE (0x0f, 0, amp_group, "side", UNMUTE); /* From widget 0x05 */ + HDA_INMUTE (0x0f, 1, amp_group, "inputmix", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP (0x0b, group, misc_group, "inputmix", n, "misc", 0)) /* Misc widget 0x0b */ + { + /* Src 0x18=pink1 */ + /* Src 0x19=pink2 */ + /* Src 0x1a=blue1 */ + /* Src 0x1b=blue2 */ + /* Src 0x1c=cd */ + /* Src 0x1d=beep */ + /* Src 0x14=green */ + /* Src 0x15=black */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "vol"); + HDA_INAMP (0x0b, 0, amp_group, "pink1", 90); /* From widget 0x18 */ + HDA_INAMP (0x0b, 1, amp_group, "pink2", 90); /* From widget 0x19 */ + HDA_INAMP (0x0b, 2, amp_group, "blue1", 90); /* From widget 0x1a */ + HDA_INAMP (0x0b, 3, amp_group, "blue2", 90); /* From widget 0x1b */ + HDA_INAMP (0x0b, 4, amp_group, "cd", 90); /* From widget 0x1c */ + HDA_INAMP (0x0b, 5, amp_group, "beep", 90); /* From widget 0x1d */ + HDA_INAMP (0x0b, 6, amp_group, "green", 90); /* From widget 0x14 */ + HDA_INAMP (0x0b, 7, amp_group, "black", 90); /* From widget 0x15 */ + } + } + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_asus_P4B_E.c b/kernel/drv/oss_hdaudio/hdaudio_asus_P4B_E.c new file mode 100644 index 0000000..c7f416c --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_asus_P4B_E.c @@ -0,0 +1,395 @@ +/* + * + * 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. + * + */ +/* Codec index is 0 */ +/* Codec vendor 11d4:1988 */ +/* HD codec revision 1.0 (4.0) (0x00100400) */ +/* Subsystem ID 104381e1 */ +/* Default amplifier caps: in=80000000, out=00052727 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_Asus_P4B_E_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, + int top_group) +{ + int ctl = 0; + + DDB (cmn_err (CE_CONT, "hdaudio_Asus_P4B_E_mixer_init got called.\n")); + + HDA_OUTAMP_F (0x04, top_group, "front", 100, MIXF_PCMVOL); + HDA_COLOR (ctl, OSS_RGB_GREEN); + HDA_OUTAMP_F (0x0a, top_group, "side", 100, MIXF_PCMVOL); + HDA_COLOR (ctl, OSS_RGB_GRAY); + HDA_OUTAMP_F (0x05, top_group, "center/LFE", 100, MIXF_PCMVOL); + HDA_COLOR (ctl, OSS_RGB_ORANGE); + HDA_OUTAMP_F (0x06, top_group, "rear", 100, MIXF_PCMVOL); + HDA_COLOR (ctl, OSS_RGB_BLACK); + HDA_OUTAMP_F (0x03, top_group, "headphone", 100, MIXF_PCMVOL); + HDA_OUTAMP_F (0x21, top_group, "input-mix", 100, MIXF_PCMVOL); + HDA_OUTAMP_F (0x10, top_group, "pcbeep", 100, MIXF_PCMVOL); + + /* Handle misc widgets */ + { + int n, group; + + n = 0; + + HDA_GROUP (group, top_group, "input-mix"); + + //if (HDA_MISC_GROUP(0x20, group, misc_group, "input-mix", n, "misc", 4)) /* Misc widget 0x20 */ + { + /* Src 0x39=fppink-micboost */ + /* Src 0x33=blue-insel */ + /* Src 0x38=fpgreen-micboost */ + /* Src 0x3d=green-micboost */ + /* Src 0x34=pink-insel */ + /* Src 0x3b=black-micboost */ + /* Src 0x18=cd */ + /* Src 0x1a=beep */ + HDA_INAMP (0x20, 0, group, "fp-pink", 100); /* From widget 0x39 */ + HDA_COLOR (ctl, OSS_RGB_PINK); + + HDA_INAMP (0x20, 1, group, "blue", 100); /* From widget 0x33 */ + HDA_COLOR (ctl, OSS_RGB_BLUE); + + HDA_INAMP (0x20, 2, group, "fp-green", 100); /* From widget 0x38 */ + HDA_COLOR (ctl, OSS_RGB_GREEN); + + HDA_INAMP (0x20, 3, group, "green", 100); /* From widget 0x3d */ + HDA_COLOR (ctl, OSS_RGB_GREEN); + + HDA_INAMP (0x20, 4, group, "pink", 100); /* From widget 0x34 */ + HDA_COLOR (ctl, OSS_RGB_PINK); + + HDA_INAMP (0x20, 5, group, "black", 100); /* From widget 0x3b */ + HDA_COLOR (ctl, OSS_RGB_BLACK); + + HDA_INAMP (0x20, 6, group, "cd", 100); /* From widget 0x18 */ + HDA_COLOR (ctl, 0); + + HDA_INAMP (0x20, 7, group, "pcbeep", 100); /* From widget 0x1a */ + HDA_COLOR (ctl, 0); + +#if 0 + // This seems to be unnecessary selector + /* Widget 0x33 (blue-insel) */ + /* Src 0x3a=blue-micboost */ + /* Src 0x25=grey */ + /* Src 0x24=orange */ + if (HDA_SELECT (0x33, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "blue grey orange"); + } +#endif + +#if 0 + // This seems to be unnecessary selector + /* Widget 0x34 (pink-insel) */ + /* Src 0x3c=pink-micboost */ + /* Src 0x25=grey */ + /* Src 0x24=orange */ + if (HDA_SELECT (0x34, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "pink grey orange"); + } +#endif + } + } + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n = 0; + + HDA_GROUP (rec_group, top_group, "record"); + +#if 0 + if (HDA_ADC_GROUP (0x07, group, rec_group, "spdin", n, "record", 4)) /* ADC widget 0x07 */ + { + /* Src 0x1c=spdif-in */ + } +#endif + + if (HDA_ADC_GROUP (0x08, group, rec_group, "rec1", n, "record", 4)) /* ADC widget 0x08 */ + { + /* Src 0xc=rec1-src */ + + /* Widget 0x0c (rec1-src) */ + /* Src 0x38=fpgreen-micboost */ + /* Src 0xbc= (0x3c=porte-boost?) */ + /* Src 0x18=int-black */ + /* Src 0x24=orange */ + /* Src 0x25=grey */ + /* Src 0x3d=green-micboost */ + /* Src 0x20=input-mix */ + if (HDA_SELECT (0x0c, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "fp-green pink cd orange grey green input-mix"); + } + HDA_OUTAMP_F (0x0c, group, "-", 100, MIXF_RECVOL); + } + + if (HDA_ADC_GROUP (0x09, group, rec_group, "rec2", n, "record", 4)) /* ADC widget 0x09 */ + { + /* Src 0xd=rec2-src */ + + /* Widget 0x0d (rec2-src) */ + /* Src 0x38=fpgreen-micboost */ + /* Src 0xbc= (0x3c=porte-boost?) */ + /* Src 0x18=int-black */ + /* Src 0x24=orange */ + /* Src 0x25=grey */ + /* Src 0x3d=green-micboost */ + /* Src 0x20=input-mix */ + if (HDA_SELECT (0x0d, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "fp-green pink cd orange grey green input-mix"); + } + HDA_OUTAMP_F (0x0d, group, "-", 100, MIXF_RECVOL); + } + + if (HDA_ADC_GROUP (0x0f, group, rec_group, "rec3", n, "record", 4)) /* ADC widget 0x0f */ + { + /* Src 0xe=rec3-src */ + + /* Widget 0x0e (rec3-src) */ + /* Src 0x38=fpgreen-micboost */ + /* Src 0xbc= (0x3c=porte-boost?) */ + /* Src 0x18=int-black */ + /* Src 0x24=orange */ + /* Src 0x25=grey */ + /* Src 0x3d=green-micboost */ + /* Src 0x20=input-mix */ + if (HDA_SELECT (0x0e, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "fp-green pink cd orange grey green input-mix"); + } + HDA_OUTAMP_F (0x0e, group, "-", 100, MIXF_RECVOL); + } + } + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n = 0; + + HDA_GROUP (pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP (0x11, group, pin_group, "fp-green", n, "jack", 4)) /* Pin widget 0x11 */ + { + /* Src 0x22=headphon-mix */ + if (HDA_PINSELECT (0x11, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "headphone-out input"); + HDA_OUTMUTE (0x11, group, "inmute", UNMUTE); + + /* Widget 0x22 (headphon-mix) */ + /* Src 0x37=fpgreen-outsel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x22, 0, amp_group, "headphone", UNMUTE, MIXF_MAINVOL); /* From widget 0x37 */ + HDA_INMUTE_F (0x22, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Widget 0x38 (fpgreen-micboost) */ + /* Src 0x11=fp-green */ + HDA_OUTAMP (0x38, group, "micboost", 100); + } + + if (HDA_PIN_GROUP (0x14, group, pin_group, "fp-pink", n, "jack", 4)) /* Pin widget 0x14 */ + { + /* Src 0x2b=fp-mic-mix */ + if (HDA_PINSELECT (0x14, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "headphone-out input"); + HDA_OUTMUTE (0x14, group, "inmute", UNMUTE); + + /* Widget 0x2b (fp-mic-mix) */ + /* Src 0x30=fppink-outsel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x2b, 0, amp_group, "headphone", UNMUTE, MIXF_MAINVOL); /* From widget 0x30 */ + HDA_INMUTE_F (0x2b, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Widget 0x39 (fppink-micboost) */ + /* Src 0x14=fp-pink */ + HDA_OUTAMP (0x39, group, "micboost", 100); + } + + if (HDA_PIN_GROUP (0x12, group, pin_group, "green", n, "jack", 0)) /* Pin widget 0x12 */ + { + /* Src 0x29=front-mix */ + if (HDA_PINSELECT (0x12, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "front-out input"); + HDA_OUTMUTE (0x12, group, "inmute", UNMUTE); + + /* Widget 0x29 (front-mix) */ + /* Src 0x4=front */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x29, 0, amp_group, "front", UNMUTE, MIXF_MAINVOL); /* From widget 0x04 */ + HDA_INMUTE_F (0x29, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Widget 0x3d (green-micboost) */ + /* Src 0x12=green */ + HDA_OUTAMP (0x3d, group, "micboost", 100); + } + + if (HDA_PIN_GROUP (0x13, group, pin_group, "int-black", n, "jack", 4)) /* Pin widget 0x13 */ + { + /* Src 0x2d=mono-mixdown */ + if (HDA_PINSELECT (0x13, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "mono-out input"); + HDA_OUTAMP (0x13, group, "invol", 100); + + /* Widget 0x2d (mono-mixdown) */ + /* Src 0x1e=mono-mix */ + + /* Widget 0x1e (mono-mix) */ + /* Src 0x36=mono-sel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x1e, 0, amp_group, "mono", UNMUTE, MIXF_MAINVOL); /* From widget 0x36 */ + HDA_INMUTE_F (0x1e, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + } + + if (HDA_PIN_GROUP (0x15, group, pin_group, "blue", n, "jack", 4)) /* Pin widget 0x15 */ + { + /* Src 0x2c=linein-mix */ + if (HDA_PINSELECT (0x15, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "front-out input"); + HDA_OUTMUTE (0x15, group, "inmute", UNMUTE); + + /* Widget 0x2c (linein-mix) */ + /* Src 0x31=blue-outsel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x2c, 0, amp_group, "front", UNMUTE, MIXF_MAINVOL); /* From widget 0x31 */ + HDA_INMUTE_F (0x2c, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Src 0x15=linein */ + HDA_OUTAMP (0x3a, group, "micboost", 100); + } + + if (HDA_PIN_GROUP (0x16, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x16 */ + { + /* Src 0x2a=rear-mix */ + if (HDA_PINSELECT (0x16, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "rear-out input"); + HDA_OUTMUTE (0x16, group, "inmute", UNMUTE); + + /* Widget 0x2a (rear-mix) */ + /* Src 0x6=rear */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x2a, 0, amp_group, "rear", UNMUTE, MIXF_MAINVOL); /* From widget 0x06 */ + HDA_INMUTE_F (0x2a, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Widget 0x3b (black-micboost) */ + /* Src 0x16=black */ + HDA_OUTAMP (0x3b, group, "micboost", 100); + } + + if (HDA_PIN_GROUP (0x17, group, pin_group, "pink", n, "jack", 0)) /* Pin widget 0x17 */ + { + /* Src 0x26=mic-mix */ + if (HDA_PINSELECT (0x17, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "center/LFE-out input"); + HDA_OUTMUTE (0x17, group, "inmute", UNMUTE); + + /* Widget 0x26 (mic-mix) */ + /* Src 0x32=pink-outsel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x26, 0, amp_group, "center/LFE", UNMUTE, MIXF_MAINVOL); /* From widget 0x32 */ + HDA_INMUTE_F (0x26, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + /* Src 0x17=mic */ + HDA_OUTAMP (0x3c, group, "micboost", 100); + } + +#if 0 + if (HDA_PIN_GROUP (0x18, group, pin_group, "int-black", n, "jack", 4)) /* Pin widget 0x18 */ + { + if (HDA_PINSELECT (0x18, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } + + if (HDA_PIN_GROUP (0x1a, group, pin_group, "int-black", n, "jack", 4)) /* Pin widget 0x1a */ + { + if (HDA_PINSELECT (0x1a, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } +#endif + + if (HDA_PIN_GROUP (0x24, group, pin_group, "orange", n, "jack", 4)) /* Pin widget 0x24 */ + { + /* Src 0x27=center/LFE-mix */ + if (HDA_PINSELECT (0x24, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "center/LFE-out input"); + HDA_OUTMUTE (0x24, group, "inmute", UNMUTE); + + /* Widget 0x27 (center/LFE-mix) */ + /* Src 0x5=center/LFE */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x27, 0, amp_group, "center/LFE", UNMUTE, MIXF_MAINVOL); /* From widget 0x05 */ + HDA_INMUTE_F (0x27, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + } + + if (HDA_PIN_GROUP (0x25, group, pin_group, "grey", n, "jack", 4)) /* Pin widget 0x25 */ + { + /* Src 0x28=side-mix */ + if (HDA_PINSELECT (0x25, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "side-out input"); + HDA_OUTMUTE (0x25, group, "inmute", UNMUTE); + + /* Widget 0x28 (side-mix) */ + /* Src 0xa=side */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP (amp_group, group, "mute"); + HDA_INMUTE_F (0x28, 0, amp_group, "side", UNMUTE, MIXF_MAINVOL); /* From widget 0x0a */ + HDA_INMUTE_F (0x28, 1, amp_group, "input-mix", UNMUTE, MIXF_MAINVOL); /* From widget 0x21 */ + } + } + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_asus_m9.c b/kernel/drv/oss_hdaudio/hdaudio_asus_m9.c new file mode 100644 index 0000000..054b4eb --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_asus_m9.c @@ -0,0 +1,36 @@ +/* + * Purpose: init handler for Asus m9. + */ + +/* + * + * 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. + * + */ + +/* Codec index is 0 */ +/* Codec vendor 10ec:0260 */ +/* HD codec revision 1.0 (4.0) (0x00100400) */ +/* Subsystem ID 1025160d */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" +#include "hdaudio_mixers.h" + +int +hdaudio_asus_m9_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + DDB(cmn_err(CE_CONT, "hdaudio_asus_m9_mixer_init got called.\n")); + + corb_write (mixer, cad, 0x1b, 0, SET_EAPD, 0); + + return hdaudio_generic_mixer_init(dev, mixer, cad, top_group); +} + diff --git a/kernel/drv/oss_hdaudio/hdaudio_codec.c b/kernel/drv/oss_hdaudio/hdaudio_codec.c new file mode 100644 index 0000000..fb29840 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_codec.c @@ -0,0 +1,3580 @@ +/* + * Purpose: Codec handling for Intel High Definition Audio (HDA/Azalia). + */ +/* + * + * 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_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_codecids.h" + +extern int hdaudio_snoopy; +extern int hdaudio_jacksense; +extern int hdaudio_noskip; + +static codec_t NULL_codec = { 0 }; /* TODO: Temporary workaround - to be removed */ + + +/* Si3055 functions (implemented in hdaudio_si3055.c) */ +extern void hdaudio_si3055_endpoint_init(hdaudio_mixer_t *mixer, int cad); +extern void hdaudio_si3055_set_rate(hdaudio_mixer_t *mixer, int cad, int rate); +extern int hdaudio_si3055_set_offhook(hdaudio_mixer_t *mixer, int cad, int offhook); + + +static int attach_codec (hdaudio_mixer_t * mixer, int cad, char *hw_info, + unsigned int pci_subdevice, int group_type); +int +hdaudio_mixer_get_outendpoints (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t ** endpoints, int size) +{ + int i; + + if (size != sizeof (hdaudio_endpointinfo_t)) + { + cmn_err (CE_WARN, "Bad endpoint size\n"); + return OSS_EIO; + } + + *endpoints = (hdaudio_endpointinfo_t *) & mixer->outendpoints; + + for (i = 0; i < mixer->num_outendpoints; i++) + { + hdaudio_endpointinfo_t *ep = *endpoints + i; + + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + + if (hdaudio_snoopy) + { + char *s = ep->name + strlen(ep->name); + sprintf(s, ":%d:%d", ep->cad, ep->base_wid); + } + } + return mixer->num_outendpoints; +} + +int +hdaudio_mixer_get_inendpoints (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t ** endpoints, int size) +{ + int i; + + if (size != sizeof (hdaudio_endpointinfo_t)) + { + cmn_err (CE_WARN, "Bad endpoint size\n"); + return OSS_EIO; + } + + *endpoints = (hdaudio_endpointinfo_t *) & mixer->inendpoints; + + for (i = 0; i < mixer->num_inendpoints; i++) + { + hdaudio_endpointinfo_t *ep = *endpoints + i; + + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + + if (hdaudio_snoopy) + { + char *s = ep->name + strlen(ep->name); + sprintf(s, ":%d:%d", ep->cad, ep->base_wid); + } + } + return mixer->num_inendpoints; +} + +/*ARGSUSED*/ +static int +hda_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC || + cmd == SOUND_MIXER_READ_STEREODEVS) + return *arg = 0; + + return OSS_EINVAL; +} + +static mixer_driver_t hda_mixer_driver = { + hda_mixer_ioctl +}; + + +static void +propagate_names (hdaudio_mixer_t * mixer) +{ + int c, w; + int i; +/* + * Check if the same name can be used for all the widgets on an unique path. + */ + + for (i = 0; i < 20; i++) + for (c = 0; c < mixer->ncodecs; c++) + if (mixer->codecs[c] != &NULL_codec) + { + for (w = 1; w < mixer->codecs[c]->nwidgets; w++) + { + widget_t *widget = &mixer->codecs[c]->widgets[w]; + widget_t *src_widget = + &mixer->codecs[c]->widgets[widget->connections[0]]; + + if (widget->nconn != 1) + continue; + +#if 0 + if (src_widget->wid_type == NT_PIN + || src_widget->wid_type == NT_DAC) + continue; + + if (src_widget->wid_type != NT_MIXER && src_widget->wid_type != NT_VENDOR) /* Mixer */ + continue; +#endif + + strcpy (widget->name, src_widget->name); + + /* + * Copy widget's RGB color to all widgets in the path + */ + if (widget->rgbcolor == 0) + widget->rgbcolor = src_widget->rgbcolor; + } + } +#if 0 + // Debugging code + for (c = 0; c < mixer->ncodecs; c++) + if (mixer->codecs[c] != &NULL_codec) + for (w = 1; w < mixer->codecs[c]->nwidgets; w++) + { + widget_t *widget = &mixer->codecs[c]->widgets[w]; + + cmn_err(CE_CONT, "w= %02x rgb=%06x: %s (%s)\n", w, widget->rgbcolor, widget->name, widget->color); + } +#endif +} + +static void +check_names (hdaudio_mixer_t * mixer) +{ + int c, c2, w, w2; + int n, start; + +/* + * Make sure all widgets have unique names. + */ + for (c = 0; c < mixer->ncodecs; c++) + if (mixer->codecs[c] != &NULL_codec) + { + for (w = 1; w < mixer->codecs[c]->nwidgets; w++) + { + char tmp[16]; + n = 0; + if (mixer->codecs[c]->widgets[w].skip) /* Not available */ + continue; + + strcpy (tmp, mixer->codecs[c]->widgets[w].name); + + start = w + 1; + + for (c2 = c; c2 < mixer->ncodecs; c2++) + { + for (w2 = start; w2 < mixer->codecs[c2]->nwidgets; w2++) + { + if (mixer->codecs[c2]->widgets[w2].skip) /* Not available */ + continue; + + if (strcmp (tmp, mixer->codecs[c2]->widgets[w2].name) == + 0) + n++; + } + + start = 1; + } + + if (n > 0) /* Duplicates found */ + { + n = 0; + start = w; + for (c2 = c; c2 < mixer->ncodecs; c2++) + { + for (w2 = start; w2 < mixer->codecs[c2]->nwidgets; w2++) + { + if (mixer->codecs[c2]->widgets[w2].skip) /* Not available */ + continue; + + if (strcmp (tmp, mixer->codecs[c2]->widgets[w2].name) + == 0) + { + n++; + sprintf (mixer->codecs[c2]->widgets[w2].name, + "%s%d", tmp, n); + } + } + + start = 1; + } + } + } + } +} + +int +hdaudio_amp_maxval (unsigned int ampcaps) +{ + int step, range, maxval; + + range = ((ampcaps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + 1; + step = ((ampcaps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + 1; + + maxval = range * step * 25; /* Now in 0.01 dB steps */ + maxval = (maxval / 10) - 1; /* Truncate to centibel (0.1 dB) scaling */ + + return maxval; +} + +static int +scaleout_vol (int v, unsigned int ampcaps) +{ + int step, range, maxval; + + range = ((ampcaps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + 1; + step = ((ampcaps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + 1; + + maxval = range * step * 25; /* Now in 0.01 dB steps */ + maxval = (maxval / 10) - 1; /* Truncate to centibel (0.1 dB) scaling */ + if (v > maxval) + v = maxval; + + v *= 10; /* centibels -> millibels */ + + v = (v + (25 * step) / 2) / (25 * step); + + if (v > 0x7f || v >= range) + { + v = range - 1; + } + + if (v < 0) + v = 0; + return v; +} + +static int +scalein_vol (int v, unsigned int ampcaps) +{ + int step, range, maxval; + + range = ((ampcaps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + 1; + step = ((ampcaps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + 1; + + maxval = range * step * 25; /* Now in 0.01 dB steps */ + maxval = (maxval / 10) - 1; /* Truncate to centibel (0.1 dB) scaling */ + + v *= step * 25; /* Convert to millibels */ + + v = v / 10 - 1; /* millibels -> centibels */ + + if (v > maxval) + { + v = maxval; + } + if (v < 0) + v = 0; + + return v; +} + +static int +handle_insrcselect (hdaudio_mixer_t * mixer, widget_t * widget, int value) +{ +/* + * Emulated (recording) source selection based on input amp mute controls. + * + * Mute all inputs other than the selected one. + */ + int i; + + widget->current_selector = value; + + for (i = 0; i < widget->nconn; i++) + { + int v = (i == value) ? 0 : 0x80; + + corb_write (mixer, widget->cad, widget->wid, 0, + SET_GAIN (0, 1, 1, 1, i), v); + } + + return value; +} + +int +hdaudio_set_control (int dev, int ctrl, unsigned int cmd, int value) +{ + hdaudio_mixer_t *mixer = mixer_devs[dev]->devc; + + unsigned int cad, wid, linked_wid, typ, ix, left, right, a, b, v; + widget_t *widget; + + ix = ctrl & 0xff; + typ = (ctrl >> 8) & 0xff; + wid = (ctrl >> 16) & 0xff; + cad = (ctrl >> 24) & 0xff; + + if (cad >= mixer->ncodecs) + return OSS_EIO; + + if (wid >= mixer->codecs[cad]->nwidgets) + return OSS_EIO; + + widget = &mixer->codecs[cad]->widgets[wid]; + + if (mixer->codecs[cad]->vendor_flags & VF_VAIO_HACK) + linked_wid = (wid == 0x02) ? 0x05 : ((wid == 0x05) ? 0x02 : 0); + else + linked_wid = 0; + + if (cmd == SNDCTL_MIX_READ) + switch (typ) + { + case CT_INGAINSEL: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 0), ix, &a, &b)) + return OSS_EIO; + return a & 0x7f; // TODO: Handle mute + break; + + case CT_INMONO: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 0), ix, &a, &b)) + return OSS_EIO; + if (a & 0x80) + left = 0; + else + left = scalein_vol (a, widget->inamp_caps); + return left | (left << 16); + break; + + case CT_INSTEREO: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 1), ix, &a, &b)) + return OSS_EIO; + if (a & 0x80) + left = 0; + else + left = scalein_vol (a, widget->inamp_caps); + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 0), ix, &a, &b)) + return OSS_EIO; + if (a & 0x80) + right = 0; + else + right = scalein_vol (a, widget->inamp_caps); + return left | (right << 16); + break; + + case CT_INMUTE: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 0), ix, &a, &b)) + return OSS_EIO; + return (a >> 7) & 0x01; + break; + + case CT_INSRC: /* Inverse mute */ + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (0, 0), ix, &a, &b)) + return OSS_EIO; + return !((a >> 7) & 0x01); + break; + + case CT_SELECT: + return widget->current_selector; + break; + + case CT_INSRCSELECT: /* Emulated selector based on input mute controls */ + return widget->current_selector; + + case CT_OUTGAINSEL: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (1, 1), 0, &a, &b)) + return OSS_EIO; + return a; // TODO: Handle mute + break; + + case CT_OUTMONO: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (1, 1), 0, &a, &b)) + return OSS_EIO; + left = a & 0x7f; + if (a & 0x80) + left = 0; + else + left = scalein_vol (a, widget->outamp_caps); + return left | (left << 16); + break; + + case CT_OUTSTEREO: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (1, 1), 0, &a, &b)) + return OSS_EIO; + left = a & 0x7f; + if (a & 0x80) + left = 0; + else + left = scalein_vol (a, widget->outamp_caps); + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (1, 0), 0, &a, &b)) + return OSS_EIO; + right = a & 0x7f; + if (a & 0x80) + right = 0; + else + right = scalein_vol (a, widget->outamp_caps); + return left | (right << 16); + break; + + case CT_OUTMUTE: + if (!corb_read (mixer, cad, wid, 0, GET_GAIN (1, 0), 0, &a, &b)) + return OSS_EIO; + return (a >> 7) & 0x01; + break; + + default: + return OSS_EINVAL; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (typ) + { + case CT_INMONO: + v = (value & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->inamp_caps); + + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 1, 1, ix), v); + return value; + break; + + case CT_INSTEREO: + v = (value & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->inamp_caps); + + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 1, 0, ix), v); + v = ((value >> 16) & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->inamp_caps); + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 0, 1, ix), v); + return value; + break; + + case CT_INGAINSEL: + v = (value & 0x7f); + // TODO: Handle mute + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 1, 0, ix), v); + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 0, 1, ix), v); + return value; + break; + + case CT_INMUTE: + v = 0; + if (value) + v = 0x80; + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 1, 1, ix), v); + return value; + break; + + case CT_INSRC: /* Inverse mute */ + v = 0; + if (!value) + v = 0x80; + corb_write (mixer, cad, wid, 0, SET_GAIN (0, 1, 1, 1, ix), v); + return value; + break; + + case CT_SELECT: + if (value < 0) + value = 0; + widget->current_selector = value; + + if (value < widget->nconn) + { + /* Output source select */ + corb_write (mixer, cad, wid, 0, SET_SELECTOR, value); + /* Enable output and HP amp. Set vref=Ground */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0xc0); + } + else + { + /* Input select + * Program the correct VRef Values + */ + + if (widget->pin_type == PIN_IN) /* Line-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x20); /*Ground*/ + } + else /* Mic-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x24); /*Vref=8 + 0% */ + } + } + return value; + break; + + case CT_INSRCSELECT: /* Emulated selector based on input mute mask */ + if (value < 0) + value = 0; + if (value >= widget->nconn) + value = widget->nconn; + return handle_insrcselect (mixer, widget, value); + break; + + case CT_OUTGAINSEL: + // TODO: Handle mute + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 1, 0, ix), value); + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 0, 1, ix), value); + return value; + break; + + case CT_OUTMONO: + v = (value & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->outamp_caps); + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 1, 0, ix), v); + if (linked_wid) + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 1, 0, ix), v); + return value; + break; + + case CT_OUTSTEREO: + v = (value & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->outamp_caps); + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 1, 0, ix), v); + if (linked_wid) + corb_write (mixer, cad, linked_wid, 0, SET_GAIN (1, 0, 1, 0, ix), v); + v = ((value >> 16) & 0xffff); + if (v == 0) + v = 0x80; /* Muted */ + else + v = scaleout_vol (v, widget->outamp_caps); + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 0, 1, ix), v); + if (linked_wid) + corb_write (mixer, cad, linked_wid, 0, SET_GAIN (1, 0, 0, 1, ix), v); + return value; + break; + + case CT_OUTMUTE: + v = 0; + if (value) + v = 0x80; + corb_write (mixer, cad, wid, 0, SET_GAIN (1, 0, 1, 1, ix), v); + if (linked_wid) + corb_write (mixer, cad, linked_wid, 0, SET_GAIN (1, 0, 1, 1, ix), v); + return value; + break; + + default: + return OSS_EINVAL; + } + } + + return OSS_EINVAL; +} + +static int +perform_pin_sense (hdaudio_mixer_t * mixer) +{ + int cad, wid; + unsigned int a, b; + int plugged_in; + codec_t *codec; + + for (cad = 0; cad < mixer->ncodecs; cad++) + if (mixer->codecs[cad] != &NULL_codec) + { + codec = mixer->codecs[cad]; + + for (wid = 1; wid < mixer->codecs[cad]->nwidgets; wid++) + if (mixer->codecs[cad]->widgets[wid].wid_type == NT_PIN) /* Pin complex */ + { + widget_t *widget = &mixer->codecs[cad]->widgets[wid]; + + widget->impsense = -1; + widget->sensed_pin = widget->pin_type; + + plugged_in = 1; + + /* Load the sense information */ + if ((widget->pincaps & PINCAP_JACKSENSE_CAPABLE) + || (widget->pincaps & PINCAP_IMPSENSE_CAPABLE)) + { + int tmout = 0; + if (!corb_read + (mixer, cad, wid, 0, GET_PIN_SENSE, 0, &a, &b)) + a = 0x7fffffff; /* No jack present */ + + if (a & (1UL << 31)) /* Jack present */ + if (widget->pincaps & PINCAP_TRIGGERR_RQRD) /* Trigger required */ + { + corb_write (mixer, cad, wid, 0, TRIGGER_PIN_SENSE, 0); + + do + { + oss_udelay (10); + if (!corb_read + (mixer, cad, wid, 0, GET_PIN_SENSE, 0, &a, + &b)) + break; + } + while (tmout++ < 10000 + && ((a & 0x7fffffff) == 0x7fffffff)); + } + + if (!corb_read + (mixer, cad, wid, 0, GET_PIN_SENSE, 0, &a, &b)) + continue; + } + else + continue; + + /* Precence detect */ + if (widget->pincaps & PINCAP_JACKSENSE_CAPABLE) + { +#if 0 + if (a & (1UL << 31)) + cmn_err (CE_WARN, "%s jack is plugged in\n", + widget->name); + else + cmn_err (CE_WARN, "%s NOT plugged in\n", widget->name); +#endif + if (!(a & (1UL << 31))) + plugged_in = 0; + } + + widget->plugged_in = plugged_in; + if (plugged_in) + codec->num_jacks_plugged++; + + /* Impedance sensing */ + widget->impsense = a & 0x7fffffff; + if (plugged_in && (widget->pincaps & PINCAP_IMPSENSE_CAPABLE)) + if (hdaudio_jacksense > 0) + if (widget->impsense != 0x7fffffff) /* Sense operation finished */ + { + /* cmn_err (CE_WARN, "%s sense %08x (%d)\n", widget->name, a, a & 0x7fffffff); */ + + if (widget->impsense >= 1000000) /* High impedance (line-in) pin */ + { + /* cmn_err(CE_CONT, " --> Line level input\n"); */ + widget->pin_type = widget->sensed_pin = PIN_IN; + } + else if (widget->impsense <= 10000) /* Low impedance (speaker/hp out) */ + { + /* cmn_err(CE_CONT, " --> Output pin\n"); */ + widget->pin_type = widget->sensed_pin = PIN_OUT; + } + else /* Something between low and high (mic?) */ + { + /* cmn_err(CE_CONT, " --> Mic level input\n"); */ + widget->pin_type = widget->sensed_pin = PIN_MIC; + } + } + } + } + +/* + * Set all pins to correct mode + */ + + for (cad = 0; cad < mixer->ncodecs; cad++) + if (mixer->codecs[cad] != &NULL_codec) + for (wid = 1; wid < mixer->codecs[cad]->nwidgets; wid++) + { + if (mixer->codecs[cad]->widgets[wid].wid_type == NT_PIN) /* Pin complex */ + { + widget_t *widget = &mixer->codecs[cad]->widgets[wid]; + + if (widget->pin_type == PIN_IN + || widget->pin_type == PIN_UNKNOWN) + { /* Input PIN */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x20); + } + if (widget->pin_type == PIN_MIC) + { /* Input PIN (mic) */ + /* TODO: Handle mic amp */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x24); + } + else + { /* Output PIN */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0xc0); + } + + if (widget->pincaps & PINCAP_EAPD) + { + unsigned int eapd, dummy; + DDB (cmn_err + (CE_CONT, "Pin widget %d is EAPD capable.\n", + widget->wid)); + if (corb_read + (mixer, cad, wid, 0, GET_EAPD, 0, &eapd, &dummy)) + { + eapd |= 0x02; /* EAPD enable */ + corb_write (mixer, cad, wid, 0, SET_EAPD, eapd); + } + } + } + } + + return 1; +} + +static int +hdaudio_mix_init (int dev) +{ + hdaudio_mixer_t *mixer = mixer_devs[dev]->devc; + char tmp[32]; + int err; + int working_codecs=0; + int cad; + +/* + * First pass. Count the number of active codecs. + */ + + for (cad = 0; cad < mixer->ncodecs; cad++) + if (mixer->codecs[cad] != &NULL_codec) + { + codec_t *codec = mixer->codecs[cad]; + + if (codec == &NULL_codec || codec->nwidgets == 0) /* Codec not active */ + continue; + + /* + * Enable the new generic mixer driver + */ + if (codec->mixer_init == NULL) + { + codec->mixer_init = hdaudio_generic_mixer_init; + } + + if (codec->active && codec->mixer_init != NULL_mixer_init) + working_codecs++; + } + + /* + * Second pass. Initialize the mixer interfaces for all active codecs. + */ + + for (cad = 0; cad < mixer->ncodecs; cad++) + if (mixer->codecs[cad] != &NULL_codec) + { + codec_t *codec = mixer->codecs[cad]; + int group = 0; + + if (codec == &NULL_codec || codec->nwidgets == 0) /* Codec not active */ + continue; + + if (working_codecs > 1) + { + sprintf (tmp, "codec%d", cad + 1); + if ((group = mixer_ext_create_group (dev, 0, tmp)) < 0) + { + return group; + } + } + + if (codec->active && codec->mixer_init != NULL_mixer_init) + { + if ((err = codec->mixer_init (dev, mixer, cad, group)) < 0) + { + if (err != OSS_EAGAIN) + return err; + /* + * We got EAGAIN whic means that we should fall + * to the old generic mixer. + */ + if ((err = + hdaudio_generic_mixer_init (dev, mixer, cad, group)) < 0) + { + return err; + } + } + else + continue; + } + } + + if (mixer->client_mixer_init != 0) + mixer->client_mixer_init (dev); + + return 0; +} + +static void +copy_endpoints(hdaudio_mixer_t * mixer, codec_t *codec, int pass) +{ + int i; + +/* + * Install output endpoints from the codec to the global endpoint table. + */ + + for (i = 0; i < codec->num_outendpoints; i++) + { + hdaudio_endpointinfo_t *ep = &codec->outendpoints[i]; + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + } + + for (i=0;i<codec->num_outendpoints;i++) + { + int ix = (codec->multich_map >> (i * 4)) & 0x0f; + hdaudio_endpointinfo_t *ep = &codec->outendpoints[ix]; + + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + + if (ep->skip || ep->already_used) + continue; + + switch (pass) + { + case 0: /* Pick analog endpoints */ + if (ep->is_digital) + continue; + break; + + case 1: /* Pick digital endpoints */ + if (!ep->is_digital) + continue; + break; + } + + if (mixer->copied_outendpoints >= HDA_MAX_OUTSTREAMS) + { + cmn_err (CE_WARN, + "Too many output endpoints (%d)\n", + mixer->copied_outendpoints); + continue; + } + + memcpy(&mixer->outendpoints[mixer->copied_outendpoints++], ep, sizeof(*ep)); + ep->already_used=1; + } + mixer->num_outendpoints = mixer->copied_outendpoints; + +/* + * Install input endpoints from the codec to the global endpoint table. + */ + + for (i = 0; i < codec->num_inendpoints; i++) + { + hdaudio_endpointinfo_t *ep = &codec->inendpoints[i]; + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + } + + for (i=0;i<codec->num_inendpoints;i++) + { + hdaudio_endpointinfo_t *ep = &codec->inendpoints[i]; + + ep->skip = mixer->codecs[ep->cad]->widgets[ep->base_wid].skip; + + if (ep->skip || ep->already_used) + continue; + + switch (pass) + { + case 0: /* Pick analog endpoints */ + if (ep->is_digital) + continue; + break; + + case 1: /* Pick digital endpoints */ + if (!ep->is_digital) + continue; + break; + } + + if (mixer->copied_inendpoints >= HDA_MAX_INSTREAMS) + { + cmn_err (CE_WARN, + "Too many output endpoints (%d)\n", + mixer->copied_inendpoints); + continue; + } + + memcpy(&mixer->inendpoints[mixer->copied_inendpoints++], ep, sizeof(*ep)); + ep->already_used=1; + } + mixer->num_inendpoints = mixer->copied_inendpoints; +} + + /*ARGSUSED*/ + hdaudio_mixer_t * +hdaudio_mixer_create (char *name, void *devc, + oss_device_t * osdev, + hdmixer_write_t writefunc, + hdmixer_read_t readfunc, unsigned int codecmask, + unsigned int vendor_id, unsigned int subvendor_id) +{ + hdaudio_mixer_t *mixer; + int i, func; + int ncodecs = 0; + char tmp[128]; + int mixer_dev; + + char *hw_info = osdev->hw_info; /* For printing hardware information */ + + if ((mixer = PMALLOC (osdev, sizeof (*mixer))) == NULL) + { + cmn_err (CE_WARN, "hdaudio_mixer_create: Out of memory\n"); + return NULL; + } + + memset (mixer, 0, sizeof (*mixer)); + + mixer->devc = devc; + mixer->osdev = osdev; + mixer->mixer_dev = 0; + strncpy (mixer->name, name, sizeof (mixer->name)); + mixer->name[sizeof (mixer->name) - 1] = 0; + + for (i = 0; i < MAX_CODECS; i++) + mixer->codecs[i] = &NULL_codec; + + mixer->read = readfunc; + mixer->write = writefunc; + mixer->codecmask = codecmask; + + sprintf (hw_info, "HD Audio controller %s\n" + "Vendor ID 0x%08x\n" + "Subvendor ID 0x%08x\n", name, vendor_id, subvendor_id); + hw_info += strlen (hw_info); + + if (hdaudio_snoopy) + { + sprintf(hw_info, "**** Warning: Diagnostic mode enabled (hdaudio_snoopy) ****\n"); + hw_info += strlen (hw_info); + } + +/* + * Search first all audio function groups for all codecs and then + * handle modem function groups. + */ + for (func=1;func<=2;func++) + for (i = 0; i < 16; i++) + if (mixer->codecmask & (1 << i)) + { + if (attach_codec (mixer, i, hw_info, subvendor_id, func) >= 0) + ncodecs++; + hw_info += strlen (hw_info); + } + + if (ncodecs == 0) + { + cmn_err (CE_WARN, "No hdaudio codecs were detected\n"); + return NULL; + } + +/* + * The attach_codec routine copied all analog endpoints to the global endpoint + * table. Now pick possible digital endpoints from the active codecs. + */ + + for (i = 0; i < 16; i++) + if (mixer->codecmask & (1 << i)) + if (mixer->codecs[i]->active) + { + copy_endpoints(mixer, mixer->codecs[i], 1); /* Copy digital endpoints from codec to mixer */ + } + + if (!mixer->remap_avail) + check_names (mixer); + + propagate_names (mixer); + perform_pin_sense (mixer); + + if (mixer->chip_name == NULL) + mixer->chip_name = "None"; + DDB (cmn_err (CE_CONT, "Mixer: %s %s\n", mixer->name, mixer->chip_name)); + //sprintf (tmp, "%s %s", mixer->name, mixer->chip_name); + sprintf (tmp, "High Definition Audio %s", mixer->chip_name); + + if ((mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + osdev, + osdev, + tmp, + &hda_mixer_driver, + sizeof (mixer_driver_t), mixer)) < 0) + { + return NULL; + } + + mixer_devs[mixer_dev]->hw_devc = devc; + mixer_devs[mixer_dev]->priority = 10; /* Known motherboard device */ + mixer->mixer_dev = mixer_dev; + mixer_ext_set_init_fn (mixer->mixer_dev, hdaudio_mix_init, + mixer->ncontrols * 4); + touch_mixer (mixer->mixer_dev); + + return mixer; +} + +/*ARGSUSED*/ +static int +find_playvol_widget (hdaudio_mixer_t * mixer, int cad, int wid) +{ + int this_wid = wid; + + return this_wid; +} + +/*ARGSUSED*/ +static int +find_recvol_widget (hdaudio_mixer_t * mixer, int cad, int wid) +{ + int this_wid = wid; + + return this_wid; +} + +/*ARGSUSED*/ +static int +find_recsrc_widget (hdaudio_mixer_t * mixer, int cad, int wid) +{ + int this_wid = wid; + + return this_wid; +} + +static int +attach_node (hdaudio_mixer_t * mixer, int cad, int wid, int parent) +{ + static const char *widget_types[16] = { + "Audio output", + "Audio input", + "Audio mixer", + "Audio selector", + "Pin complex", + "Power widget", + "Volume knob", + "Beep generator", + "Reserved8", + "Reserved9", + "ReservedA", + "ReservedB", + "ReservedC", + "ReservedD", + "ReservedE", + "Vendor defined audio" + }; + + static const char *widget_id[16] = { + "pcm", + "rec", + "mix", + "select", + "jack", + "power", + "vol", + "beep", + "unkn", + "unkn", + "unkn", + "unkn", + "unkn", + "unkn", + "unkn", + "vendor" + }; + + static const int bit_sizes[] = { + 8, + 16, + 20, + 24, + 32 + }; + + static const unsigned int bit_fmts[] = { + AFMT_U8, + AFMT_S16_LE, + AFMT_S32_LE, + AFMT_S32_LE, + AFMT_S32_LE + }; + + static const int srates[] = { + 8000, + 11025, + 16000, + 22050, + 32000, + 44100, + 48000, + 88200, + 96000, + 176400, + 192000, + 384000 + }; + + unsigned int widget_caps, b, pstate, group_type_in; + unsigned int inamp_caps, outamp_caps; + int group_type, wid_type; + int i; + + codec_t *codec = mixer->codecs[cad]; + widget_t *widget; + + if (codec == &NULL_codec) + return 0; + + if (!corb_read + (mixer, cad, wid, 0, GET_PARAMETER, HDA_GROUP_TYPE, &group_type_in, &b)) + group_type_in = 0; + + if (wid >= MAX_WIDGETS) + { + cmn_err (CE_WARN, "Too many widgets for codec %d (%d/%d)\n", cad, wid, MAX_WIDGETS); + return 0; + } + + mixer->ncontrols++; + + codec->nwidgets = wid + 1; + widget = &codec->widgets[wid]; + + widget->cad = cad; + widget->wid = wid; + + widget->rgbcolor = 0; + + group_type = group_type_in & 0xff; + widget->group_type = group_type_in; + + DDB (cmn_err (CE_CONT, "Node %d, parent %d type %d, unsol capa %d\n", + wid, parent, group_type, !!(group_type_in & 0x100))); + + if (!corb_read + (mixer, cad, wid, 0, GET_PARAMETER, HDA_WIDGET_CAPS, &widget_caps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_WIDGET_CAPS failed\n"); + return 0; + } + + if (widget_caps & WCAP_AMP_CAP_OVERRIDE) /* Amp param override? */ + { + if (!corb_read (mixer, widget->cad, widget->wid, 0, + GET_PARAMETER, HDA_OUTPUTAMP_CAPS, &outamp_caps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n"); + return OSS_EIO; + } + widget->outamp_caps = outamp_caps; + + if (!corb_read (mixer, widget->cad, widget->wid, 0, + GET_PARAMETER, HDA_INPUTAMP_CAPS, &inamp_caps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTAMP_CAPS failed\n"); + return OSS_EIO; + } + widget->inamp_caps = inamp_caps; + } + else + { + widget->outamp_caps = outamp_caps = codec->default_outamp_caps; + widget->inamp_caps = inamp_caps = codec->default_inamp_caps; + } + + if (!corb_read (mixer, cad, wid, 0, GET_POWER_STATE, 0, &pstate, &b)) + return 0; + + /* power up each of the widgets if there is a Power Capability (1<<10) */ + if (widget_caps & WCAP_POWER_CTL) + corb_write (mixer, cad, wid, 0, SET_POWER_STATE, 0); + + widget->widget_caps = widget_caps; + + wid_type = (widget_caps >> 20) & 0x0f; + DDB (cmn_err + (CE_CONT, "\tWidget type %d (%s)(%s)\n", wid_type, + widget_types[wid_type], widget_id[wid_type])); + DDB (cmn_err (CE_CONT, "\tPower State %d\n", pstate)); + + if (widget_caps & WCAP_CONN_LIST) + { + unsigned int clen; + /* Handle connection list */ + + if (!corb_read + (mixer, cad, wid, 0, GET_PARAMETER, HDA_CONNLIST_LEN, &clen, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_CONNLIST_LEN failed\n"); + return 0; + } + + if (clen & 0x80) + { + cmn_err (CE_WARN, "Long form connection list not supported\n"); + return 0; + } + + if (clen > 0) + { + if (clen > MAX_CONN) + { + cmn_err (CE_WARN, "Too many connections\n"); + return 0; + } + + DDB (cmn_err (CE_CONT, "\tConn list (%d): ", clen)); + + for (i = 0; i < clen; i += 4) + { + int j; + unsigned int a; + + if (!corb_read + (mixer, cad, wid, 0, GET_CONNECTION_LIST_ENTRY, i, &a, &b)) + { + cmn_err (CE_WARN, "GET_CONNECTION_LIST_ENTRY failed\n"); + return 0; + } + + for (j = 0; j < 4 && (i + j) < clen; j++) + { + int v, is_range = 0; + + if (widget->nconn >= MAX_CONN) + { + cmn_err (CE_WARN, + "Too many connections for widget %d (%d)\n", + widget->wid, widget->nconn); + break; + } + + v = (a >> (j * 8)) & 0xff; + DDB (cmn_err (CE_CONT, "%d ", v)); + + if (v & 0x80) + { + is_range = 1; + v &= ~0x80; + } + + if (v < 0 || v >= MAX_WIDGETS) + { + cmn_err (CE_NOTE, + "Connection %d for widget %d is out of range (%d) - Skipped\n", + j, widget->wid, v); + continue; + } + + if (is_range) /* Range: prev...v */ + { + int x; + codec->widgets[v].references[codec->widgets[v]. + refcount++] = wid; + + if (widget->nconn < 1) + { + cmn_err (CE_CONT, + "Bad range connection for widget %d\n", + widget->wid); + continue; + } + + for (x = widget->connections[widget->nconn - 1] + 1; + x <= v; x++) + { + if (widget->nconn >= MAX_CONN) + { + cmn_err (CE_WARN, + "Too many connections(B) for widget %d (%d)\n", + widget->wid, widget->nconn); + break; + } + + widget->connections[widget->nconn++] = x; + codec->widgets[x].references[codec->widgets[x]. + refcount++] = wid; + } + } + else + { + widget->connections[widget->nconn++] = v; + codec->widgets[v].references[codec->widgets[v]. + refcount++] = wid; + } + } + } + + DDB (cmn_err (CE_CONT, "\n")); + } + } + + widget->wid_type = wid_type; + + strcpy (widget->name, widget_id[wid_type]); + + if (group_type == 0) /* Not group but a widget */ + switch (wid_type) + { + case NT_DAC: /* Audio output */ + case NT_ADC: /* Audio input */ + { + unsigned int sizes; + int j; + hdaudio_endpointinfo_t *endpoint; + + if (wid_type == 0) + { /* Output endpoint */ + if (mixer->num_outendpoints >= HDA_MAX_OUTSTREAMS) + { + cmn_err (CE_WARN, "Too many output endpoints\n"); + return 0; + } + + endpoint = &codec->outendpoints[codec->num_outendpoints++]; + + endpoint->stream_number = endpoint->default_stream_number = + ++mixer->num_outendpoints; + endpoint->ix = codec->num_outendpoints - 1; + endpoint->iddle_stream = 0; + } + else + { /* Input endpoint */ + if (mixer->num_inendpoints >= HDA_MAX_INSTREAMS) + { + cmn_err (CE_WARN, "Too many input endpoints\n"); + return 0; + } + + endpoint = &codec->inendpoints[codec->num_inendpoints++]; + + endpoint->stream_number = endpoint->default_stream_number = + ++mixer->num_inendpoints; + endpoint->ix = codec->num_inendpoints - 1; + endpoint->iddle_stream = 0; + } + + endpoint->cad = cad; + endpoint->base_wid = wid; + endpoint->recsrc_wid = wid; + endpoint->volume_wid = wid; + endpoint->nrates=0; + endpoint->name = widget->name; + + widget->endpoint = endpoint; + + /* + * Find the widgets that manage rec/play volumes and recording + * source selection. + */ + switch (wid_type) + { + case NT_DAC: + endpoint->volume_wid = find_playvol_widget (mixer, cad, wid); + break; + + case NT_ADC: + endpoint->volume_wid = find_recvol_widget (mixer, cad, wid); + endpoint->recsrc_wid = find_recsrc_widget (mixer, cad, wid); + break; + } + + if (widget->widget_caps & WCAP_STEREO) + endpoint->channels = 2; + else + endpoint->channels = 1; + + sizes = codec->sizes; + + if (widget->widget_caps & WCAP_DIGITAL) /* Digital */ + { + endpoint->is_digital = 1; + if (wid_type == NT_ADC) + strcpy (widget->name, "spdifin"); + else + { + strcpy (widget->name, "spdifout"); + corb_write (mixer, cad, wid, 0, SET_SPDIF_CONTROL1, 1); /* Digital output enable */ + endpoint->iddle_stream = FRONT_STREAM; + } + + endpoint->fmt_mask |= AFMT_AC3; + if (sizes & (1 << 20)) /* 32 bits */ + { + endpoint->fmt_mask |= AFMT_SPDIF_RAW; + } + } + else + { + endpoint->is_digital = 0; + } + + if (widget->widget_caps & WCAP_FORMAT_OVERRIDE) /* Override */ + { + if (!corb_read (mixer, cad, wid, 0, + GET_PARAMETER, HDA_PCM_SIZES, &sizes, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_PCM_SIZES failed\n"); + return 0; + } + } + + widget->sizes = sizes; + endpoint->sizemask = sizes; + if (sizes == 0) + { + corb_read (mixer, cad, codec->afg, 0, GET_PARAMETER, + HDA_PCM_SIZES, &sizes, &b); + widget->sizes = sizes; + endpoint->sizemask = sizes; + } + + DDB (cmn_err (CE_CONT, "\tPCM Size/Rate %08x\n", sizes)); + + for (j = 0; j < 5; j++) + if (sizes & (1 << (j + 16))) + { + DDB (cmn_err + (CE_CONT, "\t\tSupports %d bits\n", bit_sizes[j])); + endpoint->fmt_mask |= bit_fmts[j]; + } + + for (j = 0; j < 12; j++) + if (sizes & (1 << j)) + { + DDB (cmn_err (CE_CONT, "\t\tSupports %d Hz\n", srates[j])); + if (endpoint->nrates < 20) + { + endpoint->rates[endpoint->nrates++] = srates[j]; + } + } + + if ((widget->widget_caps & WCAP_DIGITAL) && wid_type == NT_DAC) /* Digital output */ + { + /* + * Select front output as the default stream number. In + * this way copy of the analog front signal will automatically + * be delivered to the S/PDIF outpput when the S/PDIF device + * is not being used for some other purpose. + */ + corb_write (mixer, cad, wid, 0, SET_CONVERTER, + FRONT_STREAM << 4); + } + else + { + /* Select the iddle stream (0) for analog outputs */ + corb_write (mixer, cad, wid, 0, SET_CONVERTER, + IDDLE_STREAM << 4); + } + /* Select 48 kHz/16 bits/stereo */ + corb_write (mixer, cad, wid, 0, SET_CONVERTER_FORMAT, 0x0009); + + } + break; + + case NT_KNOB: /* Volume knob */ + /* Clear the direct control bit */ + corb_write (mixer, cad, wid, 0, SET_VOLUME_KNOB_CONTROL, 0x00); + break; + + case NT_PIN: /* Pin complex */ + { + unsigned int conf; + unsigned int pincaps; + + if (!corb_read + (mixer, cad, wid, 0, GET_CONFIG_DEFAULT, 0, &conf, &b)) + return 0; + if (!corb_read (mixer, cad, wid, 0, + GET_PARAMETER, HDA_PIN_CAPS, &pincaps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_PIN_CAPS failed\n"); + return 0; + } + + widget->pincaps = pincaps; +#if 0 + if (widget->widget_caps & WCAP_UNSOL_CAPABLE) + corb_write (mixer, cad, wid, 0, SET_UNSOLICITED, 0x80 | wid); +#endif + + if (conf != 0) + { + int default_device = (conf >> 20) & 0x0f; + int default_loc = (conf >> 24) & 0x3f; + int conn = (conf >> 30) & 0x03; + + int color; + int no_color=0; + char *name = NULL, *loc = "", *color_name = NULL; + + color = (conf >> 12) & 0x0f; + + if (pincaps & (1 << 6)) + cmn_err (CE_WARN, "Balanced I/O not supported\n"); + if (!(pincaps & (1 << 5))) /* No input */ + widget->pin_type = PIN_OUT; + if (!(pincaps & (1 << 4))) + widget->pin_type = PIN_IN; + + DDB (cmn_err (CE_CONT, "\tConfig default %08x\n", conf)); + + if ((default_loc & 0x0f) == 0x1) /* Rear panel - default */ + loc = ""; + if ((default_loc & 0x0f) == 0x2) /* Front panel */ + loc = "fp-"; + if ((default_loc & 0xf0) == 0x10) /* Internal func - eg cd/tad/spk */ + loc = "int-"; + + if (conn == 1 && !(hdaudio_noskip & 1)) /* Pin not connected to anything */ + { + widget->skip = 1; + widget->skip_output = 1; + } + + switch (default_device) + { + case 0x0: + name = "lineout"; + widget->pin_type = PIN_OUT; + break; + case 0x1: + name = "speaker"; + no_color=1; + widget->pin_type = PIN_OUT; + break; + case 0x2: + name = "headphone"; + widget->pin_type = PIN_OUT; + break; + case 0x3: + name = "cd"; + no_color=1; + widget->pin_type = PIN_IN; + break; + case 0x4: + name = "spdifout"; + no_color=1; + widget->pin_type = PIN_OUT; + break; + case 0x5: + name = "digout"; + no_color=1; + widget->pin_type = PIN_OUT; + break; + case 0x6: + name = "modem"; + no_color=1; + break; + case 0x7: + name = "phone"; + no_color=1; + break; + case 0x8: + name = "linein"; + widget->pin_type = PIN_IN; + break; + case 0x9: + name = "aux"; + break; + case 0xa: + name = "mic"; + widget->pin_type = PIN_MIC; + break; + case 0xb: + name = "telephony"; + no_color=1; + break; + case 0xc: + name = "spdifin"; + no_color=1; + break; + case 0xd: + name = "digin"; + no_color=1; + break; + case 0xe: + name = "reserved"; + no_color=1; + break; + case 0xf: /* Unused pin widget */ + if (hdaudio_noskip & 2) break; + widget->skip = 1; + widget->skip_output = 1; + break; + } + +/* process only colored jacks and skip fixed function jacks */ + switch (color) + { + case 0x1: + color_name = "black"; + widget->rgbcolor = OSS_RGB_BLACK; + break; + case 0x2: + color_name = "gray"; + widget->rgbcolor = OSS_RGB_GRAY; + break; + case 0x3: + color_name = "blue"; + widget->rgbcolor = OSS_RGB_BLUE; + break; + case 0x4: + color_name = "green"; + widget->rgbcolor = OSS_RGB_GREEN; + break; + case 0x5: + color_name = "red"; + widget->rgbcolor = OSS_RGB_RED; + break; + case 0x6: + color_name = "orange"; + widget->rgbcolor = OSS_RGB_ORANGE; + break; + case 0x7: + color_name = "yellow"; + widget->rgbcolor = OSS_RGB_YELLOW; + break; + case 0x8: + color_name = "purple"; + widget->rgbcolor = OSS_RGB_PURPLE; + break; + case 0x9: + color_name = "pink"; + widget->rgbcolor = OSS_RGB_PINK; + break; + case 0xe: + color_name = "white"; + widget->rgbcolor = OSS_RGB_WHITE; + break; + + default: + if (name != NULL) + color_name = name; + else + color_name = "internal"; + } + + if (no_color) + widget->rgbcolor = 0; + + if (default_device == 0xf) /* Not present */ + { + widget->rgbcolor=0; + color_name = "internal"; + } + + sprintf (widget->color, "%s%s", loc, color_name); +/* + * By Hannu 20080111 + * Use jack color as the widget name if no name was defined or if the default + * function is lineout. This fixes the problem of several jacks being named + * as lineout. + */ + if (name == NULL || default_device == 0x00) + name = color_name; + sprintf (widget->name, "%s%s", loc, name); + } + } + break; + } + +#if 0 + if (!corb_read + (mixer, cad, wid, 0, GET_PARAMETER, HDA_NODE_COUNT, &node_count, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT1 failed\n"); + return 0; + } + + first_node = (node_count >> 16) & 0xff; + num_nodes = node_count & 0xff; + + DDB (cmn_err + (CE_CONT, "\tFirst node %d, num nodes %d\n", first_node, num_nodes)); + + if (first_node > 0) + for (i = first_node; i < first_node + num_nodes; i++) + if (!attach_node (mixer, cad, i, wid)) + return 0; +#endif +/* + * Handle hardcodded widget names + */ + + if (codec->remap != NULL) + { + int w; + + mixer->remap_avail=1; + + for (w = 0; codec->remap[w] != NULL; w++) + if (w == wid) + { + char *s = codec->remap[w]; + + if (*s != 0) + { + strcpy (widget->name, s); + if (*widget->color == 0) + { + strcpy (widget->color, widget->name); + } + } + break; + } + } + + return 1; +} + +/*ARGSUSED*/ +static int +attach_group (hdaudio_mixer_t * mixer, int cad, int wid, int parent, int group_type) +{ + unsigned int a, b, gt; + int i, first_node, num_nodes; + codec_t *codec = mixer->codecs[cad]; + + if (codec == &NULL_codec) + return 0; + + if (!corb_read (mixer, cad, wid, 0, + GET_PARAMETER, HDA_OUTPUTAMP_CAPS, + &codec->default_outamp_caps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_OUTPUTAMP_CAPS failed\n"); + return 0; + } + + if (!corb_read (mixer, cad, wid, 0, + GET_PARAMETER, HDA_INPUTAMP_CAPS, + &codec->default_inamp_caps, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_INPUTTAMP_CAPS failed\n"); + return 0; + } + + if (!corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_NODE_COUNT, &a, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT2 failed\n"); + return 0; + } + + first_node = (a >> 16) & 0xff; + num_nodes = a & 0xff; + + corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_GROUP_TYPE, >, &b); + DDB (cmn_err (CE_CONT, "\tGroup %d First node %d, num nodes %d\n", wid, + first_node, num_nodes)); +/* + * Ignore other than audio function groups. Codecs probably allocate + * higher widget number for the modem group than the audio group. So in this + * way we can have smaller MAX_WIDGETS which in turn conserves memory. + */ + if ((gt & 0xff) != group_type) + return 0; + + if (corb_read (mixer, cad, wid, 0, GET_PARAMETER, HDA_PCM_SIZES, &a, &b)) + { + codec->sizes = a; + } + + if (first_node > 0) + for (i = first_node; i < first_node + num_nodes; i++) + if (!attach_node (mixer, cad, i, wid)) + return 0; + + if (num_nodes >= 1) + codec->active=1; + return 1; +} + +static void +polish_widget_list (hdaudio_mixer_t * mixer, int cad) +{ + widget_t *widget; + codec_t *codec; + int wid, conn, loop; + int skip = 0; + int do_jacksense = 0; + + if (hdaudio_noskip & 4) return; + + if (mixer->codecs[cad] == &NULL_codec) + { + cmn_err (CE_WARN, "Bad codec %d\n", cad); + } + codec = mixer->codecs[cad]; + + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + } + +/* + * Use jack sensing information to remove unconnected I/O pints from the mixer + * interface. + */ + + do_jacksense = 1; + if (codec->num_jacks_plugged < 1 || hdaudio_jacksense < 1) + do_jacksense = 0; + + if (do_jacksense) + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->wid_type != NT_PIN) /* Not a pin widget */ + continue; + + if (!widget->plugged_in) + widget->skip = 1; + } + + /* + * Check all widgets and mark them unusable (skip=1) if all of their input + * connections are marked to be skipped. + * + * This needs to be done number of times so that the skip status propagates + * to the end of the longest path. + */ + + for (loop = 0; loop < codec->nwidgets / 4; loop++) /* nwidgets/4 iterations */ + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->skip || widget->used) + continue; + + skip = 1; /* For now */ + for (conn = 0; conn < widget->nconn; conn++) + { + if (!codec->widgets[widget->connections[conn]].skip) + skip = 0; /* Cannot be skipped */ + } + + if (skip && widget->nconn > 0) + { + widget->skip = 1; + widget->used = 1; + } + } + +/* + * Do the same backwards. Remove widgets that don't have connectivity to any + * of the pin widgets. + */ + for (loop = 0; loop < codec->nwidgets / 4; loop++) /* nwidgets/4 iterations */ + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->skip_output || widget->used) + continue; + + skip = 1; /* For now */ + for (conn = 0; conn < widget->refcount; conn++) + { + if (!codec->widgets[widget->references[conn]].skip_output) + skip = 0; /* Cannot be skipped */ + } + + if (skip && widget->refcount > 0) + { + widget->skip_output = 1; + widget->used = 1; + } + } + +/* + * Final pass. + */ + + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->skip_output) + { + widget->skip = 1; + } + } +} + + +/* ARGSUSED */ +static int +attach_codec (hdaudio_mixer_t * mixer, int cad, char *hw_info, + unsigned int pci_subdevice, int group_type) +{ + unsigned int a, b, x; + int subix, ix, i; + int first_node, num_nodes; + int has_audio_group = 0; + codec_t *codec; + + if (cad >= MAX_CODECS) + { + cmn_err (CE_WARN, "attach_codec: Too many codecs %d\n", cad); + return OSS_EIO; + } + + mixer->ncodecs = cad + 1; + + if (mixer->codecs[cad] == &NULL_codec) + { + if ((codec = PMALLOC (mixer->osdev, sizeof (*codec))) == NULL) + { + cmn_err (CE_CONT, "Cannot allocate codec descriptor\n"); + return OSS_ENOMEM; + } + + memset (codec, 0, sizeof (*codec)); + + mixer->codecs[cad] = codec; + } + else + { + codec = mixer->codecs[cad]; + } + + corb_write (mixer, cad, 0, 0, SET_POWER_STATE, 0); /* Power up everything */ + + if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &a, &b)) + { + if (group_type == 1) + { + sprintf (hw_info, " Codec %2d: Not present\n", cad); + cmn_err (CE_NOTE, + "attach_codec: Codec #%d is not physically present\n", + cad); + } + return OSS_EIO; + } + codec->vendor_id = a; + +/* + * Find out the primary group list + */ + + if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_NODE_COUNT, &x, &b)) + { + cmn_err (CE_WARN, "GET_PARAMETER HDA_NODE_COUNT3 failed\n"); + return OSS_EIO; + } + + codec->first_node = first_node = (x >> 16) & 0xff; + num_nodes = x & 0xff; + +/* + * Check if this one is an audio codec (has an audio function group) + */ + for (i = first_node; i < first_node + num_nodes; i++) + { + unsigned int gt; + + corb_read (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, >, &b); +/* + * Handle only the function group type requested by the upper layer code. + */ + if ((gt & 0xff) != 1) + continue; + + has_audio_group = 1; + } + +/* + * Find codec specific settings + */ + for (ix = 0; codecs[ix].id != 0; ix++) + if (codecs[ix].id == a) + break; + + DDB (cmn_err + (CE_CONT, "HD audio Codec ID: %08x (%s)\n", a, codecs[ix].name)); + + if (codecs[ix].id == 0) /* Unknown codec */ + { + if (group_type == 1) + sprintf (hw_info, " Codec %2d: Unknown (0x%08x", cad, a); + cmn_err (CE_NOTE, "HDA codec 0x%08x not known yet\n", a); + /* + * Create hexadecimal codec ID + */ + if (has_audio_group && mixer->chip_name == NULL) + if ((mixer->chip_name = PMALLOC (mixer->osdev, 32)) != NULL) + { + sprintf (mixer->chip_name, "0x%08x", a); + } + } + else + { + if (group_type == 1) + sprintf (hw_info, " Codec %2d: %s (0x%08x", cad, codecs[ix].name, a); + } + + if (has_audio_group && mixer->chip_name == NULL) + { + mixer->chip_name = codecs[ix].name; + + } + + if (codecs[ix].remap != NULL) + codec->remap = codecs[ix].remap; + + if (codecs[ix].flags != 0) + codec->vendor_flags = codecs[ix].flags; + + if (codecs[ix].mixer_init != NULL) + codec->mixer_init = codecs[ix].mixer_init; + + codec->multich_map = codecs[ix].multich_map; + + if (corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_REVISION, &a, &b)) + { + DDB (cmn_err (CE_CONT, "HDA codec revision %d.%d (%d.%d) (0x%08x)\n", + (a >> 20) & 0xf, + (a >> 16) & 0xf, (a >> 8) & 0xff, a & 0xff, a)); + } + else + DDB (cmn_err (CE_CONT, "Can't get codec revision\n")); + + codec->codec_desc = &codecs[ix]; + + DDB (cmn_err (CE_CONT, "**** Codec %d ****\n", cad)); + DDB (cmn_err + (CE_CONT, "First node %d, num nodes %d\n", first_node, num_nodes)); + + for (i = first_node; i < first_node + num_nodes; i++) + { + corb_read (mixer, cad, i, 0, GET_PARAMETER, HDA_GROUP_TYPE, &a, &b); + if ((a & 0xff) == group_type) /* Proper function group type */ + { + codec->afg = i; + + if (corb_read (mixer, cad, i, 0, GET_SUBSYSTEM_ID, 0, &a, &b)) + { + DDB (cmn_err (CE_CONT, "Subsystem ID = 0x%08x\n", a)); + + if (group_type == 1) + { + /* Append subvendor ID to hw_info */ + hw_info += strlen (hw_info); + sprintf (hw_info, "/0x%08x", a); + } + + codec->subvendor_id = a; + + for (subix = 0; subdevices[subix].id != 0; subix++) + if (subdevices[subix].id == a) + { + if (subdevices[subix].main_id != 0) + if (subdevices[subix].main_id != codec->vendor_id) + continue; + + if (subdevices[subix].pci_subdevice != 0) + if (subdevices[subix].pci_subdevice != pci_subdevice) + continue; + + + DDB (cmn_err + (CE_CONT, "Subdevice known as %s\n", + subdevices[subix].name)); + if (group_type == 1) + { + hw_info += strlen (hw_info); + sprintf (hw_info, " %s", subdevices[subix].name); + } + if (subdevices[subix].remap != NULL) + { + codec->remap = subdevices[subix].remap; + } + + if (subdevices[subix].multich_map != 0) + codec->multich_map = subdevices[subix].multich_map; + if (subdevices[subix].flags != 0) + codec->vendor_flags = subdevices[subix].flags; + if (subdevices[subix].mixer_init != NULL) + { + codec->mixer_init = subdevices[subix].mixer_init; + } + } + } + break; + } + } + + hw_info += strlen (hw_info); + if (group_type == 1) + strcpy (hw_info, ")\n"); + + if (codec->multich_map == 0) + { + codec->multich_map = 0x76543210; /* Sequential order */ + } + + for (i = first_node; i < first_node + num_nodes; i++) + { + if (!attach_group (mixer, cad, i, 0, group_type)) + continue; + + /* power up the AFG! */ + corb_write (mixer, cad, i, 0, SET_POWER_STATE, 0); + } + + /* Initialize and setup manually endpoints for Si3055. */ + if ((mixer->codecs[cad]->vendor_flags & VF_SI3055_HACK) && (group_type == 2)) + { + hdaudio_si3055_endpoint_init(mixer, cad); + } + + if (has_audio_group) + { + polish_widget_list (mixer, cad); + } + + copy_endpoints(mixer, codec, 0); /* Copy analog endpoints from codec to mixer */ + + return (has_audio_group) ? 0 : OSS_EIO; +} + +int +hdaudio_mixer_get_mixdev (hdaudio_mixer_t * mixer) +{ + return mixer->mixer_dev; +} + +void +hdaudio_mixer_set_initfunc (hdaudio_mixer_t * mixer, + mixer_create_controls_t func) +{ + mixer->client_mixer_init = func; +} + +#define BASE44k (1<<14) + +static const struct hdaudio_rate_def _hdaudio_rates[] = { + /* 48 kHz based rates */ + {192000, (3 << 11)}, /* 4x */ + {96000, (1 << 11)}, /* 2x */ + {48000, 0}, /* 1x */ + {24000, (1 << 8)}, /* 1/2x */ + {16000, (2 << 8)}, /* 1/3x */ + {12000, (3 << 8)}, /* 1/4x */ + {9600, (4 << 8)}, /* 1/5x */ + {8000, (5 << 8)}, /* 1/6x */ + /* TODO: These rates didn't work for some reason. */ + /* 44.1 kHz based rates */ + {176400, BASE44k | (3 << 11)}, /* 4x */ + {88200, BASE44k | (1 << 11)}, /* 2x */ + {44100, BASE44k}, /* 1x */ + {22050, BASE44k | (1 << 8)}, /* 1/2x */ + {14700, BASE44k | (2 << 8)}, /* 1/3x */ + {11025, BASE44k | (3 << 8)}, /* 1/4x */ + {8820, BASE44k | (4 << 8)}, /* 1/5x */ + {7350, BASE44k | (5 << 8)}, /* 1/6x */ + {0} +}; + +const struct hdaudio_rate_def *hdaudio_rates = _hdaudio_rates; + +int +hdaudio_codec_setup_endpoint (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, + int rate, int channels, int fmt, + int stream_number, unsigned int *setupbits) +{ + + unsigned int tmp, spdif, dummy; + int i; + + endpoint->auto_muted = 0; + + if (!corb_read + (mixer, endpoint->cad, endpoint->base_wid, 0, GET_SPDIF_CONTROL, 0, + &spdif, &dummy)) + spdif = 0; + + spdif &= ~(1 << 5); /* Audio */ + + tmp = 0; + + if (fmt == AFMT_AC3) + channels = 2; + + tmp |= channels - 1; + + switch (fmt) + { + case AFMT_U8: + break; + + case AFMT_S16_LE: + tmp |= 0x00000010; + break; + + case AFMT_S32_LE: + if (endpoint->sizemask & (1 << 20)) /* 32 bits */ + tmp |= 0x00000040; + else if (endpoint->sizemask & (1 << 19)) /* 24 bits */ + tmp |= 0x00000030; + else if (endpoint->sizemask & (1 << 18)) /* 20 bits */ + tmp |= 0x00000020; + else + { + cmn_err (CE_WARN, "Bad bit size\n"); + return OSS_EIO; + } + break; + + case AFMT_AC3: + tmp &= 0xff; + tmp |= 0x11; /* 16 bits stereo */ + spdif |= (1 << 5); /* Data */ + break; + + case AFMT_SPDIF_RAW: + tmp &= 0xff; + tmp |= 0x81; /* 32 bits stereo */ + break; + + default: + cmn_err (CE_WARN, "Bad format %x\n", fmt); + return OSS_EIO; + } + + corb_write (mixer, endpoint->cad, endpoint->base_wid, 0, SET_SPDIF_CONTROL1, + spdif & 0xff); +/* + * Finally the sample rate setup + */ + + for (i = 0; hdaudio_rates[i].rate != 0; i++) + if (hdaudio_rates[i].rate == rate) + { + tmp |= hdaudio_rates[i].mask; + break; + } + + *setupbits = tmp; + + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_SI3055_HACK) + { + hdaudio_si3055_set_rate(mixer, endpoint->cad, rate); + } + + corb_write (mixer, endpoint->cad, endpoint->base_wid, 0, + SET_CONVERTER_FORMAT, tmp); + corb_write (mixer, endpoint->cad, endpoint->base_wid, 0, SET_CONVERTER, + stream_number << 4); + + if (channels > 2) + { + /* + * Set up the converters for the other stereo pairs + */ +#if 1 + // TODO: Test this + + int n = (channels + 1) / 2; + + for (i = 1; i < n; i++) + { + hdaudio_endpointinfo_t *ep; + ep = &endpoint[i]; + + corb_write (mixer, ep->cad, ep->base_wid, 0, SET_CONVERTER_FORMAT, + tmp); + corb_write (mixer, ep->cad, ep->base_wid, 0, SET_CONVERTER, + (stream_number << 4) | (i * 2)); + } +#endif + } + + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_VAIO_HACK) + { + /* + * STAC9872 specific hack. In Sony VAIO configurations, the DAC widget + * used for the headphone jack needs to duplicate the stream playing on + * the DAC widget for the speaker when not in multichannel mode. + */ + if (channels <= 2 && endpoint->base_wid == 0x05) + { + corb_write (mixer, endpoint->cad, 0x02, 0, SET_CONVERTER_FORMAT, + tmp); + corb_write (mixer, endpoint->cad, 0x02, 0, SET_CONVERTER, + stream_number << 4); + } + } + +#if 1 + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_ALC88X_HACK) + { + /* + * ALC88x specfic hack. These codecs cannot play S/PDIF unless the front + * DAC widget is playing the same stream. + * + * Analog front output (widget 0x14) will be automatically muted. + */ + if (endpoint->is_digital) + { + unsigned int v, b; + + hdaudio_codec_setup_endpoint (mixer, &mixer->outendpoints[0], rate, + channels, fmt, stream_number, &tmp); + + if (fmt == AFMT_AC3) + if (corb_read + (mixer, endpoint->cad, 0x14, 0, GET_GAIN (1, 0), 0, &v, &b)) + { + endpoint->auto_muted = !(v & 0x80); + + v |= 0x80; /* Mute */ + corb_write (mixer, endpoint->cad, 0x14, 0, + SET_GAIN (1, 0, 1, 1, 0), v); + } + } + } +#endif + + return 0; +} + +int +hdaudio_codec_reset_endpoint (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, int channels) +{ + + int i; + unsigned int v, b; + int n = (channels + 1) / 2; + + /* + * Set all converters to play stream iddle stream (usually 0=silence). + */ + + corb_write (mixer, endpoint->cad, endpoint->base_wid, 0, SET_CONVERTER, + endpoint->iddle_stream << 4); + +#if 1 + // TODO: Test this + if (channels > 2) + for (i = 1; i < n; i++) + { + hdaudio_endpointinfo_t *ep; + + ep = &endpoint[i]; + + corb_write (mixer, ep->cad, ep->base_wid, 0, SET_CONVERTER, + ep->iddle_stream << 4); + } +#endif + + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_VAIO_HACK) + /* Also set headphone DAC to play the iddle stream */ + if (channels <= 2 && endpoint->base_wid == 0x05) + { + corb_write (mixer, endpoint->cad, 0x02, 0, SET_CONVERTER, + endpoint->iddle_stream << 4); + } + + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_ALC88X_HACK) + if (endpoint->is_digital && endpoint->auto_muted) /* Restore automatic analog mute back to normal */ + { + if (corb_read + (mixer, endpoint->cad, 0x14, 0, GET_GAIN (1, 0), 0, &v, &b)) + { + v &= ~0x80; /* Unmute */ + corb_write (mixer, endpoint->cad, 0x14, 0, + SET_GAIN (1, 0, 1, 1, 0), v); + endpoint->auto_muted = 0; + } + } + + return 0; +} + +/*ARGSUSED*/ +void +hda_codec_unsol (hdaudio_mixer_t * mixer, unsigned int upper, + unsigned int lower) +{ + DDB (cmn_err (CE_CONT, "Unsol event %08x %08x\n", upper, lower)); +} + +int +hda_codec_getname (hdaudio_mixer_t * mixer, hda_name_t * name) +{ + widget_t *widget; + + if (name->cad >= mixer->ncodecs) + return OSS_EIO; + if (mixer->codecs[name->cad] == &NULL_codec) + return OSS_EIO; +#if 1 + if (name->wid >= mixer->codecs[name->cad]->nwidgets) + return OSS_EIO; +#endif + + widget = &mixer->codecs[name->cad]->widgets[name->wid]; + strcpy (name->name, widget->name); + + return 0; +} + +int +hda_codec_getwidget (hdaudio_mixer_t * mixer, hda_widget_info_t * info) +{ + widget_t *widget; + + if (info->cad >= mixer->ncodecs) + return OSS_EIO; + if (mixer->codecs[info->cad] == &NULL_codec) + return OSS_EIO; + + widget = &mixer->codecs[info->cad]->widgets[info->wid]; + if (info->wid >= mixer->codecs[info->cad]->nwidgets) + return OSS_EIO; + if (widget == NULL) + return OSS_EIO; + memcpy (info->info, widget, sizeof (*widget)); + + return 0; +} + +int +hdaudio_codec_audio_ioctl (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, + unsigned int cmd, ioctl_arg arg) +{ + //widget_t *base_widget = &mixer->codecs[endpoint->cad]->widgets[endpoint->base_wid]; + widget_t *recsrc_widget = + &mixer->codecs[endpoint->cad]->widgets[endpoint->recsrc_wid]; + widget_t *volume_widget = + &mixer->codecs[endpoint->cad]->widgets[endpoint->volume_wid]; + char tmp[128], *t; + unsigned int linked_wid, a, b; + int i, v, left, right; + int nsteps; + + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_VAIO_HACK) + linked_wid = (endpoint->volume_wid == 0x02) ? 0x05 : + ((endpoint->volume_wid == 0x05) ? 0x02 : 0); + else + linked_wid = 0; + + switch (cmd) + { + case SNDCTL_DSP_GET_RECSRC_NAMES: + *tmp = 0; + t = tmp; + + for (i = 0; i < recsrc_widget->nconn; i++) + { + if (*tmp) /* Not empty */ + *t++ = ' '; + strcpy (t, + mixer->codecs[recsrc_widget->cad]->widgets[recsrc_widget-> + connections[i]]. + name); + t += strlen (t); + } + return oss_encode_enum ((oss_mixer_enuminfo *) arg, tmp, 0); + break; + + case SNDCTL_DSP_GET_RECSRC: + if (!corb_read + (mixer, recsrc_widget->cad, recsrc_widget->wid, 0, GET_SELECTOR, 0, + &a, &b)) + return OSS_EIO; + return *arg = a; + break; + + case SNDCTL_DSP_SET_RECSRC: + a = *arg; + if (a > recsrc_widget->nconn) + return OSS_EIO; + + corb_write (mixer, recsrc_widget->cad, recsrc_widget->wid, 0, + SET_SELECTOR, a); + recsrc_widget->current_selector = a; + mixer_devs[mixer->mixer_dev]->modify_counter++; + return *arg = a; + break; + + case SNDCTL_DSP_GETRECVOL: + nsteps = (volume_widget->inamp_caps >> 8) & 0x3f; + if (nsteps < 1) + nsteps = 1; + if (!corb_read + (mixer, volume_widget->cad, volume_widget->wid, 0, GET_GAIN (0, 1), + 0, &a, &b)) + return OSS_EIO; + if (a & 0x80) /* Muted */ + left = 0; + else + left = ((a & 0x7f) * 100) / nsteps; + if (!corb_read + (mixer, volume_widget->cad, volume_widget->wid, 0, GET_GAIN (0, 0), + 0, &a, &b)) + return OSS_EIO; + if (a & 0x80) /* Muted */ + right = 0; + else + right = ((a & 0x7f) * 100) / nsteps; + v = left | (right << 8); + return *arg = v; + break; + + case SNDCTL_DSP_SETRECVOL: + v = *arg; + + left = v & 0xff; + right = (v >> 8) & 0xff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + v = left | (right << 8); + + nsteps = (volume_widget->inamp_caps >> 8) & 0x3f; + if (nsteps < 1) + nsteps = 1; + + a = (left * nsteps) / 100; + if (left == 0) + a |= 0x80; /* Mute */ + corb_write (mixer, volume_widget->cad, volume_widget->wid, 0, + SET_GAIN (0, 1, 1, 0, 0), a); + a = (right * nsteps) / 100; + if (right == 0) + a |= 0x80; /* Mute */ + corb_write (mixer, volume_widget->cad, volume_widget->wid, 0, + SET_GAIN (0, 1, 0, 1, 0), a); + + mixer_devs[mixer->mixer_dev]->modify_counter++; + return *arg = v; + break; + + case SNDCTL_DSP_GETPLAYVOL: + nsteps = (volume_widget->outamp_caps >> 8) & 0x3f; + if (nsteps < 1) + nsteps = 1; + if (!corb_read + (mixer, volume_widget->cad, volume_widget->wid, 0, GET_GAIN (1, 1), + 0, &a, &b)) + return OSS_EIO; + if (a & 0x80) /* Muted */ + left = 0; + else + left = ((a & 0x7f) * 100) / nsteps; + if (!corb_read + (mixer, volume_widget->cad, volume_widget->wid, 0, GET_GAIN (1, 0), + 0, &a, &b)) + return OSS_EIO; + if (a & 0x80) /* Muted */ + right = 0; + else + right = ((a & 0x7f) * 100) / nsteps; + v = left | (right << 8); + return *arg = v; + break; + + case SNDCTL_DSP_SETPLAYVOL: + v = *arg; + + left = v & 0xff; + right = (v >> 8) & 0xff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + v = left | (right << 8); + + nsteps = (volume_widget->outamp_caps >> 8) & 0x3f; + if (nsteps < 1) + nsteps = 1; + + a = (left * nsteps) / 100; + if (left == 0) + a |= 0x80; /* Mute */ + corb_write (mixer, volume_widget->cad, volume_widget->wid, 0, + SET_GAIN (1, 0, 1, 0, 0), a); + if (linked_wid) + corb_write (mixer, volume_widget->cad, linked_wid, 0, + SET_GAIN (1, 0, 1, 0, 0), a); + a = (right * nsteps) / 100; + if (right == 0) + a |= 0x80; /* Mute */ + corb_write (mixer, volume_widget->cad, volume_widget->wid, 0, + SET_GAIN (1, 0, 0, 1, 1), a); + if (linked_wid) + corb_write (mixer, volume_widget->cad, linked_wid, 0, + SET_GAIN (1, 0, 0, 1, 1), a); + + mixer_devs[mixer->mixer_dev]->modify_counter++; + return *arg = v; + break; + + case SNDCTL_DSP_MODEM_OFFHOOK: + if (!endpoint->is_modem) + { + return OSS_EINVAL; + } + v = *arg; + if (mixer->codecs[endpoint->cad]->vendor_flags & VF_SI3055_HACK) + { + v = hdaudio_si3055_set_offhook(mixer, endpoint->cad, v); + } + else + { + return OSS_ENOTSUP; + } + return *arg = v; + break; + } + + return OSS_EINVAL; +} + +/* + * Support routines for dedicated mixer drivers + */ + +void +hda_codec_add_group (int dev, hdaudio_mixer_t * mixer, int cad, int *group, + int parent_group, const char *name) +{ + int grp; + + if ((grp = mixer_ext_create_group (dev, parent_group, name)) > 0) + *group = grp; +} + +int +hda_codec_add_pingroup (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int *group, int top_group, int *parent_group, + const char *name, int *n, const char *parent_name, + int group_size) +{ + int grp; + widget_t *widget; + codec_t *codec; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + if (widget->used || widget->skip) + return 0; + + if (group_size <= 1 || ((*n % group_size) == 0 && *n > 0)) + { + if ((grp = mixer_ext_create_group (dev, top_group, parent_name)) > 0) + *parent_group = grp; + *n = 0; + } + + if ((grp = mixer_ext_create_group (dev, *parent_group, name)) > 0) + *group = grp; + (*n)++; + + return 1; +} + +int +hda_codec_add_adcgroup (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int *group, int top_group, int *parent_group, + const char *name, int *n, const char *parent_name, + int group_size) +{ + int grp; + widget_t *widget; + codec_t *codec; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + if (widget->used || widget->skip) + return 0; + + if (group_size <= 1 || ((*n % group_size) == 0 && *n > 0)) + { + if ((grp = mixer_ext_create_group (dev, top_group, parent_name)) > 0) + *parent_group = grp; + *n = 0; + } + + if ((grp = mixer_ext_create_group (dev, *parent_group, name)) > 0) + *group = grp; + (*n)++; + + return 1; +} + +int +hda_codec_add_miscgroup (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int *group, int top_group, int *parent_group, + const char *name, int *n, const char *parent_name, + int group_size) +{ + int grp; + widget_t *widget; + codec_t *codec; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + if (widget->used || widget->skip) + return 0; + + if (group_size <= 1 || ((*n % group_size) == 0 && *n > 0)) + { + if ((grp = mixer_ext_create_group (dev, top_group, parent_name)) > 0) + *parent_group = grp; + *n = 0; + } + + if ((grp = mixer_ext_create_group (dev, *parent_group, name)) > 0) + *group = grp; + (*n)++; + + return 1; +} + +int +create_outgain_selector (hdaudio_mixer_t * mixer, widget_t * widget, + int group, const char *name) +{ + int num = MIXNUM (widget, CT_OUTGAINSEL, 0); + int ctl, i; + int maxval; + int offs, step, range; + oss_mixext *ent; + + char tmp[128], *t; + + range = + ((widget->outamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + + 1; + step = + ((widget->outamp_caps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + + 1; + offs = (widget->outamp_caps >> AMPCAP_OFFSET_SHIFT) & AMPCAP_OFFSET_MASK; + + maxval = range; + + if (widget->outamp_caps & AMPCAP_MUTE) + maxval += 1; + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + num, hdaudio_set_control, + MIXT_ENUM, + name, maxval, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + t = tmp; + *t = 0; + + for (i = 0; i < range; i++) + { + int v; + + v = (i - offs) * step * 4; + + if (*tmp != 0) + *t++ = ' '; + + sprintf (t, "%d.%ddB", v / 10, v % 10); + t += strlen (t); + } + + if (widget->outamp_caps & AMPCAP_MUTE) + { + if (*tmp != 0) + *t++ = ' '; + strcpy (t, "mute"); + t += strlen (t); + } + + mixer_ext_set_strings (mixer->mixer_dev, ctl, tmp, 0); + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (mixer->mixer_dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + return 0; +} + +int +create_ingain_selector (hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int group, int ix, + const char *name) +{ + int num = MIXNUM (widget, CT_INGAINSEL, ix); + + int ctl, i; + int maxval; + int offs, step, range; + oss_mixext *ent; + + char tmp[128], *t; + + range = + ((widget->inamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + + 1; + step = + ((widget->inamp_caps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + + 1; + offs = (widget->inamp_caps >> AMPCAP_OFFSET_SHIFT) & AMPCAP_OFFSET_MASK; + + maxval = range; + + if (widget->inamp_caps & AMPCAP_MUTE) + maxval += 1; + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + num, hdaudio_set_control, + MIXT_ENUM, + name, maxval, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + t = tmp; + *t = 0; + + for (i = 0; i < range; i++) + { + int v; + + v = (i - offs) * step * 4; + + if (*tmp != 0) + *t++ = ' '; + + sprintf (t, "%d.%ddB", v / 10, v % 10); + t += strlen (t); + } + + if (widget->inamp_caps & AMPCAP_MUTE) + { + if (*tmp != 0) + *t++ = ' '; + strcpy (t, "mute"); + t += strlen (t); + } + + mixer_ext_set_strings (mixer->mixer_dev, ctl, tmp, 0); + /* Copy RGB color */ + if (widget->color != 0) + if ((ent = mixer_find_ext (mixer->mixer_dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + return 0; +} + +int +hda_codec_add_outamp (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int group, const char *name, int percent, + unsigned int flags) +{ + widget_t *widget; + codec_t *codec; + int typ, num, maxval, val, ctl = 0; + int range, step; + oss_mixext *ent; + extern int mixer_muted; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + range = + ((widget-> + outamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + 1; + step = + ((widget-> + outamp_caps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + 1; + + if (step > 20 /* 5dB */ && range < 5) + { + create_outgain_selector (mixer, widget, group, name); + } + else + { + + maxval = hdaudio_amp_maxval (widget->outamp_caps); + + if (widget->widget_caps & WCAP_STEREO) + { + typ = MIXT_STEREOSLIDER16; + num = MIXNUM (widget, CT_OUTSTEREO, 0); + } + else + { + typ = MIXT_MONOSLIDER16; + num = MIXNUM (widget, CT_OUTMONO, 0); + } + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + num, hdaudio_set_control, + typ, + name, maxval, + flags | MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return ctl; + + /* setup volume */ + val = (maxval * percent) / 100; + val = val | (val << 16); + if (mixer_muted) + val = 0; + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, val); + } + + return ctl; +} + +int +hda_codec_add_outmute (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int group, const char *name, int muted) +{ + widget_t *widget; + codec_t *codec; + int ctl = 0; + oss_mixext *ent; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if (widget->outamp_caps & AMPCAP_MUTE) /* Only mute control */ + { + // name = "mute"; + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, + CT_OUTMUTE, 0), + hdaudio_set_control, + MIXT_MUTE, name, 2, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return ctl; + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_OUTMUTE, 0), + SNDCTL_MIX_WRITE, muted); + return ctl; + } + return 0; +} + +int +hda_codec_add_inamp (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int ix, int group, const char *name, int percent, int flags) +{ + widget_t *widget; + widget_t *src_widget; + codec_t *codec; + int typ, num, maxval, val, ctl = 0, range, step; + oss_mixext *ent; + extern int mixer_muted; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + range = + ((widget-> + outamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + 1; + step = + ((widget-> + outamp_caps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + 1; + + if (step > 20 /* 5dB */ && range < 5) + { + return create_ingain_selector (mixer, codec, widget, group, ix, name); + } + maxval = hdaudio_amp_maxval (widget->inamp_caps); + + if (widget->widget_caps & WCAP_STEREO) + { + typ = MIXT_STEREOSLIDER16; + num = MIXNUM (widget, CT_INSTEREO, ix); + } + else + { + typ = MIXT_MONOSLIDER16; + num = MIXNUM (widget, CT_INMONO, ix); + } + + if (codec->widgets[widget->connections[ix]].skip) + { + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, 0); + return 0; + } + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + num, + hdaudio_set_control, + typ, + name, maxval, + MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL | flags)) < 0) + return ctl; + + /* Setup initial volume */ + val = (maxval * percent) / 100; + val = val | (val << 16); + if (mixer_muted) + val = 0; + + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, val); + + /* Copy RGB color */ + src_widget = &codec->widgets[widget->connections[ix]]; + if (src_widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, ctl)) != NULL) + ent->rgbcolor = src_widget->rgbcolor; + + return ctl; +} + +int +hda_codec_add_inmute (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int ix, int group, const char *name, int muted, unsigned int flags) +{ + widget_t *widget; + codec_t *codec; + oss_mixext *ent; + int ctl = 0; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if (codec->widgets[widget->connections[ix]].skip) + { + int num = MIXNUM (widget, CT_INMUTE, ix); + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, 1); + return 0; + } + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, + CT_INMUTE, ix), + hdaudio_set_control, + MIXT_MUTE, name, 2, + flags | MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_INMUTE, ix), + SNDCTL_MIX_WRITE, muted); + return ctl; +} + +int +hda_codec_set_inmute (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int ix, int group, const char *name, int muted) +{ + widget_t *widget; + codec_t *codec; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + +// cmn_err(CE_CONT, "Set inmute 0x%02x:%d=%d\n", wid, ix, muted); + return hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_INMUTE, ix), + SNDCTL_MIX_WRITE, muted); +} + +int +hda_codec_add_insrc (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int ix, int group, const char *name, int unselected) +{ + widget_t *widget; + codec_t *codec; + oss_mixext *ent; + int ctl = 0; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if (codec->widgets[widget->connections[ix]].skip) + { + int num = MIXNUM (widget, CT_INMUTE, ix); + + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, 1); + return 0; + } + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, + CT_INSRC, ix), + hdaudio_set_control, + MIXT_ONOFF, name, 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, ctl)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_INSRC, ix), + SNDCTL_MIX_WRITE, unselected); + return ctl; +} + +int +hda_codec_add_insrcselect (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int group, int *ctl, const char *name, + int initial_selection) +{ + widget_t *widget; + codec_t *codec; + int i; + oss_mixext *ext; + + *ctl = 0; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if ((*ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, + CT_INSRCSELECT, 0), + hdaudio_set_control, + MIXT_ENUM, name, widget->nconn, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return 0; + + ext = mixer_find_ext (mixer->mixer_dev, *ctl); + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension (x)\n"); + return OSS_EIO; + } + + /* Copy RGB color */ + if (widget->color != 0) + ext->rgbcolor = widget->rgbcolor; + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < widget->nconn; i++) + { + + /* + * ensure that the connection list has a valid widget id - some + * devices have bogus connection lists + */ + if (codec->widgets[widget->connections[i]].wid < codec->first_node) + continue; + + /* + * Show only widgets that are not marked to be ignored. + * Also hide I/O pins that are known to be outputs. + */ + if (!codec->widgets[widget->connections[i]].skip + && codec->widgets[widget->connections[i]].sensed_pin != PIN_OUT) + ext->enum_present[i / 8] |= (1 << (i % 8)); + } + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_INSRCSELECT, 0), + SNDCTL_MIX_WRITE, initial_selection); + return 1; +} + +int +hda_codec_add_select (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int group, const char *name, int *ctl, + int initial_select) +{ + widget_t *widget; + codec_t *codec; + oss_mixext *ext; + int i; + + *ctl = 0; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if ((*ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, CT_SELECT, 0), + hdaudio_set_control, + MIXT_ENUM, + name, + widget->nconn, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return *ctl; + + ext = mixer_find_ext (mixer->mixer_dev, *ctl); + + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension (x)\n"); + return OSS_EIO; + } + /* Copy RGB color */ + if (widget->color != 0) + ext->rgbcolor = widget->rgbcolor; + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < widget->nconn; i++) + { + + /* + * ensure that the connection list has a valid widget id - some + * devices have bogus connection lists + */ + if (codec->widgets[widget->connections[i]].wid < codec->first_node) + continue; + + /* + * Show only widgets that are not marked to be ignored. + * Also hide I/O pins that are known to be outputs. + */ + if (!codec->widgets[widget->connections[i]].skip + && codec->widgets[widget->connections[i]].sensed_pin != PIN_OUT) + ext->enum_present[i / 8] |= (1 << (i % 8)); + } + + if (initial_select > -1) + widget->current_selector = initial_select; + + if (widget->current_selector >= widget->nconn) + widget->current_selector = 0; + corb_write (mixer, widget->cad, widget->wid, 0, SET_SELECTOR, + widget->current_selector); + + return *ctl; +} + +int +hda_codec_add_pinselect (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int group, const char *name, int *ctl, + int initial_select) +{ + widget_t *widget; + codec_t *codec; + unsigned int conf, b; + oss_mixext *ext; + int i; + + *ctl = 0; + + if (cad < 0 || cad >= mixer->ncodecs) + return OSS_ENXIO; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return OSS_ENXIO; + + widget = &codec->widgets[wid]; + + if ((*ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, CT_SELECT, 0), + hdaudio_set_control, + MIXT_ENUM, + name, + widget->nconn + 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return *ctl; + + ext = mixer_find_ext (mixer->mixer_dev, *ctl); + + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension (x)\n"); + return OSS_EIO; + } + + /* Copy RGB color */ + if (widget->color != 0) + ext->rgbcolor = widget->rgbcolor; + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < widget->nconn; i++) + { + + /* + * ensure that the connection list has a valid widget id - some + * devices have bogus connection lists + */ + if (codec->widgets[widget->connections[i]].wid < codec->first_node) + continue; + + /* + * Show only widgets that are not marked to be ignored. + * Also hide I/O pins that are known to be outputs. + */ + if (!codec->widgets[widget->connections[i]].skip + && codec->widgets[widget->connections[i]].sensed_pin != PIN_OUT) + ext->enum_present[i / 8] |= (1 << (i % 8)); + } + + /* + * Enable the input selection (if available) + */ + i = widget->nconn; + if (widget->pincaps & PINCAP_INPUT_CAPABLE) + ext->enum_present[i / 8] |= (1 << (i % 8)); + +/* + * Set the initial value. + * + * Use the default sequence as an index to the output source selectors. + */ + if (widget->sensed_pin == PIN_OUT) + { + if (corb_read + (mixer, widget->cad, widget->wid, 0, GET_CONFIG_DEFAULT, 0, &conf, + &b)) + { + int association, sequence; + + association = (conf >> 4) & 0x0f; + sequence = conf & 0x0f; + + if (association != 0) + { + widget->current_selector = sequence; + } + + } + } + else if (widget->sensed_pin == PIN_IN || widget->sensed_pin == PIN_MIC) + widget->current_selector = widget->nconn; /* Turn on input mode */ + + if (initial_select > -1) + widget->current_selector = initial_select; + + if (widget->current_selector < 0 + || widget->current_selector >= widget->nconn + 1) + widget->current_selector = 0; + + if (widget->current_selector < widget->nconn) + { + /* Output source select */ + corb_write (mixer, cad, wid, 0, SET_SELECTOR, widget->current_selector); + /* Enable output and HP amp. Set vref=Ground */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0xc0); + } + else + { + /* Input select + * Program the correct VRef Values + */ + + if (widget->pin_type == PIN_IN) /* Line-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x20); /*Ground*/ + } + else /* Mic-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x24); /*Vref=8 + 0% */ + } + } + + return *ctl; +} + +void +hda_codec_set_select (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int value) +{ + codec_t *codec; + widget_t *widget; + + if (cad < 0 || cad >= mixer->ncodecs) + return; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return; + + widget = &codec->widgets[wid]; + + widget->current_selector = value; + + corb_write (mixer, cad, wid, 0, SET_SELECTOR, value); +} + +void +hda_codec_set_pinselect (int dev, hdaudio_mixer_t * mixer, int cad, int wid, + int value) +{ + codec_t *codec; + widget_t *widget; + + if (cad < 0 || cad >= mixer->ncodecs) + return; + codec = mixer->codecs[cad]; + + if (wid < 0 || wid >= codec->nwidgets) + return; + + widget = &codec->widgets[wid]; + + widget->current_selector = value; + + if (widget->current_selector < widget->nconn) + { + /* Output source select */ + corb_write (mixer, cad, wid, 0, SET_SELECTOR, widget->current_selector); + /* Enable output and HP amp. Set vref=Ground */ + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0xc0); + } + else + { + /* Input select + * Program the correct VRef Values + */ + + if (widget->pin_type == PIN_IN) /* Line-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x20); /*Ground*/ + } + else /* Mic-in */ + { + corb_write (mixer, cad, wid, 0, SET_PINCTL, 0x24); /*Vref=8 + 0% */ + } + } +} + +int +hda_codec_add_choices (int dev, hdaudio_mixer_t * mixer, int ctl, + const char *choiselist) +{ + mixer_ext_set_strings (dev, ctl, choiselist, 0); + + return 0; +} + +void +hda_codec_set_color(int dev, hdaudio_mixer_t *mixer, int ctl, int color) +{ + oss_mixext *ext; + + if ((ext = mixer_find_ext (mixer->mixer_dev, ctl)) != NULL) + { + ext->rgbcolor = color; +//cmn_err(CE_CONT, "Mixer %s rgb->%06x\n", ext->extname, ext->rgbcolor); + } +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_codec.h b/kernel/drv/oss_hdaudio/hdaudio_codec.h new file mode 100644 index 0000000..c990e31 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_codec.h @@ -0,0 +1,379 @@ +/* + * Purpose: Definitions of HD audio codec functions, structures and macros + */ +/* + * + * 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. + * + */ +#ifndef HDAUDIO_CODEC_H +#define HDAUDIO_CODEC_H + +#define HDA_MAX_OUTSTREAMS 12 +#define HDA_MAX_INSTREAMS 8 + +#define MAX_CODECS 16 +#define MAX_WIDGETS 150 +#define MAX_CONN 24 + +#define CT_INMONO 0x0001 +#define CT_INSTEREO 0x0002 +#define CT_INMUTE 0x0003 +#define CT_INSRC 0x0004 /* Negation of a mute control */ +#define CT_SELECT 0x0005 + +#define CT_OUTMONO 0x0006 +#define CT_OUTSTEREO 0x0007 +#define CT_OUTMUTE 0x0008 + +#define CT_OUTGAINSEL 0x0009 +#define CT_INGAINSEL 0x000a +#define CT_INSRCSELECT 0x000b + +#define corb_read(m, cad, wid, d, verb, parm, p1, p2) \ + m->read(m->devc, cad, wid, d, verb, parm, p1, p2) +#define corb_write(m, cad, wid, d, verb, parm) \ + m->write(m->devc, cad, wid, d, verb, parm) + +#define MIXNUM(widget, ty, ix) \ + ((ix) | (ty<<8) | (widget->wid<<16) | (widget->cad << 24)) +extern int hdaudio_set_control (int dev, int ctrl, unsigned int cmd, + int value); + +typedef struct _hdaudio_mixer_struct hdaudio_mixer_t; + +/* + * Reserved (predefined) stream numbers + */ +#define IDDLE_STREAM 0 /* Reserved for silence */ +#define FRONT_STREAM 1 /* Reserved for front channel stereo pair */ + +typedef struct +{ + char *name; + int is_output; + unsigned char ix, cad, base_wid; + unsigned char recsrc_wid; + unsigned char volume_wid; + int borrow_count; /* Number of other endpoints grouped with this one (for multich) */ + int binding; + int afg; + int min_rate, max_rate; + int channels; + int fmt_mask; + volatile int busy; + int nrates, rates[20]; + unsigned int sizemask; + int stream_number, default_stream_number, iddle_stream; + int is_digital; + int is_modem; + int auto_muted; + int skip; /* Not connected to anywhere */ + int already_used; +} hdaudio_endpointinfo_t; + +/* + * Codec requests + */ + +#define GET_GAIN(inout, leftright) (0xb00|(inout<<7)|(leftright<<5)) +#define SET_GAIN(out,inp,lft, rght, ix) (0x300|(out<<7)|(inp<<6)|(lft<<5)|(rght<<4)|ix) +#define GET_CONVERTER_FORMAT 0xa00 +#define SET_CONVERTER_FORMAT 0x200 +#define GET_PARAMETER 0xf00 +#define GET_SELECTOR 0xf01 +#define SET_SELECTOR 0x701 +#define GET_CONNECTION_LIST_ENTRY 0xf02 +#define GET_PROCESSING_STATE 0xf03 +#define SET_PROCESSING_STATE 0x703 +#define GET_SDI_SELECT 0xf04 +#define SET_SDI_SELECT 0x704 +#define GET_CONVERTER 0xf06 +#define SET_CONVERTER 0x706 +#define GET_PINCTL 0xf07 +#define SET_PINCTL 0x707 +#define GET_UNSOLICITED 0xf08 +#define SET_UNSOLICITED 0x708 +#define GET_CONFIG_DEFAULT 0xf1c +#define SET_POWER_STATE 0x705 +#define GET_POWER_STATE 0xf05 +#define GET_PIN_SENSE 0xf09 +#define TRIGGER_PIN_SENSE 0x709 +#define GET_BEEP 0xf0a +#define SET_BEEP 0x70a +#define GET_EAPD 0xf0c +#define SET_EAPD 0x70c +#define GET_SPDIF_CONTROL 0xf0d +#define SET_SPDIF_CONTROL1 0x70d +#define SET_SPDIF_CONTROL2 0x70e +#define GET_VOLUME_KNOB_CONTROL 0xf0f +#define SET_VOLUME_KNOB_CONTROL 0x70f +#define GET_GPI_DATA 0xf10 +#define SET_GPI_DATA 0x710 +#define GET_GPI_WAKE 0xf11 +#define SET_GPI_WAKE 0x711 +#define GET_GPI_UNSOL 0xf12 +#define SET_GPI_UNSOL 0x712 +#define GET_GPI_STICKY 0xf13 +#define SET_GPI_STICKY 0x713 +#define GET_GPO_DATA 0xf14 +#define SET_GPO_DATA 0x714 +#define GET_GPIO_DATA 0xf15 +#define SET_GPIO_DATA 0x715 +#define GET_GPIO_ENABLE 0xf16 +#define SET_GPIO_ENABLE 0x716 +#define GET_GPIO_DIR 0xf17 +#define SET_GPIO_DIR 0x717 +#define GET_GPIO_WKEN 0xf18 +#define SET_GPIO_WKEN 0x718 +#define GET_GPIO_UNSOL 0xf19 +#define SET_GPIO_UNSOL 0x719 +#define GET_GPIO_STICKY 0xf1a +#define SET_GPIO_STICKY 0x71a +#define GET_SUBSYSTEM_ID 0xf20 +#define GET_STRIPE_CONTROL 0xf24 +#define SET_CODEC_RESET 0x7ff + +/* + * Parameters + */ + +#define HDA_VENDOR 0x00 +#define HDA_REVISION 0x02 +#define HDA_NODE_COUNT 0x04 +#define HDA_GROUP_TYPE 0x05 +#define HDA_AUDIO_GROUP_CAPS 0x08 +#define HDA_WIDGET_CAPS 0x09 +#define HDA_PCM_SIZES 0x0a +#define HDA_STREAM_FMTS 0x0b +#define HDA_PIN_CAPS 0x0c +#define HDA_INPUTAMP_CAPS 0x0d +#define HDA_CONNLIST_LEN 0x0e +#define HDA_SUPPORTED_POWER_STATES 0x0f +#define HDA_PROCESSING_CAPS 0x10 +#define HDA_GPIO_COUNT 0x11 +#define HDA_OUTPUTAMP_CAPS 0x12 +#define HDA_VOLUMEKNOB_CAPS 0x13 + +typedef int (*hdmixer_write_t) (void *devc, unsigned int cad, + unsigned int nid, unsigned int d, + unsigned int verb, unsigned int parm); +typedef int (*hdmixer_read_t) (void *devc, unsigned int cad, unsigned int nid, + unsigned int d, unsigned int verb, + unsigned int parm, unsigned int *upper, + unsigned int *lower); + +#ifdef _KERNEL +extern hdaudio_mixer_t *hdaudio_mixer_create (char *name, void *devc, + oss_device_t * osdev, + hdmixer_write_t writefunc, + hdmixer_read_t readfunc, + unsigned int codecmask, + unsigned int vendor_id, + unsigned int subvendor_id); +extern void hdaudio_mixer_set_initfunc (hdaudio_mixer_t * mixer, + mixer_create_controls_t func); +#endif + +extern int hdaudio_mixer_get_mixdev (hdaudio_mixer_t * mixer); + +extern int hdaudio_mixer_get_outendpoints (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t ** + endpoints, int size); +extern int hdaudio_mixer_get_inendpoints (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t ** endpoints, + int size); + +extern int hdaudio_codec_setup_endpoint (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, + int rate, int channels, int fmt, + int stream_number, + unsigned int *setupbits); +extern int hdaudio_codec_reset_endpoint (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, + int channels); +extern int hdaudio_codec_audio_ioctl (hdaudio_mixer_t * mixer, + hdaudio_endpointinfo_t * endpoint, + unsigned int cmd, ioctl_arg arg); + +extern int hda_codec_getname (hdaudio_mixer_t * mixer, hda_name_t *name); +extern int hda_codec_getwidget (hdaudio_mixer_t * mixer, hda_widget_info_t *info); +extern void hda_codec_unsol (hdaudio_mixer_t * mixer, unsigned int upper, + unsigned int lower); +extern int hdaudio_amp_maxval (unsigned int ampcaps); + +/* + * Audio widget types + */ + +#define NT_DAC 0 +#define NT_ADC 1 +#define NT_MIXER 2 +#define NT_SELECT 3 +#define NT_PIN 4 +#define NT_POWER 5 +#define NT_KNOB 6 +#define NT_BEEP 7 +#define NT_VENDOR 15 + +#endif + +/* + * Struct for sample rate table + */ +struct hdaudio_rate_def +{ + unsigned int rate, mask; +}; + +extern const struct hdaudio_rate_def *hdaudio_rates; + +typedef struct +{ + unsigned char cad, wid; + char name[32]; + char color[32]; + unsigned char wid_type, group_type; + char used; /* Already bound to mixer */ + char skip; /* Ignore this widget as input source */ + char skip_output; /* Ignore this widget as output target */ + + unsigned int widget_caps; +#define WCAP_STEREO (1 << 0) +#define WCAP_INPUT_AMP_PRESENT (1 << 1) +#define WCAP_OUTPUT_AMP_PRESENT (1 << 2) +#define WCAP_AMP_CAP_OVERRIDE (1 << 3) +#define WCAP_FORMAT_OVERRIDE (1 << 4) +#define WCAP_STRIPE (1 << 5) +#define WCAP_PROC_WIDGET (1 << 6) +#define WCAP_UNSOL_CAPABLE (1 << 7) +#define WCAP_CONN_LIST (1 << 8) +#define WCAP_DIGITAL (1 << 9) +#define WCAP_POWER_CTL (1 << 10) +#define WCAP_LR_SWAP (1 << 11) + + unsigned int inamp_caps; + unsigned int outamp_caps; +#define AMPCAP_MUTE (1UL<<31) +#define AMPCAP_STEPSIZE_SHIFT 16 +#define AMPCAP_STEPSIZE_MASK 0x7f +#define AMPCAP_NUMSTEPS_SHIFT 8 +#define AMPCAP_NUMSTEPS_MASK 0x7f +#define AMPCAP_OFFSET_SHIFT 0 +#define AMPCAP_OFFSET_MASK 0x7f + + unsigned int pincaps; +#define PINCAP_EAPD (1<<16) +#define PINCAP_VREF_MASK 0x7f +#define PINCAP_VREF_SHIFT 8 +#define PINCAP_RESERVED (1<<7) +#define PINCAP_BALANCED_PINS (1<<6) +#define PINCAP_INPUT_CAPABLE (1<<5) +#define PINCAP_OUTPUT_CAPABLE (1<<4) +#define PINCAP_HP_DRIVE_CAPABLE (1<<3) +#define PINCAP_JACKSENSE_CAPABLE (1<<2) +#define PINCAP_TRIGGERR_RQRD (1<<1) +#define PINCAP_IMPSENSE_CAPABLE (1<<0) + + unsigned int sizes; + + int nconn; + short connections[MAX_CONN]; + short references[MAX_CONN]; + short refcount; + char plugged_in; + int impsense; /* Impedanse sensing result. -1=no info */ + char pin_type, sensed_pin; +#define PIN_UNKNOWN 0 +#define PIN_IN 1 +#define PIN_MIC 2 +#define PIN_OUT 3 +#define PIN_HEADPHONE 4 + hdaudio_endpointinfo_t *endpoint; + int current_selector; + int rgbcolor; /* RGB value of the jack color */ + int association, sequence; +} widget_t; + +typedef int (*hda_mixer_init_func) (int dev, hdaudio_mixer_t * mixer, int cad, + int group); + +typedef struct codec_desc codec_desc_t; + +typedef struct +{ + const codec_desc_t *codec_desc; + int active; /* Codec has audio or modem functionality */ + unsigned long vendor_flags; + + int nwidgets; + widget_t widgets[MAX_WIDGETS]; + int afg; + int jack_number; + int first_node; + int num_jacks_plugged; + unsigned int sizes; + hda_mixer_init_func mixer_init; + unsigned int default_inamp_caps; + unsigned int default_outamp_caps; + unsigned int vendor_id, subvendor_id; + + int speaker_mode; +#define SPKMODE_DEFAULT 0 +#define SPKMODE_SPEAKER 1 +#define SPKMODE_STEREO 2 +#define SPKMODE_51 3 +#define SPKMODE_71 4 + + int num_inendpoints; + hdaudio_endpointinfo_t inendpoints[HDA_MAX_INSTREAMS]; + int num_outendpoints; + hdaudio_endpointinfo_t outendpoints[HDA_MAX_OUTSTREAMS]; + + unsigned int multich_map; /* See codec_desc_t.multich_map */ + + int mixer_mode; /* For use by dedicated drivers. Initially set to 0 */ + char **remap; +} codec_t; + +struct _hdaudio_mixer_struct +{ + void *devc; + oss_device_t *osdev; + + char name[64]; + char *chip_name; + int mixer_dev; + + hdmixer_write_t write; + hdmixer_read_t read; + + unsigned int codecmask; + + int ncodecs; + codec_t *codecs[MAX_CODECS]; + + int ncontrols; /* Total number of widgets (all codecs) */ + + int num_inendpoints, copied_inendpoints; + hdaudio_endpointinfo_t inendpoints[HDA_MAX_INSTREAMS]; + int num_outendpoints, copied_outendpoints; + hdaudio_endpointinfo_t outendpoints[HDA_MAX_OUTSTREAMS]; + + int npins; /* Used for managing the width of the connectors group */ + int split_connectors; /* Fearless flag used for splitting the connectors geroup */ + mixer_create_controls_t client_mixer_init; + + int remap_avail; +}; + +extern int create_outgain_selector (hdaudio_mixer_t * mixer, widget_t * widget, int group, const char *name); +extern int create_ingain_selector (hdaudio_mixer_t * mixer, codec_t * codec, widget_t * widget, int group, int ix, const char *name); + +#include "hdaudio_mixers.h" diff --git a/kernel/drv/oss_hdaudio/hdaudio_codecids.h b/kernel/drv/oss_hdaudio/hdaudio_codecids.h new file mode 100644 index 0000000..22e6c70 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_codecids.h @@ -0,0 +1,1154 @@ +/* + * Purpose: Definitions for HDaudio codec chips known by OSS. + */ +/* + * + * 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. + * + */ + +/* + * NULL mixer init function. Used to disable mixer creation for given codec. + */ +static int NULL_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) { return 0;} + +struct codec_desc +{ + unsigned int id; /* Codec id (however subdevice ID in the subdevices[] table) */ + char *name; + unsigned long flags; +#define VF_NONE 0x00000000 +#define VF_ALC88X_HACK 0x00000001 /* ALC88x requires special handling for +S/PDIF */ +#define VF_VAIO_HACK 0x00000002 /* VAIO STAC9872 requires special +handling for headphone DAC */ +#define VF_SI3055_HACK 0x00000004 /* Si3055 modem requires manual endpoint +setuping and rate and ioctl hacks. */ + char **remap; + + /* + * Order of the output converter (DAC) widgets in multi channel mode. + * If left to 0 then 0x76543210 (sequential order) is assumed. Some + * motherboards are known to use their own channel ordering which can be + * fixed using this approach. + */ + unsigned int multich_map; + hda_mixer_init_func mixer_init; + unsigned int main_id; /* In the subdevices[] table this is used for the codec ID */ + unsigned int pci_subdevice; /* PCI subdevice ID of the controller (subdevices[]) */ +}; + + +/* + * Meaningful widget naming schemes for some known codecs. + * The list is terminated by a NULL string. An empty string + * (EMPTY_STR) means that the automatically selected name will be used. + * + * Define EMPTY_STR as a pointer to a common "" variable to conserve space. + */ + +static const char hda_empty_string[] = ""; +#define EMPTY_STR hda_empty_string + +static const char *alc880remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "front", /* 2 */ + "rear", /* 3 */ + "center/LFE", /* 4 */ + "side", /* 5 */ + "spdif-out", /* 6 */ + "rec1", /* 7 */ + "rec2", /* 8 */ + "rec3", /* 9 */ + "spdif-in", /* 10 */ + "inputmix", /* 11 */ + "front", /* 12 */ + "rear", /* 13 */ + "center/LFE", /* 14 */ + "side", /* 15 */ + "source-a", /* 16 */ + "source-b", /* 17 */ + "source-c", /* 18 */ + "source-d", /* 19 */ + EMPTY_STR, /* 20 */ + EMPTY_STR, /* 21 */ + EMPTY_STR, /* 22 */ + EMPTY_STR, /* 23 */ + EMPTY_STR, /* 24 */ + EMPTY_STR, /* 25 */ + EMPTY_STR, /* 26 */ + EMPTY_STR, /* 27 */ + EMPTY_STR, /* 28 */ + EMPTY_STR, /* 29 */ + EMPTY_STR, /* 30 */ + EMPTY_STR, /* 31 */ + EMPTY_STR, /* 32 */ + EMPTY_STR, /* 33 */ + EMPTY_STR, /* 34 */ + EMPTY_STR, /* 35 */ + EMPTY_STR, /* 36 */ + "fp-front", /* 37 */ + NULL +}; + +static const char *alc883remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "front", /* 2 */ + "rear", /* 3 */ + "center/LFE", /* 4 */ + "side", /* 5 */ + "spdif-out", /* 6 */ + EMPTY_STR, /* 7 */ + "rec1", /* 8 */ + "rec2", /* 9 */ + "spdif-in", /* a */ + "input-mix", /* b */ + "front", /* c */ + "rear", /* d */ + "center/LFE", /* e */ + "side", /* f */ + EMPTY_STR, /* 10 */ + EMPTY_STR, /* 11 */ + EMPTY_STR, /* 12 */ + EMPTY_STR, /* 13 */ + EMPTY_STR, /* 14 */ + EMPTY_STR, /* 15 */ + EMPTY_STR, /* 16 */ + EMPTY_STR, /* 17 */ + EMPTY_STR, /* 18 */ + EMPTY_STR, /* 19 */ + EMPTY_STR, /* 1a */ + EMPTY_STR, /* 1b */ + EMPTY_STR, /* 1c */ + EMPTY_STR, /* 1d */ + EMPTY_STR, /* 1e */ + EMPTY_STR, /* 1f */ + EMPTY_STR, /* 20 */ + EMPTY_STR, /* 21 */ + EMPTY_STR, /* 22 */ + EMPTY_STR, /* 23 */ + EMPTY_STR, /* 24 */ + "pcm4", /* 25 */ + "pcm4", /* 26 */ + NULL +}; + +static const char *alc260remap[] = { + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + "front", /* 0x02 */ + "spdif-out", /* 0x03 */ + "rec1", /* 0x04 */ + "rec2", /* 0x05 */ + "spdif-in", /* 0x06 */ + "inputmix", /* 0x07 */ + "speaker-mix", /* 0x08 */ + "headphone-mix", /* 0x09 */ + "mono-mix", /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + "speaker", /* 0x0f */ + "headphone", /* 0x10 */ + "mono", /* 0x11 */ + EMPTY_STR, /* 0x12 */ + EMPTY_STR, /* 0x13 */ + EMPTY_STR, /* 0x14 */ + EMPTY_STR, /* 0x15 */ + EMPTY_STR, /* 0x16 */ + "beep", /* 0x17 */ + "spdif-out", /* 0x18 */ + "spdif-in", /* 0x19 */ + NULL +}; + +static const char *alc262remap[] = { + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + "speaker", /* 0x02 */ + "headphone", /* 0x03 */ + EMPTY_STR, /* 0x04 */ + EMPTY_STR, /* 0x05 */ + "spdif-out", /* 0x06 */ + "rec1", /* 0x07 */ + "rec2", /* 0x08 */ + "rec3", /* 0x09 */ + "spdif-in", /* 0x0a */ + "mix", /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + "mono", /* 0x11 */ + "dmic", /* 0x12 */ + EMPTY_STR, /* 0x13 */ + "line-out", /* 0x14 */ + "headphone", /* 0x15 */ + "mono", /* 0x16 */ + "beep", /* 0x17 */ + EMPTY_STR, /* 0x18 */ + EMPTY_STR, /* 0x19 */ + EMPTY_STR, /* 0x1a */ + EMPTY_STR, /* 0x1b */ + EMPTY_STR, /* 0x1c */ + "beep", /* 0x1d */ + "spdif-out", /* 0x1e */ + "spdif-in", /* 0x1f */ + NULL +}; + +static const char *alc662remap[] = { + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + "front", /* 0x02 */ + "rear", /* 0x03 */ + "center/LFE", /* 0x04 */ + EMPTY_STR, /* 0x05 */ + "spdif-out", /* 0x06 */ + "spdout", /* 0x07 */ + "rec1", /* 0x08 */ + "rec2", /* 0x09 */ + EMPTY_STR, /* 0x0a */ + "mix", /* 0x0b */ + "front", /* 0x0c */ + "rear", /* 0x0d */ + "c/lfe", /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + EMPTY_STR, /* 0x12 */ + EMPTY_STR, /* 0x13 */ + EMPTY_STR, /* 0x14 */ + EMPTY_STR, /* 0x15 */ + EMPTY_STR, /* 0x16 */ + EMPTY_STR, /* 0x17 */ + EMPTY_STR, /* 0x18 */ + EMPTY_STR, /* 0x19 */ + EMPTY_STR, /* 0x1a */ + EMPTY_STR, /* 0x1b */ + EMPTY_STR, /* 0x1c */ + EMPTY_STR, /* 0x1d */ + EMPTY_STR, /* 0x1e */ + EMPTY_STR, /* 0x1f */ + EMPTY_STR, /* 0x20 */ + EMPTY_STR, /* 0x21 */ + EMPTY_STR, /* 0x22 */ + EMPTY_STR, /* 0x23 */ + NULL +}; + +static const char *alc861remap[] = { + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + EMPTY_STR, /* 0x02 */ + "front", /* 0x03 */ + "side", /* 0x04 */ + "center/LFE", /* 0x05 */ + "rear", /* 0x06 */ + "spdout", /* 0x07 */ + "rec", /* 0x08 */ + EMPTY_STR, /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + EMPTY_STR, /* 0x12 */ + EMPTY_STR, /* 0x13 */ + "recmix", /* 0x14 */ + "outmix", /* 0x15 */ + "frontmix", /* 0x16 */ + "sidemix", /* 0x17 */ + "c/l-mix", /* 0x18 */ + "rearmix", /* 0x19 */ + "line2-mix", /* 0x1a */ + "mic2mix", /* 0x1b */ + "line1mix", /* 0x1c */ + EMPTY_STR, /* 0x1d */ + "vendor", /* 0x1e */ + "center/LFE", /* 0x1f */ + "side", /* 0x20 */ + EMPTY_STR, /* 0x21 */ + EMPTY_STR, /* 0x22 */ + "beep", /* 0x23 */ + NULL +}; + +static const char *cmi9880remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + EMPTY_STR, /* 2 */ + "front", /* 3 */ + "rear", /* 4 */ + "side", /* 5 */ + "center/LFE", /* 6 */ + "spdif-out", /* 7 */ + EMPTY_STR, /* 8 */ + EMPTY_STR, /* 9 */ + EMPTY_STR, /* 10 */ + EMPTY_STR, /* 11 */ + EMPTY_STR, /* 12 */ + EMPTY_STR, /* 13 */ + EMPTY_STR, /* 14 */ + EMPTY_STR, /* 15 */ + EMPTY_STR, /* 16 */ + EMPTY_STR, /* 17 */ + EMPTY_STR, /* 18 */ + EMPTY_STR, /* 19 */ + EMPTY_STR, /* 20 */ + EMPTY_STR, /* 21 */ + EMPTY_STR, /* 22 */ + "pcbeep", /* 23 */ + EMPTY_STR, /* 24 */ + EMPTY_STR, /* 25 */ + EMPTY_STR, /* 26 */ + EMPTY_STR, /* 27 */ + EMPTY_STR, /* 28 */ + EMPTY_STR, /* 29 */ + EMPTY_STR, /* 30 */ + EMPTY_STR, /* 31 */ + NULL +}; + +static const char *ad1981remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "spdif", /* 2 */ + "play", /* 3 */ + "rec", /* 4 */ + EMPTY_STR, /* 5 */ + EMPTY_STR, /* 6 */ + EMPTY_STR, /* 7 */ + EMPTY_STR, /* 8 */ + EMPTY_STR, /* 9 */ + "spdif-out", /* a */ + "mono-sel", /* b */ + "mic-mix", /* c */ + "pcbeep-sel", /* d */ + "rec-mix", /* e */ + "mono-mix", /* f */ + "digital-beep", /* 10 */ + "frontmix-amp", /* 11 */ + "mic-mixamp", /* 12 */ + "linein-mixamp", /* 13 */ + "powerdown", /* 14 */ + "rec-sel", /* 15 */ + EMPTY_STR, /* 16 */ + EMPTY_STR, /* 17 */ + EMPTY_STR, /* 18 */ + EMPTY_STR, /* 19 */ + "lineout-mixamp", /* 1a */ + "aux-mixamp", /* 1b */ + "mic-mixamp", /* 1c */ + "CD-mixamp", /* 1d */ + "fp-mic-mute", /* 1e */ + "mic-mute", /* 1f */ + NULL +}; + +static const char *ad1983remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "spdif", /* 2 */ + "play", /* 3 */ + "rec", /* 4 */ + EMPTY_STR, /* 5 */ + EMPTY_STR, /* 6 */ + EMPTY_STR, /* 7 */ + EMPTY_STR, /* 8 */ + EMPTY_STR, /* 9 */ + "spdif-out", /* a */ + "mono-sel", /* b */ + "mic-boost", /* c */ + "linein-sel", /* d */ + "rec-mix", /* e */ + "mono-mix", /* f */ + "digital-beep", /* 10 */ + "frontmix-amp", /* 11 */ + "mic-mixamp", /* 12 */ + "linein-mixamp", /* 13 */ + "rec-sel", /* 14 */ + "powerdown", /* 15 */ + NULL +}; + +static const char *ad1984remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "spdif", /* 2 */ + "headphone", /* 3 */ + "front", /* 4 */ + "dig-mic1", /* 5 */ + "dig-mic2", /* 6 */ + "headphone-mix", /* 7 */ + "rec1", /* 8 */ + "rec2", /* 9 */ + "lineout-mix", /* a */ + "aux-mix", /* b */ + "rec1-sel", /* c */ + "rec2-sel", /* d */ + "mono-sel", /* e */ + "aux-sel", /* f */ + "beep", /* 10 */ + EMPTY_STR, /* 11 */ + EMPTY_STR, /* 12 */ + EMPTY_STR, /* 13 */ + EMPTY_STR, /* 14 */ + EMPTY_STR, /* 15 */ + EMPTY_STR, /* 16 */ + EMPTY_STR, /* 17 */ + EMPTY_STR, /* 18 */ + "mixer-powerdown", /* 19 */ + "beep", /* 1a */ + "spdif-out", /* 1b */ + EMPTY_STR, /* 1c */ + EMPTY_STR, /* 1d */ + "mono-mix", /* 1e */ + "mono-downmix", /* 1f */ + "input-mix", /* 20 */ + "input-mixamp", /* 21 */ + "headphone-sel", /* 22 */ + "dock-sel", /* 23 */ + "dock-mix", /* 24 */ + "dock-micboost", /* 25 */ + EMPTY_STR, /* 26 */ + NULL +}; + +static const char *ad1986remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "spdif-out", /* 2 */ + "front", /* 3 */ + "rear", /* 4 */ + "center/LFE", /* 5 */ + "rec", /* 6 */ + "recmon", /* 7 */ + "mono-mix", /* 8 */ + "stereo-downmix", /* 9 */ + "headphone-sel", /* a */ + "lineout-sel", /* b */ + "rear-sel", /* c */ + "center/LFE-sel", /* d */ + "mono-sel", /* e */ + "mic-sel", /* f */ + "linein-sel", /* 10 */ + "mic-src", /* 11 */ + "rec-src" /* 12 */ + "mic-mix", /* 13 */ + "phone-mix", /* 14 */ + "cd-mix", /* 15 */ + "aux-mix", /* 16 */ + "linein-mix", /* 17 */ + "beep", /* 18 */ + "digital-beep", /* 19 */ + EMPTY_STR, /* 1a */ + EMPTY_STR, /* 1b */ + EMPTY_STR, /* 1c */ + EMPTY_STR, /* 1d */ + EMPTY_STR, /* 1e */ + EMPTY_STR, /* 1f */ + EMPTY_STR, /* 20 */ + EMPTY_STR, /* 21 */ + EMPTY_STR, /* 22 */ + EMPTY_STR, /* 23 */ + EMPTY_STR, /* 24 */ + "spdif-out", /* 25 */ + "analog-powerdown", /* 26 */ + "mic-c/LFE-mix", /* 27 */ + "mic-linein-mix", /* 28 */ + "c/LFE-linein-mix", /* 29 */ + "mic-linein-c/LFE-mix", /* 2a */ + "mic-sel", /* 2b */ + NULL +}; + +static const char *ad1988remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ /* This is both audio-fgr and DAC???? */ + "spdout", /* 2 */ /* Not used? */ + "headphone", /* 3 */ + "front", /* 4 */ + "center/LFE", /* 5 */ + "rear", /* 6 */ + "spdin", /* 7 */ + "rec1", /* 8 */ + "rec2", /* 9 */ + "side", /* a */ + "spdin-src", /* b */ + "rec1-src", /* c */ + "rec2-src", /* d */ + "rec3-src", /* e */ + "rec3", /* f */ + "pcbeep", /* 10 */ + EMPTY_STR, /* 11 */ + EMPTY_STR, /* 12 */ + EMPTY_STR, /* 13 */ + EMPTY_STR, /* 14 */ + EMPTY_STR, /* 15 */ + EMPTY_STR, /* 16 */ + EMPTY_STR, /* 17 */ + EMPTY_STR, /* 18 */ + "power-down", /* 19 */ + "beep", /* 1a */ + "spdif-out", /* 1b */ + "spdif-in", /* 1c */ + "spdifout-mix", /* 1d */ + "mono-mix", /* 1e */ + "main-volume", /* 1f */ + "analog-mix", /* 20 */ + "outamp", /* 21 */ + "headphon-mix", /* 22 */ + "hp-powerdown", /* 23 */ + EMPTY_STR, /* 24 */ + EMPTY_STR, /* 25 */ + "mic-mix", /* 26 */ + "center/LFE-mix", /* 27 */ + "side-mix", /* 28 */ + "front-mix", /* 29 */ + "rear-mix", /* 2a */ + "fp-mic-mix", /* 2b */ + "linein-mix", /* 2c */ + "mono-mixdown", /* 2d */ + EMPTY_STR, /* 2e */ + "bias-pdown", /* 2f */ + "fppink-outsel", /* 30 */ + "blue-outsel", /* 31 */ + "pink-outsel", /* 32 */ + "blue-insel", /* 33 */ + "pink-insel", /* 34 */ + EMPTY_STR, /* 35 */ + "mono-sel", /* 36 */ + "fpgreen-outsel", /* 37 */ + "fpgreen-micboost", /* 38 */ + "fppink-micboost", /* 39 */ + "blue-micboost", /* 3a */ + "black-micboost", /* 3b */ + "pink-micboost", /* 3c */ + "green-micboost", /* 3d */ + NULL +}; + +#if 0 +static const char *stac9200remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 0x01 */ + "play", /* 0x02 */ + "rec", /* 0x03 */ + "spdif-in", /* 0x04 */ + "spdif-out", /* 0x05 */ + EMPTY_STR, /* 0x06 */ + "playmux", /* 0x07 */ + EMPTY_STR, /* 0x08 */ + EMPTY_STR, /* 0x09 */ + "recmux", /* 0x0a */ + "mainvol", /* 0x0b */ + "inputmux", /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + EMPTY_STR, /* 0x12 */ + "mono-mix", /* 0x13 */ + "beep", /* 0x14 */ + NULL +}; +#endif + +static const char *stac920xremap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 0x01 */ + EMPTY_STR, /* 0x02 */ + EMPTY_STR, /* 0x03 */ + EMPTY_STR, /* 0x04 */ + EMPTY_STR, /* 0x05 */ + EMPTY_STR, /* 0x06 */ + EMPTY_STR, /* 0x07 */ + EMPTY_STR, /* 0x08 */ + EMPTY_STR, /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + "front", /* 0x10 */ + "rear", /* 0x11 */ + "rec1", /* 0x12 */ + "rec2", /* 0x13 */ + "mono-out", /* 0x14 */ + "mono-mix", /* 0x15 */ + "cd", /* 0x16 */ + "dig-mic1", /* 0x17 */ + "dig-mic2", /* 0x18 */ + "input1-mux", /* 0x19 */ + "input2-mux", /* 0x1a */ + "rec1-vol", /* 0x1b */ + "rec2-vol", /* 0x1c */ + "rec1-mux", /* 0x1d */ + "rec2-mux", /* 0x1e */ + "spdif-out", /* 0x1f */ + "spdif-in", /* 0x20 */ + "digital-out", /* 0x21 */ + "digital-in", /* 0x22 */ + "beep", /* 0x23 */ + "mastervol", /* 0x24 */ + EMPTY_STR, /* 0x25 */ + NULL +}; + +static const char *stac925xremap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 0x01 */ + "play", /* 0x02 */ + "rec", /* 0x03 */ + "spdif-in", /* 0x04 */ + "spdif-out", /* 0x05 */ + "output-mux", /* 0x06 */ + EMPTY_STR, /* 0x07 */ + EMPTY_STR, /* 0x08 */ + "rec-vol", /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + "vol", /* 0x0e */ + "input-mux", /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + "mono-mix", /* 0x12 */ + "beep", /* 0x13 */ + "rec-mux", /* 0x14 */ + EMPTY_STR, /* 0x15 */ + NULL +}; + +static const char *stac922xremap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 0x01 */ + "front", /* 0x02 */ + "center/LFE", /* 0x03 */ + "rear", /* 0x04 */ + "side", /* 0x05 */ + "rec1", /* 0x06 */ + "rec2", /* 0x07 */ + "spdif-out", /* 0x08 */ + "spdif-in", /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + "rec1mux", /* 0x12 */ + "rec2mux", /* 0x13 */ + "pcbeep", /* 0x14 */ + "cd", /* 0x15 */ + "mainvol", /* 0x16 */ + "rec1vol", /* 0x17 */ + "rec2vol", /* 0x18 */ + "adat", /* 0x19 */ + "i2s-out", /* 0x1a */ + "i2s-in", /* 0x1b */ + NULL +}; + +static const char *stac923xremap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 0x01 */ + "front", /* 0x02 */ + "center/LFE", /* 0x03 */ + "rear", /* 0x04 */ + "side", /* 0x05 */ + "headphone", /* 0x06 */ + "rec1", /* 0x07 */ + "rec2", /* 0x08 */ + "rec3", /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + "cd", /* 0x12 */ + "dig-mic1", /* 0x13 */ + "dig-mic2", /* 0x14 */ + "input1-mux", /* 0x15 */ + "input2-mux", /* 0x16 */ + "input3-mux", /* 0x17 */ + "rec1vol", /* 0x18 */ + "rec2vol", /* 0x19 */ + "rec3vol", /* 0x1a */ + "rec1-mux", /* 0x1b */ + "rec2-mux", /* 0x1c */ + "rec3-mux", /* 0x1d */ + "spdif-out", /* 0x1e */ + "adat", /* 0x1f */ + NULL +}; + + +static const char *conexant_modem_remap[] = +{ + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + EMPTY_STR, /* 0x02 */ + EMPTY_STR, /* 0x03 */ + EMPTY_STR, /* 0x04 */ + EMPTY_STR, /* 0x05 */ + EMPTY_STR, /* 0x06 */ + EMPTY_STR, /* 0x07 */ + EMPTY_STR, /* 0x08 */ + EMPTY_STR, /* 0x09 */ + EMPTY_STR, /* 0x0a */ + EMPTY_STR, /* 0x0b */ + EMPTY_STR, /* 0x0c */ + EMPTY_STR, /* 0x0d */ + EMPTY_STR, /* 0x0e */ + EMPTY_STR, /* 0x0f */ + EMPTY_STR, /* 0x10 */ + EMPTY_STR, /* 0x11 */ + EMPTY_STR, /* 0x12 */ + EMPTY_STR, /* 0x13 */ + EMPTY_STR, /* 0x14 */ + EMPTY_STR, /* 0x15 */ + EMPTY_STR, /* 0x16 */ + EMPTY_STR, /* 0x17 */ + EMPTY_STR, /* 0x18 */ + EMPTY_STR, /* 0x19 */ + EMPTY_STR, /* 0x1a */ + EMPTY_STR, /* 0x1b */ + EMPTY_STR, /* 0x1c */ + EMPTY_STR, /* 0x1d */ + EMPTY_STR, /* 0x1e */ + EMPTY_STR, /* 0x1f */ + EMPTY_STR, /* 0x20 */ + EMPTY_STR, /* 0x21 */ + EMPTY_STR, /* 0x22 */ + EMPTY_STR, /* 0x23 */ + EMPTY_STR, /* 0x24 */ + EMPTY_STR, /* 0x25 */ + EMPTY_STR, /* 0x26 */ + EMPTY_STR, /* 0x27 */ + EMPTY_STR, /* 0x28 */ + EMPTY_STR, /* 0x29 */ + EMPTY_STR, /* 0x2a */ + EMPTY_STR, /* 0x2b */ + EMPTY_STR, /* 0x2c */ + EMPTY_STR, /* 0x2d */ + EMPTY_STR, /* 0x2e */ + EMPTY_STR, /* 0x2f */ + EMPTY_STR, /* 0x30 */ + EMPTY_STR, /* 0x31 */ + EMPTY_STR, /* 0x32 */ + EMPTY_STR, /* 0x33 */ + EMPTY_STR, /* 0x34 */ + EMPTY_STR, /* 0x35 */ + EMPTY_STR, /* 0x36 */ + EMPTY_STR, /* 0x37 */ + EMPTY_STR, /* 0x38 */ + EMPTY_STR, /* 0x39 */ + EMPTY_STR, /* 0x3a */ + EMPTY_STR, /* 0x3b */ + EMPTY_STR, /* 0x3c */ + EMPTY_STR, /* 0x3d */ + EMPTY_STR, /* 0x3e */ + EMPTY_STR, /* 0x3f */ + EMPTY_STR, /* 0x40 */ + EMPTY_STR, /* 0x41 */ + EMPTY_STR, /* 0x42 */ + EMPTY_STR, /* 0x43 */ + EMPTY_STR, /* 0x44 */ + EMPTY_STR, /* 0x45 */ + EMPTY_STR, /* 0x46 */ + EMPTY_STR, /* 0x47 */ + EMPTY_STR, /* 0x48 */ + EMPTY_STR, /* 0x49 */ + EMPTY_STR, /* 0x4a */ + EMPTY_STR, /* 0x4b */ + EMPTY_STR, /* 0x4c */ + EMPTY_STR, /* 0x4d */ + EMPTY_STR, /* 0x4e */ + EMPTY_STR, /* 0x4f */ + EMPTY_STR, /* 0x50 */ + EMPTY_STR, /* 0x51 */ + EMPTY_STR, /* 0x52 */ + EMPTY_STR, /* 0x53 */ + EMPTY_STR, /* 0x54 */ + EMPTY_STR, /* 0x55 */ + EMPTY_STR, /* 0x56 */ + EMPTY_STR, /* 0x57 */ + EMPTY_STR, /* 0x58 */ + EMPTY_STR, /* 0x59 */ + EMPTY_STR, /* 0x5a */ + EMPTY_STR, /* 0x5b */ + EMPTY_STR, /* 0x5c */ + EMPTY_STR, /* 0x5d */ + EMPTY_STR, /* 0x5e */ + EMPTY_STR, /* 0x5f */ + EMPTY_STR, /* 0x60 */ + EMPTY_STR, /* 0x61 */ + EMPTY_STR, /* 0x62 */ + EMPTY_STR, /* 0x63 */ + EMPTY_STR, /* 0x64 */ + EMPTY_STR, /* 0x65 */ + EMPTY_STR, /* 0x66 */ + EMPTY_STR, /* 0x67 */ + EMPTY_STR, /* 0x68 */ + EMPTY_STR, /* 0x69 */ + EMPTY_STR, /* 0x6a */ + EMPTY_STR, /* 0x6b */ + EMPTY_STR, /* 0x6c */ + EMPTY_STR, /* 0x6d */ + EMPTY_STR, /* 0x6e */ + EMPTY_STR, /* 0x6f */ + "modem-control",/* 0x70 */ // Vendor defined widget + "modem-in", /* 0x71 */ + "modem-out", /* 0x72 */ + "modem-jack", /* 0x73 */ + NULL +}; + +extern int hdaudio_GPIO_init_1 (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); + +static const codec_desc_t codecs[] = { + /* Realtek HDA codecs */ + {0x10ec0260, "ALC260", VF_NONE, (char **) &alc260remap}, + {0x10ec0262, "ALC262", VF_NONE, (char **) &alc262remap}, + {0x10ec0268, "ALC268", VF_NONE, (char **) &alc262remap}, + {0x10ec0662, "ALC662", VF_NONE, (char **) &alc662remap}, + {0x10ec0663, "ALC663", VF_NONE, (char **) &alc662remap}, + {0x10ec0861, "ALC861", VF_NONE, (char **) &alc861remap}, + {0x10ec0862, "ALC862", VF_NONE, (char **) &alc861remap}, + {0x10ec0880, "ALC880", VF_ALC88X_HACK, (char **) &alc880remap}, + {0x10ec0882, "ALC882", VF_ALC88X_HACK, (char **) &alc880remap}, + {0x10ec0883, "ALC883", VF_ALC88X_HACK, (char **) &alc883remap}, + {0x10ec0885, "ALC885", VF_ALC88X_HACK, (char **) &alc883remap}, + {0x10ec0887, "ALC887", VF_ALC88X_HACK, (char **) &alc883remap}, + {0x10ec0888, "ALC888", VF_ALC88X_HACK, (char **) &alc883remap}, + {0x10ec0889, "ALC889", VF_ALC88X_HACK, (char **) &alc883remap}, + {0x10ec0892, "ALC892", VF_ALC88X_HACK, (char **) &alc883remap}, + + /* CMedia HDA codecs */ + {0x13f69880, "CMI9880", VF_NONE, (char **) &cmi9880remap}, + {0x434d4980, "CMI9880", VF_NONE, (char **) &cmi9880remap}, + + {0x111d7603, "92HD75B3X5", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d7608, "92HD75B2X5", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b0, "92HD71B8X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b1, "92HD71B8X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b2, "92HD71B7X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b3, "92HD71B7X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b4, "92HD71B6X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b5, "92HD71B6X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b6, "92HD71B5X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + {0x111d76b7, "92HD71B5X", VF_NONE, NULL, 0, hdaudio_GPIO_init_1}, + + /* Analog Devices HDA codecs */ + {0x11d41981, "AD1981", VF_NONE, (char **) &ad1981remap, 0x76543021}, + {0x11d41983, "AD1983", VF_NONE, (char **) &ad1983remap, 0x76543021}, + {0x11d41984, "AD1984", VF_NONE, (char **) &ad1984remap, 0x76543012}, + {0x11d41986, "AD1986A", VF_NONE, (char **) &ad1986remap, 0x76540321}, + {0x11d41988, "AD1988A", VF_NONE, (char **) &ad1988remap, 0x76015432}, + {0x11d4198b, "AD1988B", VF_NONE, (char **) &ad1988remap, 0x76015432}, + + /* Sigmatel HDA codecs (some of them) */ + {0x83847690, "STAC9200", VF_NONE, (char **) &stac920xremap }, + {0x838476a0, "STAC9205", VF_NONE, (char **) &stac920xremap }, + {0x838476a1, "STAC9205D", VF_NONE, (char **) &stac920xremap }, + {0x838476a2, "STAC9204", VF_NONE, (char **) &stac920xremap }, + {0x838476a3, "STAC9204D", VF_NONE, (char **) &stac920xremap }, + + /* Apple Macbook ids */ + {0x83847880, "STAC9220 A1", VF_NONE, (char **) &stac922xremap }, + {0x83847882, "STAC9220 A2", VF_NONE, (char **) &stac922xremap }, + {0x83847680, "STAC9221 A1", VF_NONE, (char **) &stac922xremap }, + + {0x83847681, "STAC9220D", VF_NONE, (char **) &stac922xremap }, + {0x83847682, "STAC9221", VF_NONE, (char **) &stac922xremap }, + {0x83847683, "STAC9221D", VF_NONE, (char **) &stac922xremap }, + + {0x83847610, "STAC9230XN", VF_NONE, (char **) &stac923xremap }, + {0x83847611, "STAC9230DN", VF_NONE, (char **) &stac923xremap }, + {0x83847612, "STAC9230XT", VF_NONE, (char **) &stac923xremap }, + {0x83847613, "STAC9230DT", VF_NONE, (char **) &stac923xremap }, + {0x83847614, "STAC9229X", VF_NONE, (char **) &stac923xremap }, + {0x83847615, "STAC9229D", VF_NONE, (char **) &stac923xremap }, + {0x83847616, "STAC9228X", VF_NONE, (char **) &stac923xremap }, + {0x83847617, "STAC9228D", VF_NONE, (char **) &stac923xremap }, + {0x83847618, "STAC9227X", VF_NONE, (char **) &stac923xremap }, /* Intel D975XBX2 (at least) */ + {0x83847619, "STAC9227D", VF_NONE, (char **) &stac923xremap }, + + {0x838476a4, "STAC9255", VF_NONE, (char **) &stac925xremap }, + {0x838476a5, "STAC9255D", VF_NONE, (char **) &stac925xremap }, + {0x838476a6, "STAC9254", VF_NONE, (char **) &stac925xremap }, + {0x838476a7, "STAC9254D", VF_NONE, (char **) &stac925xremap }, + + {0x83847620, "STAC9274", VF_NONE, (char **) &stac923xremap }, + {0x83847621, "STAC9274D", VF_NONE, (char **) &stac923xremap }, + {0x83847622, "STAC9273X", VF_NONE, (char **) &stac923xremap }, + {0x83847623, "STAC9273D", VF_NONE, (char **) &stac923xremap }, + {0x83847624, "STAC9272X", VF_NONE, (char **) &stac923xremap }, + {0x83847625, "STAC9272D", VF_NONE, (char **) &stac923xremap }, + {0x83847626, "STAC9271X", VF_NONE, (char **) &stac923xremap }, + {0x83847627, "STAC9271D", VF_NONE, (char **) &stac923xremap }, + + {0x83847628, "STAC9274X5NH", VF_NONE, (char **) &stac923xremap }, + {0x83847629, "STAC9274D5NH", VF_NONE, (char **) &stac923xremap }, + {0x83847661, "CXD9872RD", VF_NONE, NULL, 0x76543012}, + {0x83847662, "STAC9872AK", VF_NONE, NULL, 0x76543012}, + {0x83847664, "STAC9872K", VF_NONE, NULL, 0x76543210}, /* Vaio VGN-AR51J */ + + /* Conexant */ + {0x14f15045, "CX20548", VF_NONE, NULL, 0x76543201}, + {0x14f15047, "CX20551", VF_NONE, NULL, 0x76543201}, + {0x14f15051, "CX20561", VF_NONE, NULL, 0x76543210}, + {0x14f12c06, "Conexant2c06", VF_NONE, (char **) &conexant_modem_remap, 0, NULL_mixer_init}, /* Modem codec (Vaio) */ + {0x14f12bfa, "Conexant2bfa", VF_NONE, (char **) &conexant_modem_remap, 0, NULL_mixer_init}, /* Modem codec (Acer Ferrari 5k) */ + + /* Si3055 and compatible modems */ + {0x163c3055, "Si3055", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x163c3155, "Si3155", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x11c13026, "Agere3026", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x11c13055, "Agere3055", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x11c13155, "Agere3155", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x10573055, "Motorola3055", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x10573057, "Motorola3057", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + {0x10573155, "Motorola3155", VF_SI3055_HACK, NULL, 0, NULL_mixer_init }, + + /* Creative Labs */ + {0x1102000a, "Createive XFi XTreme", VF_NONE, NULL, 0x76543210}, + + {0x11c11040, "Agere HDA Modem", VF_NONE, NULL, 0, NULL_mixer_init}, + + /* Unknown */ + {0, "Unknown"} +}; + +static const char *abit_AA8_remap[] = { + EMPTY_STR, /* 0 */ + EMPTY_STR, /* 1 */ + "front", /* 2 */ + "rear", /* 3 */ + "center/LFE", /* 4 */ + "side", /* 5 */ + "spdif-out", /* 6 */ + "rec1", /* 7 */ + "rec2", /* 8 */ + "rec3", /* 9 */ + "spdif-in", /* 10 */ + "inputmix", /* 11 */ + "front", /* 12 */ + "rear", /* 13 */ + "center/LFE", /* 14 */ + "side", /* 15 */ + "out-source", /* 16 */ + "out-source", /* 17 */ + "out-source", /* 18 */ + "out-source", /* 19 */ + "green1", /* 20 */ + "black1", /* 21 */ + "C-L", /* 22 */ + "surr", /* 23 */ + "pink1", /* 24 */ + "pink2", /* 25 */ + "blue1", /* 26 */ + "blue2", /* 27 */ + "cd", /* 28 */ + "beep", /* 29 */ + "spdout", /* 30 */ + "spdin", /* 31 */ + "vendor", /* 32 */ + "vol", /* 33 */ + NULL +}; + +static const char *vaio_remap[] = { + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + "headphone", /* 0x02 */ + "pcm", /* 0x03 */ // Unused + "pcm", /* 0x04 */ // Unused + "speaker", /* 0x05 */ + "rec1", /* 0x06 */ + "rec1-vol", /* 0x07 */ + "rec", /* 0x08 */ + "rec-vol", /* 0x09 */ + "headphone", /* 0x0a */ + EMPTY_STR, /* 0x0b */ // Unused + EMPTY_STR, /* 0x0c */ // Unused + "mic", /* 0x0d */ + EMPTY_STR, /* 0x0e */ + "int-speaker", /* 0x0f */ + "spdifout1", /* 0x10 */ + "int-digout1", /* 0x11 */ + "spdifin", /* 0x12 */ + "int-digout", /* 0x13 */ + "int-mic", /* 0x14 */ + "rec", /* 0x15 */ + "beep", /* 0x16 */ + "vol", /* 0x17 */ + "spdifout", /* 0x18 */ + NULL +}; + +static const char *alc262_vaio_remap[] = +{ + EMPTY_STR, /* 0x00 */ + EMPTY_STR, /* 0x01 */ + "speaker", /* 0x02 */ + "headphone", /* 0x03 */ + "vendor", /* 0x04 */ + "vendor", /* 0x05 */ + "hdmi-out", /* 0x06 */ + "rec1", /* 0x07 */ + "rec2", /* 0x08 */ + "rec3", /* 0x09 */ + "spdif-in", /* 0x0a */ + "mix", /* 0x0b */ + "mix", /* 0x0c */ + "mix", /* 0x0d */ + "mono", /* 0x0e */ + "vendor", /* 0x0f */ + "vendor", /* 0x10 */ + "mono", /* 0x11 */ + "dmic", /* 0x12 */ + "vendor", /* 0x13 */ + "line-out", /* 0x14 */ + "headphone", /* 0x15 */ + "mono", /* 0x16 */ + "beep", /* 0x17 */ + "speaker", /* 0x18 */ + "speaker", /* 0x19 */ + "speaker", /* 0x1a */ + "speaker", /* 0x1b */ + "speaker", /* 0x1c */ + "beep", /* 0x1d */ + "spdif-out", /* 0x1e */ + "spdif-in", /* 0x1f */ + "vendor", /* 0x20 */ + "vol", /* 0x21 */ + "rec3", /* 0x22 */ + "rec2", /* 0x23 */ + "rec1", /* 0x24 */ + NULL +}; + +/* + * Table for subsystem ID's that require special handling + */ + +extern int hdaudio_Asus_P4B_E_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_scaleoP_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_abit_AA8_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_ferrari5k_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_vaio_vgn_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_thinkpad_r61_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_mac_sigmatel_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_mac_realtek_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_eeepc_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_asus_a7k_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); +extern int hdaudio_asus_m9_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group); + +static const codec_desc_t subdevices[] = { + {0x98801019, "ECS 915P-A", VF_NONE, NULL, 0x76541320}, + {0x104381e1, "Asus P4B-E/AD1988A", VF_NONE, (char **) &ad1988remap, 0x76015432, hdaudio_Asus_P4B_E_mixer_init}, + // {0x1043e601, "ScaleoP/ALC888", VF_ALC88X_HACK, (char **) &alc883remap, 0, hdaudio_scaleoP_mixer_init}, + + /* Abit AA8 (at least some revisions) have bogus codec config information, + * including the subvendor ID. 0x08800000 is used by many other motherboards + * too. Have to use the pci_subvendor field for alc880 based devices: + * 0x147b1039 = Abit AA8 motherboard. + * 0x15849077 = Rock Pegasus 665 laptop. + */ + {0x08800000, "Abit AA8/ALC880", VF_ALC88X_HACK, (char **) &abit_AA8_remap, 0, hdaudio_abit_AA8_mixer_init, 0, 0x147b1039}, + + {0x10250000, "Ferrari5k/ALC883", VF_ALC88X_HACK, (char **) &alc883remap, 0, hdaudio_ferrari5k_mixer_init, 0x10ec0883, 0x1025010a}, + {0x10250000, "Acer_aspire5052/ALC883", VF_ALC88X_HACK, (char **) &alc883remap, 0, hdaudio_ferrari5k_mixer_init, 0x10ec0883, 0x1025010f}, + {0x1025160d, "Acer_travelmate4060/ALC260", VF_NONE, (char **) &alc260remap, 0, hdaudio_GPIO_init_1, 0x10ec0260, 0x1025008f}, + {0x10431153, "Asus M9", VF_NONE, (char **) &ad1986remap, 0x76540321, hdaudio_asus_m9_mixer_init}, + + /* + **** Sony Vaio VGN-AR51 *** + * Has three codecs. Primary (Stac9872K), Modem (Conexant) and + * HDMI digital output (ALC262). Disable the mixer entries for codecs 2 and 3. + */ + {0x104d2200, "Vaio/STAC9872K", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847664, 0x104d9016}, + /* 2nd codec (#1) is "Conexant2c06" modem */ + {0x104d2200, "Vaio/HDMI", VF_NONE, (char **) &alc262_vaio_remap, 0, NULL_mixer_init, 0x10ec0262, 0x104d9016}, + /****/ + + /* + * Sony VAIO SZ2, SZ3, FE and FE31B + */ + {0x104d0700, "Vaio/CXD9872RD", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847661, 0x104d81e6}, + {0x104d1000, "Vaio/CXD9872RD", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847661, 0x104d81ef}, + {0x104d0c00, "Vaio/CXD9872RD", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847661, 0x104d81ef}, + + /* + * Sony VAIO AR + */ + {0x104d1300, "Vaio/CXD9872AKD", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847664, 0x104d81fd}, + + /* + * Sony Vaio SZ (SZ650) has two codecs, STAC9872AK and Conexant modem. + * Assume the audio codec is identical with Vaio AGN (above). + */ + {0x104d1e00, "Vaio/STAC9872AK", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847662, 0x104d9008}, + /* Vaio VGC-LA1 */ + {0x104d1200, "Vaio/STAC9872AK", VF_VAIO_HACK, (char**) &vaio_remap, 0x76540213, hdaudio_vaio_vgn_mixer_init, 0x83847662, 0x104d8205}, + +/* + * Thinkpad R61 + */ + {0x17aa20bb, "Thinkpad R61", VF_NONE, (char**) &ad1984remap, 0, hdaudio_thinkpad_r61_mixer_init}, + +/* + * Asus Eee PC (model 900 at least) + */ + {0x10438337, "Asus Eee PC", VF_NONE, NULL, 0, hdaudio_eeepc_mixer_init}, + + /* + * Asus A7K + */ + {0x10431339, "Asus A7K", VF_ALC88X_HACK, (char **) &alc880remap, 0, hdaudio_asus_a7k_GPIO_init}, // ALC660 + +/* + * Known Macintosh systems + */ + {0x106b0800, "Intel Mac V1", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0700, "Intel Mac V2", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0600, "Intel Mac V2", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0200, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0e00, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0f00, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b1600, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b1700, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b1e00, "Intel Mac V3", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b1a00, "Intel Mac V4", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + // {0x00000100, "Intel Mac V4", VF_NONE, (char **) &stac922xremap, ?, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b0a00, "Intel Mac V5", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b2200, "Intel Mac V5", VF_NONE, (char **) &stac922xremap, 0, hdaudio_mac_sigmatel_GPIO_init}, + {0x106b3200, "Intel iMac", VF_ALC88X_HACK, (char **) &alc883remap, 0, hdaudio_mac_realtek_GPIO_init}, // ALC885 + + {0, "Unknown"} +}; + diff --git a/kernel/drv/oss_hdaudio/hdaudio_dedicated.h b/kernel/drv/oss_hdaudio/hdaudio_dedicated.h new file mode 100644 index 0000000..a4ddcfb --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_dedicated.h @@ -0,0 +1,74 @@ +/* + * Purpose: Definitions for dedicated HD audio codec drivers + */ +/* + * + * 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. + * + */ +#ifndef HDAUDIO_DEDICATED_H +#define HDAUDIO_DEDICATED_H + +extern void hda_codec_add_group(int dev, hdaudio_mixer_t * mixer, int cad, int *group, int parent_group, const char *name); +extern int hda_codec_add_pingroup(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int *group, int top_group, int *parent_group, const char *name, int *n, const char *parent_name, int group_size); +extern int hda_codec_add_adcgroup(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int *group, int top_group, int *parent_group, const char *name, int *n, const char *parent_name, int group_size); +extern int hda_codec_add_miscgroup(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int *group, int top_group, int *parent_group, const char *name, int *n, const char *parent_name, int group_size); + +#define HDA_GROUP(group, top_group, name) hda_codec_add_group(dev, mixer, cad, &group, top_group, name) +#define HDA_PIN_GROUP(wid, group, pin_group, name, n, parent_name, group_size) \ + hda_codec_add_pingroup(dev, mixer, cad, wid, &group, top_group, &pin_group, name, &n, parent_name, group_size) +#define HDA_ADC_GROUP(wid, group, rec_group, name, n, parent_name, group_size) \ + hda_codec_add_adcgroup(dev, mixer, cad, wid, &group, top_group, &rec_group, name, &n, parent_name, group_size) +#define HDA_MISC_GROUP(wid, group, misc_group, name, n, parent_name, group_size) \ + hda_codec_add_miscgroup(dev, mixer, cad, wid, &group, top_group, &misc_group, name, &n, parent_name, group_size) + +#define UNMUTE 0 +#define MUTE 1 +#define RECORD 1 +#define NOREC 0 + +extern int hda_codec_add_outamp(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int group, const char *name, int percent, unsigned int flags); +extern int hda_codec_add_outmute(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int group, const char *name, int state); +#define HDA_OUTAMP(wid, group, name, percent) ctl=hda_codec_add_outamp(dev, mixer, cad, wid, group, name, percent, 0) +#define HDA_OUTAMP_F(wid, group, name, percent, flags) hda_codec_add_outamp(dev, mixer, cad, wid, group, name, percent, flags) +#define HDA_OUTMUTE(wid, group, name, muted) ctl=hda_codec_add_outmute(dev, mixer, cad, wid, group, name, muted) + +extern int hda_codec_add_inamp(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int ix, int group, const char *name, int percent, unsigned int flags); +extern int hda_codec_add_inmute(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int ix, int group, const char *name, int muted, int flags); +extern int hda_codec_set_inmute(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int ix, int muted); +extern int hda_codec_add_insrc(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int ix, int group, const char *name, int muted); +extern int hda_codec_add_insrcselect(int dev, hdaudio_mixer_t * mixer, int cad, int wid, int group, int *ctl, const char *name, int initial_selection); + +#define HDA_INAMP(wid, ix, group, name, percent) ctl=hda_codec_add_inamp(dev, mixer, cad, wid, ix, group, name, percent, 0) +#define HDA_INAMP_F(wid, ix, group, name, percent, flags) ctl=hda_codec_add_inamp(dev, mixer, cad, wid, ix, group, name, percent, flags) + +#define HDA_INMUTE(wid, ix, group, name, muted) ctl=hda_codec_add_inmute(dev, mixer, cad, wid, ix, group, name, muted, 0) +#define HDA_INMUTE_F(wid, ix, group, name, muted, flags) ctl=hda_codec_add_inmute(dev, mixer, cad, wid, ix, group, name, muted, flags) +#define HDA_SET_INMUTE(wid, ix, muted) hda_codec_set_inmute(dev, mixer, cad, wid, ix, muted) +#define HDA_INSRC(wid, ix, group, name, muted) hda_codec_add_insrc(dev, mixer, cad, wid, ix, group, name, muted) +#define HDA_INSRC_SELECT(wid, group, ctl, name, initial_selection) \ + hda_codec_add_insrcselect(dev, mixer, cad, wid, group, &ctl, name, initial_selection) + +extern int hda_codec_add_select(int dev, hdaudio_mixer_t *mixer, int cad, int wid, int group, const char *name, int *ctl, int initial_select); +extern void hda_codec_set_select(int dev, hdaudio_mixer_t *mixer, int cad, int wid, int value); +extern void hda_codec_set_pinselect(int dev, hdaudio_mixer_t *mixer, int cad, int wid, int value); +extern int hda_codec_add_pinselect(int dev, hdaudio_mixer_t *mixer, int cad, int wid, int group, const char *name, int *ctl, int initial_select); +#define HDA_SELECT(wid, name, ctl, group, sel) hda_codec_add_select(dev, mixer, cad, wid, group, name, &ctl, sel) +#define HDA_PINSELECT(wid, ctl, group, name, sel) hda_codec_add_pinselect(dev, mixer, cad, wid, group, name, &ctl, sel) +#define HDA_SETSELECT(wid, value) hda_codec_set_select(dev, mixer, cad, wid, value) +#define HDA_SET_PINSELECT(wid, value) hda_codec_set_pinselect(dev, mixer, cad, wid, value) + +extern int hda_codec_add_choices(int dev, hdaudio_mixer_t *mixer, int ctl, const char *choiselist); +#define HDA_CHOICES(ctl, choicelist) hda_codec_add_choices(dev, mixer, ctl, choicelist) + +extern void hda_codec_set_color(int dev, hdaudio_mixer_t *mixer, int ctl, int color); +#define HDA_COLOR(ctl, color) hda_codec_set_color(dev, mixer, ctl, color) + +#endif + diff --git a/kernel/drv/oss_hdaudio/hdaudio_eeepc.c b/kernel/drv/oss_hdaudio/hdaudio_eeepc.c new file mode 100644 index 0000000..8fef9f7 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_eeepc.c @@ -0,0 +1,293 @@ +/* + * + * 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. + * + */ + +/* + * Purpose: Dedicated HDaudio mixer driver for Asus Eee PC + */ + +/* Codec index is 0 */ +/* Codec vendor 10ec:0662 */ +/* HD codec revision 1.0 (1.1) (0x00100101) */ +/* Subsystem ID 10438337 */ +/* Default amplifier caps: in=00000000, out=00000000 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_eeepc_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + int ctl=0; + + DDB(cmn_err(CE_CONT, "hdaudio_eeepc_mixer_init got called.\n")); + + HDA_OUTAMP(0x02, top_group, "pcm-front", 100); + HDA_OUTAMP(0x04, top_group, "pcm-rear", 100); + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n=0; + + HDA_GROUP(pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP(0x14, group, pin_group, "speaker", n, "jack", 4)) /* Pin widget 0x14 */ + { + /* Src 0xc=front */ +#if 1 + HDA_SET_PINSELECT(0x14, 0); // Hardwire as output +#else + if (HDA_PINSELECT(0x14, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out input"); +#endif + HDA_OUTMUTE(0x14, group, "mute", UNMUTE); + } + +#if 0 + if (HDA_PIN_GROUP(0x15, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x15 */ + { + /* Src 0xd=rear */ + if (HDA_PINSELECT(0x15, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "rear-out input"); + HDA_OUTMUTE(0x15, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP(0x16, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x16 */ + { + /* Src 0xe=rear */ + if (HDA_PINSELECT(0x16, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "rear-out input"); + HDA_OUTMUTE(0x16, group, "mute", UNMUTE); + } +#endif + + if (HDA_PIN_GROUP(0x19, group, pin_group, "mic", n, "jack", 4)) /* Pin widget 0x19 */ + { + /* Src 0xc=front */ + /* Src 0xe=rear */ +#if 0 + if (HDA_PINSELECT(0x19, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out input"); + // HDA_OUTMUTE(0x19, group, "inmute", UNMUTE); +#else + HDA_SET_PINSELECT(0x19, 2); // Hardwire to input +#endif + HDA_INAMP(0x19, 0, group, "in", 90); /* From widget 0x0c */ + } + +#if 0 + if (HDA_PIN_GROUP(0x1a, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x1a */ + { + /* Src 0xd=rear */ + if (HDA_PINSELECT(0x1a, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "rear-out input"); + HDA_OUTMUTE(0x1a, group, "inmute", UNMUTE); + } +#endif + + if (HDA_PIN_GROUP(0x1b, group, pin_group, "green", n, "jack", 4)) /* Pin widget 0x1b */ + { + /* Src 0xc=front */ + /* Src 0xe=rear */ + if (HDA_PINSELECT(0x1b, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out input"); + HDA_OUTMUTE(0x1b, group, "inmute", UNMUTE); + HDA_INAMP(0x1b, 0, group, "out", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP(0x18, group, pin_group, "pink", n, "jack", 4)) /* Pin widget 0x18 */ + { + /* Src 0xe=rear */ + if (HDA_PINSELECT(0x18, ctl, group, "mode", 1)) + HDA_CHOICES(ctl, "rear-out input"); + HDA_OUTMUTE(0x18, group, "mute", UNMUTE); + HDA_INAMP(0x18, 0, group, "in", 90); /* From widget 0x0e */ + } + +#if 0 + if (HDA_PIN_GROUP(0x1c, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x1c */ + { + if (HDA_PINSELECT(0x1c, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + } + + if (HDA_PIN_GROUP(0x1d, group, pin_group, "purple", n, "jack", 4)) /* Pin widget 0x1d */ + { + if (HDA_PINSELECT(0x1d, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + } +#endif + } + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n=0; + + HDA_GROUP(rec_group, top_group, "record"); + + if (HDA_ADC_GROUP(0x08, group, rec_group, "pcmin0", n, "record", 4)) /* ADC widget 0x08 */ + { + /* Src 0x23=mix */ + HDA_INAMP(0x08, 0, group, "-", 90); /* From widget 0x23 */ + + /* Widget 0x23 (mix) */ + /* Src 0x18=pink */ + /* Src 0x19=mic */ + /* Src 0x1a=black */ + /* Src 0x1b=green */ + /* Src 0x1c=black */ + /* Src 0x1d=purple */ + /* Src 0x14=speaker */ + /* Src 0x15=black */ + /* Src 0x16=black */ + /* Src 0xb=mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "rec-mute"); + HDA_INMUTE(0x23, 0, amp_group, "pink", MUTE); /* From widget 0x18 */ + HDA_INMUTE(0x23, 1, amp_group, "mic", UNMUTE); /* From widget 0x19 */ + HDA_INMUTE(0x23, 2, amp_group, "black", MUTE); /* From widget 0x1a */ + HDA_INMUTE(0x23, 3, amp_group, "green", MUTE); /* From widget 0x1b */ + HDA_INMUTE(0x23, 4, amp_group, "black", MUTE); /* From widget 0x1c */ + HDA_INMUTE(0x23, 5, amp_group, "purple", MUTE); /* From widget 0x1d */ + HDA_INMUTE(0x23, 6, amp_group, "speaker", MUTE); /* From widget 0x14 */ + HDA_INMUTE(0x23, 7, amp_group, "black", MUTE); /* From widget 0x15 */ + HDA_INMUTE(0x23, 8, amp_group, "black", MUTE); /* From widget 0x16 */ + HDA_INMUTE(0x23, 9, amp_group, "input-mixer", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_ADC_GROUP(0x09, group, rec_group, "pcmin1", n, "record", 4)) /* ADC widget 0x09 */ + { + /* Src 0x22=mix */ + HDA_INAMP(0x09, 0, group, "-", 90); /* From widget 0x22 */ + + /* Widget 0x22 (mix) */ + /* Src 0x18=pink */ + /* Src 0x19=mic */ + /* Src 0x1a=black */ + /* Src 0x1b=green */ + /* Src 0x1c=black */ + /* Src 0x1d=purple */ + /* Src 0x14=speaker */ + /* Src 0x15=black */ + /* Src 0x16=black */ + /* Src 0xb=mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "rec-mute"); + HDA_INMUTE(0x22, 0, amp_group, "pink", MUTE); /* From widget 0x18 */ + HDA_INMUTE(0x22, 1, amp_group, "mic", MUTE); /* From widget 0x19 */ + HDA_INMUTE(0x22, 2, amp_group, "black", MUTE); /* From widget 0x1a */ + HDA_INMUTE(0x22, 3, amp_group, "green", MUTE); /* From widget 0x1b */ + HDA_INMUTE(0x22, 4, amp_group, "black", MUTE); /* From widget 0x1c */ + HDA_INMUTE(0x22, 5, amp_group, "purple", MUTE); /* From widget 0x1d */ + HDA_INMUTE(0x22, 6, amp_group, "speaker", MUTE); /* From widget 0x14 */ + HDA_INMUTE(0x22, 7, amp_group, "black", MUTE); /* From widget 0x15 */ + HDA_INMUTE(0x22, 8, amp_group, "black", MUTE); /* From widget 0x16 */ + HDA_INMUTE(0x22, 9, amp_group, "input-mixer", UNMUTE); /* From widget 0x0b */ + } + } + } + /* Handle misc widgets */ + { + int n, group, misc_group; + + n=0; + + HDA_GROUP(misc_group, top_group, "misc"); + + if (HDA_MISC_GROUP(0x0c, group, misc_group, "front", n, "misc", 8)) /* Misc widget 0x0c */ + { + /* Src 0x2=front */ + /* Src 0xb=mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0c, 0, amp_group, "pcm-front", UNMUTE); /* From widget 0x02 */ + HDA_INMUTE(0x0c, 1, amp_group, "input-mixer", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0d, group, misc_group, "rear", n, "misc", 8)) /* Misc widget 0x0d */ + { + /* Src 0x3=rear */ + /* Src 0xb=mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0d, 0, amp_group, "pcm-rear", UNMUTE); /* From widget 0x03 */ + HDA_INMUTE(0x0d, 1, amp_group, "input-mixer", UNMUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0e, group, misc_group, "rear", n, "misc", 8)) /* Misc widget 0x0e */ + { + /* Src 0x4=rear */ + /* Src 0xb=mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0e, 0, amp_group, "rear", UNMUTE); /* From widget 0x04 */ + HDA_INMUTE(0x0e, 1, amp_group, "input-mixer", UNMUTE); /* From widget 0x0b */ + } + } + +#if 0 + if (HDA_MISC_GROUP(0x02, group, misc_group, "pcm-front", n, "misc", 8)) /* Misc widget 0x02 */ + { + HDA_OUTAMP(0x02, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x03, group, misc_group, "pcm", n, "misc", 8)) /* Misc widget 0x03 */ + { + HDA_OUTAMP(0x03, group, "-", 0); + } + + if (HDA_MISC_GROUP(0x04, group, misc_group, "pcm-rear", n, "misc", 8)) /* Misc widget 0x04 */ + { + HDA_OUTAMP(0x04, group, "-", 90); + } +#endif + + if (HDA_MISC_GROUP(0x0b, group, misc_group, "input-mixer", n, "misc", 8)) /* Misc widget 0x0b */ + { + /* Src 0x18=rear */ + /* Src 0x19=mic */ + /* Src 0x1a=rear */ + /* Src 0x1b=headphone */ + /* Src 0x1c=speaker */ + /* Src 0x1d=speaker */ + /* Src 0x14=front */ + /* Src 0x15=rear */ + /* Src 0x16=rear */ + HDA_INAMP(0x0b, 0, group, "pink", 20); /* From widget 0x18 */ + HDA_INAMP(0x0b, 1, group, "mic", 20); /* From widget 0x19 */ + HDA_INAMP(0x0b, 2, group, "black", 90); /* From widget 0x1a */ + HDA_INAMP(0x0b, 3, group, "green", 90); /* From widget 0x1b */ + HDA_INAMP(0x0b, 4, group, "black", 90); /* From widget 0x1c */ + HDA_INAMP(0x0b, 5, group, "purple", 90); /* From widget 0x1d */ + // HDA_INAMP(0x0b, 6, group, "speaker", 90); /* From widget 0x14 */ + HDA_INAMP(0x0b, 7, group, "black", 90); /* From widget 0x15 */ + HDA_INAMP(0x0b, 8, group, "black", 90); /* From widget 0x16 */ + } + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_ferrari5k.c b/kernel/drv/oss_hdaudio/hdaudio_ferrari5k.c new file mode 100644 index 0000000..1ee3eca --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_ferrari5k.c @@ -0,0 +1,303 @@ +/* + * + * 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. + * + */ +/* Codec index is 1 */ +/* Codec vendor 10ec:0883 */ +/* HD codec revision 1.0 (0.2) (0x00100002) */ +/* Subsystem ID 10250000 */ +/* Default amplifier caps: in=00000000, out=00000000 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_ferrari5k_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + int ctl=0; + + DDB(cmn_err(CE_CONT, "hdaudio_ferrari5k_mixer_init got called.\n")); + + // Main volume controls for PCM channels. Moved from the misc group + HDA_OUTAMP_F(0x0c, top_group, "front", 90, MIXF_MAINVOL); + HDA_OUTAMP_F(0x0d, top_group, "rear", 90, MIXF_MAINVOL); + HDA_OUTAMP_F(0x0e, top_group, "center/lfe", 90, MIXF_MAINVOL); + HDA_OUTAMP_F(0x0f, top_group, "side", 90, MIXF_MAINVOL); + HDA_OUTAMP_F(0x26, top_group, "pcm4", 90, MIXF_MAINVOL); + + // Mute controls for the output pins + HDA_OUTMUTE(0x15, top_group, "speaker-mute", UNMUTE); + HDA_OUTMUTE(0x14, top_group, "headph-mute", UNMUTE); + HDA_OUTMUTE(0x1a, top_group, "lineout-mute", UNMUTE); + HDA_OUTMUTE(0x18, top_group, "mic-jack-mute", UNMUTE); + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n=0; + + HDA_GROUP(pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP(0x15, group, pin_group, "int-speaker", n, "jack", 8)) /* Pin widget 0x15 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT(0x15, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out center/LFE-out side-out pcm4-out unused"); + //HDA_INAMP(0x15, 0, group, "inlevel", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP(0x14, group, pin_group, "headphone", n, "jack", 8)) /* Pin widget 0x14 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT(0x14, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_INAMP(0x14, 0, group, "inlevel", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP(0x18, group, pin_group, "ext-mic", n, "jack", 8)) /* Pin widget 0x18 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT(0x18, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_INAMP(0x18, 0, group, "inlevel", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP(0x19, group, pin_group, "int-mic", n, "jack", 8)) /* Pin widget 0x19 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ +#if 1 + HDA_SETSELECT(0x19, 5); // Hardwired to mic-input +#else + if (HDA_PINSELECT(0x19, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "front-out rear-out center/LFE-out side-out pcm4-out input"); +#endif + //HDA_OUTMUTE(0x19, group, "outmute", UNMUTE); + HDA_INAMP(0x19, 0, group, "inlevel", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP(0x1a, group, pin_group, "line-out", n, "jack", 8)) /* Pin widget 0x1a */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT(0x1a, ctl, group, "mode", 0)) + HDA_CHOICES(ctl, "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_INAMP(0x1a, 0, group, "inlevel", 90); /* From widget 0x0c */ + } + } + + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n=0; + + HDA_GROUP(rec_group, top_group, "record"); + + if (HDA_ADC_GROUP(0x08, group, rec_group, "rec1", n, "record", 4)) /* ADC widget 0x08 */ + { + /* Src 0x23=rec1 */ + HDA_INAMP_F(0x08, 0, group, "rec1", 80, MIXF_RECVOL); /* From widget 0x23 */ + + /* Widget 0x23 (rec1) */ + /* Src 0x18=ext-mic */ + /* Src 0x19=int-mic */ + /* Src 0x1a=line-out */ + /* Src 0x1b=black */ + /* Src 0x1c=black */ + /* Src 0x1d=black */ + /* Src 0x14=black */ + /* Src 0x15=int-speaker */ + /* Src 0x16=black */ + /* Src 0x17=black */ + /* Src 0xb=input-mix */ + { +#if 1 + if (HDA_INSRC_SELECT(0x23, group, ctl, "recsrc", 1)) + HDA_CHOICES(ctl, "ext-mic int-mic line-out-jack unused unused unused unused unused unused unused input-mix"); +#else + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x23, 0, amp_group, "ext-mic", UNMUTE); /* From widget 0x18 */ + HDA_INMUTE(0x23, 1, amp_group, "int-mic", UNMUTE); /* From widget 0x19 */ + HDA_INMUTE(0x23, 2, amp_group, "line-out", UNMUTE); /* From widget 0x1a */ + HDA_INMUTE(0x23, 3, amp_group, "black", UNMUTE); /* From widget 0x1b */ + HDA_INMUTE(0x23, 4, amp_group, "black", UNMUTE); /* From widget 0x1c */ + HDA_INMUTE(0x23, 5, amp_group, "black", UNMUTE); /* From widget 0x1d */ + HDA_INMUTE(0x23, 6, amp_group, "headph-jack", UNMUTE); /* From widget 0x14 */ + HDA_INMUTE(0x23, 7, amp_group, "int-speaker", UNMUTE); /* From widget 0x15 */ + HDA_INMUTE(0x23, 8, amp_group, "black", UNMUTE); /* From widget 0x16 */ + HDA_INMUTE(0x23, 9, amp_group, "black", UNMUTE); /* From widget 0x17 */ + HDA_INMUTE(0x23, 10, amp_group, "input-mix", MUTE); /* From widget 0x0b */ +#endif + } + } + + if (HDA_ADC_GROUP(0x09, group, rec_group, "rec2", n, "record", 4)) /* ADC widget 0x09 */ + { + /* Src 0x22=rec2 */ + HDA_INAMP_F(0x09, 0, group, "rec2", 80, MIXF_RECVOL); /* From widget 0x22 */ + + /* Widget 0x22 (rec2) */ + /* Src 0x18=ext-mic */ + /* Src 0x19=int-mic */ + /* Src 0x1a=line-out */ + /* Src 0x1b=black */ + /* Src 0x1c=black */ + /* Src 0x1d=black */ + /* Src 0x14=black */ + /* Src 0x15=int-speaker */ + /* Src 0x16=black */ + /* Src 0x17=black */ + /* Src 0xb=input-mix */ + { +#if 1 + if (HDA_INSRC_SELECT(0x22, group, ctl, "recsrc", 1)) + HDA_CHOICES(ctl, "ext-mic int-mic line-out-jack unused unused unused unused unused unused unused input-mix"); +#else + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x22, 0, amp_group, "ext-mic", UNMUTE); /* From widget 0x18 */ + HDA_INMUTE(0x22, 1, amp_group, "int-mic", UNMUTE); /* From widget 0x19 */ + HDA_INMUTE(0x22, 2, amp_group, "line-out", UNMUTE); /* From widget 0x1a */ + HDA_INMUTE(0x22, 3, amp_group, "black", UNMUTE); /* From widget 0x1b */ + HDA_INMUTE(0x22, 4, amp_group, "black", UNMUTE); /* From widget 0x1c */ + HDA_INMUTE(0x22, 5, amp_group, "black", UNMUTE); /* From widget 0x1d */ + HDA_INMUTE(0x22, 6, amp_group, "headph-jack", UNMUTE); /* From widget 0x14 */ + HDA_INMUTE(0x22, 7, amp_group, "int-speaker", UNMUTE); /* From widget 0x15 */ + HDA_INMUTE(0x22, 8, amp_group, "black", UNMUTE); /* From widget 0x16 */ + HDA_INMUTE(0x22, 9, amp_group, "black", UNMUTE); /* From widget 0x17 */ + HDA_INMUTE(0x22, 10, amp_group, "input-mix", MUTE); /* From widget 0x0b */ +#endif + } + } + + if (HDA_ADC_GROUP(0x0a, group, rec_group, "spdif-in", n, "record", 4)) /* ADC widget 0x0a */ + { + /* Src 0x1f=speaker */ + } + } + /* Handle misc widgets */ + { + int n, group, misc_group; + + n=0; + + HDA_GROUP(misc_group, top_group, "misc"); + + if (HDA_MISC_GROUP(0x0c, group, misc_group, "front", n, "misc", 8)) /* Misc widget 0x0c */ + { + /* Src 0x2=front */ + /* Src 0xb=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0c, 0, amp_group, "front", UNMUTE); /* From widget 0x02 */ + HDA_INMUTE(0x0c, 1, amp_group, "input-mix", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0d, group, misc_group, "rear", n, "misc", 8)) /* Misc widget 0x0d */ + { + /* Src 0x3=rear */ + /* Src 0xb=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0d, 0, amp_group, "rear", UNMUTE); /* From widget 0x03 */ + HDA_INMUTE(0x0d, 1, amp_group, "input-mix", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0e, group, misc_group, "center/LFE", n, "misc", 8)) /* Misc widget 0x0e */ + { + /* Src 0x4=center/LFE */ + /* Src 0xb=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0e, 0, amp_group, "center/LFE", UNMUTE); /* From widget 0x04 */ + HDA_INMUTE(0x0e, 1, amp_group, "input-mix", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0f, group, misc_group, "side", n, "misc", 8)) /* Misc widget 0x0f */ + { + /* Src 0x5=side */ + /* Src 0xb=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0f, 0, amp_group, "side", UNMUTE); /* From widget 0x05 */ + HDA_INMUTE(0x0f, 1, amp_group, "input-mix", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x26, group, misc_group, "pcm4", n, "misc", 8)) /* Misc widget 0x26 */ + { + /* Src 0x25=pcm4 */ + /* Src 0xb=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x26, 0, amp_group, "pcm4", UNMUTE); /* From widget 0x25 */ + HDA_INMUTE(0x26, 1, amp_group, "input-mix", MUTE); /* From widget 0x0b */ + } + } + + if (HDA_MISC_GROUP(0x0b, group, misc_group, "input-mix", n, "misc", 8)) /* Misc widget 0x0b */ + { + /* Src 0x18=mic */ + /* Src 0x19=int-mic */ + /* Src 0x1a=linein */ + /* Src 0x1b=speaker */ + /* Src 0x1c=speaker */ + /* Src 0x1d=speaker */ + /* Src 0x14=headphone */ + /* Src 0x15=int-speaker */ + /* Src 0x16=speaker */ + /* Src 0x17=speaker */ + HDA_INAMP(0x0b, 0, group, "ext-mic", 10); /* From widget 0x18 */ + HDA_INAMP(0x0b, 1, group, "int-mic", 10); /* From widget 0x19 */ + HDA_INAMP(0x0b, 2, group, "line-out", 0); /* From widget 0x1a */ + HDA_INAMP(0x0b, 3, group, "black", 0); /* From widget 0x1b */ + HDA_INAMP(0x0b, 4, group, "black", 0); /* From widget 0x1c */ + HDA_INAMP(0x0b, 5, group, "black", 0); /* From widget 0x1d */ + //HDA_INAMP(0x0b, 6, group, "headph-jack", 90); /* From widget 0x14 */ + //HDA_INAMP(0x0b, 7, group, "int-speaker", 0); /* From widget 0x15 */ + HDA_INAMP(0x0b, 8, group, "black", 0); /* From widget 0x16 */ + HDA_INAMP(0x0b, 9, group, "black", 0); /* From widget 0x17 */ + } + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_generic.c b/kernel/drv/oss_hdaudio/hdaudio_generic.c new file mode 100644 index 0000000..2ea9811 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_generic.c @@ -0,0 +1,868 @@ +/* + * Purpose: Default mixer/control panel driver for HDA codecs + * + * This generic driver is used to create mixer/control panels for HDaudio + * codec chips that don't have any dedicated driver available. + * + * This driver will obtain the widget definitions from the codec and then + * try to guess a mixer layout that makes some sense. However this approach + * works properly only with a small set of codecs. + * + * Most codecs are unbearably complex and provide loads of redundant + * functionality. The generic driver approach will not properly work with them + * because the mixer (GUI) layout will become too large to fit on any screen. + * In addition such automatically generated mixer controls will not make any + * sense to the users. So in the future the only possible approach will be + * creating dedicated mixer drivers for all possible codecs in the market. + * Unfortunately in some cases the driver may even need to be motherboard + * specific. Apparently this is going to be enormous task. + */ +/* + * + * 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_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" + +extern int hdaudio_snoopy; +extern int hdaudio_jacksense; +extern int hdaudio_noskip; + +static int +count_linked_controls (hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int recursive) +{ +/* + * This function counts the number of mixer control elements this + * widget has. + * If recursive==1 then control counts of the previous widgets in the + * processing chain will be counted if number of inputs is exactly 1. + * Input sources are not checked if number of connections is larger than 1 + * because separate mixer group is required for such widgets. + * + * Note! The policies used by this function must match exactly the policies + * used by follow_widget_chain() + */ + int count = 0; + + if (widget->skip) + return 0; + + /* + * Output amp? + */ + if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT) + count += 1; + + /* + * Input amp(s)? + */ + if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT) + { + if (widget->wid_type == NT_MIXER) + count += widget->nconn; + else + count++; + } + + /* + * Input selector? + */ + if (widget->wid_type == NT_SELECT && widget->nconn > 1) + count += 1; + + if (recursive) + if (widget->nconn == 1) /* Exactly one input wource */ + count += + count_linked_controls (mixer, codec, + &codec->widgets[widget->connections[0]], + recursive); + + return count; +} + +/*ARGSUSED*/ +static int +attach_amplifiers (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int group, int group_mode) +{ + int i, cnum, ninputs; + int g = group; + int use_mutegroup = 0; + oss_mixext *ent; + +/* + * Control for input amplifier(s) + */ + if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT) + { + if (widget->wid_type == NT_MIXER) + ninputs = widget->nconn; + else + ninputs = 1; + + /* + * Check if it's possible to save horizontal space by creating a separate + * mute group. In this way the names of mute selectors become shorter. + */ + if (!(widget->inamp_caps & ~AMPCAP_MUTE) + && (widget->inamp_caps & AMPCAP_MUTE) && ninputs > 2) + { + use_mutegroup = 1; + if ((g = + mixer_ext_create_group (mixer->mixer_dev, group, "mute")) < 0) + return g; + } + + for (i = 0; i < ninputs; i++) /* All inputs */ + { + char tmpname[32], tmp[40]; + char *name = codec->widgets[widget->connections[i]].name; + + if (ninputs == 1) /* Hide name */ + name = "-"; + + if (codec->widgets[widget->connections[i]].skip) + continue; + + if (widget->inamp_caps & ~AMPCAP_MUTE) /* Supports gain control */ + { + int typ, num, maxval, val, range, step; + range = + ((widget-> + outamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & + AMPCAP_NUMSTEPS_MASK) + 1; + step = + ((widget-> + outamp_caps >> AMPCAP_STEPSIZE_SHIFT) & + AMPCAP_STEPSIZE_MASK) + 1; + + if (step > 20 /* 5dB */ && range < 5) + { + create_ingain_selector (mixer, codec, widget, group, i, + name); + continue; + } + maxval = hdaudio_amp_maxval (widget->inamp_caps); + + if (widget->widget_caps & WCAP_STEREO) + { + typ = MIXT_STEREOSLIDER16; + num = MIXNUM (widget, CT_INSTEREO, i); + } + else + { + typ = MIXT_MONOSLIDER16; + num = MIXNUM (widget, CT_INMONO, i); + } + + if (hdaudio_snoopy > 0) + { + sprintf (tmp, "%s:R%x", name, widget->wid); + name = tmp; + } + + if ((cnum = mixer_ext_create_control (mixer->mixer_dev, + group, + num, + hdaudio_set_control, + typ, + name, maxval, + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return cnum; + + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, cnum)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + /* Setup initial volume */ + val = (maxval * 8) / 10; /* 80% of the maximum */ + val = val | (val << 16); + + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, + val); + continue; /* Skip to the next input */ + } + + if (widget->inamp_caps & AMPCAP_MUTE) /* Supports only mute */ + { + if (use_mutegroup) + strcpy (tmpname, name); + else + sprintf (tmpname, "%s-mute", name); + name = tmpname; + + if (hdaudio_snoopy > 0) + { + sprintf (tmp, "%s:Q%x", name, widget->wid); + name = tmp; + } + + if ((cnum = mixer_ext_create_control (mixer->mixer_dev, + g, + MIXNUM (widget, + CT_INMUTE, i), + hdaudio_set_control, + MIXT_MUTE, name, 2, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return cnum; + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, cnum)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_INMUTE, i), + SNDCTL_MIX_WRITE, 0); + } + + } + } + +/* + * Output amplifier control + */ + + if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT) + { + char tmp[32]; + char *name = "-"; + + if (hdaudio_snoopy) + name = "outamp"; + + if (widget->outamp_caps & ~AMPCAP_MUTE) /* Has gain control */ + { + int range, step, typ, num, maxval, val; + range = + ((widget-> + outamp_caps >> AMPCAP_NUMSTEPS_SHIFT) & AMPCAP_NUMSTEPS_MASK) + + 1; + step = + ((widget-> + outamp_caps >> AMPCAP_STEPSIZE_SHIFT) & AMPCAP_STEPSIZE_MASK) + + 1; + + if (step > 20 /* 5dB */ && range < 5) + { + create_outgain_selector (mixer, widget, group, name); + } + else + { + + maxval = hdaudio_amp_maxval (widget->outamp_caps); + + if (widget->widget_caps & WCAP_STEREO) + { + typ = MIXT_STEREOSLIDER16; + num = MIXNUM (widget, CT_OUTSTEREO, 0); + } + else + { + typ = MIXT_MONOSLIDER16; + num = MIXNUM (widget, CT_OUTMONO, 0); + } + + if (hdaudio_snoopy > 0) + { + sprintf (tmp, "%s:V%x", name, widget->wid); + name = tmp; + } + else + { + sprintf (tmp, "%s", widget->name); + name = tmp; + } + + if ((cnum = mixer_ext_create_control (mixer->mixer_dev, + group, + num, hdaudio_set_control, + typ, + name, maxval, + MIXF_READABLE | + MIXF_WRITEABLE | + MIXF_CENTIBEL)) < 0) + return cnum; + + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, cnum)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + /* setup volume */ + val = (maxval * 8) / 10; /* 80% of the maximum */ + val = val | (val << 16); + hdaudio_set_control (mixer->mixer_dev, num, SNDCTL_MIX_WRITE, + val); + } + } + else if (widget->outamp_caps & AMPCAP_MUTE) /* Only mute control */ + { + char tmpname[32]; + name = "mute"; + if (hdaudio_snoopy > 0) + { + sprintf (tmpname, "%s:U%x", name, widget->wid); + name = tmpname; + } + + if ((cnum = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, + CT_OUTMUTE, 0), + hdaudio_set_control, + MIXT_MUTE, name, 2, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return cnum; + + /* Copy RGB color */ + if (widget->rgbcolor != 0) + if ((ent = mixer_find_ext (dev, cnum)) != NULL) + ent->rgbcolor = widget->rgbcolor; + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_OUTMUTE, 0), + SNDCTL_MIX_WRITE, 0); + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +attach_selector (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int group, int group_mode) +{ + unsigned int c, b; + char *name = "src"; + + int i, ctl; + char tmp[256], *t = tmp; + oss_mixext *ext; + int count = 0; + + + /* + * first check to see if there are more that 2 valid options to create a + * selector for. + */ + for (i = 0; i < widget->nconn; i++) + if (!codec->widgets[widget->connections[i]].skip + && codec->widgets[widget->connections[i]].sensed_pin != PIN_OUT) + count++; + + if (count < 2) + return 0; + + + name = widget->name; + + if (corb_read (mixer, widget->cad, widget->wid, 0, GET_SELECTOR, 0, &c, &b)) + widget->current_selector = c; + + if (hdaudio_snoopy > 0) + { + sprintf (tmp, "%s:%x", name, widget->wid); + name = tmp; + } + + + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + group, + MIXNUM (widget, CT_SELECT, 0), + hdaudio_set_control, + MIXT_ENUM, + name, + widget->nconn, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + + *tmp = 0; + ext = mixer_find_ext (mixer->mixer_dev, ctl); + + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension (a)\n"); + return OSS_EIO; + } + + /* Copy RGB color */ + ext->rgbcolor = widget->rgbcolor; + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < widget->nconn; i++) + { + char *s; + + /* + * ensure that the connection list has a valid widget id - some + * devices have bogus connection lists + */ + if (codec->widgets[widget->connections[i]].wid < codec->first_node) + continue; + + s = codec->widgets[widget->connections[i]].name; + if (strlen (tmp) + strlen (s) + 1 < sizeof (tmp) - 1) + { + if (*tmp != 0) + *t++ = ' '; + strcpy (t, s); + if (hdaudio_snoopy > 0) + sprintf (t, "A%s:%x", s, + mixer->codecs[widget->cad]->widgets[widget-> + connections[i]].wid); + t += strlen (t); + + /* + * Show only widgets that are not marked to be ignored. + * Also hide I/O pins that are known to be outputs. + */ + if (!codec->widgets[widget->connections[i]].skip + && codec->widgets[widget->connections[i]].sensed_pin != PIN_OUT) + ext->enum_present[i / 8] |= (1 << (i % 8)); + else + { + if (widget->current_selector == i) + widget->current_selector++; + } + } + } + mixer_ext_set_strings (mixer->mixer_dev, ctl, tmp, 0); + + if (widget->current_selector >= widget->nconn) + widget->current_selector = 0; + corb_write (mixer, widget->cad, widget->wid, 0, SET_SELECTOR, + widget->current_selector); + + return 0; +} + +static int +follow_widget_chain (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int group) +{ + int err; + + if (widget->used) /* Already handled */ + return 0; + + widget->used = 1; + + if (widget->nconn >= 1) + if ((err = + follow_widget_chain (dev, mixer, codec, + &codec->widgets[widget->connections[0]], + group)) < 0) + return err; + + if ((err = attach_amplifiers (dev, mixer, codec, widget, group, 1)) < 0) + return err; + + if (widget->wid_type == NT_SELECT) + if ((err = attach_selector (dev, mixer, codec, widget, group, 1)) < 0) + return err; + + return 0; +} + +static int +attach_pin_widget (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int parent_group) +{ + int group = parent_group, g; + unsigned int b, c, conf; + int i, ctl, err; + int inselects = 0, outselects = 0, linked_controls = 0; + int num_amps = 0; + char tmp[256], *t = tmp; + oss_mixext *ext; + + if (widget->pincaps & PINCAP_OUTPUT_CAPABLE) + { + outselects = widget->nconn; + + if (widget->nconn == 1) /* Exactly one connection */ + { + linked_controls = + count_linked_controls (mixer, codec, + &codec->widgets[widget->connections[0]], + 1); + } + } + + if (widget->pincaps & PINCAP_INPUT_CAPABLE) + { + if (!(widget->widget_caps & WCAP_DIGITAL)) /* Analog pin */ + { + inselects = 1; + } + } + + if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT) + { + num_amps++; + } + + if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT) + { + num_amps++; + } + + if ((inselects + outselects > 1) || num_amps > 0 || linked_controls > 0) /* Have something to control */ + { + if (widget->color[0] == 0) /* Empty name */ + sprintf (widget->color, "jack%02x", widget->wid); + if ((g = + mixer_ext_create_group (mixer->mixer_dev, group, + widget->color)) < 0) + return g; + + if (corb_read + (mixer, widget->cad, widget->wid, 0, GET_SELECTOR, 0, &c, &b)) + widget->current_selector = c; + + if (inselects + outselects > 1) + { + if ((ctl = mixer_ext_create_control (mixer->mixer_dev, + g, + MIXNUM (widget, CT_SELECT, 0), + hdaudio_set_control, + MIXT_ENUM, + "mode", + inselects + outselects, + MIXF_READABLE | + MIXF_WRITEABLE)) < 0) + return ctl; + + *tmp = 0; + ext = mixer_find_ext (mixer->mixer_dev, ctl); + + if (ext == NULL) + { + cmn_err (CE_WARN, "Cannot locate the mixer extension (b)\n"); + return OSS_EIO; + } + /* Copy RGB color */ + ext->rgbcolor = widget->rgbcolor; + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + + for (i = 0; i < widget->nconn; i++) + { + char *s; + + s = codec->widgets[widget->connections[i]].name; + if (strlen (tmp) + strlen (s) + 1 < sizeof (tmp) - 1) + { + if (*tmp != 0) + *t++ = ' '; + strcpy (t, s); + if (hdaudio_snoopy > 0) + sprintf (t, "A%s:%x", s, + mixer->codecs[widget->cad]->widgets[widget-> + connections + [i]].wid); + t += strlen (t); + + /* + * Show only widgets that are not marked to be ignored. + */ + if (!codec->widgets[widget->connections[i]].skip) + ext->enum_present[i / 8] |= (1 << (i % 8)); + else + { + if (widget->current_selector == i) + widget->current_selector++; + } + } + } + +/* + * Use the default sequence as an index to the output source selectors. + */ + if (widget->sensed_pin == PIN_OUT) + if (corb_read + (mixer, widget->cad, widget->wid, 0, GET_CONFIG_DEFAULT, 0, + &conf, &b)) + { + int association, sequence; + + association = (conf >> 4) & 0x0f; + sequence = conf & 0x0f; + + if (association != 0) + { + widget->current_selector = sequence; + } + + } + + if (widget->current_selector >= widget->nconn) + widget->current_selector = 0; + + if (inselects > 0) /* Input capable */ + { + char *s; + + i = widget->nconn; + s = widget->name; + + if (*tmp != 0) + *t++ = ' '; + + strcpy (t, "input"); + + t += strlen (t); + ext->enum_present[i / 8] |= (1 << (i % 8)); + i++; + + if (widget->pin_type == PIN_IN) + widget->current_selector = widget->nconn; + } + + mixer_ext_set_strings (mixer->mixer_dev, ctl, tmp, 0); + } + + hdaudio_set_control (mixer->mixer_dev, + MIXNUM (widget, CT_SELECT, 0), + SNDCTL_MIX_WRITE, widget->current_selector); + + if ((err = attach_amplifiers (dev, mixer, codec, widget, g, 0)) < 0) + return err; + + if (widget->nconn == 1) + if ((err = + follow_widget_chain (dev, mixer, codec, + &codec->widgets[widget->connections[0]], + g)) < 0) + return err; + } + + return 0; +} + +static int +attach_record_widget (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int parent_group) +{ + int group = parent_group, g; + int err; + int linked_controls = 0; + int num_amps = 0; + + if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT) + { + num_amps++; + } + + if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT) + { + num_amps++; + } + + if (widget->nconn == 1) /* Exactly one connection */ + { + linked_controls = + count_linked_controls (mixer, codec, + &codec->widgets[widget->connections[0]], 1); + } + + if (num_amps > 0 || linked_controls > 1) /* Have something to control */ + { + if ((g = + mixer_ext_create_group (mixer->mixer_dev, group, + widget->name)) < 0) + return g; + + if (widget->nconn == 1) + if ((err = + follow_widget_chain (dev, mixer, codec, + &codec->widgets[widget->connections[0]], + g)) < 0) + return err; + + if ((err = attach_amplifiers (dev, mixer, codec, widget, g, 0)) < 0) + return err; + if ((err = attach_selector (dev, mixer, codec, widget, g, 0)) < 0) + return err; + } + + return 0; +} + +static int +attach_misc_widget (int dev, hdaudio_mixer_t * mixer, codec_t * codec, + widget_t * widget, int parent_group) +{ + int err; + int nselect = 0; + int num_amps = 0; + + if (widget->widget_caps & WCAP_INPUT_AMP_PRESENT) + { + num_amps++; + } + + if (widget->widget_caps & WCAP_OUTPUT_AMP_PRESENT) + { + num_amps++; + } + + if ((widget->wid_type == NT_SELECT || widget->wid_type == NT_MIXER) + && widget->nconn > 0) + nselect = widget->nconn; + + if (num_amps > 0 || nselect > 1) /* Have something to control */ + { +#if 0 + if ((g = + mixer_ext_create_group (mixer->mixer_dev, group, + widget->name)) < 0) + return g; +#endif + if ((err = + attach_amplifiers (dev, mixer, codec, widget, parent_group, + 0)) < 0) + return err; + + if (nselect > 1) + if ((err = + attach_selector (dev, mixer, codec, widget, parent_group, + 0)) < 0) + return err; + } + + return 0; +} + +int +hdaudio_generic_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, + int parent_group) +{ + unsigned int vendorid, b; + int err; + int wid, n; + codec_t *codec; + widget_t *widget; + int group = parent_group; + + if (mixer->codecs[cad] == NULL) + { + cmn_err (CE_WARN, "Bad codec %d\n", cad); + return OSS_EIO; + } + codec = mixer->codecs[cad]; + + if (!corb_read (mixer, cad, 0, 0, GET_PARAMETER, HDA_VENDOR, &vendorid, &b)) + { + cmn_err (CE_WARN, "Cannot get codec ID\n"); + return OSS_EIO; + } + +/* + * First handle all the PIN widgets + */ + n = 0; + + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->wid_type != NT_PIN) /* Not a pin widget */ + continue; + + widget->used = 1; + + if (widget->skip) /* Unused/unconnected PIN widget */ + { + continue; + } + + if ((n++ % 3) == 0) + { + if ((group = + mixer_ext_create_group (mixer->mixer_dev, parent_group, + "jack")) < 0) + return group; + } + + + if ((err = attach_pin_widget (dev, mixer, codec, widget, group)) < 0) + return err; + } + +/* + * Next handle all the ADC widgets + */ + n = 0; + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->wid_type != NT_ADC) /* Not a pin widget */ + continue; + + if (widget->skip) + continue; + + widget->used = 1; + + if ((n++ % 3) == 0) + { + if ((group = + mixer_ext_create_group (mixer->mixer_dev, parent_group, + "record")) < 0) + return group; + } + + if ((err = attach_record_widget (dev, mixer, codec, widget, group)) < 0) + return err; + } + +/* + * Finally handle all the widgets that have not been attached yet + */ + + n = 0; + for (wid = 0; wid < codec->nwidgets; wid++) + { + widget = &codec->widgets[wid]; + + if (widget->skip) + continue; + + if (widget->used) /* Already handled */ + continue; + + widget->used = 1; + + if (count_linked_controls (mixer, codec, widget, 0) > 0) + if ((n++ % 4) == 0) + { + if ((group = + mixer_ext_create_group (mixer->mixer_dev, parent_group, + "misc")) < 0) + return group; + } + + if ((err = attach_misc_widget (dev, mixer, codec, widget, group)) < 0) + return err; + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_gpio_handlers.c b/kernel/drv/oss_hdaudio/hdaudio_gpio_handlers.c new file mode 100644 index 0000000..357b689 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_gpio_handlers.c @@ -0,0 +1,128 @@ +/* + * Purpose: GPIO initialization handlers for some High Definition Audio systems + * + * This file contains codec initialization functions for some HDaudio + * systems that require initialization of GPIO bits. All functions should + * return OSS_EAGAIN so that hdaudio_codec.c knows to call the generic + * codec/mixer initialization routine for the codec. Alternatively the + * GPIO init function may call the codec/mixer init function for the + * given system directly (return my_mixer_init_func()). + * + * Note that if the system has a dedicated mixer initialization function + * then also GPIO initialization needs to be performed in the mixer init + * function (since the same mixer_init function pointers in hdaudio_codecds.h + * are shared for both purposes). + * + * For example: + * + * int + * hdaudio_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) + * { + * codec_t *codec = mixer->codecs[cad]; + * int afg = codec->afg; // Audio function group root widget + * + * // Now use the corb_read() and corb_write() functions to set the + * // GPIO related verbs (registers) to the required values. + * + * return OSS_EAGAIN; // Fallback + * } + * + * To write the GPIO registers you can use: + * + * corb_write (mixer, cad, afg, 0, SET_GPIO_DIR, 0xNNNNNNNN); + * corb_write (mixer, cad, afg, 0, SET_GPIO_ENABLE, 0xNNNNNNNN); + * corb_write (mixer, cad, afg, 0, SET_GPIO_DATA, 0xNNNNNNNN); + * + * Also (if necessary) you can use the following calls. However they will probably + * need changes to hdaudio_codec.c so that the unsolicited responses are handled peoperly: + * + * corb_write (mixer, cad, afg, 0, SET_GPIO_WKEN, 0xNNNNNNNN); + * corb_write (mixer, cad, afg, 0, SET_GPIO_UNSOL, 0xNNNNNNNN); + * corb_write (mixer, cad, afg, 0, SET_GPIO_STICKY, 0xNNNNNNNN); + * + * Next the function prototype should be added to hdaudio_codecids.h. Finally + * edit the subdevices[] array in hdaudio_codecids.h so that the function + * gets called when given codec (subsystem vendor+device) is detected in the + * system. It is not recommended to use the codecs[] table to + * detect systems that need GPIO handling. The same codec may be used + * in many different systems and most of them don't require GPIO init. + * However this is possible if the handler uses the subvendor+subdevice ID to detect the system. + */ +/* + * + * 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_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_codecids.h" + +int +hdaudio_mac_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + codec_t *codec = mixer->codecs[cad]; + int afg = codec->afg; // Audio function group root widget + unsigned int subdevice = codec->subvendor_id; + unsigned int codec_id = codec->vendor_id; + + // TODO: Populate this function with the real stuff + +cmn_err(CE_CONT, "hdaudio_mac_GPIO_init() entered, afg=%d, subdevice=0x%08x, codec=0x%08x\n", afg, subdevice, codec_id); + + return OSS_EAGAIN; /* Continue with the default mixer init */ +} + +int +hdaudio_mac_sigmatel_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ +cmn_err(CE_CONT, "iMac Sigmatel hdaudio initialization\n"); + return hdaudio_mac_GPIO_init(dev, mixer, cad, top_group); +} + +int +hdaudio_mac_realtek_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + codec_t *codec = mixer->codecs[cad]; + int afg = codec->afg; // Audio function group root widget + +cmn_err(CE_CONT, "iMac Realtek hdaudio initialization\n"); + + corb_write (mixer, cad, afg, 0, SET_GPIO_DIR, 0xffffffff); + corb_write (mixer, cad, afg, 0, SET_GPIO_ENABLE, 0xffffffff); + corb_write (mixer, cad, afg, 0, SET_GPIO_DATA, 0xffffffff); + return hdaudio_mac_GPIO_init(dev, mixer, cad, top_group); +} + +int +hdaudio_asus_a7k_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + DDB(cmn_err(CE_CONT, "hdaudio_asus_a7k_GPIO_init got called.\n")); + + corb_write (mixer, cad, 0x01, 0, SET_GPIO_ENABLE, 3); + corb_write (mixer, cad, 0x01, 0, SET_GPIO_DIR, 1); + corb_write (mixer, cad, 0x01, 0, SET_GPIO_DATA, 1); + + return hdaudio_generic_mixer_init(dev, mixer, cad, top_group); +} + +int +hdaudio_GPIO_init_1 (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + DDB(cmn_err(CE_CONT, "hdaudio_GPIO_init_1 got called.\n")); + + /* Acer TravelMate 4060 and similar Aspire series, with ALC260 codec, need + * that we init GPIO to get internal speaker and headphone jack working. */ + corb_write(mixer, cad, 0x01, 0, SET_GPIO_ENABLE, 1); + corb_write(mixer, cad, 0x01, 0, SET_GPIO_DIR, 1); + corb_write(mixer, cad, 0x01, 0, SET_GPIO_DATA, 1); + + return hdaudio_generic_mixer_init(dev, mixer, cad, top_group); +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_mixers.h b/kernel/drv/oss_hdaudio/hdaudio_mixers.h new file mode 100644 index 0000000..eb92910 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_mixers.h @@ -0,0 +1,20 @@ +/* + * Purpose: Declarations of some functions and structures for HD audio mixers + */ +/* + * + * 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. + * + */ +/* + * Prototype definitions for dedicated HDAudio codec/mixer drivers. + */ + +extern int hdaudio_generic_mixer_init (int dev, hdaudio_mixer_t * mixer, + int cad, int group); diff --git a/kernel/drv/oss_hdaudio/hdaudio_scaleoP.c b/kernel/drv/oss_hdaudio/hdaudio_scaleoP.c new file mode 100644 index 0000000..b4bab5f --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_scaleoP.c @@ -0,0 +1,277 @@ +/* + * + * 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. + * + */ +/* Codec index is 0 */ +/* Codec vendor 0804:7d10 */ +/* HD codec revision 1.0 (0.1) (0x00100001) */ +/* Subsystem ID 1043e601 */ +/* Default amplifier caps: in=00000000, out=00000000 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_scaleoP_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, + int top_group) +{ + int ctl = 0; + + DDB (cmn_err (CE_CONT, "hdaudio_scaleoP_mixer_init got called.\n")); + + HDA_OUTAMP_F (0x0c, top_group, "front", 90, MIXF_PCMVOL); + HDA_OUTAMP_F (0x0d, top_group, "rear", 90, MIXF_PCMVOL); + HDA_OUTAMP_F (0x0e, top_group, "center/LFE", 90, MIXF_PCMVOL); + HDA_OUTAMP_F (0x0f, top_group, "side", 90, MIXF_PCMVOL); + HDA_OUTAMP_F (0x26, top_group, "pcm4", 90, MIXF_PCMVOL); + + /* + * Unmute all inputs for the above sliders. + */ + HDA_SET_INMUTE (0x0c, 0, UNMUTE); /* From widget 0x02 */ + HDA_SET_INMUTE (0x0c, 1, UNMUTE); /* From widget 0x0b */ + HDA_SET_INMUTE (0x0d, 0, UNMUTE); /* From widget 0x03 */ + HDA_SET_INMUTE (0x0d, 1, UNMUTE); /* From widget 0x0b */ + HDA_SET_INMUTE (0x0e, 0, UNMUTE); /* From widget 0x04 */ + HDA_SET_INMUTE (0x0e, 1, UNMUTE); /* From widget 0x0b */ + HDA_SET_INMUTE (0x0f, 0, UNMUTE); /* From widget 0x05 */ + HDA_SET_INMUTE (0x0f, 1, UNMUTE); /* From widget 0x0b */ + HDA_SET_INMUTE (0x26, 0, UNMUTE); /* From widget 0x25 */ + HDA_SET_INMUTE (0x26, 1, UNMUTE); /* From widget 0x0b */ + + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n = 0; + + HDA_GROUP (rec_group, top_group, "record"); + + if (HDA_ADC_GROUP (0x08, group, rec_group, "rec1", n, "record", 2)) /* ADC widget 0x08 */ + { + /* Src 0x23=mix */ + HDA_INAMP (0x08, 0, group, "-", 90); /* From widget 0x23 */ + + /* Widget 0x23 (mix) */ + /* Src 0x18=pink */ + /* Src 0x19=fp-pink */ + /* Src 0x1a=blue */ + /* Src 0x1b=fp-green */ + /* Src 0x1c=int-aux */ + /* Src 0x1d=black */ + /* Src 0x14=green */ + /* Src 0x15=black */ + /* Src 0x16=orange */ + /* Src 0x17=grey */ + /* Src 0x0b=input-mix */ + if (HDA_INSRC_SELECT (0x23, group, ctl, "recsrc", 10)) + HDA_CHOICES (ctl, + "pink fp-pink blue fp-green int-aux black green black orange grey input-mix"); + } + + if (HDA_ADC_GROUP (0x09, group, rec_group, "rec2", n, "record", 2)) /* ADC widget 0x09 */ + { + /* Src 0x22=mix */ + HDA_INAMP (0x09, 0, group, "-", 90); /* From widget 0x22 */ + + /* Widget 0x22 (mix) */ + /* Src 0x18=pink */ + /* Src 0x19=fp-pink */ + /* Src 0x1a=blue */ + /* Src 0x1b=fp-green */ + /* Src 0x1c=int-aux */ + /* Src 0x1d=black */ + /* Src 0x14=green */ + /* Src 0x15=black */ + /* Src 0x16=orange */ + /* Src 0x17=grey */ + /* Src 0xb=input-mix */ + if (HDA_INSRC_SELECT (0x23, group, ctl, "recsrc", 10)) + HDA_CHOICES (ctl, + "pink fp-pink blue fp-green int-aux black green black orange grey input-mix"); + } + +#if 0 + if (HDA_ADC_GROUP (0x0a, group, rec_group, "spdif-in", n, "record", 4)) /* ADC widget 0x0a */ + { + /* Src 0x1f=speaker */ + } +#endif + } + /* Handle misc widgets */ + { + int n, group; + + n = 0; + + HDA_GROUP (group, top_group, "input-mix"); + + /* Src 0x18=mic */ + /* Src 0x19=fp-mic */ + /* Src 0x1a=linein */ + /* Src 0x1b=fp-headphone */ + /* Src 0x1c=int-aux */ + /* Src 0x1d=speaker */ + /* Src 0x14=lineout */ + /* Src 0x15=lineout */ + /* Src 0x16=lineout */ + /* Src 0x17=lineout */ + HDA_INAMP (0x0b, 0, group, "pink", 30); /* From widget 0x18 */ + HDA_INAMP (0x0b, 2, group, "blue", 90); /* From widget 0x1a */ + HDA_INAMP (0x0b, 4, group, "int-aux", 90); /* From widget 0x1c */ + HDA_INAMP (0x0b, 5, group, "black", 90); /* From widget 0x1d */ + HDA_INAMP (0x0b, 6, group, "green", 90); /* From widget 0x14 */ + HDA_INAMP (0x0b, 7, group, "black", 90); /* From widget 0x15 */ + HDA_INAMP (0x0b, 8, group, "orange", 90); /* From widget 0x16 */ + HDA_INAMP (0x0b, 9, group, "grey", 90); /* From widget 0x17 */ + HDA_INAMP (0x0b, 3, group, "fp-green", 90); /* From widget 0x1b */ + HDA_INAMP (0x0b, 1, group, "fp-pink", 30); /* From widget 0x19 */ + } + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n = 0; + + HDA_GROUP (pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP (0x14, group, pin_group, "green", n, "jack", 4)) /* Pin widget 0x14 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x14, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x14, group, "inmute", UNMUTE); + HDA_INAMP (0x14, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x15, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x15 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x15, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x15, group, "inmute", UNMUTE); + HDA_INAMP (0x15, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x16, group, pin_group, "orange", n, "jack", 4)) /* Pin widget 0x16 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x16, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x16, group, "inmute", UNMUTE); + HDA_INAMP (0x16, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x17, group, pin_group, "grey", n, "jack", 4)) /* Pin widget 0x17 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x17, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x17, group, "inmute", UNMUTE); + HDA_INAMP (0x17, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x18, group, pin_group, "pink", n, "jack", 4)) /* Pin widget 0x18 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x18, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x18, group, "inmute", UNMUTE); + HDA_INAMP (0x18, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x1a, group, pin_group, "blue", n, "jack", 4)) /* Pin widget 0x1a */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x1a, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x1a, group, "inmute", UNMUTE); + HDA_INAMP (0x1a, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x1b, group, pin_group, "fp-green", n, "jack", 4)) /* Pin widget 0x1b */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x1b, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x1b, group, "inmute", UNMUTE); + HDA_INAMP (0x1b, 0, group, "in", 90); /* From widget 0x0c */ + } + + if (HDA_PIN_GROUP (0x19, group, pin_group, "fp-pink", n, "jack", 4)) /* Pin widget 0x19 */ + { + /* Src 0xc=front */ + /* Src 0xd=rear */ + /* Src 0xe=center/LFE */ + /* Src 0xf=side */ + /* Src 0x26=pcm4 */ + if (HDA_PINSELECT (0x19, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, + "front-out rear-out center/LFE-out side-out pcm4-out input"); + HDA_OUTMUTE (0x19, group, "inmute", UNMUTE); + HDA_INAMP (0x19, 0, group, "in", 90); /* From widget 0x0c */ + } + +#if 0 + /* + * Non-used pins + */ + if (HDA_PIN_GROUP (0x1c, group, pin_group, "int-aux", n, "jack", 4)) /* Pin widget 0x1c */ + { + if (HDA_PINSELECT (0x1c, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } + + if (HDA_PIN_GROUP (0x1d, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x1d */ + { + if (HDA_PINSELECT (0x1d, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } +#endif + } + + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_si3055.c b/kernel/drv/oss_hdaudio/hdaudio_si3055.c new file mode 100644 index 0000000..d47fbbd --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_si3055.c @@ -0,0 +1,206 @@ +/* + * Purpose: Driver for Si3055 and compatible modems. + */ +/* + * + * 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. + * + */ + + +/* + * Documentation Note + * + * There is no publicly available documentation for Si3055. However, + * there is a very similar modem (Si3038) for which a datasheet is + * publicly available: + * + * https://www.silabs.com/Support%20Documents/TechnicalDocs/si3038.pdf + * + * This driver was written by reading the ALSA code, looking for a + * similar modem (Si3038), and figuring out the corresponding Si3055 + * register IDs for Si3038 registers, again by reading the ALSA code, + * and by checking the default after-reset values. + * + */ + +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" +#include "hdaudio_mixers.h" + +/* + * Si3055 register IDs. + */ +#define SI3055_EXT_MODEM_STATUS 2 +#define SI3055_LINE_RATE 3 +#define SI3055_HDA_STREAMS 4 +#define SI3055_GPIO_CONFIG 5 +#define SI3055_GPIO_PIN_STATUS 10 +#define SI3055_LINE_CONFIG 13 + + +/* Corresponding registers in Si3038 (for reference): + * + * SI3055_EXT_MODEM_STATUS 3Eh (Extended Modem Status & Control) + * SI3055_LINE_RATE 40h (Line 1 DAC/ADC Rate) + * SI3055_GPIO_PIN_STATUS 54h (GPIO Pin Status) + * SI3055_LINE_CONFIG 56h (Line Side Configuration 1) + */ + +/* + * The SI3055_HDA_STREAMS register has no corresponding in Si3038. + * It contains the playback and recording stream descriptors in the + * following format: + * + * ((playback_stream_num << 4) << 8) | (recording_stream_num << 4) + */ + +/* Si3055 verbs. */ +#define SI3055_REG_GET_VERB 0x900 +#define SI3055_REG_SET_VERB 0x100 + +/* Convenience macros for reading from and writing to Si3055 registers. */ +#define SI3055_REG_GET(mixer, cad, reg, a, b) corb_read(mixer, cad, reg, 0, SI3055_REG_GET_VERB, 0, a, b) +#define SI3055_REG_SET(mixer, cad, reg, val) corb_write(mixer, cad, reg, 0, SI3055_REG_SET_VERB, val) + + +void hdaudio_si3055_set_rate(hdaudio_mixer_t *mixer, int cad, int rate) +{ + SI3055_REG_SET(mixer, cad, SI3055_LINE_RATE, rate); +} + +int hdaudio_si3055_set_offhook(hdaudio_mixer_t *mixer, int cad, int offhook) +{ + unsigned int a, b; + SI3055_REG_GET(mixer, cad, SI3055_GPIO_PIN_STATUS, &a, &b); + + if (offhook) + { + a |= 0x1; /* Set Off-Hook bit */ + } + else + { + a &= ~0x1; /* Unset Off-Hook bit */ + } + + SI3055_REG_SET(mixer, cad, SI3055_GPIO_PIN_STATUS, a); + SI3055_REG_GET(mixer, cad, SI3055_GPIO_PIN_STATUS, &a, &b); + return ((a & 0x1) == 0x1); +} + +void hdaudio_si3055_endpoint_init(hdaudio_mixer_t *mixer, int cad) +{ + codec_t *codec = mixer->codecs[cad]; /* Modem codec */ + widget_t *widget; /* MFG widget */ + hdaudio_endpointinfo_t *endpoint; + unsigned int a, b; /* Used for reading data. */ + int tmout; /* Timeout counter. */ + + /* Output and input stream numbers. */ + int playback_stream_num, recording_stream_num; + + + DDB(cmn_err(CE_CONT, "hdaudio_si3055_endpoint_init got called.\n")); + + /* Reset the modem codec. */ + corb_write(mixer, cad, 0x00, 0, SET_CODEC_RESET, 0); + corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER, IDDLE_STREAM << 4); + corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER_FORMAT, 0); + + /* Set 9600Hz as the initial line sampling rate. + * It can be changed later when desired. + */ + SI3055_REG_SET(mixer, cad, SI3055_LINE_RATE, 9600); + + /* Assign the "unused" value to the playback and recording + * stream descriptors (ref. HDAudio_03.pdf, page 40). + */ + SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, 0x0000); + + /* Write 0x0000 to the Extended Modem Status & Control register + * to power up the modem (ref. si3038.pdf, page 22). + */ + SI3055_REG_SET(mixer, cad, SI3055_EXT_MODEM_STATUS, 0x0000); + + /* Wait for the modem to complete power up. The lower 8 bits + * indicate that it is ready (ref. si3038.pdf, page 22). + */ + tmout = 10; + do + { + SI3055_REG_GET(mixer, cad, SI3055_EXT_MODEM_STATUS, &a, &b); + DDB(cmn_err(CE_CONT, "si3055: ext modem status: %04x.\n", a)); + oss_udelay(1000); + } + while(((a & 0xf) == 0) && --tmout); + + if ((a & 0xf) == 0) + { + cmn_err(CE_WARN, "si3055: power up timeout (status: %04x).\n", a); + } + + /* This register contains 0x1fff after reset. We need to set it + * to zero to get the modem working. No corresponding register + * could be found in the Si3038 datasheet. + */ + SI3055_REG_SET(mixer, cad, SI3055_GPIO_CONFIG, 0x0000); + + /* Program line interface parameters. The register value after + * a reset is 0xF010. Set it to 0x0010 to unmute the analog + * receive and transmit paths. + */ + SI3055_REG_SET(mixer, cad, SI3055_LINE_CONFIG, 0x0010); + + /* Setup the widget info. */ + widget = &codec->widgets[codec->afg]; + widget->endpoint = &codec->inendpoints[0]; + widget->sizes = 0x20000; /* 16 bits */ + strcpy(widget->name, "modem"); + + /* Setup the output endpoint. */ + codec->num_outendpoints = 1; + endpoint = &codec->outendpoints[0]; + endpoint->ix = 0; + endpoint->iddle_stream = 0; + endpoint->cad = cad; + endpoint->base_wid = codec->afg; + endpoint->recsrc_wid = endpoint->volume_wid = -1; + endpoint->nrates = 3; + endpoint->rates[0] = 8000; + endpoint->rates[1] = 9600; + endpoint->rates[2] = 16000; + endpoint->name = widget->name; + endpoint->channels = 1; + endpoint->is_digital = 0; + endpoint->is_modem = 1; + endpoint->sizemask = widget->sizes; + endpoint->fmt_mask = AFMT_S16_LE; + endpoint->afg = codec->afg; + endpoint->min_rate = 8000; + endpoint->max_rate = 16000; + + /* Setup the input endpoint. */ + codec->num_inendpoints = 1; + memcpy(&codec->inendpoints[0], endpoint, sizeof(*endpoint)); + + /* Choose stream numbers for output and input streams. */ + playback_stream_num = ++mixer->num_outendpoints; + endpoint->stream_number = endpoint->default_stream_number = playback_stream_num; + + endpoint = &codec->inendpoints[0]; + recording_stream_num = ++mixer->num_inendpoints; + endpoint->stream_number = endpoint->default_stream_number = recording_stream_num; + + /* Setup the stream numbers. */ + SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, ((playback_stream_num << 4) << 8) | + (recording_stream_num << 4)); +} + diff --git a/kernel/drv/oss_hdaudio/hdaudio_thinkpad_r61.c b/kernel/drv/oss_hdaudio/hdaudio_thinkpad_r61.c new file mode 100755 index 0000000..047c493 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_thinkpad_r61.c @@ -0,0 +1,301 @@ +/* + * + * 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. + * + */ +/* Codec index is 0 */ +/* Codec vendor 11d4:1984 */ +/* HD codec revision 1.0 (4.0) (0x00100400) */ +/* Subsystem ID 17aa20bb */ +/* Default amplifier caps: in=80000000, out=00052727 */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_thinkpad_r61_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group) +{ + int ctl=0; + + DDB(cmn_err(CE_CONT, "hdaudio_thinkpad_r61_mixer_init got called.\n")); + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n=0; + + HDA_GROUP(pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP(0x11, group, pin_group, "green", n, "jack", 4)) /* Pin widget 0x11 */ + { + /* Src 0x7=headphone-mix */ + if (HDA_PINSELECT(0x11, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "headphone-mix-out input"); + HDA_OUTMUTE(0x11, group, "inmute", UNMUTE); + } + + if (HDA_PIN_GROUP(0x12, group, pin_group, "int-speaker", n, "jack", 4)) /* Pin widget 0x12 */ + { + /* Src 0xa=lineout-mix */ + if (HDA_PINSELECT(0x12, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "lineout-mix-out input"); + HDA_OUTMUTE(0x12, group, "inmute", UNMUTE); + } + + if (HDA_PIN_GROUP(0x13, group, pin_group, "int-speaker", n, "jack", 4)) /* Pin widget 0x13 */ + { + /* Src 0x1f=mono-mix */ + if (HDA_PINSELECT(0x13, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "mono-mix-out input"); + HDA_OUTAMP(0x13, group, "invol", 90); + } + + if (HDA_PIN_GROUP(0x14, group, pin_group, "red", n, "jack", 4)) /* Pin widget 0x14 */ + { + if (HDA_PINSELECT(0x14, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + HDA_INAMP(0x14, 0, group, "out", 0); /* From widget 0x00 */ + } + + if (HDA_PIN_GROUP(0x15, group, pin_group, "int-mic", n, "jack", 4)) /* Pin widget 0x15 */ + { + if (HDA_PINSELECT(0x15, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + HDA_INAMP(0x15, 0, group, "out", 0); /* From widget 0x00 */ + } + + if (HDA_PIN_GROUP(0x16, group, pin_group, "int-cd", n, "jack", 4)) /* Pin widget 0x16 */ + { + /* Src 0xb=aux-mix */ + if (HDA_PINSELECT(0x16, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "aux-mix-out input"); + HDA_OUTMUTE(0x16, group, "inmute", UNMUTE); + } + + if (HDA_PIN_GROUP(0x17, group, pin_group, "int-mic", n, "jack", 4)) /* Pin widget 0x17 */ + { + if (HDA_PINSELECT(0x17, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + } + + if (HDA_PIN_GROUP(0x18, group, pin_group, "int-mic", n, "jack", 4)) /* Pin widget 0x18 */ + { + if (HDA_PINSELECT(0x18, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + } + + if (HDA_PIN_GROUP(0x1a, group, pin_group, "int-internal", n, "jack", 4)) /* Pin widget 0x1a */ + { + if (HDA_PINSELECT(0x1a, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "input"); + } + + if (HDA_PIN_GROUP(0x1b, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x1b */ + { + /* Src 0x2=spdif */ + if (HDA_PINSELECT(0x1b, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "spdif-out input"); + HDA_OUTAMP(0x1b, group, "invol", 90); + + /* Widget 0x02 (spdif) */ + /* Src 0x1= */ + /* Src 0x8=rec1-sel */ + /* Src 0x9=rec2-sel */ + } + + if (HDA_PIN_GROUP(0x1c, group, pin_group, "red", n, "jack", 4)) /* Pin widget 0x1c */ + { + /* Src 0x24=dock-mix */ + if (HDA_PINSELECT(0x1c, ctl, group, "mode", -1)) + HDA_CHOICES(ctl, "dock-mix-out input"); + HDA_OUTMUTE(0x1c, group, "inmute", UNMUTE); + } + } + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n=0; + + HDA_GROUP(rec_group, top_group, "record"); + + if (HDA_ADC_GROUP(0x05, group, rec_group, "int-mic", n, "record", 4)) /* ADC widget 0x05 */ + { + /* Src 0x17=int-mic */ + HDA_INAMP(0x05, 0, group, "int-mic", 90); /* From widget 0x17 */ + } + + if (HDA_ADC_GROUP(0x06, group, rec_group, "int-mic", n, "record", 4)) /* ADC widget 0x06 */ + { + /* Src 0x18=int-mic */ + HDA_INAMP(0x06, 0, group, "int-mic", 90); /* From widget 0x18 */ + } + + if (HDA_ADC_GROUP(0x08, group, rec_group, "rec1-sel", n, "record", 4)) /* ADC widget 0x08 */ + { + /* Src 0xc=rec1-sel */ + } + + if (HDA_ADC_GROUP(0x09, group, rec_group, "rec2-sel", n, "record", 4)) /* ADC widget 0x09 */ + { + /* Src 0xd=rec2-sel */ + } + } + /* Handle misc widgets */ + { + int n, group, misc_group; + + n=0; + + HDA_GROUP(misc_group, top_group, "misc"); + + if (HDA_MISC_GROUP(0x03, group, misc_group, "headphone", n, "misc", 8)) /* Misc widget 0x03 */ + { + HDA_OUTAMP(0x03, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x04, group, misc_group, "front", n, "misc", 8)) /* Misc widget 0x04 */ + { + HDA_OUTAMP(0x04, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x07, group, misc_group, "headphone-mix", n, "misc", 8)) /* Misc widget 0x07 */ + { + /* Src 0x22=headphone-sel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x07, 0, amp_group, "headphone-sel", UNMUTE); /* From widget 0x22 */ + HDA_INMUTE(0x07, 1, amp_group, "input-mix", UNMUTE); /* From widget 0x21 */ + } + + /* Widget 0x22 (headphone-sel) */ + /* Src 0x3=headphone */ + /* Src 0x4=front */ + if (HDA_SELECT(0x22, "src", ctl, group, 1 /* Select front */)) + { + HDA_CHOICES(ctl, "headphone front"); + } + + /* Widget 0x21 (input-mix) */ + /* Src 0x20=input-mix */ + HDA_OUTAMP(0x21, group, "-", 90); + + /* Widget 0x20 (input-mix) */ + /* Src 0x14=red */ + /* Src 0x96= */ + /* Src 0x1a=int-internal */ + /* Src 0x25=dock-mix */ + HDA_INAMP(0x20, 0, group, "red", 90); /* From widget 0x14 */ + HDA_INAMP(0x20, 1, group, "", 90); /* From widget 0x96 */ + HDA_INAMP(0x20, 2, group, "int-internal", 90); /* From widget 0x1a */ + HDA_INAMP(0x20, 3, group, "dock-mix", 90); /* From widget 0x25 */ + } + + if (HDA_MISC_GROUP(0x0a, group, misc_group, "lineout-mix", n, "misc", 8)) /* Misc widget 0x0a */ + { + /* Src 0x4=front */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0a, 0, amp_group, "front", UNMUTE); /* From widget 0x04 */ + HDA_INMUTE(0x0a, 1, amp_group, "input-mix", UNMUTE); /* From widget 0x21 */ + } + } + + if (HDA_MISC_GROUP(0x0b, group, misc_group, "aux-mix", n, "misc", 8)) /* Misc widget 0x0b */ + { + /* Src 0xf=aux-sel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x0b, 0, amp_group, "aux-sel", UNMUTE); /* From widget 0x0f */ + HDA_INMUTE(0x0b, 1, amp_group, "input-mix", UNMUTE); /* From widget 0x21 */ + } + + /* Widget 0x0f (aux-sel) */ + /* Src 0x3=headphone */ + /* Src 0x4=front */ + if (HDA_SELECT(0x0f, "src", ctl, group, -1)) + { + HDA_CHOICES(ctl, "headphone front"); + } + } + + if (HDA_MISC_GROUP(0x0c, group, misc_group, "rec1-sel", n, "misc", 8)) /* Misc widget 0x0c */ + { + /* Src 0x14=mic */ + /* Src 0x96= */ + /* Src 0x20=input-mix */ + /* Src 0x25=dock-mix */ + if (HDA_SELECT(0x0c, "src", ctl, group, -1)) + { + HDA_CHOICES(ctl, "mic unknown input-mix dock-mix"); + } + HDA_OUTAMP(0x0c, group, "-", 90); + + /* Widget 0x25 (dock-mix) */ + /* Src 0x1c=red */ + HDA_OUTAMP(0x25, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x0d, group, misc_group, "rec2-sel", n, "misc", 8)) /* Misc widget 0x0d */ + { + /* Src 0x14=mic */ + /* Src 0x96= */ + /* Src 0x20=input-mix */ + /* Src 0x25=dock-mix */ + if (HDA_SELECT(0x0d, "src", ctl, group, -1)) + { + HDA_CHOICES(ctl, "mic unknown input-mix dock-mix"); + } + HDA_OUTAMP(0x0d, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x10, group, misc_group, "beep", n, "misc", 8)) /* Misc widget 0x10 */ + { + HDA_OUTAMP(0x10, group, "-", 90); + } + + if (HDA_MISC_GROUP(0x1e, group, misc_group, "mono-mix", n, "misc", 8)) /* Misc widget 0x1e */ + { + /* Src 0xe=mono-sel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x1e, 0, amp_group, "mono-sel", UNMUTE); /* From widget 0x0e */ + HDA_INMUTE(0x1e, 1, amp_group, "input-mix", UNMUTE); /* From widget 0x21 */ + } + } + + if (HDA_MISC_GROUP(0x24, group, misc_group, "dock-mix", n, "misc", 8)) /* Misc widget 0x24 */ + { + /* Src 0x23=dock-sel */ + /* Src 0x21=input-mix */ + { + int amp_group; + + HDA_GROUP(amp_group, group, "mute"); + HDA_INMUTE(0x24, 0, amp_group, "dock-sel", UNMUTE); /* From widget 0x23 */ + HDA_INMUTE(0x24, 1, amp_group, "input-mix", UNMUTE); /* From widget 0x21 */ + } + } + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/hdaudio_vaio_vgn.c b/kernel/drv/oss_hdaudio/hdaudio_vaio_vgn.c new file mode 100644 index 0000000..2472672 --- /dev/null +++ b/kernel/drv/oss_hdaudio/hdaudio_vaio_vgn.c @@ -0,0 +1,144 @@ +/* + * + * 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. + * + */ +/* Codec index is 0 */ +/* Codec vendor 0804:73dc */ +/* HD codec revision 1.0 (2.1) (0x00100201) */ +/* Subsystem ID 104d2200 */ +/* Default amplifier caps: in=80050f00, out=80027f7f */ +#include "oss_hdaudio_cfg.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "hdaudio_dedicated.h" + +int +hdaudio_vaio_vgn_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, + int top_group) +{ + int ctl = 0; + + DDB (cmn_err (CE_CONT, "hdaudio_vaio_vgn_mixer_init got called.\n")); + + HDA_OUTAMP_F (0x05, top_group, "speaker", 90, MIXF_MAINVOL); + /* We sync the volume of the headphone DAC to the speaker DAC */ +#if 1 + HDA_OUTAMP_F (0x02, top_group, "headphone", 90, MIXF_MAINVOL); +#endif + + + HDA_SETSELECT (0x0f, 0); /* Int speaker mode */ + HDA_SETSELECT (0x14, 1); /* Int mic mode */ + + /* Handle PIN widgets */ + { + int n, group, pin_group; + + n = 0; + + HDA_GROUP (pin_group, top_group, "jack"); + + if (HDA_PIN_GROUP (0x0a, group, pin_group, "headphone", n, "jack", 4)) /* Pin widget 0x0a */ + { + /* Src 0x2=pcm */ + if (HDA_PINSELECT (0x0a, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "pcm-out input"); + HDA_OUTMUTE (0x0a, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x0b, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x0b */ + { + /* Src 0x4=pcm */ + if (HDA_PINSELECT (0x0b, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "pcm-out input"); + HDA_OUTMUTE (0x0b, group, "mute", UNMUTE); + + /* Widget 0x04 (pcm) */ + HDA_OUTAMP (0x04, group, "-", 90); + } + + if (HDA_PIN_GROUP (0x0c, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x0c */ + { + /* Src 0x3=pcm */ + if (HDA_PINSELECT (0x0c, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "pcm-out input"); + HDA_OUTMUTE (0x0c, group, "mute", UNMUTE); + + /* Widget 0x03 (pcm) */ + HDA_OUTAMP (0x03, group, "-", 90); + } + + if (HDA_PIN_GROUP (0x0d, group, pin_group, "red", n, "jack", 4)) /* Pin widget 0x0d */ + { + /* Src 0x2=pcm */ + if (HDA_PINSELECT (0x0d, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "pcm-out input"); + HDA_OUTMUTE (0x0d, group, "mute", UNMUTE); + } + + if (HDA_PIN_GROUP (0x0e, group, pin_group, "black", n, "jack", 4)) /* Pin widget 0x0e */ + { + if (HDA_PINSELECT (0x0e, ctl, group, "mode", -1)) + HDA_CHOICES (ctl, "input"); + } + } + /* Handle ADC widgets */ + { + int n, group, rec_group; + + n = 0; + + HDA_GROUP (rec_group, top_group, "record"); + + if (HDA_ADC_GROUP (0x06, group, rec_group, "rec1", n, "record", 4)) /* ADC widget 0x06 */ + { + /* Src 0x7=rec */ + + /* Widget 0x07 (rec) */ + /* Src 0xe=black */ + HDA_INAMP_F (0x07, 0, group, "black", 80, MIXF_RECVOL); /* From widget 0x0e */ + } + + if (HDA_ADC_GROUP (0x08, group, rec_group, "rec", n, "record", 8)) /* ADC widget 0x08 */ + { + /* Src 0x9=rec */ + + /* Widget 0x09 (rec) */ + /* Src 0x15=rec */ + HDA_INAMP_F (0x09, 0, group, "rec", 80, MIXF_RECVOL); /* From widget 0x15 */ + + /* Widget 0x15 (rec) */ + /* Src 0xa=black */ + /* Src 0xd=red */ + /* Src 0x14=int-mic */ + /* Src 0x2=pcm */ + if (HDA_SELECT (0x15, "src", ctl, group, -1)) + { + HDA_CHOICES (ctl, "headphone mic int-mic pcm"); + } + HDA_OUTAMP (0x15, group, "micboost", 0); + } + + if (HDA_ADC_GROUP (0x12, group, rec_group, "spdifin", n, "record", 4)) /* ADC widget 0x12 */ + { + /* Src 0x13=speaker */ + } + } + /* Handle misc widgets */ + { +#if 0 + if (HDA_MISC_GROUP (0x16, group, misc_group, "beep", n, "misc", 8)) /* Misc widget 0x16 */ + { + HDA_OUTAMP (0x16, group, "-", 90); + } +#endif + } + return 0; +} diff --git a/kernel/drv/oss_hdaudio/oss_hdaudio.c b/kernel/drv/oss_hdaudio/oss_hdaudio.c new file mode 100644 index 0000000..6492bec --- /dev/null +++ b/kernel/drv/oss_hdaudio/oss_hdaudio.c @@ -0,0 +1,1996 @@ +/* + * Purpose: The High Definition Audio (HDA/Azalia) 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. + * + */ + +#include "oss_hdaudio_cfg.h" +#include "oss_pci.h" +#include "hdaudio.h" +#include "hdaudio_codec.h" +#include "spdif.h" + +#define CORB_DELAY 10 +#define CORB_LOOPS 1000 + +#define INTEL_VENDOR_ID 0x8086 +#define INTEL_DEVICE_ICH6 0x2668 +#define INTEL_DEVICE_ICH7 0x27d8 +#define INTEL_DEVICE_ESB2 0x269a +#define INTEL_DEVICE_ICH8 0x284b +#define INTEL_DEVICE_ICH9 0x293f +#define INTEL_DEVICE_ICH10 0x3a3e +#define INTEL_DEVICE_ICH10_B 0x3a6e +#define INTEL_DEVICE_CPT 0x1c20 +#define INTEL_DEVICE_PCH 0x3b56 +#define INTEL_DEVICE_PCH2 0x3b57 +#define INTEL_DEVICE_SCH 0x811b +#define INTEL_DEVICE_P35 0x293e + +#define NVIDIA_VENDOR_ID 0x10de +#define NVIDIA_DEVICE_MCP51 0x026c +#define NVIDIA_DEVICE_MCP55 0x0371 +#define NVIDIA_DEVICE_MCP61 0x03e4 +#define NVIDIA_DEVICE_MCP61A 0x03f0 +#define NVIDIA_DEVICE_MCP65 0x044a +#define NVIDIA_DEVICE_MCP67 0x055c +#define NVIDIA_DEVICE_MCP73 0x07fc +#define NVIDIA_DEVICE_MCP78S 0x0774 +#define NVIDIA_DEVICE_MCP79 0x0ac0 + +#define ATI_VENDOR_ID 0x1002 +#define ATI_DEVICE_SB450 0x437b +#define ATI_DEVICE_SB600 0x4383 + +#define VIA_VENDOR_ID 0x1106 +#define VIA_DEVICE_HDA 0x3288 + +#define SIS_VENDOR_ID 0x1039 +#define SIS_DEVICE_HDA 0x7502 + +#define ULI_VENDOR_ID 0x10b9 +#define ULI_DEVICE_HDA 0x5461 + +#define CREATIVE_ID 0x1102 +#define CREATIVE_XFI_HDA 0x0009 + +#define BDL_SIZE 32 +#define HDA_MAX_ENGINES 8 +#define MAX_OUTPUTS 8 +#define MAX_INPUTS 4 + +typedef struct +{ + oss_uint64_t addr; + unsigned int len; + unsigned int ioc; +} bdl_t; + +typedef struct hda_portc_t hda_portc_t; + +typedef struct +{ + int num; + int busy; + bdl_t *bdl; + oss_uint64_t bdl_phys; + oss_dma_handle_t bdl_dma_handle; + int bdl_size, bdl_max; + unsigned char *base; + unsigned int intrmask; + hda_portc_t *portc; +} hda_engine_t; + +struct hda_portc_t +{ + int num; + int open_mode; + int speed, bits, channels; + int audio_enabled; + int trigger_bits; + int audiodev; + int port_type; +#define PT_OUTPUT 0 +#define PT_INPUT 1 + hdaudio_endpointinfo_t *endpoint; + hda_engine_t *engine; +}; + +typedef struct +{ + unsigned int response, resp_ex; +} rirb_entry_t; + +typedef struct hda_devc_t +{ + oss_device_t *osdev; + oss_native_word base; + unsigned int membar_addr; + unsigned char *azbar; + + char *chip_name; + unsigned int vendor_id, subvendor_id; + + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* CORB and RIRB */ + int corbsize, rirbsize; + unsigned int *corb; + rirb_entry_t *rirb; + oss_uint64_t corb_phys, rirb_phys; + int rirb_rp; + unsigned int rirb_upper, rirb_lower; + volatile int rirb_empty; + + oss_dma_handle_t corb_dma_handle; + + /* Mixer */ + unsigned short codecmask; + hdaudio_mixer_t *mixer; + int mixer_dev; + spdif_devc spdc; + + /* Audio */ + int first_dev; + hda_engine_t inengines[HDA_MAX_ENGINES]; + hda_engine_t outengines[HDA_MAX_ENGINES]; + int num_outengines, num_inengines; + hdaudio_endpointinfo_t *spdifout_endpoint; + + hda_portc_t output_portc[MAX_OUTPUTS]; + hda_portc_t input_portc[MAX_INPUTS]; + int num_outputs, num_inputs; + + int num_spdin, num_spdout; + int num_mdmin, num_mdmout; +} +hda_devc_t; + +static int +rirb_intr (hda_devc_t * devc) +{ + int serviced = 0; + unsigned char rirbsts; + oss_native_word flags; + + rirbsts = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBSTS); + if (rirbsts != 0) + { + serviced = 1; + + if (rirbsts & 0x01) + { + /* RIRB response interrupt */ + int wp, rp; + unsigned int upper = 0, lower = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + wp = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBWP) & 0x00ff; + while (devc->rirb_rp != wp) + { + devc->rirb_rp++; + devc->rirb_rp %= devc->rirbsize; + rp = devc->rirb_rp; + upper = devc->rirb[rp].response; + lower = devc->rirb[rp].resp_ex; + + if (lower & 0x10) /* Unsolicited response */ + { + hda_codec_unsol (devc->mixer, upper, lower); + } + else if (devc->rirb_empty) + { + devc->rirb_upper = upper; + devc->rirb_lower = lower; + devc->rirb_empty--; + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + } + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBSTS, rirbsts); + } + + return serviced; +} + +static int +hdaintr (oss_device_t * osdev) +{ + hda_devc_t *devc = (hda_devc_t *) osdev->devc; + unsigned int status; + int serviced = 0; + int i; + + if (devc == NULL) /* Too bad */ + return 1; + + status = PCI_READL (devc->osdev, devc->azbar + HDA_INTSTS); + if (status != 0) + { + serviced = 1; + + for (i = 0; i < devc->num_outengines; i++) + { + hda_engine_t *engine = &devc->outengines[i]; + + hda_portc_t *portc; + if (status & engine->intrmask) + { + PCI_WRITEB (devc->osdev, engine->base + 0x03, 0x1e); + + portc = engine->portc; + + if (portc != NULL && (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + oss_audio_outputintr (portc->audiodev, 1); + } + } + + for (i = 0; i < devc->num_inengines; i++) + { + hda_engine_t *engine = &devc->inengines[i]; + + hda_portc_t *portc; + if (status & engine->intrmask) + { + PCI_WRITEB (devc->osdev, engine->base + 0x03, 0x1e); + + portc = engine->portc; + + if (portc != NULL && (portc->trigger_bits & PCM_ENABLE_INPUT)) + oss_audio_inputintr (portc->audiodev, 0); + } + } + PCI_WRITEL (devc->osdev, devc->azbar + HDA_INTSTS, status); /* ACK */ + + if (status & (1 << 30)) /* Controller interrupt (RIRB) */ + { + if (rirb_intr (devc)) + serviced = 1; + } + } + return serviced; +} + +static int +do_corb_write (void *dc, unsigned int cad, unsigned int nid, unsigned int d, + unsigned int verb, unsigned int parm) +{ + unsigned int wp; + unsigned int tmp; + oss_native_word flags; + hda_devc_t *devc = (hda_devc_t *) dc; + + tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | (parm & 0xffff); + wp = PCI_READB (devc->osdev, devc->azbar + HDA_CORBWP) & 0x00ff; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + wp = (wp + 1) % devc->corbsize; + + devc->corb[wp] = tmp; + devc->rirb_empty++; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + PCI_WRITEL (devc->osdev, devc->azbar + HDA_CORBWP, wp); + + return 1; +} + +static int +do_corb_write_nomutex (void *dc, unsigned int cad, unsigned int nid, unsigned int d, + unsigned int verb, unsigned int parm) +{ + unsigned int wp; + unsigned int tmp; + hda_devc_t *devc = (hda_devc_t *) dc; + + tmp = (cad << 28) | (d << 27) | (nid << 20) | (verb << 8) | (parm & 0xffff); + wp = PCI_READB (devc->osdev, devc->azbar + HDA_CORBWP) & 0x00ff; + + wp = (wp + 1) % devc->corbsize; + + devc->corb[wp] = tmp; + devc->rirb_empty++; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_CORBWP, wp); + + return 1; +} + +static int +do_corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d, + unsigned int verb, unsigned int parm, unsigned int *upper, + unsigned int *lower) +{ + int tmout; + hda_devc_t *devc = (hda_devc_t *) dc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + do_corb_write_nomutex (devc, cad, nid, d, verb, parm); + + tmout = CORB_LOOPS; + while (devc->rirb_empty) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (--tmout < 0) + { + devc->rirb_rp = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBWP); + devc->rirb_empty = 0; + return 0; + } + oss_udelay (CORB_DELAY); + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + } + + *upper = devc->rirb_upper; + *lower = devc->rirb_lower; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 1; +} + +static int +do_corb_read_poll (void *dc, unsigned int cad, unsigned int nid, + unsigned int d, unsigned int verb, unsigned int parm, + unsigned int *upper, unsigned int *lower) +{ + int tmout = 0; + hda_devc_t *devc = (hda_devc_t *) dc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + do_corb_write_nomutex (devc, cad, nid, d, verb, parm); + + tmout = CORB_LOOPS; + while (devc->rirb_empty) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + rirb_intr (devc); + + if (--tmout < 0) + { + devc->rirb_rp = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBWP); + devc->rirb_empty = 0; + return 0; + } + oss_udelay (CORB_DELAY); + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + } + + *upper = devc->rirb_upper; + *lower = devc->rirb_lower; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 1; +} + +#undef corb_read + +static int +corb_read (void *dc, unsigned int cad, unsigned int nid, unsigned int d, + unsigned int verb, unsigned int parm, unsigned int *upper, + unsigned int *lower) +{ + hda_devc_t *devc = (hda_devc_t *) dc; + +/* + * Do three retries using different access methods + */ + if (do_corb_read (dc, cad, nid, d, verb, parm, upper, lower)) + return 1; + + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x02); /* Intr disable */ + + if (do_corb_read_poll (dc, cad, nid, d, verb, parm, upper, lower)) + { + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x03); /* Intr re-enable */ + return 1; + } + + if (do_corb_read_poll (dc, cad, nid, d, verb, parm, upper, lower)) + { + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x03); /* Intr re-enable */ + return 1; + } + +#if 0 + // TODO: Implement this + if (do_corb_read_single (dc, cad, nid, d, verb, parm, upper, lower)) + { + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x03); /* Intr re-enable */ + return 1; + } +#endif + + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x03); /* Intr re-enable */ + + cmn_err (CE_WARN, + "RIRB timeout (cad=%d, nid=%d, d=%d, verb=%03x, parm=%x)\n", + cad, nid, d, verb, parm); + + return 0; +} + +/* + * Audio routines + */ + +static int +hda_audio_set_rate (int dev, int arg) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + adev_p adev = audio_engines[dev]; + + int best = -1, bestdiff = 10000000; + int i; + + if (arg == 0) + return portc->speed; + + for (i = 0; i < adev->nrates; i++) + { + int diff = arg - adev->rates[i]; + if (diff < 0) + diff = -diff; + + if (diff < bestdiff) + { + best = i; + bestdiff = diff; + } + } + + if (best == -1) + { + cmn_err (CE_WARN, "No suitable rate found!\n"); + return portc->speed = 48000; /* Some default */ + } + portc->speed = adev->rates[best]; + return portc->speed; +} + +static short +hda_audio_set_channels (int dev, short arg) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + hda_devc_t *devc = audio_engines[dev]->devc; + adev_p adev = audio_engines[dev]; + int i, n1, n2; + + if (arg == 0) + { + return portc->channels; + } + + if (arg < 1) + arg = 1; + + if (arg > adev->max_channels) + { + arg = adev->max_channels; + } + + if (arg != 1 && arg != 2 && arg != 4 && arg != 6 && arg != 8) + { + cmn_err (CE_NOTE, "Ignored request for odd number (%d) of channels\n", arg); + return portc->channels = arg & ~1; + } + + if (arg < adev->min_channels) + arg = adev->min_channels; + + /* + * Check if more output endpoints need to be allocated + */ + n2 = (arg + 1) / 2; + n1 = (portc->channels + 1) / 2; + if (n1 < 1) + n1 = 1; + + if (n2 > n1) /* Needs more stereo pairs */ + { + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + for (i = n1; i < n2; i++) + { + if (portc->endpoint[i].busy) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->channels; + } + } + + for (i = n1; i < n2; i++) + { + portc->endpoint[i].busy = 1; + portc->endpoint->borrow_count++; + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + } + else if (n2 < n1) /* Some stereo pairs can be released */ + { + for (i = n2; i < n1; i++) + { + portc->endpoint[i].busy = 0; + portc->endpoint->borrow_count--; + } + } + + return portc->channels = arg; +} + +static unsigned int +hda_audio_set_format (int dev, unsigned int arg) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & audio_engines[dev]->oformat_mask)) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +static int +do_corb_write_simple (void *dc, unsigned int v) +{ + unsigned int wp; + hda_devc_t *devc = (hda_devc_t *) dc; + + wp = PCI_READB (devc->osdev, devc->azbar + HDA_CORBWP) & 0x00ff; + + wp = (wp + 1) % devc->corbsize; + + devc->corb[wp] = v; + devc->rirb_empty++; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_CORBWP, wp); + + return 1; +} + +static int +do_corb_read_simple (void *dc, unsigned int cmd, unsigned int *v) +{ + int tmout = 0; + hda_devc_t *devc = (hda_devc_t *) dc; + + do_corb_write_simple (dc, cmd); + + tmout = CORB_LOOPS; + while (devc->rirb_empty) + { + if (--tmout < 0) + { + cmn_err (CE_WARN, "RIRB timeout (cmd=%08x)\n", cmd); + devc->rirb_rp = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBWP); + devc->rirb_empty = 0; + return 0; + } + oss_udelay (CORB_DELAY); + } + + *v = devc->rirb_upper; + + return 1; +} + +static int +hda_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + hda_devc_t *devc = audio_engines[dev]->devc; + hda_portc_t *portc = audio_engines[dev]->portc; + + //if (hdaudio_snoopy) + switch (cmd) + { + case HDA_IOCTL_WRITE: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + do_corb_write_simple (devc, *(unsigned int *) arg); + return 0; + break; + + case HDA_IOCTL_READ: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + if (!do_corb_read_simple + (devc, *(unsigned int *) arg, (unsigned int *) arg)) + return OSS_EIO; + + return 0; + break; + + case HDA_IOCTL_NAME: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + return hda_codec_getname (devc->mixer, (hda_name_t *) arg); + break; + + case HDA_IOCTL_WIDGET: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + return hda_codec_getwidget (devc->mixer, (hda_widget_info_t *) arg); + break; + + } + return hdaudio_codec_audio_ioctl (devc->mixer, portc->endpoint, cmd, arg); +} + +static void hda_audio_trigger (int dev, int state); + +static void +hda_audio_reset (int dev) +{ + hda_audio_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +hda_audio_open (int dev, int mode, int openflags) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + hda_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + hda_engine_t *engines, *engine = NULL; + int i, n; + unsigned int tmp; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode || portc->endpoint->busy) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + if (portc->port_type == PT_INPUT) + { + engines = devc->inengines; + n = devc->num_inengines; + } + else + { + engines = devc->outengines; + n = devc->num_outengines; + } + + for (i = 0; i < n && engine == NULL; i++) + { + if (!engines[i].busy) + engine = &engines[i]; + } + + if (engine == NULL) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + cmn_err (CE_WARN, "No free DMA engines.\nn"); + return OSS_EBUSY; + } + + portc->open_mode = mode; + portc->audio_enabled &= ~mode; + portc->endpoint->busy = 1; + portc->endpoint->borrow_count = 1; + + portc->engine = engine; + engine->portc = portc; + portc->engine->busy = 1; + + portc->endpoint->stream_number = portc->endpoint->default_stream_number; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + +/* + * Reset the DMA engine and wait for the reset to complete + */ + tmp = PCI_READL (devc->osdev, engine->base); + PCI_WRITEL (devc->osdev, engine->base, tmp | 0x01); /* Stream reset */ + + for (i = 0; i < 1000; i++) + { + if (PCI_READL (devc->osdev, engine->base) & 0x01) + break; + oss_udelay (1000); + } + + /* Unreset and wait */ + + tmp = PCI_READL (devc->osdev, engine->base); + PCI_WRITEL (devc->osdev, engine->base, tmp & ~0x01); /* Release reset */ + + for (i = 0; i < 1000; i++) + { + if (!(PCI_READL (devc->osdev, engine->base) & 0x01)) + break; + oss_udelay (1000); + } + + return 0; +} + +static void +hda_audio_close (int dev, int mode) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + hda_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + int i; + + if (!portc->open_mode) + { + cmn_err (CE_WARN, "Bad close %d\n", dev); + return; + } + + hda_audio_reset (dev); + hdaudio_codec_reset_endpoint (devc->mixer, portc->endpoint, + portc->channels); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->audio_enabled &= ~mode; + portc->engine->busy = 0; + portc->engine->portc = NULL; + portc->engine = NULL; + portc->endpoint->busy = 0; + portc->endpoint->stream_number = portc->endpoint->default_stream_number; + + for (i = 1; i < portc->endpoint->borrow_count; i++) + { + portc->endpoint[i].busy = 0; + } + + portc->endpoint->borrow_count = 1; + portc->open_mode = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +hda_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +hda_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + hda_portc_t *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +hda_audio_trigger (int dev, int state) +{ + hda_devc_t *devc = audio_engines[dev]->devc; + hda_portc_t *portc = audio_engines[dev]->portc; + hda_engine_t *engine = portc->engine; + oss_native_word flags; + unsigned char tmp, intr; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + tmp = PCI_READB (devc->osdev, engine->base + 0x00); + intr = PCI_READB (devc->osdev, devc->azbar + HDA_INTCTL); + if (portc->open_mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + !(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + tmp |= 0x1e; /* DMA and Stream Interrupt enable */ + intr |= engine->intrmask; + PCI_WRITEB (devc->osdev, engine->base + 0x00, tmp); + PCI_WRITEB (devc->osdev, devc->azbar + HDA_INTCTL, intr); + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + tmp &= ~0x1e; /* Run-off & intr disable */ + intr &= ~engine->intrmask; + /* Stop DMA and Stream Int */ + PCI_WRITEB (devc->osdev, engine->base + 0x00, tmp); + /* Ack pending ints */ + PCI_WRITEB (devc->osdev, engine->base + 0x03, 0x1c); + /* Disable Interrupts */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_INTCTL, intr); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->trigger_bits |= PCM_ENABLE_INPUT; + tmp |= 0x1e; /* dma & intr enable */ + intr |= engine->intrmask; + PCI_WRITEB (devc->osdev, engine->base + 0x00, tmp); + PCI_WRITEB (devc->osdev, devc->azbar + HDA_INTCTL, intr); + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + tmp &= ~0x1e; /* Run-off & intr disable */ + intr &= ~engine->intrmask; + /* Stop DMA and Stream Int */ + PCI_WRITEB (devc->osdev, engine->base + 0x00, tmp); + /* Ack pending ints */ + PCI_WRITEB (devc->osdev, engine->base + 0x03, 0x1c); + /* Disable Interrupts */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_INTCTL, intr); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +init_bdl (hda_devc_t * devc, hda_engine_t * engine, dmap_p dmap) +{ + int i; + bdl_t *bdl = engine->bdl; + + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_BDLPL, 0); + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_BDLPU, 0); + for (i = 0; i < dmap->nfrags; i++) + { + bdl[i].addr = dmap->dmabuf_phys + (i * dmap->fragment_size); + bdl[i].len = dmap->fragment_size; + bdl[i].ioc = 0x01; + } +} + +static int +setup_audio_engine (hda_devc_t * devc, hda_engine_t * engine, hda_portc_t * portc, + dmap_t * dmap) +{ + unsigned int tmp, tmout; + +/* make sure the run bit is zero for SD */ + PCI_WRITEB (devc->osdev, engine->base + HDA_SD_CTL, + PCI_READB (devc->osdev, engine->base + HDA_SD_CTL) & ~0x2); +/* + * First reset the engine. + */ + + tmp = PCI_READB (devc->osdev, engine->base + HDA_SD_CTL); + PCI_WRITEB (devc->osdev, engine->base + HDA_SD_CTL, tmp | 0x01); /* Reset */ + oss_udelay (1000); + + tmout = 300; + while (!(PCI_READB (devc->osdev, engine->base + HDA_SD_CTL) & 0x01) + && --tmout) + oss_udelay (1000); + + PCI_WRITEB (devc->osdev, engine->base + HDA_SD_CTL, tmp & ~0x01); /* Release reset */ + oss_udelay (1000); + tmout = 300; + while ((PCI_READB (devc->osdev, engine->base + HDA_SD_CTL) & 0x01) + && --tmout) + oss_udelay (1000); + +/* + * Set the engine tag number field + */ + tmp = PCI_READL (devc->osdev, engine->base + HDA_SD_CTL); + tmp &= ~(0xf << 20); + tmp |= portc->endpoint->stream_number << 20; + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_CTL, tmp); + +/* program buffer size and fragments in the engine */ + + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_CBL, dmap->bytes_in_use); + PCI_WRITEW (devc->osdev, engine->base + HDA_SD_LVI, dmap->nfrags - 1); + +/* setup the BDL base address */ + tmp = engine->bdl_phys; + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_BDLPL, tmp & 0xffffffff); + tmp = engine->bdl_phys >> 32; + PCI_WRITEL (devc->osdev, engine->base + HDA_SD_BDLPU, tmp & 0xffffffff); + PCI_WRITEB (devc->osdev, engine->base + HDA_SD_STS, 0x1c); /* mask out ints */ + +/* + * Next the sample rate and format setup + */ + if (hdaudio_codec_setup_endpoint + (devc->mixer, portc->endpoint, portc->speed, portc->channels, + portc->bits, portc->endpoint->stream_number, &tmp) < 0) + { + cmn_err (CE_WARN, "Codec setup failed\n"); + return OSS_EIO; + } + + PCI_WRITEW (devc->osdev, engine->base + HDA_SD_FORMAT, tmp); + tmp = PCI_READW (devc->osdev, engine->base + HDA_SD_FORMAT); + + return 0; +} + +/*ARGSUSED*/ +static int +hda_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + hda_devc_t *devc = audio_engines[dev]->devc; + hda_portc_t *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + hda_engine_t *engine; + + if (portc->port_type != PT_INPUT) + return OSS_ENOTSUP; + + engine = portc->engine; + + if (dmap->nfrags > engine->bdl_max) /* Overflow protection */ + { + dmap->nfrags = engine->bdl_max; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + } + + init_bdl (devc, engine, dmap); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return setup_audio_engine (devc, engine, portc, dmap); +} + +/*ARGSUSED*/ +static int +hda_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + hda_devc_t *devc = audio_engines[dev]->devc; + hda_portc_t *portc = audio_engines[dev]->portc; + hda_engine_t *engine; + + dmap_t *dmap = audio_engines[dev]->dmap_out; + oss_native_word flags; + + if (portc->port_type != PT_OUTPUT) + return OSS_ENOTSUP; + + engine = portc->engine; + + if (dmap->nfrags > engine->bdl_max) /* Overflow protection */ + { + dmap->nfrags = engine->bdl_max; + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; + } + + init_bdl (devc, engine, dmap); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return setup_audio_engine (devc, engine, portc, dmap); +} + +/*ARGSUSED*/ +static int +hda_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + hda_portc_t *portc = audio_engines[dev]->portc; +#ifdef sun + // PCI_READL under solaris needs devc->osdev + hda_devc_t *devc = audio_engines[dev]->devc; +#endif + hda_engine_t *engine; + unsigned int ptr; + + engine = portc->engine; + ptr = + PCI_READL (devc->osdev, engine->base + HDA_SD_LPIB) % dmap->bytes_in_use; + + return ptr; +} + +static const audiodrv_t hda_audio_driver = { + hda_audio_open, + hda_audio_close, + hda_audio_output_block, + hda_audio_start_input, + hda_audio_ioctl, + hda_audio_prepare_for_input, + hda_audio_prepare_for_output, + hda_audio_reset, + NULL, + NULL, + NULL, + NULL, + hda_audio_trigger, + hda_audio_set_rate, + hda_audio_set_format, + hda_audio_set_channels, + NULL, + NULL, + NULL, /* hda_check_input, */ + NULL, /* hda_check_output, */ + NULL, /* hda_alloc_buffer */ + NULL, /* hda_free_buffer */ + NULL, + NULL, + hda_get_buffer_pointer +}; + +static int +reset_controller (hda_devc_t * devc) +{ + unsigned int tmp, tmout; + + /*reset the controller by writing a 0*/ + tmp = PCI_READL (devc->osdev, devc->azbar + HDA_GCTL); + tmp &= ~CRST; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_GCTL, tmp); + + /*wait until the controller writes a 0 to indicate reset is done or until 50ms have passed*/ + tmout = 50; + while ((PCI_READL (devc->osdev, devc->azbar + HDA_GCTL) & CRST) && --tmout) + oss_udelay (1000); + + oss_udelay (1000); + + /*bring the controller out of reset by writing a 1*/ + tmp = PCI_READL (devc->osdev, devc->azbar + HDA_GCTL); + tmp |= CRST; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_GCTL, tmp); + + /*wait until the controller writes a 1 to indicate it is ready is or until 50ms have passed*/ + tmout = 50; + while (!(PCI_READL (devc->osdev, devc->azbar + HDA_GCTL) & CRST) && --tmout) + oss_udelay (1000); + + oss_udelay (1000); + + /*if the controller is not ready now, abort*/ + if (!(PCI_READL (devc->osdev, devc->azbar + HDA_GCTL))) + { + cmn_err (CE_WARN, "Controller not ready\n"); + return 0; + } + + if (!devc->codecmask) + { + devc->codecmask = PCI_READW (devc->osdev, devc->azbar + HDA_STATESTS); + DDB (cmn_err (CE_CONT, "Codec mask %x\n", devc->codecmask)); + } + + return 1; +} + +static int +setup_controller (hda_devc_t * devc) +{ + unsigned int tmp, tmout; + oss_native_word phaddr; + +/* + * Allocate the CORB and RIRB buffers. + */ + tmp = PCI_READB (devc->osdev, devc->azbar + HDA_CORBSIZE) & 0x03; + + switch (tmp) + { + case 0: + devc->corbsize = 2; + break; + case 1: + devc->corbsize = 16; + break; + case 2: + devc->corbsize = 256; + break; + default: + cmn_err (CE_WARN, "Bad CORB size\n"); + return 0; + } + + tmp = PCI_READB (devc->osdev, devc->azbar + HDA_RIRBSIZE) & 0x03; + + switch (tmp) + { + case 0: + devc->rirbsize = 2; + break; + case 1: + devc->rirbsize = 16; + break; + case 2: + devc->rirbsize = 256; + break; + default: + cmn_err (CE_WARN, "Bad CORB size\n"); + return 0; + } + + if ((devc->corb = + CONTIG_MALLOC (devc->osdev, 4096, MEMLIMIT_32BITS, &phaddr, devc->corb_dma_handle)) == NULL) + { + cmn_err (CE_WARN, "Out of memory (CORB)\n"); + return 0; + } + + devc->corb_phys = phaddr; + + devc->rirb = (rirb_entry_t *) (devc->corb + 512); /* 512 dwords = 2048 bytes */ + devc->rirb_phys = devc->corb_phys + 2048; + +/* + * Initialize CORB registers + */ + + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBCTL, 0); /* Stop */ + + tmout = 0; + + while (tmout++ < 500 + && (PCI_READB (devc->osdev, devc->azbar + HDA_CORBCTL) & 0x02)); + + if (PCI_READB (devc->osdev, devc->azbar + HDA_CORBCTL) & 0x02) + { + cmn_err (CE_WARN, "CORB didn't stop\n"); + } + + tmp = devc->corb_phys & 0xffffffff; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_CORBLBASE, tmp); + tmp = (devc->corb_phys >> 32) & 0xffffffff; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_CORBUBASE, tmp); + + PCI_WRITEW (devc->osdev, devc->azbar + HDA_CORBWP, 0x0); /* Reset to 0 */ + PCI_WRITEW (devc->osdev, devc->azbar + HDA_CORBRP, 0x8000); /* Reset to 0 */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBCTL, 0x02); /* Start */ + +/* + * Initialize RIRB registers + */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0); /* Stop */ + + tmout = 0; + + while (tmout++ < 500 + && (PCI_READB (devc->osdev, devc->azbar + HDA_RIRBCTL) & 0x02)); + + if (PCI_READB (devc->osdev, devc->azbar + HDA_RIRBCTL) & 0x02) + { + cmn_err (CE_WARN, "RIRB didn't stop\n"); + } + + tmp = devc->rirb_phys & 0xffffffff; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_RIRBLBASE, tmp); + tmp = (devc->rirb_phys >> 32) & 0xffffffff; + PCI_WRITEL (devc->osdev, devc->azbar + HDA_RIRBUBASE, tmp); + devc->rirb_rp = 0; + + PCI_WRITEW (devc->osdev, devc->azbar + HDA_RIRBWP, 0x8000); /* Reset to 0 */ + PCI_WRITEW (devc->osdev, devc->azbar + HDA_RINTCNT, 1); /* reset hw write ptr */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0x03); /* Start & Intr enable */ + + return 1; +} + +static int +setup_engines (hda_devc_t * devc) +{ + int i, p; + unsigned int gcap; + unsigned int num_inputs, num_outputs; + oss_native_word phaddr; + gcap = PCI_READW (devc->osdev, devc->azbar + HDA_GCAP); + + num_outputs = (gcap >> 12) & 0x0f; + num_inputs = (gcap >> 8) & 0x0f; + + /* Init output engines */ + p = num_inputs; /* Output engines are located after the input ones */ + + if (num_outputs > HDA_MAX_ENGINES) + { + cmn_err (CE_WARN, + "Using only %d out of %d available output engines\n", + HDA_MAX_ENGINES, num_outputs); + num_outputs = HDA_MAX_ENGINES; + } + + if (num_inputs > HDA_MAX_ENGINES) + { + cmn_err (CE_WARN, + "Using only %d out of %d available input engines\n", + HDA_MAX_ENGINES, num_inputs); + num_inputs = HDA_MAX_ENGINES; + } + + for (i = 0; i < num_outputs; i++) + { + hda_engine_t *engine = &devc->outengines[i]; + + engine->bdl = + CONTIG_MALLOC (devc->osdev, 4096, MEMLIMIT_32BITS, &phaddr, engine->bdl_dma_handle); + if (engine->bdl == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + engine->bdl_max = 4096 / sizeof (bdl_t); + engine->bdl_phys = phaddr; + engine->base = devc->azbar + 0x80 + (p * 0x20); + engine->num = i; + engine->intrmask = (1 << p); + engine->portc = NULL; + p++; + devc->num_outengines = i + 1; + } + + /* Init input engines */ + p = 0; + for (i = 0; i < num_inputs; i++) + { + hda_engine_t *engine = &devc->inengines[i]; + + engine->bdl = + CONTIG_MALLOC (devc->osdev, 4096, MEMLIMIT_32BITS, &phaddr, engine->bdl_dma_handle); + if (engine->bdl == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + engine->bdl_max = 4096 / sizeof (bdl_t); + engine->bdl_phys = phaddr; + engine->base = devc->azbar + 0x80 + (p * 0x20); + engine->num = i; + engine->intrmask = (1 << p); + engine->portc = NULL; + p++; + devc->num_inengines = i + 1; + } + return 1; +} + +/*ARGSUSED*/ +static void +init_adev_caps (hda_devc_t * devc, adev_p adev, hdaudio_endpointinfo_t * ep) +{ + int i; + + adev->oformat_mask = ep->fmt_mask; + adev->iformat_mask = ep->fmt_mask; + + adev->min_rate = 500000; + adev->max_rate = 0; + + adev->nrates = ep->nrates; + if (adev->nrates > OSS_MAX_SAMPLE_RATES) + { + cmn_err(CE_NOTE, "Too many supported sample rates (%d)\n", adev->nrates); + adev->nrates = OSS_MAX_SAMPLE_RATES; + } + + for (i = 0; i < adev->nrates; i++) + { + int r = ep->rates[i]; + + adev->rates[i] = r; + + if (adev->min_rate > r) + adev->min_rate = r; + if (adev->max_rate < r) + adev->max_rate = r; + } +} + +/* + * S/PDIF lowlevel driver + */ +/*ARGSUSED*/ +static int +hdaudio_reprogram_spdif (void *_devc, void *_portc, + oss_digital_control * ctl, unsigned int mask) +{ + unsigned short cbits = 0; + hda_devc_t *devc = _devc; + oss_native_word flags; + hdaudio_endpointinfo_t *endpoint = devc->spdifout_endpoint; + + if (endpoint == NULL) + return OSS_EIO; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + cbits = 0x01; /* Digital interface enabled */ + + cbits |= (1 << 2); /* VCFG */ + + if (ctl->out_vbit == VBIT_ON) + cbits |= (1 << 1); /* Turn on the V bit */ + + if (ctl->cbitout[0] & 0x02) /* Audio/Data */ + cbits |= (1 << 5); /* /AUDIO */ + + if (ctl->cbitout[0] & 0x01) /* Pro */ + cbits |= (1 << 6); + else + { + + if (ctl->cbitout[0] & 0x04) /* Copyright */ + cbits |= (1 << 4); /* COPY */ + + if (ctl->cbitout[1] & 0x80) /* Generation level */ + cbits |= (1 << 7); /* L */ + + if (ctl->emphasis_type & 1) /* Pre-emphasis */ + cbits |= (1 << 3); /* PRE */ + } + do_corb_write (devc, endpoint->cad, endpoint->base_wid, 0, + SET_SPDIF_CONTROL1, cbits); + + cbits = ctl->cbitout[1] & 0x7f; /* Category code */ + do_corb_write (devc, endpoint->cad, endpoint->base_wid, 0, + SET_SPDIF_CONTROL2, cbits); + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +spdif_driver_t hdaudio_spdif_driver = { +/* reprogram_device: */ hdaudio_reprogram_spdif, +}; + +static int +spdif_mixer_init (int dev) +{ + hda_devc_t *devc = mixer_devs[dev]->hw_devc; + int err; + + if ((err = oss_spdif_mix_init (&devc->spdc)) < 0) + return err; + + return 0; +} + +static void +install_outputdevs (hda_devc_t * devc) +{ + int i, n, pass, audio_dev, output_num=0; + char tmp_name[64]; + hdaudio_endpointinfo_t *endpoints; + + if ((n = + hdaudio_mixer_get_outendpoints (devc->mixer, &endpoints, + sizeof (*endpoints))) < 0) + return; + +#if 0 + // This check will be done later. + if (n > MAX_OUTPUTS) + { + cmn_err (CE_WARN, + "Only %d out of %d output devices can be installed\n", + MAX_OUTPUTS, n); + n = MAX_OUTPUTS; + } +#endif + +/* + * Install the output devices in two passes. First install the analog + * endpoints and then the digital one(s). + */ + for (pass = 0; pass < 3; pass++) + for (i = 0; i < n; i++) + { + adev_p adev; + hda_portc_t *portc = &devc->output_portc[i]; + unsigned int formats = AFMT_S16_LE; + int opts = ADEV_AUTOMODE | ADEV_NOINPUT; + char *devfile_name = ""; + char devname[16]; + +/* Skip endpoints that are not physically connected on the motherboard. */ + if (endpoints[i].skip) + continue; + + if (output_num >= MAX_OUTPUTS) + { + cmn_err(CE_CONT, "Too many output endpoints. Endpoint %d ignored.\n", i); + continue; + } + + switch (pass) + { + case 0: /* Pick analog and non-modem ones */ + if (endpoints[i].is_digital || endpoints[i].is_modem) + continue; + break; + + case 1: /* Pick digital one(s) */ + if (!endpoints[i].is_digital) + continue; + break; + + case 2: /* Pick modem one(s) */ + if (!endpoints[i].is_modem) + continue; + } + + if (endpoints[i].is_digital) + { + opts |= ADEV_SPECIAL; + sprintf (devname, "spdout%d", devc->num_spdout++); + devfile_name = devname; + } + if (endpoints[i].is_modem) + { + opts |= ADEV_SPECIAL; + sprintf (devname, "mdmout%d", devc->num_mdmout++); + devfile_name = devname; + } + + // sprintf (tmp_name, "%s %s", devc->chip_name, endpoints[i].name); + sprintf (tmp_name, "HD Audio play %s", endpoints[i].name); + + if ((audio_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &hda_audio_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + return; + } + + if (output_num == 0) + devc->first_dev = audio_dev; + + adev = audio_engines[audio_dev]; + devc->num_outputs = i+1; + + adev->devc = devc; + adev->portc = portc; + adev->rate_source = devc->first_dev; + adev->mixer_dev = devc->mixer_dev; + adev->min_rate = 8000; + adev->max_rate = 192000; + adev->min_channels = 2; + + if (output_num == 0) + adev->max_channels = 8; + else + adev->max_channels = 2; + + if (endpoints[i].is_modem) + { + adev->min_channels = 1; + adev->max_channels = 1; + adev->caps |= PCM_CAP_MODEM; + } + + if (adev->max_channels > 4) + adev->dmabuf_alloc_flags |= DMABUF_LARGE | DMABUF_QUIET; + adev->min_block = 128; /* Hardware limitation */ + adev->min_fragments = 4; /* Vmix doesn't work without this */ + portc->num = output_num; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = audio_dev; + portc->port_type = PT_OUTPUT; + portc->endpoint = &endpoints[i]; + init_adev_caps (devc, adev, portc->endpoint); + portc->engine = NULL; + + if (portc->endpoint->is_digital) + { + int err; + + devc->spdifout_endpoint = portc->endpoint; + +/* + * To be precise the right place for the spdc field might be portc instead of + * devc. In this way it's possible to have multiple S/PDIF output DACs connected + * to the same HDA controller. OTOH having it in devc saves space. Multiple + * oss_spdif_install() calls on the same spdc structure doesn't cause any + * problems. + * + * If spdc is moved to portc then care must be taken that oss_spdif_uninstall() + * is called for all all output_portc instances. + */ + if ((err = oss_spdif_install (&devc->spdc, devc->osdev, + &hdaudio_spdif_driver, + sizeof (spdif_driver_t), devc, NULL, + devc->mixer_dev, SPDF_OUT, + DIG_PASSTHROUGH | DIG_EXACT | + DIG_CBITOUT_LIMITED | DIG_VBITOUT | + DIG_PRO | DIG_CONSUMER)) != 0) + { + cmn_err (CE_WARN, + "S/PDIF driver install failed. Error %d\n", err); + } + else + { + hdaudio_mixer_set_initfunc (devc->mixer, spdif_mixer_init); + } + } + output_num++; + } +} + +static void +install_inputdevs (hda_devc_t * devc) +{ + int i, n, audio_dev; + char tmp_name[64]; + hdaudio_endpointinfo_t *endpoints; + char devname[16], *devfile_name = ""; + + if ((n = + hdaudio_mixer_get_inendpoints (devc->mixer, &endpoints, + sizeof (*endpoints))) < 0) + return; + + if (n > MAX_INPUTS) + { + cmn_err (CE_WARN, + "Only %d out of %d input devices can be installed\n", + MAX_INPUTS, n); + n = MAX_INPUTS; + } + + for (i = 0; i < n; i++) + { + adev_p adev; + hda_portc_t *portc = &devc->input_portc[i]; + unsigned int formats = AFMT_S16_LE; + int opts = ADEV_AUTOMODE | ADEV_NOOUTPUT; + +/* Skip endpoints that are not physically connected on the motherboard. */ + if (endpoints[i].skip) + continue; + + if (endpoints[i].is_digital) + { + opts |= ADEV_SPECIAL; + sprintf (devname, "spdin%d", devc->num_spdin++); + devfile_name = devname; + } + if (endpoints[i].is_modem) + { + opts |= ADEV_SPECIAL; + sprintf (devname, "mdmin%d", devc->num_mdmin++); + devfile_name = devname; + } + + //sprintf (tmp_name, "%s %s", devc->chip_name, endpoints[i].name); + sprintf (tmp_name, "HD Audio rec %s", endpoints[i].name); + + if ((audio_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &hda_audio_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + return; + } + + if (i == 0 && devc->first_dev == -1) + devc->first_dev = audio_dev; + + adev = audio_engines[audio_dev]; + devc->num_inputs = i+1; + + adev->devc = devc; + adev->portc = portc; + adev->rate_source = devc->first_dev; + adev->mixer_dev = devc->mixer_dev; + adev->min_rate = 8000; + adev->max_rate = 192000; + adev->min_channels = 2; + adev->max_channels = 2; + + if (endpoints[i].is_modem) + { + adev->min_channels = 1; + adev->max_channels = 1; + adev->caps |= PCM_CAP_MODEM; + } + + adev->min_block = 128; /* Hardware limitation */ + adev->min_fragments = 4; /* Vmix doesn't work without this */ + portc->num = i; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = audio_dev; + portc->port_type = PT_INPUT; + portc->endpoint = &endpoints[i]; + portc->engine = NULL; + init_adev_caps (devc, adev, portc->endpoint); + } +} + +static void +activate_vmix (hda_devc_t * devc) +{ +#ifdef CONFIG_OSS_VMIX +/* + * Attach vmix engines to all outputs and inputs. + */ + + if (devc->num_outputs > 0) + { + if (devc->num_inputs < 1) + vmix_attach_audiodev(devc->osdev, devc->output_portc[0].audiodev, -1, 0); + else + vmix_attach_audiodev(devc->osdev, devc->output_portc[0].audiodev, devc->input_portc[0].audiodev, 0); + }; +#endif +} + +static int +init_HDA (hda_devc_t * devc) +{ + unsigned int gcap; + unsigned int tmp; + + /* Reset controller */ + + if (!reset_controller (devc)) + return 0; + + PCI_WRITEL (devc->osdev, devc->azbar + HDA_INTCTL, PCI_READL (devc->osdev, devc->azbar + HDA_INTCTL) | 0xc0000000); /* Intr enable */ + + /* + * Set CORB and RIRB sizes to 256, 16 or 2 entries. + * + */ + tmp = (PCI_READB (devc->osdev, devc->azbar + HDA_CORBSIZE) >> 4) & 0x07; + if (tmp & 0x4) /* 256 entries */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBSIZE, 0x2); + else if (tmp & 0x2) /* 16 entries */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBSIZE, 0x1); + else /* Assume that 2 entries is supported */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBSIZE, 0x0); + + tmp = (PCI_READB (devc->osdev, devc->azbar + HDA_RIRBSIZE) >> 4) & 0x07; + if (tmp & 0x4) /* 256 entries */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBSIZE, 0x2); + else if (tmp & 0x2) /* 16 entries */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBSIZE, 0x1); + else /* Assume that 2 entries is supported */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBSIZE, 0x0); + + /* setup the CORB/RIRB structs */ + if (!setup_controller (devc)) + return 0; + + /* setup the engine structs */ + if (!setup_engines (devc)) + return 0; + + if (!devc->codecmask) + { + cmn_err (CE_WARN, "No codecs found after reset\n"); + return 0; + } + else + devc->mixer = hdaudio_mixer_create (devc->chip_name, devc, devc->osdev, + do_corb_write, corb_read, + devc->codecmask, devc->vendor_id, + devc->subvendor_id); + if (devc->mixer == NULL) + return 0; + + devc->mixer_dev = hdaudio_mixer_get_mixdev (devc->mixer); + + gcap = PCI_READW (devc->osdev, devc->azbar + HDA_GCAP); + DDB (cmn_err (CE_CONT, " GCAP register content 0x%x\n", gcap)); + + if (((gcap >> 3) & 0x0f) > 0) + cmn_err (CE_WARN, "Bidirectional engines not supported\n"); + if (((gcap >> 1) & 0x03) > 0) + cmn_err (CE_WARN, "Multiple SDOs not supported\n"); + + install_outputdevs (devc); + install_inputdevs (devc); + activate_vmix (devc); + + return 1; +} + + +int +oss_hdaudio_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision, btmp; + unsigned short pci_command, vendor, device, wtmp; + unsigned short subvendor, subdevice; + hda_devc_t *devc; + static int already_attached = 0; + int err; + unsigned short devctl; + + DDB (cmn_err (CE_CONT, "oss_hdaudio_attach entered\n")); + + if (already_attached) + { + cmn_err (CE_WARN, "oss_hdaudio_attach: Already attached\n"); + return 0; + } + already_attached = 1; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + +#if 0 + // This check is not necessary because the kernel has already checked + // the vendor&device ID + + if ((vendor != INTEL_VENDOR_ID && vendor != NVIDIA_VENDOR_ID && + vendor != ATI_VENDOR_ID && vendor != SIS_VENDOR_ID && + vendor != VIA_VENDOR_ID && vendor != ULI_VENDOR_ID) || + (device != INTEL_DEVICE_ICH6 && device != INTEL_DEVICE_ICH7 && + device != INTEL_DEVICE_ESB2 && device != INTEL_DEVICE_ICH8 && + device != INTEL_DEVICE_ICH9 && device != INTEL_DEVICE_P35 && + device != INTEL_DEVICE_ICH10 && device != INTEL_DEVICE_ICH10_B && + device != INTEL_DEVICE_PCH && + device != NVIDIA_DEVICE_MCP51 && device != NVIDIA_DEVICE_MCP55 && + device != NVIDIA_DEVICE_MCP61 && device != NVIDIA_DEVICE_MCP61A && + device != NVIDIA_DEVICE_MCP65 && device != NVIDIA_DEVICE_MCP67 && + device != NVIDIA_DEVICE_MCP73 && device != NVIDIA_DEVICE_MCP78S && + device != NVIDIA_DEVICE_MCP79 && + device != VIA_DEVICE_HDA && + device != SIS_DEVICE_HDA && + device != ULI_DEVICE_HDA && + device != ATI_DEVICE_SB450 && device != ATI_DEVICE_SB600)) + + { + return 0; + } +#endif + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor); + pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &subdevice); + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + + devc->osdev = osdev; + osdev->devc = devc; + devc->first_dev = -1; + + osdev->hw_info = PMALLOC (osdev, HWINFO_SIZE); /* Text buffer for additional device info */ + memset (osdev->hw_info, 0, HWINFO_SIZE); + + devc->vendor_id = (vendor << 16) | device; + devc->subvendor_id = (subvendor << 16) | subdevice; + + oss_pci_byteswap (osdev, 1); + + switch (device) + { + case INTEL_DEVICE_SCH: + pci_read_config_word (osdev, 0x78, &devctl); + DDB (cmn_err (CE_CONT, " DEVC register content 0x%04x\n", devctl);) + pci_write_config_word (osdev, 0x78, (devctl & (~0x0800)) ); + DDB (pci_read_config_word (osdev, 0x78, &devctl);) + DDB (cmn_err (CE_CONT, " DEVC register content (after clearing DEVC.NSNPEN) 0x%04x\n", devctl);) + /* continue is intentional */ + case INTEL_DEVICE_ICH6: + case INTEL_DEVICE_ICH7: + case INTEL_DEVICE_ESB2: + case INTEL_DEVICE_ICH8: + case INTEL_DEVICE_ICH9: + case INTEL_DEVICE_P35: + case INTEL_DEVICE_ICH10: + case INTEL_DEVICE_ICH10_B: + case INTEL_DEVICE_PCH: + case INTEL_DEVICE_PCH2: + case INTEL_DEVICE_CPT: + devc->chip_name = "Intel HD Audio"; + break; + + case NVIDIA_DEVICE_MCP51: + case NVIDIA_DEVICE_MCP55: + case NVIDIA_DEVICE_MCP61: + case NVIDIA_DEVICE_MCP61A: + case NVIDIA_DEVICE_MCP65: + case NVIDIA_DEVICE_MCP67: + case NVIDIA_DEVICE_MCP73: + case NVIDIA_DEVICE_MCP78S: + case NVIDIA_DEVICE_MCP79: + devc->chip_name = "nVidia HD Audio"; + pci_read_config_byte (osdev, 0x4e, &btmp); + pci_write_config_byte (osdev, 0x4e, (btmp & 0xf0) | 0x0f); + pci_read_config_byte (osdev, 0x4d, &btmp); + pci_write_config_byte (osdev, 0x4d, (btmp & 0xfe) | 0x01); + pci_read_config_byte (osdev, 0x4c, &btmp); + pci_write_config_byte (osdev, 0x4c, (btmp & 0xfe) | 0x01); + break; + + case ATI_DEVICE_SB450: + case ATI_DEVICE_SB600: + devc->chip_name = "ATI HD Audio"; + pci_read_config_byte (osdev, 0x42, &btmp); + pci_write_config_byte (osdev, 0x42, (btmp & 0xf8) | 0x2); + break; + + case VIA_DEVICE_HDA: + devc->chip_name = "VIA HD Audio"; + break; + + case SIS_DEVICE_HDA: + devc->chip_name = "SiS HD Audio"; + break; + + case ULI_DEVICE_HDA: + devc->chip_name = "ULI HD Audio"; + pci_read_config_word (osdev, 0x40, &wtmp); + pci_write_config_word (osdev, 0x40, wtmp | 0x10); + pci_write_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, 0); + break; + + case CREATIVE_XFI_HDA: + devc->chip_name = "Creative Labs XFi XTreme Audio"; + break; + + default: + devc->chip_name = "High definition audio device"; + } + + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &devc->membar_addr); + + devc->membar_addr &= ~7; + + /* get virtual address */ + devc->azbar = + (void *) MAP_PCI_MEM (devc->osdev, 0, devc->membar_addr, 16 * 1024); + + /*verify interrupt*/ + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS.\n"); + return 0; + } + + devc->irq = pci_irq_line; + + /* activate the device */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + + 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, hdaintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + devc->base = devc->membar_addr; + + /* Setup the TCSEL register. Don't do this with ATI chipsets. */ + if (vendor != ATI_VENDOR_ID) + { + pci_read_config_byte (osdev, 0x44, &btmp); + pci_write_config_byte (osdev, 0x44, btmp & 0xf8); + } + + err = init_HDA (devc); + return err; +} + +int +oss_hdaudio_detach (oss_device_t * osdev) +{ + hda_devc_t *devc = (hda_devc_t *) osdev->devc; + int j; + + if (oss_disable_device (osdev) < 0) + return 0; + + PCI_WRITEL (devc->osdev, devc->azbar + HDA_INTSTS, 0xc0000000); /* ack pending ints */ + + PCI_WRITEL (devc->osdev, devc->azbar + HDA_INTCTL, 0); /* Intr disable */ + PCI_WRITEL (devc->osdev, devc->azbar + HDA_STATESTS, 0x7); /* Intr disable */ + PCI_WRITEL (devc->osdev, devc->azbar + HDA_RIRBSTS, 0x5); /* Intr disable */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_RIRBCTL, 0); /* Stop */ + PCI_WRITEB (devc->osdev, devc->azbar + HDA_CORBCTL, 0); /* Stop */ + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + if (devc->corb != NULL) + CONTIG_FREE (devc->osdev, devc->corb, 4096, devc->corb_dma_handle); + + devc->corb = NULL; + + for (j = 0; j < devc->num_outengines; j++) + { + hda_engine_t *engine = &devc->outengines[j]; + + if (engine->bdl == NULL) + continue; + CONTIG_FREE (devc->osdev, engine->bdl, 4096, engine->bdl_dma_handle); + } + + for (j = 0; j < devc->num_inengines; j++) + { + hda_engine_t *engine = &devc->inengines[j]; + + if (engine->bdl == NULL) + continue; + CONTIG_FREE (devc->osdev, engine->bdl, 4096, engine->bdl_dma_handle); + } + + if (devc->membar_addr != 0) + { + UNMAP_PCI_MEM (devc->osdev, 0, devc->membar_addr, devc->azbar, + 16 * 1024); + devc->membar_addr = 0; + } + + oss_spdif_uninstall (&devc->spdc); + + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_hdaudio/oss_hdaudio.man b/kernel/drv/oss_hdaudio/oss_hdaudio.man new file mode 100644 index 0000000..e2bae7a --- /dev/null +++ b/kernel/drv/oss_hdaudio/oss_hdaudio.man @@ -0,0 +1,77 @@ +NAME + oss_hdaudio - Intel High Definition Audio (AZALIA) + +DESCRIPTION + Open Sound System driver for Intels high definition audio known as + "Azalia". This driver supports Intel 915/925 chipsets with the + Realtek ALC880 and CMedia 9880 8 channel codecs. + + The HDA driver supports: + + o 8-96Khz Playback/Recording + o 8 or 16 or 32 bits + o 2, 4, 6 or 8 channel audio. + o SPDIF digital output and Input + o AC3 passthrough + + HDAUDIO MIXER + The Intel HDA mixer is a new type of mixer that doesn't have + the normal volume controls found on AC97 or legacy SB devices. + The HDA mixer presents a concept of Jacks and you can configure + any jack to be either an output or an input jack. + + Some motherboards may not correctly initialize the jacks according + to their color and functionality but in general here's the + configuration that should generally be followed: + + o Orange = Center/LFE o Blue = Line-in + o Black = Rear o Green = Front + o Grey = Side o Pink = Mic + + Some Azalia codecs support front panel connectors and so if you see + fp-green and fp-pink connectors, then these are for front panel + speaker and mic/line-in Jacks. + + There is a function selector for most of the analog audio jacks (for example + connector.pink.mode). This selector is used to control if the jack is used + as an input (microphone or line in) or output (front, rear, side, speaker, + etc). + +KNOWN PROBLEMS +In general Azalia based systems (laptops/motherboards) would require a custom +driver to work properly. Due to enormous number of different systems it is not +possible to develop such custom drivers for all systems. A generic driver is +used for systems that don't have dedicated drivers. + +Unfortunately the mixer and control panel interface (see ossmix(1)) +for "generic" systems is very cryptic and difficult to +understand. To solve problems with volumes or signal routing you need to +start ossxmix(1) and change the controls one at time until you get the desired +effect. + +OPTIONS +o hdaudio_jacksense enables jack sensing mode when the hdaudio driver is + loaded. In this mode all I/O pin's that are not + in use will be disabled as well as the mixer controls + that are related with them. In this way the + mixer/control panel will become more intuitive. + However OSS will need to be restarted with soundoff; + soundon every time new inputs or outputs are attached + to the audio jacks. Default : 0. + + NOTE! hdaudio_jacksense=1 works only in some systems. + Many laptops and motherboards don't support jack + sensing. + +o hdaudio_noskip Disable skipping unconnected jack. All mixer controls + will be shown, even for disabled I/O pins. + Can get values 0-7. 1-7 is a bitmask, where every bit + masks a different check. Bit 3 (= value 4) overrides + jacksense check too. + Default: 0 - unconnected jacks are skipped. +FILES + CONFIGFILEPATH/oss_hdaudio.conf Device configuration file + +AUTHOR + 4Front Technologies + diff --git a/kernel/drv/oss_ich/.changelog b/kernel/drv/oss_ich/.changelog new file mode 100644 index 0000000..7f16ede --- /dev/null +++ b/kernel/drv/oss_ich/.changelog @@ -0,0 +1 @@ +20080115 by Dev: Added Nvidia MCP04 (10de:003a) model to driver/database diff --git a/kernel/drv/oss_ich/.config b/kernel/drv/oss_ich/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_ich/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_ich/.devices b/kernel/drv/oss_ich/.devices new file mode 100644 index 0000000..8880e15 --- /dev/null +++ b/kernel/drv/oss_ich/.devices @@ -0,0 +1,21 @@ +oss_ich pci1022,7445 AMD 786 +oss_ich pci1022,746d AMD 8111 +oss_ich pci1039,7012 SiS 7012 +oss_ich pci10de,1b1 Nvidia nForce +oss_ich pci10de,3a Nvidia MCP4 +oss_ich pci10de,6a Nvidia nForce2 +oss_ich pci10de,8a Nvidia CK8 +oss_ich pci10de,da Nvidia nForce3 +oss_ich pci10de,ea Nvidia CK8S +oss_ich pci10de,59 Nvidia nForce4 +oss_ich pci10de,26b Nvidia MCP51 +oss_ich pci8086,2415 Intel AC97 (ICH) +oss_ich pci8086,2425 Intel AC97 (ICH1) +oss_ich pci8086,2445 Intel AC97 (ICH2) +oss_ich pci8086,2485 Intel AC97 (ICH3) +oss_ich pci8086,24c5 Intel AC97 (ICH4) +oss_ich pci8086,24d5 Intel AC97 (ICH5) +oss_ich pci8086,25a6 Intel AC97 (ESB) +oss_ich pci8086,266e Intel AC97 (ICH6) +oss_ich pci8086,27de Intel AC97 (ICH7) +oss_ich pci8086,7195 Intel 440MX (440MX) diff --git a/kernel/drv/oss_ich/.name b/kernel/drv/oss_ich/.name new file mode 100644 index 0000000..3ad1ec7 --- /dev/null +++ b/kernel/drv/oss_ich/.name @@ -0,0 +1 @@ +Intel ICH1-7, nVidia nForce, SiS7012, AMD8111/786 diff --git a/kernel/drv/oss_ich/.params b/kernel/drv/oss_ich/.params new file mode 100644 index 0000000..4b7771d --- /dev/null +++ b/kernel/drv/oss_ich/.params @@ -0,0 +1,16 @@ +int intelpci_rate_tuning = 240; +/* + * Few broken motherboards had nonstandard crystal clocks that cause wrong + * sampling rates. With such motherboards it was necessary to use + * the intelpci_rate_tuning option to fix the rate. See the manual + * for more info. + */ +int intelpci_force_mmio = 0; +/* + * intelpci_force_mmio forces the driver to use Memory Mapped IO + * (some bioses don't provide I/O mapped addresses). + */ +int ich_jacksense = 0; +/* + * Force enabling jacksense on some AD198x mixers. + */ diff --git a/kernel/drv/oss_ich/oss_ich.c b/kernel/drv/oss_ich/oss_ich.c new file mode 100644 index 0000000..fc23e01 --- /dev/null +++ b/kernel/drv/oss_ich/oss_ich.c @@ -0,0 +1,1470 @@ +/* + * Purpose: Driver for the Intel ICH AC97 audio controller + * + * The same design is also used in many PC chipsets by nVidia, AMD and SiS for + * audio functionality. + */ + +/* + * + * 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_ich_cfg.h" +#include <oss_pci.h> + +#include <ac97.h> +extern int intelpci_force_mmio; + +#define INTEL_VENDOR_ID 0x8086 +#define SIS_VENDOR_ID 0x1039 +#define NVIDIA_VENDOR_ID 0x10de +#define AMD_VENDOR_ID 0x1022 +#define SIS_DEVICE_7012 0x7012 +#define INTEL_DEVICE_ICH1 0x2415 +#define INTEL_DEVICE_ICH1R1 0x2425 +#define INTEL_DEVICE_ICH1R2 0x7195 +#define INTEL_DEVICE_ICH2 0x2445 +#define INTEL_DEVICE_ICH3 0x2485 +#define INTEL_DEVICE_ICH4 0x24c5 +#define INTEL_DEVICE_ICH5 0x24d5 +#define INTEL_DEVICE_ESB 0x25a6 +#define INTEL_DEVICE_ICH6 0x266e +#define INTEL_DEVICE_ICH7 0x27de +#define NVIDIA_DEVICE_NFORCE 0x01b1 +#define NVIDIA_DEVICE_MCP4 0x003a +#define NVIDIA_DEVICE_NFORCE2 0x006a +#define NVIDIA_DEVICE_CK8 0x008a +#define NVIDIA_DEVICE_NFORCE3 0x00da +#define NVIDIA_DEVICE_CK8S 0x00ea +#define NVIDIA_DEVICE_NFORCE4 0x0059 +#define NVIDIA_DEVICE_MCP51 0x026b +#define AMD_DEVICE_768 0x7445 +#define AMD_DEVICE_8111 0x746d + +extern int intelpci_rate_tuning; + +#define MAX_PORTC 3 +#define BDL_SIZE 32 + +extern int ich_jacksense; + +typedef struct +{ + int open_mode; + int speed, bits, channels; + int audio_enabled; + int trigger_bits; + int audiodev; + int port_type; +#define DF_PCM 0 +#define DF_SPDIF 1 +} +ich_portc; + +typedef struct +{ + unsigned int addr; + unsigned short size; + unsigned short flags; +} +bdl_t; + +typedef struct ich_devc +{ + oss_device_t *osdev; + oss_native_word base, ac97_base; + oss_native_word membar_addr, ac97_membar_addr; + char *membar_virt, *ac97_membar_virt; +#define CTL_BASE 0 /* addressing controller regs */ +#define MIXER_BASE 1 /* addressing mixer regs */ + int mem_mode; +#define MMAP_MODE 0 /* ICH4/ICH5 uses MEM BARS */ +#define IO_MODE 1 /* ICH1/2/3/4/5 uses IO BARS */ + + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* Mixer */ + ac97_devc ac97devc; + int mixer_dev; + int inverted_amplifier; + + /* Audio parameters */ + int open_mode; + int fifo_errors; + + /* Buffer Descriptor List */ + char *bdlBuffer; + bdl_t *playBDL, *recBDL, *spdifBDL; + oss_native_word playBDL_phys, recBDL_phys, spdifBDL_phys; + oss_dma_handle_t bldbuf_dma_handle; + + int play_currbuf, play_currfrag; + int spdif_currbuf, spdif_currfrag; + int rec_currbuf, rec_currfrag; +#define INTEL_ICH1 0 +#define INTEL_ICH3 1 +#define INTEL_ICH4 2 +#define SIS_7012 3 +#define AMD_768 4 +#define AMD_8111 5 +#define NVIDIA_NFORCE 6 +#define NVIDIA_NFORCE2 7 + int model; + char *chip_name; + ich_portc portc[MAX_PORTC]; + int play_frag_index[BDL_SIZE]; + int rec_frag_index[BDL_SIZE]; + int spdif_frag_index[BDL_SIZE]; +} +ich_devc; + +static unsigned int +ich_INL (ich_devc * devc, int base, unsigned int a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + return *(volatile unsigned int *) (devc->membar_virt + (a)); + else + return *(volatile unsigned int *) (devc->ac97_membar_virt + (a)); + } + else + { + if (base == CTL_BASE) + return INL (devc->osdev, devc->base + a); + else + return INL (devc->osdev, devc->ac97_base + a); + } +} + +static unsigned short +ich_INW (ich_devc * devc, int base, unsigned short a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + return *(volatile unsigned short *) (devc->membar_virt + (a)); + else + return *(volatile unsigned short *) (devc->ac97_membar_virt + (a)); + } + else + { + if (base == CTL_BASE) + return INW (devc->osdev, devc->base + a); + else + return INW (devc->osdev, devc->ac97_base + a); + } +} + +static unsigned char +ich_INB (ich_devc * devc, int base, unsigned char a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + return *(volatile unsigned char *) (devc->membar_virt + (a)); + else + return *(volatile unsigned char *) (devc->ac97_membar_virt + (a)); + } + else + { + if (base == CTL_BASE) + return INB (devc->osdev, devc->base + a); + else + return INB (devc->osdev, devc->ac97_base + a); + } +} + +static void +ich_OUTL (ich_devc * devc, unsigned int d, int base, unsigned int a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + *(volatile unsigned int *) (devc->membar_virt + (a)) = d; + else + *(volatile unsigned int *) (devc->ac97_membar_virt + (a)) = d; + } + else + { + if (base == CTL_BASE) + OUTL (devc->osdev, d, devc->base + a); + else + OUTL (devc->osdev, d, devc->ac97_base + a); + } +} + +static void +ich_OUTW (ich_devc * devc, unsigned short d, int base, unsigned short a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + *(volatile unsigned short *) (devc->membar_virt + (a)) = d; + else + *(volatile unsigned short *) (devc->ac97_membar_virt + (a)) = d; + } + else + { + if (base == CTL_BASE) + OUTW (devc->osdev, d, devc->base + a); + else + OUTW (devc->osdev, d, devc->ac97_base + a); + } +} + +static void +ich_OUTB (ich_devc * devc, unsigned char d, int base, unsigned char a) +{ + if (devc->mem_mode == MMAP_MODE) + { + if (base == CTL_BASE) + *(volatile unsigned char *) (devc->membar_virt + (a)) = d; + else + *(volatile unsigned char *) (devc->ac97_membar_virt + (a)) = d; + } + else + { + if (base == CTL_BASE) + OUTB (devc->osdev, d, devc->base + a); + else + OUTB (devc->osdev, d, devc->ac97_base + a); + } +} + +static int +ac97_read (void *devc_, int reg) +{ + ich_devc *devc = devc_; + int i = 100, status; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + status = ich_INB (devc, CTL_BASE, 0x34); + + while (status & 0x01 && i-- > 0) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + oss_udelay (10); + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + status = ich_INB (devc, CTL_BASE, 0x34); + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ich_INW (devc, MIXER_BASE, reg); +} + +static int +ac97_write (void *devc_, int reg, int data) +{ + ich_devc *devc = devc_; + int i = 100, status; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + status = ich_INB (devc, CTL_BASE, 0x34); + + while (status & 0x01 && i-- > 0) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + oss_udelay (10); + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + status = ich_INB (devc, CTL_BASE, 0x34); + } + + ich_OUTW (devc, data, MIXER_BASE, reg); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +/* + * The top half interrupt handler + */ +static int +ichintr (oss_device_t * osdev) +{ + int serviced = 0; + ich_devc *devc = osdev->devc; + ich_portc *portc; + unsigned int glob_status, status, p, f; + oss_native_word flags; + int i; + + flags = 0; /* To prevent compiler warnings */ + MUTEX_ENTER (devc->mutex, flags); + /* Get pending interrupts and acknowledge them */ + glob_status = ich_INL (devc, CTL_BASE, 0x30); + ich_OUTL (devc, glob_status, CTL_BASE, 0x30); + + /* + * Check the interrupt bits of the status register + */ + if (!(glob_status & 0x0cf7)) + { + /* Not for me */ + MUTEX_EXIT (devc->mutex, flags); + return 0; + } + + /*-------------------- Handle PCM -------------------*/ + if (devc->model == SIS_7012) + status = ich_INB (devc, CTL_BASE, 0x18); + else + status = ich_INB (devc, CTL_BASE, 0x16); + + if (status & 0x10) /* FIFO error */ + devc->fifo_errors++; + + if (status & 0x08) + { + for (i = 0; i < MAX_PORTC - 1; i++) + { + portc = &devc->portc[i]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + p = ich_INB (devc, CTL_BASE, 0x14); + + if (p != devc->play_currbuf) + { + p = devc->play_currbuf; + f = devc->play_currfrag; + devc->playBDL[p].addr = + dmap->dmabuf_phys + (f * dmap->fragment_size); + + /* SIS uses bytes, intelpci uses samples */ + if (devc->model == SIS_7012) + devc->playBDL[p].size = (dmap->fragment_size); + else + devc->playBDL[p].size = (dmap->fragment_size / 2); + devc->playBDL[p].flags = 0xc000; /* IOC interrupts */ + + ich_OUTB (devc, p, CTL_BASE, 0x15); /* Set LVD */ + devc->play_frag_index[p] = f; + devc->play_currbuf = (p + 1) % BDL_SIZE; + devc->play_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_outputintr (portc->audiodev, 1); + } + } + if (devc->model == SIS_7012) + ich_OUTB (devc, status, CTL_BASE, 0x18); /* Clear interrupts */ + else + ich_OUTB (devc, status, CTL_BASE, 0x16); /* Clear interrupts */ + } + + /*------------------- handle SPDIF interrupts -------------------------*/ + + if (devc->model == NVIDIA_NFORCE2) + { + status = ich_INB (devc, CTL_BASE, 0x76); + if (status & 0x08) + { + portc = &devc->portc[2]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + p = ich_INB (devc, CTL_BASE, 0x74); + + if (p != devc->spdif_currbuf) + { + p = devc->spdif_currbuf; + f = devc->spdif_currfrag; + devc->spdifBDL[p].addr = + dmap->dmabuf_phys + (f * dmap->fragment_size); + /* SIS uses bytes, intelpci uses samples */ + devc->spdifBDL[p].size = (dmap->fragment_size / 2); + devc->spdifBDL[p].flags = 0xc000; /* IOC interrupts */ + + ich_OUTB (devc, p, CTL_BASE, 0x75); /* Set LVD */ + devc->spdif_frag_index[p] = f; + devc->spdif_currbuf = (p + 1) % BDL_SIZE; + devc->spdif_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_outputintr (portc->audiodev, 1); + } + ich_OUTB (devc, status, CTL_BASE, 0x76); /* Clear interrupts */ + } + } + + /*----------------------- Handle Recording Interrupts --------------------*/ + + if (devc->model == SIS_7012) + status = ich_INB (devc, CTL_BASE, 0x08); + else + status = ich_INB (devc, CTL_BASE, 0x06); + + if (status & 0x08) + { + for (i = 0; i < MAX_PORTC - 1; i++) + { + portc = &devc->portc[i]; + serviced = 1; + if ((portc->trigger_bits & PCM_ENABLE_INPUT)) /* IOC interrupt */ + { + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in; + p = ich_INB (devc, CTL_BASE, 0x04); + + if (p != devc->rec_currbuf) + { + p = devc->rec_currbuf; + f = devc->rec_currfrag; + devc->recBDL[p].addr = + dmap->dmabuf_phys + (f * dmap->fragment_size); + + /* SIS uses bytes, intelpci uses samples */ + if (devc->model == SIS_7012) + devc->recBDL[p].size = (dmap->fragment_size); + else + devc->recBDL[p].size = (dmap->fragment_size / 2); + + devc->recBDL[p].flags = 0xc000; /* IOC interrupts */ + + ich_OUTB (devc, p, CTL_BASE, 0x05); /* Set LVD */ + devc->rec_frag_index[p] = f; + devc->rec_currbuf = (p + 1) % BDL_SIZE; + devc->rec_currfrag = (f + 1) % dmap->nfrags; + } + oss_audio_inputintr (portc->audiodev, 0); + } + } + if (devc->model == SIS_7012) + ich_OUTB (devc, status, CTL_BASE, 0x08); /* Clear int */ + else + ich_OUTB (devc, status, CTL_BASE, 0x06); /* Clear int */ + } + MUTEX_EXIT (devc->mutex, flags); + return serviced; +} + + +/* + * Audio routines + */ + +static int +ich_audio_set_rate (int dev, int arg) +{ + ich_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 +ich_audio_set_channels (int dev, short arg) +{ + ich_portc *portc = audio_engines[dev]->portc; + + if ((arg == 1) || (arg == 2)) + { + audio_engines[dev]->flags |= ADEV_STEREOONLY; + arg = 2; + } + else + audio_engines[dev]->flags &= ~ADEV_STEREOONLY; + + if (arg>6) + arg=6; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +ich_audio_set_format (int dev, unsigned int arg) +{ + ich_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + +#if 1 + if (portc->open_mode & OPEN_READ) + return portc->bits = AFMT_S16_LE; +#endif + if (!(arg & (AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +ich_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void ich_audio_trigger (int dev, int state); + +static void +ich_audio_reset (int dev) +{ + ich_audio_trigger (dev, 0); +} + +static void +ich_audio_reset_input (int dev) +{ + ich_portc *portc = audio_engines[dev]->portc; + ich_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +ich_audio_reset_output (int dev) +{ + ich_portc *portc = audio_engines[dev]->portc; + ich_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +ich_audio_open (int dev, int mode, int openflags) +{ + ich_portc *portc = audio_engines[dev]->portc; + ich_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 (portc->port_type == DF_SPDIF) + { + if (mode & OPEN_READ) + { + cmn_err (CE_NOTE, "The S/PDIF device supports only playback\n"); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EIO; + } + } + else + { + 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; + devc->fifo_errors = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +ich_audio_close (int dev, int mode) +{ + ich_portc *portc = audio_engines[dev]->portc; + ich_devc *devc = audio_engines[dev]->devc; + + ich_audio_reset (dev); + portc->open_mode = 0; + + if (devc->fifo_errors > 0) + cmn_err (CE_CONT, "%d fifo errors were detected\n", devc->fifo_errors); + + if (portc->port_type != DF_SPDIF) + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +ich_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ich_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +ich_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ich_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +ich_audio_trigger (int dev, int state) +{ + ich_devc *devc = audio_engines[dev]->devc; + ich_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + 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->port_type == DF_SPDIF) + ich_OUTB (devc, 0x1d, CTL_BASE, 0x7b); /* Kickstart */ + else + ich_OUTB (devc, 0x1d, CTL_BASE, 0x1b); /* Kickstart */ + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + if (portc->port_type == DF_SPDIF) + ich_OUTB (devc, 0x00, CTL_BASE, 0x7b); /* reset */ + else + ich_OUTB (devc, 0x00, CTL_BASE, 0x1b); /* reset */ + } + } + } + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + ich_OUTB (devc, 0x1d, CTL_BASE, 0x0b); /* Kickstart */ + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + ich_OUTB (devc, 0x00, CTL_BASE, 0x0b); /* reset */ + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +ich_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + ich_devc *devc = audio_engines[dev]->devc; + ich_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int i, n, speed; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + ich_OUTB (devc, 0x02, CTL_BASE, 0x0b); /* Reset */ + ich_OUTL (devc, devc->recBDL_phys, CTL_BASE, 0x00); /* BDL base */ + + speed = portc->speed; + speed = (speed * 240) / intelpci_rate_tuning; + ac97_recrate (&devc->ac97devc, speed); + + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->recBDL[i].addr = dmap->dmabuf_phys + (i * dmap->fragment_size); + + /* SiS7012 uses bytes, ICH uses samples */ + if (devc->model == SIS_7012) + devc->recBDL[i].size = (dmap->fragment_size); + else + devc->recBDL[i].size = (dmap->fragment_size / 2); + + devc->recBDL[i].flags = 0xc000; /* IOC interrupts */ + devc->rec_frag_index[i] = i; + } + ich_OUTB (devc, n - 1, CTL_BASE, 0x05); /* Set last valid descriptor */ + + devc->rec_currbuf = n % BDL_SIZE; + devc->rec_currfrag = n; + if (devc->rec_currfrag >= dmap->nfrags) + devc->rec_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +ich_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + ich_devc *devc = audio_engines[dev]->devc; + ich_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int i, n, speed; + unsigned int tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + /* We need to add ac3 pass through support */ + if (devc->model == SIS_7012) + { + if (portc->bits == AFMT_AC3) + ich_OUTB (devc, 0, CTL_BASE, 0x4c); + else + ich_OUTB (devc, 1, CTL_BASE, 0x4c); + } + + ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits); + + if (portc->bits == AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + } + + /* do SPDIF out */ + if ((portc->port_type == DF_SPDIF) && (devc->model == NVIDIA_NFORCE2)) + { + ich_OUTB (devc, 0x02, CTL_BASE, 0x7b); /* Reset */ + ich_OUTL (devc, devc->spdifBDL_phys, CTL_BASE, 0x70); /* BDL base */ + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->spdifBDL[i].addr = + dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->spdifBDL[i].size = (dmap->fragment_size / 2); + devc->spdifBDL[i].flags = 0xc000; /* IOC interrupts */ + devc->spdif_frag_index[i] = i; + } + ich_OUTB (devc, n - 1, CTL_BASE, 0x75); /* Set last valid + * descriptor */ + devc->spdif_currbuf = n % BDL_SIZE; + devc->spdif_currfrag = n; + if (devc->spdif_currfrag >= dmap->nfrags) + devc->spdif_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; + } + /* else do PCM */ + ich_OUTB (devc, 0x02, CTL_BASE, 0x1b); /* Reset */ + ich_OUTL (devc, devc->playBDL_phys, CTL_BASE, 0x10); /* BDL base */ + + speed = portc->speed; + speed = (speed * 240) / intelpci_rate_tuning; + ac97_playrate (&devc->ac97devc, speed); + + /* Handle 4/6 channel output on 7012 */ + if (devc->model == SIS_7012) + { + tmp = ich_INL (devc, CTL_BASE, 0x30); + + /* set default to 2 channel mode */ + ich_OUTB (devc, ich_INB (devc, CTL_BASE, 0x2c) & 0x3f, CTL_BASE, 0x2c); + + if ((portc->channels == 4) && (tmp & (1 << 20))) + ich_OUTB (devc, (ich_INB (devc, CTL_BASE, 0x2c) & 0x3f) | 0x40, + CTL_BASE, 0x2c); + + if ((portc->channels == 6) && (tmp & (1 << 21))) + ich_OUTB (devc, (ich_INB (devc, CTL_BASE, 0x2c) & 0x3f) | 0x80, + CTL_BASE, 0x2c); + } + /* Handle 4/6 channel output on evrything other than ICH1 and SIS7012 */ + if ((devc->model != INTEL_ICH1) && (devc->model != SIS_7012)) + { + tmp = ich_INL (devc, CTL_BASE, 0x30); + + /* set default to 2 channel mode */ + ich_OUTL (devc, ich_INL (devc, CTL_BASE, 0x2c) & 0x0cfffff, CTL_BASE, + 0x2c); + + if ((portc->channels == 4) && (tmp & (1 << 20))) + ich_OUTL (devc, + (ich_INL (devc, CTL_BASE, 0x2c) & 0x00fffff) | 0x0100000, + CTL_BASE, 0x2c); + + if ((portc->channels == 6) && (tmp & (1 << 21))) + ich_OUTL (devc, + (ich_INL (devc, CTL_BASE, 0x2c) & 0x00fffff) | 0x0200000, + CTL_BASE, 0x2c); + } + n = bcount; + if (n > BDL_SIZE) + n = BDL_SIZE; + + for (i = 0; i < n; i++) + { + devc->playBDL[i].addr = dmap->dmabuf_phys + (i * dmap->fragment_size); + + /* SiS7012 uses bytes, ICH uses samples */ + if (devc->model == SIS_7012) + devc->playBDL[i].size = (dmap->fragment_size); + else + devc->playBDL[i].size = (dmap->fragment_size / 2); + + devc->playBDL[i].flags = 0xc000; /* IOC interrupts */ + devc->play_frag_index[i] = i; + } + ich_OUTB (devc, n - 1, CTL_BASE, 0x15); /* Set last valid descriptor */ + + + devc->play_currbuf = n % BDL_SIZE; + devc->play_currfrag = n; + if (devc->play_currfrag >= dmap->nfrags) + devc->play_currfrag = 0; + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +ich_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + ich_devc *devc = audio_engines[dev]->devc; + ich_portc *portc = audio_engines[dev]->portc; + int p = 0, f = 0, c = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + if (portc->port_type == DF_PCM) + { + f = ich_INB (devc, CTL_BASE, 0x14); /* Current buffer */ + + if (devc->model == SIS_7012) + p = ich_INW (devc, CTL_BASE, 0x16); /* Position in current + * buffer */ + else + p = ich_INW (devc, CTL_BASE, 0x18); /* Position in current + * buffer */ + c = devc->play_frag_index[f]; /* Current fragment */ + + if (devc->model == SIS_7012) + p = dmap->fragment_size - (p); /* Remaining bytes */ + else + p = dmap->fragment_size - (p * 2); /* Remaining bytes */ + } + if ((portc->port_type == DF_SPDIF) && (devc->model == NVIDIA_NFORCE2)) + { + f = ich_INB (devc, CTL_BASE, 0x74); /* Current buffer */ + p = ich_INW (devc, CTL_BASE, 0x78); /* Position in current + * buffer */ + c = devc->play_frag_index[f]; /* Current fragment */ + p = dmap->fragment_size - (p * 2); /* Remaining bytes */ + } + } + /* + * Handle input + */ + if (direction == PCM_ENABLE_INPUT) + { + + f = ich_INB (devc, CTL_BASE, 0x04); /* Current buffer */ + + if (devc->model == SIS_7012) + p = ich_INW (devc, CTL_BASE, 0x06); /* Position in current + * buffer */ + else + p = ich_INW (devc, CTL_BASE, 0x08); /* Position in current + * buffer */ + c = devc->rec_frag_index[f]; /* Current fragment */ + + if (devc->model == SIS_7012) + p = dmap->fragment_size - (p); /* Remaining bytes */ + else + p = dmap->fragment_size - (p * 2); /* Remaining bytes */ + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return p + c * dmap->fragment_size; +} + +#if 0 +static int +ich_calibrate_speed (int dev, int nominal_speed, int true_speed) +{ + unsigned int fix; + DDB (smn_err (CE_CONT, + "ich_calibrate_speed(%d, %d, %d)\n", dev, nominal_speed, + true_speed)); + + fix = ((240 * true_speed) + nominal_speed / 2) / nominal_speed; + DDB (cmn_err (CE_NOTE, "intelpci_rate_tuning = %d\n", fix)); + if (fix > 1) + intelpci_rate_tuning = fix; + + return 0; +} +#endif + +static const audiodrv_t ich_audio_driver = { + ich_audio_open, + ich_audio_close, + ich_audio_output_block, + ich_audio_start_input, + ich_audio_ioctl, + ich_audio_prepare_for_input, + ich_audio_prepare_for_output, + ich_audio_reset, + NULL, + NULL, + ich_audio_reset_input, + ich_audio_reset_output, + ich_audio_trigger, + ich_audio_set_rate, + ich_audio_set_format, + ich_audio_set_channels, + NULL, + NULL, + NULL, /* ich_check_input, */ + NULL, /* ich_check_output, */ + NULL, /* ich_alloc_buffer, */ + NULL, /* ich_free_buffer, */ + NULL, + NULL, + ich_get_buffer_pointer, + NULL /* ich_calibrate_speed */ +}; + +static int +ich_init (ich_devc * devc) +{ + int my_mixer, adev, opts; + int i, max_port; + unsigned int reg; + int first_dev = 0; + oss_native_word phaddr; + + /* ACLink on, warm reset */ + reg = ich_INL (devc, CTL_BASE, 0x2c); + if ((reg & 0x02) == 0) + reg |= 2; + else + reg |= 4; + reg &= ~8; + ich_OUTL (devc, reg, CTL_BASE, 0x2c); + oss_udelay (500); + if (devc->model == SIS_7012) + { + reg |= 0x10; + ich_OUTL (devc, reg, CTL_BASE, 0x2c); + oss_udelay (500); + } + /* disable interrupts */ + ich_OUTB (devc, 0x00, CTL_BASE, 0x0b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x1b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x2b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x7b); + + devc->bdlBuffer = + CONTIG_MALLOC (devc->osdev, 4 * 32 * 32, MEMLIMIT_32BITS, &phaddr, devc->bldbuf_dma_handle); + if (devc->bdlBuffer == NULL) + { + cmn_err (CE_WARN, "Failed to allocate BDL\n"); + return 0; + } + devc->playBDL = (bdl_t *) devc->bdlBuffer; + devc->playBDL_phys = phaddr; + devc->recBDL = (bdl_t *) (devc->bdlBuffer + (32 * 32)); + devc->recBDL_phys = phaddr + 32 * 32; + devc->spdifBDL = (bdl_t *) (devc->bdlBuffer + (2 * 32 * 32)); + devc->spdifBDL_phys = phaddr + 2 * 32 * 32; + + /* + * Init mixer + */ + my_mixer = + ac97_install_full (&devc->ac97devc, "ICH AC97 Mixer", ac97_read, ac97_write, + devc, devc->osdev, devc->inverted_amplifier | + (ich_jacksense?AC97_FORCE_SENSE:0)); + if (my_mixer == -1) + { + cmn_err (CE_WARN, "AC97 mixer installation failed\n"); + return 0; /* No mixer */ + } + + devc->mixer_dev = my_mixer; + mixer_devs[my_mixer]->priority = 10; /* Known motherboard device */ + + /* enable S/PDIF */ + devc->ac97devc.spdif_slot = SPDIF_SLOT34; + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1); + + /* enable variable rate mode */ + ac97_write (devc, 0x2a, ac97_read (devc, 0x2a) | 9); + if (!(ac97_read (devc, 0x2a) & 1)) + DDB (cmn_err (CE_NOTE, "VRA not supported...using GRC\n")); + + /* Enable SPDIF for SiS 7012 */ + if (devc->model == SIS_7012) + { + ich_OUTL (devc, ich_INL (devc, CTL_BASE, 0x2c) | (1 << 10), CTL_BASE, + 0x2c); + ich_OUTL (devc, ich_INL (devc, CTL_BASE, 0x4c) | 1, CTL_BASE, 0x4c); + } + if (devc->model == NVIDIA_NFORCE2) + max_port = 3; + else + max_port = 2; + + for (i = 0; i < max_port; i++) + { + ich_portc *portc = &devc->portc[i]; + char tmp_name[100]; + int port_fmt = DF_PCM; + int formats = AFMT_S16_LE | AFMT_AC3; + char *devfile_name = ""; + + strcpy (tmp_name, devc->chip_name); + opts = ADEV_AUTOMODE | ADEV_16BITONLY | ADEV_STEREOONLY | ADEV_COLD; + + if (!ac97_varrate (&devc->ac97devc)) + { + opts |= ADEV_FIXEDRATE; + } + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + opts |= ADEV_DUPLEX; + } + if (i == 1) + { + strcpy (tmp_name, devc->chip_name); + opts |= ADEV_DUPLEX | ADEV_SHADOW; + } + if (i == 2) + { + sprintf (tmp_name, "%s S/PDIF out", devc->chip_name); + opts |= ADEV_NOINPUT | ADEV_SPECIAL | ADEV_FIXEDRATE; + port_fmt = DF_SPDIF; + devfile_name = "spdout"; + } + if ((adev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &ich_audio_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1, + devfile_name)) < 0) + { + adev = -1; + return 0; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->max_block = 64 * 1024; + + /* fix a timeout bug with Nforce2 */ + if ((devc->model == NVIDIA_NFORCE) || + (devc->model == NVIDIA_NFORCE2)) + { + audio_engines[adev]->min_block = 4096; + audio_engines[adev]->max_block = 4096; + } + + audio_engines[adev]->min_rate = + (opts & ADEV_FIXEDRATE) ? 48000 : 5000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + audio_engines[adev]->min_channels = 2; + audio_engines[adev]->max_channels = 6; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = adev; + portc->port_type = port_fmt; + if (audio_engines[adev]->flags & ADEV_FIXEDRATE) + audio_engines[adev]->fixed_rate = 48000; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + } + return 1; +} + +int +oss_ich_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision /* , pci_latency */ ; + unsigned short pci_command, vendor, device, sub_vendor, sub_id; + unsigned int pci_ioaddr0, pci_ioaddr1; + unsigned int dw; + + ich_devc *devc; + + 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; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + DDB (cmn_err + (CE_CONT, "oss_ich_attach(Vendor %x, device %x)\n", vendor, device)); + +#if 0 + // This check is not necessary because the kernel has already checked + // the vendor&device ID + + if ((vendor != INTEL_VENDOR_ID && vendor != SIS_VENDOR_ID && + vendor != NVIDIA_VENDOR_ID && vendor != AMD_VENDOR_ID) || + (device != INTEL_DEVICE_ICH1 && device != INTEL_DEVICE_ICH1R1 && + device != INTEL_DEVICE_ICH1R2 && device != INTEL_DEVICE_ICH2 && + device != INTEL_DEVICE_ICH3 && device != INTEL_DEVICE_ICH4 && + device != INTEL_DEVICE_ICH5 && device != INTEL_DEVICE_ESB && + device != INTEL_DEVICE_ICH6 && device != INTEL_DEVICE_ICH7 && + device != SIS_DEVICE_7012 && + device != AMD_DEVICE_768 && device != AMD_DEVICE_8111 && + device != NVIDIA_DEVICE_NFORCE && device != NVIDIA_DEVICE_NFORCE2 && + device != NVIDIA_DEVICE_NFORCE3 && device != NVIDIA_DEVICE_CK8S && + device != NVIDIA_DEVICE_NFORCE4 && device != NVIDIA_DEVICE_CK8 && + device != NVIDIA_DEVICE_MCP51 && device != NVIDIA_DEVICE_MCP4 + )) + { + cmn_err (CE_WARN, "Hardware not recognized (vendor=%x, dev=%x)\n", + vendor, device); + return 0; + } +#endif + + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &sub_vendor); + pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &sub_id); + dw = (sub_id << 16) | sub_vendor; + + switch (dw) + { + case 0x202f161f: /* Gateway 7326GZ */ + case 0x203a161f: /* Gateway 4028GZ or 4542GZ */ + case 0x203e161f: /* Gateway 3520GZ/M210 */ + case 0x204c161f: /* Kvazar-Micro Senator 3592XT */ + case 0x8144104d: /* Sony VAIO PCG-TR* */ + case 0x8197104d: /* Sony S1XP */ + case 0x81c0104d: /* Sony VAIO type T */ + case 0x81c5104d: /* Sony VAIO VGN B1VP/B1XP */ + case 0x3089103c: /* Compaq Presario B3800 */ + case 0x309a103c: /* HP Compaq nx4300 */ + case 0x82131033: /* NEC VersaPro VJ10F/BH */ + case 0x82be1033: /* NEC VersaPro VJ12F/CH */ + devc->inverted_amplifier = AC97_INVERTED; + cmn_err (CE_CONT, "An inverted amplifier has been autodetected\n"); + break; + default: + devc->inverted_amplifier = 0; + break; + } + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr0); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + + switch (device) + { + case INTEL_DEVICE_ICH1: + devc->model = INTEL_ICH1; + devc->chip_name = "Intel ICH (2415)"; + break; + case INTEL_DEVICE_ICH1R1: + devc->model = INTEL_ICH1; + devc->chip_name = "Intel ICHR1(2425)"; + break; + case INTEL_DEVICE_ICH1R2: + devc->model = INTEL_ICH1; + devc->chip_name = "Intel ICHR2 (7195)"; + break; + case INTEL_DEVICE_ICH2: + devc->model = INTEL_ICH1; + devc->chip_name = "Intel ICH2 (2445)"; + break; + case INTEL_DEVICE_ICH3: + devc->model = INTEL_ICH3; + devc->chip_name = "Intel ICH3 (2485)"; + break; + case INTEL_DEVICE_ICH4: + devc->model = INTEL_ICH4; + devc->chip_name = "Intel ICH4 (24C5)"; + break; + case INTEL_DEVICE_ICH5: + devc->model = INTEL_ICH4; + devc->chip_name = "Intel ICH5 (24D5)"; + break; + case INTEL_DEVICE_ICH6: + devc->model = INTEL_ICH4; + devc->chip_name = "Intel ICH6 (266E)"; + break; + case INTEL_DEVICE_ICH7: + devc->model = INTEL_ICH4; + devc->chip_name = "Intel ICH7 (27DE)"; + break; + case INTEL_DEVICE_ESB: + devc->model = INTEL_ICH4; + devc->chip_name = "Intel ICH5 (25a6)"; + break; + case SIS_DEVICE_7012: + devc->model = SIS_7012; + devc->chip_name = "SiS 7012"; + break; + case NVIDIA_DEVICE_NFORCE: + devc->model = NVIDIA_NFORCE; + devc->chip_name = "Nvidia nForce"; + break; + case NVIDIA_DEVICE_NFORCE2: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia nForce2"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_NFORCE3: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia nForce3"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_CK8S: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia CK8S"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_NFORCE4: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia nForce4"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_CK8: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia CK8"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_MCP51: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia MCP51"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case NVIDIA_DEVICE_MCP4: + devc->model = NVIDIA_NFORCE2; + devc->chip_name = "Nvidia MCP4"; + pci_read_config_dword (osdev, 0x4c, &dw); + dw |= 0x1000000; + pci_write_config_dword (osdev, 0x4c, dw); + break; + case AMD_DEVICE_768: + devc->model = AMD_768; + devc->chip_name = "AMD 768"; + break; + case AMD_DEVICE_8111: + devc->model = AMD_8111; + devc->chip_name = "AMD 8111"; + break; + default: + devc->chip_name = "Unknown ICH chip"; + } + + if (((pci_ioaddr1 == 0) || (intelpci_force_mmio)) && + (devc->model == INTEL_ICH4)) + { + unsigned int ioaddr; + + /* read bar2 and bar3 for getting mmap address */ + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_2, &ioaddr); + devc->ac97_membar_addr = ioaddr; + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_3, &ioaddr); + devc->membar_addr = ioaddr; + + /* get virtual address */ + devc->ac97_membar_virt = + (char *) MAP_PCI_MEM (devc->osdev, 2, devc->ac97_membar_addr, 512); + devc->membar_virt = + (char *) MAP_PCI_MEM (devc->osdev, 3, devc->membar_addr, 256); + devc->mem_mode = MMAP_MODE; + } + else + devc->mem_mode = IO_MODE; + + if (devc->mem_mode == IO_MODE) + { + if (devc->model == INTEL_ICH4) + { + /* + * enable the IOSE bit in 0x41 for legacy + * mode for ICH4/ICH5 + */ + pci_write_config_byte (osdev, 0x41, 1); + + /* Set the secondary codec ID */ + pci_write_config_byte (osdev, 0x40, 0x39); + } + /* Remove I/O space marker in bit 0. */ + devc->ac97_base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr0); + devc->base = MAP_PCI_IOADDR (devc->osdev, 1, pci_ioaddr1); + devc->ac97_base &= ~0xF; + devc->base &= ~0xF; + } + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->irq = pci_irq_line; + + if (devc->mem_mode != IO_MODE) + { + devc->base = devc->membar_addr; + } + + 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 (oss_register_interrupts (devc->osdev, 0, ichintr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to install interrupt handler\n"); + return 0; + } + + return ich_init (devc); /* Detected */ +} + +int +oss_ich_detach (oss_device_t * osdev) +{ + ich_devc *devc = (ich_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + /* disable interrupts */ + ich_OUTB (devc, 0x00, CTL_BASE, 0x0b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x1b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x2b); + ich_OUTB (devc, 0x00, CTL_BASE, 0x7b); + oss_unregister_interrupts (devc->osdev); + + /* disable S/PDIF */ + if (devc->mixer_dev) + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0); + + if (devc->bdlBuffer) + CONTIG_FREE (devc->osdev, devc->bdlBuffer, 4 * 32 * 32, devc->bldbuf_dma_handle); + devc->bdlBuffer = NULL; + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + if ((devc->mem_mode == MMAP_MODE) && (devc->membar_addr != 0)) + { + UNMAP_PCI_MEM (devc->osdev, 2, devc->ac97_membar_addr, + devc->ac97_membar_virt, 512); + UNMAP_PCI_MEM (devc->osdev, 3, devc->membar_addr, devc->membar_virt, + 256); + devc->membar_addr = 0; + devc->ac97_membar_addr = 0; + } + else + { + UNMAP_PCI_IOADDR (devc->osdev, 0); + UNMAP_PCI_IOADDR (devc->osdev, 1); + } + oss_unregister_device (osdev); + return 1; +} + +#ifdef OSS_POWER_MANAGE +/* Not activated in .config at this moment */ +int +oss_ich_power (oss_device_t *osdev, int component, int level) +{ +// cmn_err(CE_CONT, "oss_ich_power(%d, %d)\n", component, level); + + return 0; /* Failed */ +} +#endif + +#ifdef OSS_SUSPEND_RESUME +int +oss_ich_suspend(oss_device_t *osdev) +{ +//cmn_err(CE_CONT, "oss_ich_suspend()\n"); + return 0; /* Failed */ +} + +int +oss_ich_resume(oss_device_t *osdev) +{ +//cmn_err(CE_CONT, "oss_ich_resume()\n"); + return 0; /* Failed */ +} +#endif diff --git a/kernel/drv/oss_ich/oss_ich.man b/kernel/drv/oss_ich/oss_ich.man new file mode 100644 index 0000000..ee15abf --- /dev/null +++ b/kernel/drv/oss_ich/oss_ich.man @@ -0,0 +1,34 @@ +NAME +oss_ich - Intel ICH/SiS7012/Nvidia/AMD audio device driver. + +DESCRIPTION +Open Sound System driver for Intel ICH, nVidia Nforce, AMD and SiS 7012 +devices. + +OPTIONS + +o intelpci_rate_tuning=<NNN> (default is 240) + Some Compaq Deskpro models (EN and EX at least) and certain Dell models + play and record audio at a higher speed than what is expected. If you have + an Intel815 motherboard with an AD1885 you can try setting the parameter + to 240, 280 or 330 and see which works for your system. The way to figure + out the the right intelpci_rate_tuning value is using the osstest application. + It reports a sample rate drift value ("Sample rate drift" or "srate drift"). + Use the following formula (round the result to the nearest integer): + + <intelpci_rate_tuning = (240*(drift+100))/100> + +o intelpci_force_mmio=<0|1> (default is 0=Disable) + This option can be used to force the ICH4/ICH5 and ICH6 controllers to + run in memory mapped mode to free up I/O address space. + +o ich_jacksense=<0|1> (default is 0) + Force use of jacksensing on some AD198x mixers. + +FILES +CONFIGFILEPATH/oss_ich.conf Device configuration file. + + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_imux/.config b/kernel/drv/oss_imux/.config new file mode 100644 index 0000000..b7929da --- /dev/null +++ b/kernel/drv/oss_imux/.config @@ -0,0 +1,2 @@ +bus=VIRTUAL +cflags=-O diff --git a/kernel/drv/oss_imux/.devices b/kernel/drv/oss_imux/.devices new file mode 100644 index 0000000..be685da --- /dev/null +++ b/kernel/drv/oss_imux/.devices @@ -0,0 +1 @@ +oss_imux oss_imux OSS Input Multiplexer diff --git a/kernel/drv/oss_imux/.name b/kernel/drv/oss_imux/.name new file mode 100644 index 0000000..88f4996 --- /dev/null +++ b/kernel/drv/oss_imux/.name @@ -0,0 +1 @@ +OSS Input Multiplexer (IMUX) diff --git a/kernel/drv/oss_imux/.params b/kernel/drv/oss_imux/.params new file mode 100644 index 0000000..c52896c --- /dev/null +++ b/kernel/drv/oss_imux/.params @@ -0,0 +1,24 @@ +/* + * IMUX supports multiple instances, please consult the man page + */ + +int imux_devices=5; +/* + * Number of IMUX client side devices to configure. + * Values: 2-48 Default: 5. + */ + +int imux_masterdev=-1; +/* + * Master physical device to use (ie attach IMUX to a specific soundcard) + * -1 means automatically detect the device. Use the device index numbers + * reported by ossinfo -a. + * Values: 0-N Default: -1 (autodetec) + */ + +int imux_rate=48000; +/* + * Select the base sampling rate for the IMUX device. The base rate must be + * one supported by the actual physical device (as reported by audioinfo -a -v2). + * Values: 8000-192000 Default: 48000 + */ diff --git a/kernel/drv/oss_imux/oss_imux.c b/kernel/drv/oss_imux/oss_imux.c new file mode 100644 index 0000000..e712436 --- /dev/null +++ b/kernel/drv/oss_imux/oss_imux.c @@ -0,0 +1,1072 @@ +/* + * Purpose: Pseudo driver for sharing one input device between multiple apps. + */ +/* + * + * 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 MAX_IMUX_INSTANCES 16 +#define MAX_IMUX_DEV 48 +#define SUPPORTED_FORMATS (AFMT_S16_NE|AFMT_S16_OE) + +#include "oss_imux_cfg.h" + +static unsigned long long used_masterdevs = 0LL; + +typedef struct +{ + int audio_dev; + int port_number; + int is_opened, is_prepared, is_triggered; + int speed, channels, fmt; + int ch_index; + int left_igain, right_igain; + oss_peaks_t peaks; +} +imux_portc; + +typedef struct +{ + oss_device_t *osdev; + oss_device_t *master_osdev; + oss_mutex_t mutex; + int installed_ok; + int hw_dev; + int hw_speed, hw_channels, hw_fmt, sw_fmt; + int hw_fragsize; + + int device_started; + struct fileinfo finfo; + + int nr_devices, open_count; + imux_portc portc[MAX_IMUX_DEV]; + int fragsize; + int prev_fragment; + +/* + * Mixer + */ + int mixer_dev; + int autoreset; /* Autoreset igain sliders to 100 during open */ + +/* + * Startup info + */ + int imux_devices; + int imux_rate; + int imux_masterdev; + int instance_no; +} +imux_devc; + +static imux_devc imux_info[MAX_IMUX_INSTANCES] = { {0} }; +static int nimuxdevs = 0; + +/*ARGSUSED*/ +static int +imux_set_rate (int dev, int arg) +{ + imux_devc *devc = audio_engines[dev]->devc; + return devc->hw_speed; +} + +/*ARGSUSED*/ +static short +imux_set_channels (int dev, short arg) +{ + imux_portc *portc = audio_engines[dev]->portc; + return portc->channels = 2; +} + +/*ARGSUSED*/ +static unsigned int +imux_set_format (int dev, unsigned int arg) +{ + imux_devc *devc = audio_engines[dev]->devc; + + return devc->sw_fmt; +} + + +static int +imux_igain (int dev, int ctrl, unsigned int cmd, int value) +{ +/* + * Access function for IMUX input gain + */ + int left, right; + imux_devc *devc = mixer_devs[dev]->devc; + imux_portc *portc; + + if (ctrl != 100 && (ctrl < 0 || ctrl >= devc->imux_devices)) + return OSS_EINVAL; + + portc = &devc->portc[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + { + if (ctrl == 100) + return devc->autoreset; + return (portc->left_igain & 0x00ff) | + ((portc->right_igain & 0x00ff) << 8); + } + + if (cmd == SNDCTL_MIX_WRITE) + { + if (ctrl == 100) + return devc->autoreset = !!value; + + left = value & 0x00ff; + right = (value >> 8) & 0x00ff; + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + + portc->left_igain = left; + portc->right_igain = right; + return left | (right << 8); + } + + return OSS_EINVAL; +} + +static int +imux_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + imux_devc *devc = audio_engines[dev]->devc; + imux_portc *portc = audio_engines[dev]->portc; + int value, i, n, p; + + switch (cmd) + { + case SNDCTL_DSP_SET_RECSRC: + { + value = *arg; + if (value <= 0 || value >= devc->hw_channels - 1) + return OSS_EINVAL; + portc->ch_index = value; + } + + case SNDCTL_DSP_GET_RECSRC: + return *arg = portc->ch_index; + break; + + case SNDCTL_DSP_GET_RECSRC_NAMES: + { + oss_mixer_enuminfo *ei = (oss_mixer_enuminfo *) arg; + + memset (ei, 0, sizeof (*ei)); + + n = ei->nvalues = devc->hw_channels - 1; + p = 0; + + if (n <= 1) /* Only one alternative */ + { + ei->nvalues = 1; + ei->strindex[0] = 0; + sprintf (ei->strings, "default"); + + } + else + /* Multiple alternatives */ + for (i = 0; i < n; i++) + { + ei->strindex[i] = p; + + sprintf (&ei->strings[p], "CH%d/%d", i + 1, i + 2); + + p += strlen (&ei->strings[p]) + 1; + } + + return 0; + } + break; + + case SNDCTL_DSP_SETRECVOL: + value = *arg; + return *arg = imux_igain (audio_engines[dev]->mixer_dev, + portc->ch_index, SNDCTL_MIX_WRITE, value); + break; + + case SNDCTL_DSP_GETRECVOL: + return *arg = imux_igain (audio_engines[dev]->mixer_dev, + portc->ch_index, SNDCTL_MIX_READ, 0); + break; + + case SNDCTL_DSP_GETIPEAKS: + memset (arg, 0, sizeof (oss_peaks_t)); + memcpy (arg, portc->peaks, sizeof (portc->peaks)); + memset (portc->peaks, 0, sizeof (portc->peaks)); + return 0; + break; + } + return OSS_EINVAL; +} + +static void imux_trigger (int dev, int state); + +static void +imux_reset (int dev) +{ + imux_trigger (dev, 0); +} + +/*ARGSUSED*/ +static void +bufcpy16ne (imux_devc * devc, imux_portc * portc, unsigned char *tbuf, + unsigned char *buf, int nbytes, int frame_size, int hw_framesize) +{ + int ns, i, hw_channels; + short *p1, *p2; + + ns = nbytes / frame_size; + + hw_channels = hw_framesize / sizeof (*p2); + + p1 = (short *) tbuf; + p2 = (short *) (buf + portc->ch_index * frame_size / 2); + + for (i = 0; i < ns; i++) + { + int v; + + /* Left channel */ + v = *p2++; + v = v * portc->left_igain / 100; + *p1++ = v; + if (v < 0) + v = -v; + if (v > portc->peaks[0]) + portc->peaks[0] = v; + + /* Right channel */ + v = *p2++; + v = v * portc->right_igain / 100; + *p1++ = v; + if (v < 0) + v = -v; + if (v > portc->peaks[1]) + portc->peaks[1] = v; + + if (hw_channels > 2) + p2 += hw_channels - 2; + } +} + +/*ARGSUSED*/ +static void +bufcpy16oe (imux_devc * devc, imux_portc * portc, unsigned char *tbuf, + unsigned char *buf, int nbytes, int frame_size, int hw_framesize) +{ + int ns, i, hw_channels; + short *p1, *p2; + + ns = nbytes / frame_size; + + hw_channels = hw_framesize / sizeof (*p2); + + p1 = (short *) tbuf; + p2 = (short *) (buf + portc->ch_index * frame_size / 2); + + for (i = 0; i < ns; i++) + { + int v; + + /* Left channel */ + v = *p2++; + v = ((v >> 8) & 0xff) | ((v & 0xff) << 8); + v = v * portc->left_igain / 100; + *p1++ = v; + if (v < 0) + v = -v; + if (v > portc->peaks[0]) + portc->peaks[0] = v; + + /* Right channel */ + v = *p2++; + v = ((v >> 8) & 0xff) | ((v & 0xff) << 8); + v = v * portc->right_igain / 100; + *p1++ = v; + if (v < 0) + v = -v; + if (v > portc->peaks[1]) + portc->peaks[1] = v; + + if (hw_channels > 2) + p2 += hw_channels - 2; + } +} + +/*ARGSUSED*/ +static void +imux_callback (int dev, int parm) +{ + dmap_t *dmap; + unsigned char *buf, *tbuf; + int i, len, frag, tail, next, n; + imux_devc *devc = NULL; + + for (i = 0; i < nimuxdevs && devc == NULL; i++) + { + if (imux_info[i].hw_dev == dev) + devc = &imux_info[i]; + } + + if (devc == NULL) + { + cmn_err (CE_WARN, "IMUX error\n"); + return; + } + + dmap = audio_engines[dev]->dmap_in; + + frag = dmap_get_qhead (dmap); + tail = dmap_get_qtail (dmap); + next = (frag + 1) % dmap->nfrags; + + n = 0; + while (n++ < 2 && frag != tail && next != tail + && devc->prev_fragment != frag) + { + devc->prev_fragment = frag; + buf = &dmap->dmabuf[frag * dmap->fragment_size]; + len = dmap->fragment_size; + + dmap->user_counter += dmap->fragment_size; + + for (i = 0; i < devc->nr_devices; i++) + { + dmap_t *client_dmap; + + imux_portc *portc = &devc->portc[i]; + client_dmap = audio_engines[portc->audio_dev]->dmap_in; + + if (!portc->is_opened || !portc->is_triggered) + continue; + + if (client_dmap->fragment_size != (2 * len) / devc->hw_channels) + { + DDB (cmn_err (CE_WARN, "Fragment warning (%d, %d, %d-%d)\n", + client_dmap->fragment_size, len, + audio_engines[portc->audio_dev]->min_block, + audio_engines[portc->audio_dev]->max_block)); +#if 1 + /* Make automatic adjustments */ + client_dmap->fragment_size = (2 * len) / devc->hw_channels; + client_dmap->nfrags = + client_dmap->buffsize / client_dmap->fragment_size; + client_dmap->bytes_in_use = + client_dmap->nfrags * client_dmap->fragment_size; +#else + continue; +#endif + } + + tbuf = + &client_dmap->dmabuf[dmap_get_qtail (client_dmap) * + client_dmap->fragment_size]; + + if (devc->hw_fmt == AFMT_S16_NE) /* Native 16 bits */ + { + bufcpy16ne (devc, portc, tbuf, buf, + client_dmap->fragment_size, + client_dmap->frame_size, dmap->frame_size); + } + else if (devc->hw_fmt == AFMT_S16_OE) /* Native 16 bits */ + { + bufcpy16oe (devc, portc, tbuf, buf, + client_dmap->fragment_size, + client_dmap->frame_size, dmap->frame_size); + } + else + memcpy (tbuf, buf, len); +#ifdef DO_TIMINGS + oss_timing_printf ("Imux: copy f=%d/%d to ch=%d t=%d/%d", frag, tail, + i, dmap_get_qtail (client_dmap), + dmap_get_qhead (client_dmap)); +#endif + oss_audio_inputintr (portc->audio_dev, 0); + + } + frag = dmap_get_qhead (dmap); + tail = dmap_get_qtail (dmap); + next = (frag + 1) % dmap->nfrags; + } + + +} + +static int +start_device (imux_devc * devc) +{ + int i, err, dev, trig, nc; + /* int frags = 0x7fff0008; fragment size of 256 bytes */ + + if (devc->hw_dev < 0 || devc->hw_dev >= num_audio_engines) + { + devc->hw_dev = 0; + } + + if (devc->hw_dev < 0 || devc->hw_dev >= num_audio_engines) + { + cmn_err (CE_WARN, "No audio hardware available\n"); + return OSS_ENXIO; + } + + if (devc->device_started) + { + return 1; + } + + devc->finfo.mode = OPEN_READ; + devc->finfo.acc_flags = 0; + devc->prev_fragment = -1; + + DDB (cmn_err (CE_NOTE, + "Instance %d: Will use audio device %d as the master\n", + devc->instance_no, devc->hw_dev)); + + if (devc->hw_dev >= devc->portc[0].audio_dev + && devc->hw_dev <= devc->portc[devc->imux_devices - 1].audio_dev) + { + cmn_err (CE_WARN, "Bad master device %d\n", devc->hw_dev); + return OSS_ENXIO; + } + + if (!(audio_engines[devc->hw_dev]->iformat_mask & SUPPORTED_FORMATS)) + { + cmn_err (CE_CONT, + "Audio device %d doesn't support compatible sample formats.\n", + devc->hw_dev); + return OSS_EIO; + } + if ((err = + oss_audio_open_engine (devc->hw_dev, OSS_DEV_DSP, &devc->finfo, 1, 0, + NULL)) < 0) + { + return err; + } + audio_engines[devc->hw_dev]->cooked_enable = 0; + strcpy (audio_engines[devc->hw_dev]->cmd, "IMUX"); + audio_engines[devc->hw_dev]->pid = 0; + + devc->hw_fmt = + oss_audio_set_format (devc->hw_dev, devc->hw_fmt, + audio_engines[devc->hw_dev]->iformat_mask); + devc->device_started = 1; + devc->hw_channels = 2; + + devc->hw_channels = + oss_audio_set_channels (devc->hw_dev, devc->hw_channels); + +/* + * TODO: Turn off OPT_SHADOW flag from the virtual devices if the master device + * works in multi channel mode. + */ + devc->hw_speed = oss_audio_set_rate (devc->hw_dev, devc->hw_speed); + +#if 0 + oss_audio_ioctl (devc->hw_dev, NULL, SNDCTL_DSP_SETFRAGMENT, + (ioctl_arg) & frags); +#endif + oss_audio_ioctl (devc->hw_dev, NULL, SNDCTL_DSP_GETBLKSIZE, + (ioctl_arg) & devc->fragsize); + + if (!(devc->hw_fmt & SUPPORTED_FORMATS)) + { + oss_audio_release (devc->hw_dev, &devc->finfo); + cmn_err (CE_WARN, + "This device doesn't support any known sample formats (%x)\n", + devc->hw_fmt); + return OSS_EIO; + } + + switch (devc->hw_fmt) + { + case AFMT_S16_NE: + devc->sw_fmt = AFMT_S16_NE; + break; + + case AFMT_S16_OE: + devc->sw_fmt = AFMT_S16_NE; + break; + + default: + cmn_err (CE_WARN, "Bad sample format %x\n", devc->hw_fmt); + } + + nc = devc->hw_channels; + if (nc < 2) + { + oss_audio_release (devc->hw_dev, &devc->finfo); + cmn_err (CE_WARN, "A 2 channel soundcard (or better) is required\n"); + return OSS_EIO; + } + + DDB (cmn_err (CE_CONT, "Started audio device %d, s=%d, c=%d, bits=%d\n", + devc->hw_dev, devc->hw_speed, devc->hw_channels, + devc->hw_fmt)); + + trig = 0; + oss_audio_ioctl (devc->hw_dev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & trig); + trig = PCM_ENABLE_INPUT; + oss_audio_ioctl (devc->hw_dev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & trig); + + devc->hw_fragsize = audio_engines[devc->hw_dev]->dmap_out->fragment_size; + + for (i = 0; i < devc->nr_devices; i++) + { + int bz = (2 * devc->hw_fragsize) / devc->hw_channels; + dev = devc->portc[i].audio_dev; + audio_engines[dev]->fixed_rate = devc->hw_speed; + audio_engines[dev]->min_block = bz; + audio_engines[dev]->max_block = bz; + } + audio_engines[devc->hw_dev]->dmap_in->audio_callback = imux_callback; + + return 1; +} + +static void +stop_device (imux_devc * devc) +{ + if (!devc->device_started) + return; + + oss_audio_ioctl (devc->hw_dev, NULL, SNDCTL_DSP_HALT, 0); + oss_audio_release (devc->hw_dev, &devc->finfo); + audio_engines[devc->hw_dev]->pid = -1; + memset (audio_engines[devc->hw_dev]->cmd, 0, + sizeof (audio_engines[devc->hw_dev]->cmd)); + audio_engines[devc->hw_dev]->flags &= ~ADEV_NOSRC; + + devc->device_started = 0; +} + +/*ARGSUSED*/ +static int +imux_open (int dev, int mode, int open_flags) +{ + imux_portc *portc = audio_engines[dev]->portc; + imux_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + int bz, err; + + if (devc->hw_dev < 0) + { + cmn_err (CE_NOTE, "No master device allocated\n"); + return OSS_EIO; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->is_opened) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->is_opened = 1; + portc->is_prepared = 0; + portc->is_triggered = 0; + portc->channels = 2; + portc->ch_index = 0; + memset (portc->peaks, 0, sizeof (portc->peaks)); + portc->fmt = AFMT_S16_NE; + audio_engines[dev]->rate_source = audio_engines[devc->hw_dev]->rate_source; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + if (!devc->device_started) + if ((err = start_device (devc)) < 0) + { + portc->is_opened = 0; + return err; + } + + bz = (2 * devc->hw_fragsize) / devc->hw_channels; + audio_engines[dev]->min_block = audio_engines[dev]->max_block = bz; + portc->ch_index = portc->port_number % (devc->hw_channels / 2); + portc->speed = devc->hw_speed; + + if (devc->autoreset) + { + portc->left_igain = 100; + portc->right_igain = 100; + mixer_devs[devc->mixer_dev]->modify_counter++; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_count++; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static void +imux_close (int dev, int mode) +{ + imux_portc *portc = audio_engines[dev]->portc; + imux_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + int count; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->is_triggered = 0; + count = --devc->open_count; + /* MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); */ + + if (count == 0) /* Last one? */ + stop_device (devc); + + /* MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); */ + portc->is_opened = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +imux_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +imux_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +static void +imux_trigger (int dev, int state) +{ + imux_portc *portc = audio_engines[dev]->portc; + + if (state & PCM_ENABLE_INPUT) + portc->is_triggered = 1; + else + portc->is_triggered = 0; +} + +/*ARGSUSED*/ +static int +imux_prepare_for_input (int dev, int bsize, int bcount) +{ + return 0; +} + +/*ARGSUSED*/ +static int +imux_prepare_for_output (int dev, int bsize, int bcount) +{ + return OSS_EIO; +} + +/*ARGSUSED*/ +static int +imux_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ +#define MY_BUFFSIZE (64*1024) + if (dmap->dmabuf != NULL) + return 0; + dmap->dmabuf_phys = 0; /* Not mmap() capable */ + dmap->dmabuf = KERNEL_MALLOC (MY_BUFFSIZE); + if (dmap->dmabuf == NULL) + return OSS_ENOSPC; + dmap->buffsize = MY_BUFFSIZE; + + return 0; +} + +/*ARGSUSED*/ +static int +imux_free_buffer (int dev, dmap_t * dmap, int direction) +{ + if (dmap->dmabuf == NULL) + return 0; + KERNEL_FREE (dmap->dmabuf); + + dmap->dmabuf = NULL; + return 0; +} + +#if 0 +static int +imux_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ +} +#endif + +static audiodrv_t imux_driver = { + imux_open, + imux_close, + imux_output_block, + imux_start_input, + imux_ioctl, + imux_prepare_for_input, + imux_prepare_for_output, + imux_reset, + NULL, + NULL, + NULL, + NULL, + imux_trigger, + imux_set_rate, + imux_set_format, + imux_set_channels, + NULL, + NULL, + NULL, + NULL, + imux_alloc_buffer, + imux_free_buffer, + NULL, + NULL, + NULL /* imux_get_buffer_pointer */ +}; + +/*ARGSUSED*/ +static int +imux_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static mixer_driver_t imux_mixer_driver = { + imux_mixer_ioctl +}; + +static const unsigned char peak_cnv[256] = { + 0, 18, 29, 36, 42, 47, 51, 54, 57, 60, 62, 65, 67, 69, 71, 72, + 74, 75, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, + 91, 92, 93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, + 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, + 108, + 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, + 114, + 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, + 119, + 119, 119, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, + 123, + 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, + 126, + 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, + 130, + 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, + 132, + 132, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 135, + 135, + 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, + 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, + 141, + 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, + 143, + 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, +}; + +/*ARGSUSED*/ +static int +imux_vu (int dev, int ctrl, unsigned int cmd, int value) +{ +/* + * Access function for PCM VU meters + */ + int left, right; + imux_devc *devc = mixer_devs[dev]->devc; + + if (ctrl < 0 || ctrl >= devc->imux_devices) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + imux_portc *portc = &devc->portc[ctrl]; + left = peak_cnv[(portc->peaks[0] * 144) / 32768]; + right = peak_cnv[(portc->peaks[1] * 144) / 32768]; + memset (portc->peaks, 0, sizeof (portc->peaks)); + return left | (right << 8); + } + + return OSS_EINVAL; +} + +static int +imux_mix_init (int dev) +{ + int group; + imux_devc *devc = mixer_devs[dev]->devc; + int i; + int err; + + if ((group = mixer_ext_create_group (dev, 0, "CLIENT")) < 0) + return group; + + for (i = 0; i < devc->imux_devices; i++) + { + char tmp[32]; + + sprintf (tmp, "@pcm%d", devc->portc[i].audio_dev); + + if ((err = mixer_ext_create_control (dev, group, i, imux_igain, + MIXT_STEREOSLIDER, + tmp, 100, + MIXF_READABLE | MIXF_WRITEABLE)) < + 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, i, imux_vu, + MIXT_STEREOPEAK, + "-", 144, MIXF_READABLE)) < 0) + return err; + } + + if ((err = mixer_ext_create_control (dev, group, 100, imux_igain, + MIXT_ONOFF, + "autoreset", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + return 0; +} + +static int +find_master_device (imux_devc * devc) +{ +/* + * Find a suitable master device. + * + * Return 1 if found and 0 if not. + */ + int dev; + adev_p adev; + + if (num_audio_devfiles < 1) + return 0; + + if (devc->imux_masterdev >= 0) + { +/* + * imux_masterdev property was given. Use the given /dev/dsp# number + * as the master device. + */ + if (devc->imux_masterdev >= num_audio_devfiles) + return 0; /* Device not attached yet */ + devc->hw_dev = audio_devfiles[devc->imux_masterdev]->engine_num; + adev = audio_engines[devc->hw_dev]; + + if (adev->flags & (ADEV_NOINPUT)) + { + cmn_err (CE_NOTE, + "Audio device %d cannot be used as an IMUX master device\n", + devc->imux_masterdev); + devc->hw_dev = -1; + return 0; + } + + devc->hw_dev = adev->engine_num; + /* TODO: Prevent the other virtual drivers from picking this one */ + } + else + { +/* + * Try to find if some of the devices currently available is suitable + * master device. + */ + devc->hw_dev = -1; + + for (dev = 0; dev < num_audio_engines; dev++) + { + adev = audio_engines[dev]; + + if (adev->flags & ADEV_NOINPUT) + continue; + + if (used_masterdevs & (1LL << dev)) + continue; + + devc->hw_dev = adev->engine_num; + break; + } + } + + return (devc->hw_dev >= 0); +} + +static int +try_to_start (void *dc) +{ + int n, adev, opts; + char tmp[32]; + imux_devc *devc = dc; + int my_mixer; + + if (!find_master_device (devc)) + return 0; + +/* + * If the situation is hopeless then just tell the caller to stop + * trying this operation. + */ + if (devc->hw_dev < 0) + return 1; + + if (used_masterdevs & (1LL << devc->hw_dev)) + { + devc->hw_dev = -1; + cmn_err (CE_WARN, + "Selected master device % for IMUX instance %d already used for some other instance\n", + devc->osdev->instance, devc->hw_dev); + return 1; + } + + used_masterdevs |= (1LL << devc->hw_dev); + + opts = + ADEV_STEREOONLY | ADEV_16BITONLY | ADEV_VIRTUAL | ADEV_NOOUTPUT | + ADEV_FIXEDRATE | ADEV_NOMMAP; + + devc->nr_devices = 0; + devc->open_count = 0; + + devc->hw_speed = devc->imux_rate; + devc->master_osdev = audio_engines[devc->hw_dev]->osdev; + devc->installed_ok = 1; + devc->autoreset = 1; + MUTEX_INIT (devc->master_osdev, devc->mutex, MH_DRV + 4); + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->master_osdev, + "IMUX Control panel", + &imux_mixer_driver, + sizeof (mixer_driver_t), devc)) >= 0) + { + mixer_ext_set_init_fn (my_mixer, imux_mix_init, 32); + } + else + my_mixer = -1; + + devc->mixer_dev = my_mixer; + + for (n = 0; n < devc->imux_devices; n++) + { + imux_portc *portc; + + if (n > 0) + opts |= ADEV_SHADOW; + + sprintf (tmp, "IMux%d audio record", devc->instance_no); + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->master_osdev, + tmp, + &imux_driver, + sizeof (audiodrv_t), + opts, AFMT_S16_NE, devc, -1)) < 0) + { + return 1; + } + + portc = &devc->portc[n]; + + audio_engines[adev]->portc = portc; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = 192000; + portc->left_igain = 100; + portc->right_igain = 100; + + portc->audio_dev = adev; + portc->is_opened = 0; + portc->is_prepared = 0; + portc->is_triggered = 0; + portc->speed = 48000; + portc->channels = 2; + portc->fmt = AFMT_S16_NE; + portc->port_number = n; + + devc->nr_devices = n + 1; + } + + return 1; +} + + +int +oss_imux_attach (oss_device_t * osdev) +{ + extern int imux_devices; + extern int imux_masterdev; + extern int imux_rate; + imux_devc *devc; + + if (imux_devices < 2) + imux_devices = 2; + if (imux_devices > MAX_IMUX_DEV) + imux_devices = MAX_IMUX_DEV; + + if (nimuxdevs >= MAX_IMUX_INSTANCES) + { + cmn_err (CE_NOTE, "Only %d instances permitted\n", MAX_IMUX_INSTANCES); + return 0; + } + + devc = &imux_info[nimuxdevs++]; + + devc->osdev = osdev; + osdev->devc = devc; + + devc->master_osdev = NULL; + devc->instance_no = osdev->instance; + devc->imux_devices = imux_devices; + devc->imux_rate = imux_rate; + devc->imux_masterdev = imux_masterdev; + imux_masterdev = -1; + devc->hw_dev = -1; + devc->sw_fmt = AFMT_S16_NE; + + oss_register_device (osdev, "OSS IMUX driver"); + + if (!try_to_start (devc)) + { + oss_audio_register_client (try_to_start, devc, devc->osdev); + } + + return 1; +} + +int +oss_imux_detach (oss_device_t * osdev) +{ + imux_devc *devc = osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + if (devc->installed_ok) + { + MUTEX_CLEANUP (devc->mutex); + } + + oss_unregister_device (devc->osdev); + + return 1; +} diff --git a/kernel/drv/oss_imux/oss_imux.man b/kernel/drv/oss_imux/oss_imux.man new file mode 100644 index 0000000..4d64206 --- /dev/null +++ b/kernel/drv/oss_imux/oss_imux.man @@ -0,0 +1,78 @@ +NAME +oss_imux - Input Muplexer audio driver. + +DESCRIPTION +IMUX is a virtual recording engine that permits up to 8 audio recording +applications to run at the same time. Generally most soundcards permit only a +single recording application to record the input source (via mic, line or CD). +With IMUX, you can use up to 8 recording applications to record the same +source in different sample rates, bits/sample and channels (mono/stereo). +IMUX does all the rate and format conversion in software. The applications +think that they are actually getting data from the physical device. For +instance, if you want to record the input from a CDROM in .wav format at +48Khz/8/Mono and at the same time you want to record the same stream in .mp3 +format in 44.1Khz 16 bit stereo, with IMUX, you can start the wave recording +application on the first IMUX device and start the MP3 encoder on the second +IMUX device and both applications will run simultaneously thinking that they +are getting data from the physical soundcard. + +CONFIGURATION +To add the IMUX driver you first need to ensure that there is a physical +soundcard present and then you can run ossdetect -i to add it. You may want +to select a master device by setting imux_masterdev, but the autodetection +should provide a good default. After OSS restart, imux should be available. + +USAGE +Connect an input source to the soundcard's line-in jack. Using the Mixer app +like ossmix (or any OSS compliant mixer) set the recording source to Line-In +(eg ossmix line.rec ON) Now you can start recording the input in multiple +formats and at different sample rates. The simplest example is: + + ossrecord -s48000 -b16 -c2 -d/dev/oss/oss_imux0/pcmin0 test1.wav & + ossrecord -s8000 -b8 -d/dev/oss/oss_imux0/pcmin0 test2.wav & + +After a few minutes of recording you can stop them by placing the command in +forground mode (type fg %1 or fg %2) and press ^c to stop. + +You now have two wav format files. test1.wav is a 48KHz 16bit stereo file and +test2.wav is a 8Khz 8bit Mono file. + +You can now playback the files as follows: +o ossplay -v test1.wav and it should show you that the file is indeed +48Khz 16bit stereo. + +o ossplay -v test2.wav - you should see that this file is indeed a +8Khz 8bit mono file. + +What you have essentially accomplished is recording a single input stream into +two different formats at the same time. + +You can now extend this analogy to record the input in mp3 format and RealAudio +format simultaneously. + +The IMUX control panel can be displayed by typing ossxmix -d<imux mixer number> +(for e.g. in the above example, IMUX mixer is #2 so we type ossxmix -d2 + +There are record level control sliders for each input channel and it will show +activity when a recording program is active on a particular channel. + + +OPTIONS +o imux_masterdev: Selects which physical device to use as the Master device +for the IMUX driver. +Values: -1: automatically selected by OSS, 1-N: Audio device index of the +master device (as reported by ossinfo -a), Default: -1. + +o imux_rate: Specifies what is the base sampling rate used by the imux driver. +Values: 5000-96000 Default: 48000 + +o imux_devices: Specifies number of Input Multiplexer devices to setup. +Values: 2-48 Default: 5 + + +FILES +CONFIGFILEPATH/oss_imux.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_madi/.devices b/kernel/drv/oss_madi/.devices new file mode 100644 index 0000000..c282a96 --- /dev/null +++ b/kernel/drv/oss_madi/.devices @@ -0,0 +1 @@ +oss_madi pci10ee,3fc6 RME MADI (not supported yet) diff --git a/kernel/drv/oss_madi/.name b/kernel/drv/oss_madi/.name new file mode 100644 index 0000000..a776e0b --- /dev/null +++ b/kernel/drv/oss_madi/.name @@ -0,0 +1 @@ +RME MADI Digital Interface diff --git a/kernel/drv/oss_madi/.params b/kernel/drv/oss_madi/.params new file mode 100644 index 0000000..9a9907e --- /dev/null +++ b/kernel/drv/oss_madi/.params @@ -0,0 +1,12 @@ +int madi_maxchannels=64; +/* + * By default OSS will create device files for all 64 channels (32 stereo + * pairs). Number of channels can be decreased by changing this parameter. + */ +int madi_devsize=2; +/* + * This parameter tells how the device files should be created for MADI + * channels. By default (2) a device file will be created for each stereo + * channel pair. Value of 1 means that separate device file will be + * created for each channel. + */ diff --git a/kernel/drv/oss_madi/madi.h b/kernel/drv/oss_madi/madi.h new file mode 100644 index 0000000..3cdd172 --- /dev/null +++ b/kernel/drv/oss_madi/madi.h @@ -0,0 +1,246 @@ +/* + * Purpose: Internal definitions for RME MADI and AES32 audio interfaces + */ +/* + * + * 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. + * + */ + + +/* + * DMA buffer size (for one direction) + */ +#define MAX_CHANNELS 64 +#define CHBUF_SIZE (64*1024) // 64k / channel +#define CHBUF_PAGES (CHBUF_SIZE/4096) +#define DMABUF_SIZE (MAX_CHANNELS*CHBUF_SIZE) // 4 Mbytes (total) + + +/* + * Monitor mixer channel + */ +#define MONITOR_CH 64 // ??? + +/* + * Registers + */ +#define MADI_control 64 +#define MADI_interruptAck 96 +#define MADI_control2 256 +#define MADI_freq 256 /* AES32 only */ +#define MADI_midiOut0 352 +#define MADI_midiOut1 356 +#define MADI_eeprom 384 /* AES32 only */ +#define MADI_outputEnableStart 512 +#define MADI_inputEnableStart 768 +#define MADI_PlayPageTable 8192 +#define MADI_RecPageTable 12288 /* 12k */ +#define MADI_MATRIX_MIXER_SIZE 8192 +#define MADI_mixerStart 32768 + +#define MADI_status 0 +#define MADI_status2 192 +#define MADI_timecode 128 +#define MADI_midiIn0 360 +#define MADI_midiIn1 364 +#define MADI_midiStatusOut0 384 +#define MADI_midiStatusOut1 388 +#define MADI_midiStatusIn0 392 +#define MADI_midiStatusIn1 396 +#define MADI_peakrmsStart 4096 +#define MADI_inpeaks (1024*4) +#define MADI_playpeaks (MADI_inpeaks+64*4) +#define MADI_outpeaks (MADI_playpeaks+64*4) + +/* + * Control register bits + */ +#define MADI_Start (1<<0) +#define MADI_Latency0 (1<<1) +#define MADI_Latency1 (1<<2) +#define MADI_Latency2 (1<<3) +#define MADI_ClockModeMaster (1<<4) +#define MADI_AudioInterruptEnable (1<<5) + +#define MADI_Freq0 (1<<6) +#define MADI_Freq1 (1<<7) +#define MADI_DblSpeed (1<<8) +#define MADI_QuadSpeed (1U<<31) + +#define MADI_ProBit (1<<9) // AES32 + +#define MADI_TX_64ch_mode (1<<10) // MADI +#define MADI_Emphasis (1<<10) // AES32 + +#define MADI_AutoInput (1<<11) // MADI +#define MADI_DataBit (1<<11) // AES32 + +#define MADI_InputSrc0 (1<<14) // MADI +#define MADI_InputSrc1 (1<<15) +#define MADI_SyncSrc0 (1<<16) +#define MADI_SyncSrc1 (1<<17) // AES32 +#define MADI_SyncSrc2 (1<<13) // AES32 +#define MADI_SyncSrc3 (1<<25) // AES32 +#define MADI_SMUX (1<<18) // MADI +#define MADI_clr_tms (1<<19) + +#define MADI_taxi_reset (1<<20) // MADI +#define MADI_WCK48 (1<<20) // AES32 + +#define MADI_Midi0IntrEna (1<<22) +#define MADI_Midi1IntrEna (1<<23) + +#define MADI_LineOut (1<<24) + +#define MADI_DS_2Wire (1<<26) // AES32 +#define MADI_QS_2Wire (1<<27) // AES32 +#define MADI_QS_4Wire (1<<28) // AES32 + +#define MADI_wclk_sel (1<<30) + +/* + * Control2 register bits + */ +#define MADI_BIGENDIAN_MODE (1<<9) + +/* + * Helper macros for the command register + */ +#define MADI_FreqMask (MADI_Freq0|MADI_Freq1|\ + MADI_DblSpeed|MADI_QuadSpeed) + +#define MADI_LatencyMask (MADI_Latency0|MADI_Latency1|MADI_Latency2) + +#define MADI_InputMask (MADI_InputSrc0|MADI_InputSrc1) +#define MADI_InputOptical 0 +#define MADI_InputCoax (MADI_InputSrc0) +#define MADI_SyncRefMask (MADI_SyncSrc0|MADI_SyncSrc1|\ + MADI_SyncSrc2|MADI_SyncSrc3) +#define MADI_SyncRef_Word 0 +#define MADI_SyncRef_MADI (MADI_SyncSrc0) + +/* + * Status register bits + */ +#define MADI_audioIntPending (1<<0) +#define MADI_RX_64ch_mode (1<<1) +#define MADI_AB_int (1<<2) +#define MADI_LockStatus (1<<3) +#define MADI_BufferPosMask 0x000FFC0 +#define MADI_madiSync (1<<18) +#define MADI_DblSpeedStatus (1<<19) + +#define MADI_Freq0_status (1<<22) +#define MADI_Freq1_status (1<<23) +#define MADI_Freq2_status (1<<24) +#define MADI_Freq3_status (1<<25) + +#define MADI_BufferHalf (1<<26) + +#define MADI_midi0IRQStatus (1<<30) +#define MADI_midi1IRQStatus (1U<<31) + +#define UNITY_GAIN 32768 +#define MUTE_GAIN 0 + +typedef struct +{ + int open_mode; + unsigned int trigger_bits; + int direction; +#define DIR_IN PCM_ENABLE_INPUT +#define DIR_OUT PCM_ENABLE_OUTPUT + int channel; /* Index to the first channel */ + + int audio_dev; + + int max_channels; + int channels; /* Number of channels */ +} madi_portc_t; + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + char *name; + + int model; +#define MDL_MADI 0 +#define MDL_AES32 1 + + char *registers; + oss_native_word physaddr; + + unsigned int cmd, cmd2; // Cached control/control2 register values + + /* Sample rate, etc. */ + unsigned int rate, next_rate; + unsigned long long active_inputs, active_outputs; /* Bitmasks indexed by ch# */ + + /* Mixer */ + int mixer_dev; + + /* Shadow of the hw mixer gain registers */ + unsigned short mixer_values[MAX_CHANNELS][2 * MAX_CHANNELS]; + + /* Playback */ + unsigned char *playbuf; + oss_native_word playbuf_phys; + oss_dma_handle_t play_dma_handle; + int num_outputs; + madi_portc_t *out_portc[MAX_CHANNELS]; + unsigned long long busy_play_channels; + + /* Recording */ + unsigned char *recbuf; + oss_native_word recbuf_phys; + oss_dma_handle_t rec_dma_handle; + int num_inputs; + madi_portc_t *in_portc[MAX_CHANNELS]; + unsigned long long busy_rec_channels; + + volatile int open_audiodevs; /* Number of audio input/output devices currently open */ + int first_audiodev; +} madi_devc_t; + +static __inline__ void +madi_write (madi_devc_t * devc, int reg, unsigned int value) +{ + PCI_WRITEL (devc->osdev, devc->registers + reg, value); +} + +static __inline__ unsigned int +madi_read (madi_devc_t * devc, int reg) +{ + return PCI_READL (devc->osdev, devc->registers + reg); +} + +static __inline__ void +madi_control (madi_devc_t * devc, unsigned int value) +{ + madi_write (devc, MADI_control, value); + devc->cmd = value; +} + +static __inline__ void +madi_control2 (madi_devc_t * devc, unsigned int value) +{ + madi_write (devc, MADI_control2, value); + devc->cmd2 = value; +} + +#define SRC_IN 0 +#define SRC_PLAY 64 +extern void madi_write_gain (madi_devc_t * devc, unsigned int chn, + unsigned int src, unsigned short value); +extern int madi_read_gain (madi_devc_t * devc, unsigned int chn, + unsigned int src); +extern int madi_install_mixer (madi_devc_t * devc); +extern void madi_activate_mixer (madi_devc_t * devc); diff --git a/kernel/drv/oss_madi/madi_mixer.c b/kernel/drv/oss_madi/madi_mixer.c new file mode 100644 index 0000000..8882fa7 --- /dev/null +++ b/kernel/drv/oss_madi/madi_mixer.c @@ -0,0 +1,459 @@ +/* + * Purpose: Mixer/control panel for RME MADI and AES32 audio interfaces + */ +/* + * + * 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_madi_cfg.h" +#include "oss_pci.h" +#include "madi.h" + +extern int madi_maxchannels; + +static const unsigned char peak_cnv[256] = { + 0, 18, 29, 36, 42, 47, 51, 54, 57, 60, 62, 65, 67, 69, 71, 72, + 74, 75, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, + 91, 92, 93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, + 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, + 108, + 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, + 114, + 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, + 119, + 119, 119, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, + 123, + 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, + 126, + 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, + 130, + 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, + 132, + 132, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 135, + 135, + 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, + 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, + 141, + 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, + 143, + 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, +}; + +void +madi_write_gain (madi_devc_t * devc, unsigned int chn, unsigned int src, + unsigned short value) +{ +/* + * Write gain value to a mixer register. Parameter chn selects the output + * channel. Parameter src is the signal source. If (src & SRC_PLAY) then set + * the audio (DMA) playback volume (pcm[src]->out[chn]). Otherwise set + * the input[src]->out[chn] volume + */ + + if (chn >= MAX_CHANNELS || src >= (SRC_PLAY + MAX_CHANNELS)) + return; + + madi_write (devc, MADI_mixerStart + (src + 128 * chn) * 4, value); + devc->mixer_values[chn][src] = value; +} + +int +madi_read_gain (madi_devc_t * devc, unsigned int chn, unsigned int src) +{ + if (chn >= MAX_CHANNELS || src >= (SRC_PLAY + MAX_CHANNELS)) + return 0; + + return devc->mixer_values[chn][src]; +} + +static int +madi_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ +#if 0 +/* + * Dummy mixer. Some broken applications require this. + */ + + if (cmd == SOUND_MIXER_READ_CAPS) + return *arg = SOUND_CAP_NOLEGACY; + + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC) + return *arg = 0; + + if (cmd == SOUND_MIXER_READ_VOLUME || cmd == SOUND_MIXER_READ_PCM) + return *arg = 100 | (100 << 8); + if (cmd == SOUND_MIXER_WRITE_VOLUME || cmd == SOUND_MIXER_WRITE_PCM) + return *arg = 100 | (100 << 8); +#endif + return OSS_EINVAL; +} + + /*ARGSUSED*/ static int +get_peak (int dev, int ctrl, unsigned int cmd, int value) +{ + madi_devc_t *devc = mixer_devs[dev]->devc; + unsigned int v; + + if (cmd != SNDCTL_MIX_READ) + return OSS_EINVAL; + + v = madi_read (devc, ctrl) >> 24; // Left channel + value = peak_cnv[v & 0xff]; + + v = madi_read (devc, ctrl + 4) >> 24; // Right channel + value |= peak_cnv[v & 0xff] << 8; + + return value; +} + + /*ARGSUSED*/ static int +vol_slider (int dev, int ctrl, unsigned int cmd, int value) +{ + madi_devc_t *devc = mixer_devs[dev]->devc; + unsigned int v; + int chn, src; + + chn = (ctrl >> 8) & 0xff; + src = ctrl & 0xff; + + if (chn >= MAX_CHANNELS || src >= 2 * MAX_CHANNELS) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + // Left channel + v = devc->mixer_values[chn][src]; + if (v > 0) + v--; + value = v & 0xffff; + + // Right channel + v = devc->mixer_values[chn + 1][src + 1]; + if (v > 0) + v--; + value |= (v & 0xffff) << 16; + + return value; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + // Left channel + v = value & 0xffff; + if (v > UNITY_GAIN) + v = UNITY_GAIN; + if (v > 0) + v++; + madi_write_gain (devc, chn, src, v); + + // Right channel + v = (value >> 16) & 0xffff; + if (v > UNITY_GAIN) + v = UNITY_GAIN; + if (v > 0) + v++; + madi_write_gain (devc, chn + 1, src + 1, v); + + return value; + } + + return OSS_EINVAL; +} + + /*ARGSUSED*/ static int +madi_set_ctl (int dev, int ctrl, unsigned int cmd, int value) +{ + madi_devc_t *devc = mixer_devs[dev]->devc; + unsigned int status; + + if (cmd == SNDCTL_MIX_READ) + switch (ctrl) + { + case 0: /* Buffer size */ + return (devc->cmd & MADI_LatencyMask) >> 1; + break; + + case 1: /* Sync locked status */ + status = madi_read (devc, MADI_status); + return !!(status & MADI_LockStatus); + break; + + case 2: /* Input source (Optical/Coax) */ + return !!(devc->cmd & MADI_InputSrc0); + break; + + case 3: /* Clock source */ + return !(devc->cmd & MADI_ClockModeMaster); + break; + + case 4: /* Preferred sync reference */ + return !!(devc->cmd & MADI_SyncRef_MADI); + break; + + case 5: /* Safe Mode (auto input) */ + return !!(devc->cmd & MADI_AutoInput); + break; + } + + if (cmd == SNDCTL_MIX_WRITE) + switch (ctrl) + { + case 0: /* Buffer size */ + if (devc->busy_play_channels || devc->busy_rec_channels) /* Device busy */ + return (devc->cmd & MADI_LatencyMask) >> 1; + + if (value < 0 || value > 7) + return OSS_EINVAL; + + devc->cmd &= ~MADI_LatencyMask; + devc->cmd |= value << 1; + madi_control (devc, devc->cmd); + return value; + break; + + case 2: /* Input source (Optical/Coax) */ + value = !!value; + if (value) + madi_control (devc, devc->cmd | MADI_InputSrc0); + else + madi_control (devc, devc->cmd & ~MADI_InputSrc0); + return value; + break; + + case 3: /* Clock source */ + value = !!value; + if (!value) + madi_control (devc, devc->cmd | MADI_ClockModeMaster); + else + madi_control (devc, devc->cmd & ~MADI_ClockModeMaster); + return value; + break; + + case 4: /* Preferred sync reference */ + value = !!value; + if (value) + madi_control (devc, devc->cmd | MADI_SyncRef_MADI); + else + madi_control (devc, devc->cmd & ~MADI_SyncRef_MADI); + return value; + break; + + case 5: /* Safe Mode (auto input) */ + if (value) + madi_control (devc, devc->cmd | MADI_AutoInput); + else + madi_control (devc, devc->cmd & ~MADI_AutoInput); + return value; + break; + } + + return OSS_EINVAL; +} + +static int +madi_mix_init (int dev) +{ + int i; + madi_devc_t *devc = mixer_devs[dev]->devc; + char tmp[16]; + int err, ctl; + int group = 0; + +/* + * Common controls + */ + + if ((ctl = mixer_ext_create_control (dev, 0, + 3, + madi_set_ctl, + MIXT_ENUM, "clock", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "master autosync", 0); + + if (devc->model == MDL_MADI) + { + if ((ctl = mixer_ext_create_control (dev, 0, + 4, + madi_set_ctl, + MIXT_ENUM, "syncref", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "WordClock MADI-in", 0); + } + + if (devc->model == MDL_MADI) + { + if ((ctl = mixer_ext_create_control (dev, 0, + 2, + madi_set_ctl, + MIXT_ENUM, "input", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "optical coax", 0); + } + + if (devc->model == MDL_MADI) + { + if ((ctl = mixer_ext_create_control (dev, 0, + 5, + madi_set_ctl, + MIXT_ONOFF, "safe-input", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + } + + if ((ctl = mixer_ext_create_control (dev, 0, + 0, + madi_set_ctl, + MIXT_ENUM, "buffer", 8, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return ctl; + mixer_ext_set_strings (dev, ctl, "64 128 256 512 1k 2k 4k 8k", 0); + + if ((ctl = mixer_ext_create_control (dev, 0, + 1, + madi_set_ctl, + MIXT_VALUE, "lock", 2, + MIXF_OKFAIL | MIXF_READABLE | + MIXF_POLL)) < 0) + return ctl; + + /* + * Input mixer + */ + + for (i = 0; i < madi_maxchannels; i += 2) + { + int offs = MADI_inpeaks + i * 4; + int ctl; + + if (!(i % 32)) + if ((group = mixer_ext_create_group (dev, 0, "in")) < 0) + return group; + + ctl = (i << 8) | (SRC_IN | i); + + sprintf (tmp, "%d-%d", i + 1, i + 2); + if ((err = + mixer_ext_create_control (dev, group, ctl, vol_slider, + MIXT_STEREOSLIDER16, tmp, UNITY_GAIN - 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = + mixer_ext_create_control (dev, group, offs, get_peak, + MIXT_STEREOPEAK, "-", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + } + + /* + * Playback (pcm) mixer + */ + for (i = 0; i < devc->num_outputs; i++) + { + int offs = MADI_playpeaks; + int ctl, ch; + madi_portc_t *portc = devc->out_portc[i]; + + ch = portc->channel; + offs += ch * 4; + + if (!(i % 16)) + if ((group = mixer_ext_create_group (dev, 0, "play")) < 0) + return group; + + ctl = (ch << 8) | (SRC_PLAY | ch); + + if ((err = + mixer_ext_create_control (dev, group, offs, get_peak, + MIXT_STEREOPEAK, "-", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + + sprintf (tmp, "@pcm%d", portc->audio_dev); + if ((err = + mixer_ext_create_control (dev, group, ctl, vol_slider, + MIXT_STEREOSLIDER16, tmp, UNITY_GAIN - 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + } + + /* + * Output mixer + */ + for (i = 0; i < madi_maxchannels; i += 2) + { + int offs = MADI_outpeaks + i * 4; + + if (!(i % 64)) + if ((group = mixer_ext_create_group (dev, 0, "out")) < 0) + return group; + + sprintf (tmp, "%d-%d", i + 1, i + 2); + if ((err = + mixer_ext_create_control (dev, group, offs, get_peak, + MIXT_STEREOPEAK, tmp, 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + } + +#if 0 + /* + * Analog monitor + */ + { + int offs = MADI_outpeaks + MONITOR_CH * 4; + + if ((err = + mixer_ext_create_control (dev, group, offs, get_peak, + MIXT_STEREOPEAK, "mon", 144, + MIXF_READABLE | MIXF_DECIBEL)) < 0) + return err; + } +#endif + + return 0; +} + +static mixer_driver_t madi_mixer_driver = { + madi_mixer_ioctl +}; + +int +madi_install_mixer (madi_devc_t * devc) +{ + int my_mixer; + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + devc->name, + &madi_mixer_driver, + sizeof (mixer_driver_t), devc)) < 0) + return my_mixer; + + mixer_devs[my_mixer]->priority = -1; /* Don't use as the default mixer */ + + return my_mixer; +} + +void +madi_activate_mixer (madi_devc_t * devc) +{ + mixer_ext_set_init_fn (devc->mixer_dev, madi_mix_init, madi_maxchannels*5 + 30); + touch_mixer (devc->mixer_dev); +} diff --git a/kernel/drv/oss_madi/oss_madi.c b/kernel/drv/oss_madi/oss_madi.c new file mode 100644 index 0000000..8f0f2fa --- /dev/null +++ b/kernel/drv/oss_madi/oss_madi.c @@ -0,0 +1,975 @@ +/* + * Purpose: Driver for RME MADI and AES32 audio interfaces + * + */ +/* + * + * 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_madi_cfg.h" +#include "oss_pci.h" +#include "madi.h" + +#define RME_VENDOR_ID 0x10ee /* Xilinx actually */ +#define RME_MADI 0x3fc6 + +#define HWINFO_SIZE 128 + +extern int madi_devsize; +extern int madi_maxchannels; + +#define LSWAP(x) x + +static void +set_output_enable (madi_devc_t * devc, unsigned int chn, int enabled) +{ + madi_write (devc, MADI_outputEnableStart + 4 * chn, enabled); +} + +static void +set_input_enable (madi_devc_t * devc, unsigned int chn, int enabled) +{ + madi_write (devc, MADI_inputEnableStart + 4 * chn, enabled); +} + +static void +start_audio (madi_devc_t * devc) +{ + madi_control (devc, devc->cmd | (MADI_AudioInterruptEnable | MADI_Start)); +} + +static void +stop_audio (madi_devc_t * devc) +{ + madi_control (devc, devc->cmd & ~(MADI_AudioInterruptEnable | MADI_Start)); +} + +static void +audio_interrupt (madi_devc_t * devc, unsigned int status) +{ + int i; + + for (i = 0; i < devc->num_outputs; i++) + { + madi_portc_t *portc = devc->out_portc[i]; + + if (!(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + continue; + + oss_audio_outputintr (portc->audio_dev, 1); + } + + for (i = 0; i < devc->num_inputs; i++) + { + madi_portc_t *portc = devc->in_portc[i]; + + if (!(portc->trigger_bits & PCM_ENABLE_INPUT)) + continue; + + oss_audio_inputintr (portc->audio_dev, 1); + } +} + +static int +madiintr (oss_device_t * osdev) +{ + madi_devc_t *devc = osdev->devc; + unsigned int status; + + status = madi_read (devc, MADI_status); + + if (status & MADI_audioIntPending) + audio_interrupt (devc, status); + + madi_write (devc, MADI_interruptAck, 0); + + return !!(status & + (MADI_audioIntPending | MADI_midi0IRQStatus | MADI_midi1IRQStatus)) + != 0; +} + +static void +madi_change_hw_rate (madi_devc_t * devc) +{ + unsigned int rate_bits = 0; + unsigned long long v; + + devc->rate = devc->next_rate; + /* + * Compute and set the sample rate in control2 register. + */ + + rate_bits = MADI_Freq1; // TODO + + devc->cmd &= ~MADI_FreqMask; + devc->cmd |= rate_bits; + + madi_control (devc, devc->cmd); + + /* + * Compute and set the DDS value + */ + v = 110100480000000ULL / (unsigned long long) devc->rate; + madi_write (devc, MADI_freq, (unsigned int) v); +} + +static void +initialize_hardware (madi_devc_t * devc) +{ + int chn, src; + +/* + * Intialize the control register + */ + devc->cmd = MADI_ClockModeMaster | MADI_LatencyMask | MADI_LineOut; + + if (devc->model == MDL_AES32) + devc->cmd |= MADI_SyncSrc0 | MADI_ProBit; + else + devc->cmd |= + MADI_InputCoax | MADI_SyncRef_MADI | MADI_TX_64ch_mode | MADI_AutoInput; + + madi_control (devc, devc->cmd); + +/* + * Set all input and output engines to stoped + */ + for (chn = 0; chn < MAX_CHANNELS; chn++) + { + set_output_enable (devc, chn, 0); + set_input_enable (devc, chn, 0); + } + +/* + * Init control2 register + */ + if (devc->model == MDL_MADI) +#ifdef OSS_BIG_ENDIAN + madi_control2 (devc, MADI_BIGENDIAN_MODE); +#else + madi_control2 (devc, 0x0); +#endif + + madi_change_hw_rate (devc); + +/* + * Write all HW mixer registers + */ + + for (chn = 0; chn < MAX_CHANNELS; chn++) + for (src = 0; src < 2 * MAX_CHANNELS; src++) + madi_write_gain (devc, chn, src, devc->mixer_values[chn][src]); +} + +static int +madi_set_rate (int dev, int arg) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + + return devc->rate; +} + +static __inline__ void +reserve_rec_channels(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + devc->busy_rec_channels |= (1ULL << ch); +} + +static __inline__ void +free_rec_channels(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + devc->busy_rec_channels &= ~(1ULL << ch); +} + +static __inline__ int +rec_channels_avail(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + if (devc->busy_rec_channels & (1ULL << ch)) + return 0; + + return 1; +} + +static __inline__ void +reserve_play_channels(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + devc->busy_play_channels |= (1ULL << ch); +} + +static __inline__ void +free_play_channels(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + devc->busy_play_channels &= ~(1ULL << ch); +} + +static __inline__ int +play_channels_avail(madi_devc_t *devc, int c, int nc) +{ + int ch; + + for (ch=c;ch < c+nc;ch++) + if (devc->busy_play_channels & (1ULL << ch)) + { + return 0; + } + + return 1; +} + +static short +madi_set_channels (int dev, short arg) +{ + madi_portc_t *portc = audio_engines[dev]->portc; + madi_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + int ok=1; + + if (arg < 1) + return portc->channels; + + if (arg != 1 && arg != 2 && arg != 4 && arg != 8 && arg != 16 && arg != 32 + && arg != 64) + return portc->channels; + + if (arg > portc->max_channels) + return portc->channels; + + if (arg == portc->channels) + return portc->channels; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (arg > portc->channels) /* Needs more channels */ + { + if (portc->direction == DIR_OUT) + { + if (!play_channels_avail(devc, portc->channel+portc->channels, arg - portc->channels)) + ok=0; + } + else + { + if (!rec_channels_avail(devc, portc->channel+portc->channels, arg - portc->channels)) + ok=0; + } + } + else + { + if (portc->direction == DIR_OUT) + { + free_play_channels(devc, portc->channel+arg, portc->channels-arg); + } + else + { + free_rec_channels(devc, portc->channel+arg, portc->channels-arg); + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (!ok) + return portc->channels; + + return portc->channels = arg; +} + + /*ARGSUSED*/ static unsigned int +madi_set_format (int dev, unsigned int arg) +{ + return AFMT_S32_LE; +} + +static int +madi_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void +madi_trigger (int dev, int state) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + int ch; + + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode & OPEN_WRITE) + { + if ((state & PCM_ENABLE_OUTPUT) + && !(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + for (ch = 0; ch < portc->channels; ch++) + set_output_enable (devc, portc->channel + ch, 1); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + devc->active_outputs |= (1ULL << portc->channel); + } + else if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + { + for (ch = 0; ch < portc->channels; ch++) + set_output_enable (devc, portc->channel + ch, 0); + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + devc->active_outputs &= ~(1ULL << portc->channel); + } + } + + if ((portc->open_mode & OPEN_READ) + && !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + for (ch = 0; ch < portc->channels; ch++) + set_input_enable (devc, portc->channel + ch, 1); + portc->trigger_bits |= PCM_ENABLE_INPUT; + devc->active_inputs |= (1ULL << portc->channel); + } + else if (portc->trigger_bits & PCM_ENABLE_INPUT) + { + for (ch = 0; ch < portc->channels; ch++) + set_input_enable (devc, portc->channel + ch, 0); + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + devc->active_inputs &= ~(1ULL << portc->channel); + } + } + + if (devc->active_inputs || devc->active_outputs) + start_audio (devc); + else + stop_audio (devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +madi_sync_control (int dev, int event, int mode) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + oss_native_word flags; + int ch; + + if (event == SYNC_PREPARE) + { + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if ((mode & PCM_ENABLE_OUTPUT) && portc->direction == DIR_OUT) + { + for (ch = 0; ch < portc->channels; ch++) + set_output_enable (devc, portc->channel + ch, 1); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + devc->active_outputs |= (1ULL << portc->channel); + } + + if ((mode & PCM_ENABLE_INPUT) && portc->direction == DIR_IN) + { + for (ch = 0; ch < portc->channels; ch++) + set_input_enable (devc, portc->channel + ch, 1); + portc->trigger_bits |= PCM_ENABLE_INPUT; + devc->active_inputs |= (1ULL << portc->channel); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + if (event == SYNC_TRIGGER) + { + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (devc->active_inputs || devc->active_outputs) + start_audio (devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; + } + + return OSS_EIO; +} + +static void +madi_halt (int dev) +{ + madi_trigger (dev, 0); +} + + /*ARGSUSED*/ static int +madi_open (int dev, int mode, int open_flags) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + oss_native_word flags; + int ok=1; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode != 0) + ok=0; + else + if (portc->direction == DIR_OUT) + { + if (!play_channels_avail(devc, portc->channel, 2)) + { + ok=0; + } + } + else + { + if (!rec_channels_avail(devc, portc->channel, 2)) + { + ok=0; + } + } + + if (!ok) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + devc->open_audiodevs++; + + portc->channels = 2; + if (portc->direction == DIR_OUT) + reserve_play_channels(devc, portc->channel, 2); + else + reserve_rec_channels(devc, portc->channel, 2); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + + /*ARGSUSED*/ static void +madi_close (int dev, int mode) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + devc->open_audiodevs--; + if (portc->direction == DIR_OUT) + { + free_play_channels(devc, portc->channel, portc->channels); + } + else + { + free_rec_channels(devc, portc->channel, portc->channels); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + /*ARGSUSED*/ static void +madi_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ +} + + /*ARGSUSED*/ static void +madi_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + + /*ARGSUSED*/ static int +madi_prepare_for_input (int dev, int bsize, int bcount) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int i; + int offs = portc->channel * CHBUF_PAGES; + + for (i = 0; i < CHBUF_PAGES * portc->channels; i++) + madi_write (devc, MADI_RecPageTable + 4 * (offs + i), + LSWAP(dmap->dmabuf_phys + i * 4096)); + + return 0; +} + + /*ARGSUSED*/ static int +madi_prepare_for_output (int dev, int bsize, int bcount) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int i; + int offs = portc->channel * CHBUF_PAGES; + + for (i = 0; i < CHBUF_PAGES * portc->channels; i++) + madi_write (devc, MADI_PlayPageTable + 4 * (offs + i), + LSWAP(dmap->dmabuf_phys + i * 4096)); + return 0; +} + + /*ARGSUSED*/ static int +madi_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + + if (direction == OPEN_READ) + { + dmap->dmabuf = devc->recbuf + portc->channel * CHBUF_SIZE; + dmap->dmabuf_phys = devc->recbuf_phys + portc->channel * CHBUF_SIZE; + dmap->buffsize = CHBUF_SIZE; + } + else + { + dmap->dmabuf = devc->playbuf + portc->channel * CHBUF_SIZE; + dmap->dmabuf_phys = devc->playbuf_phys + portc->channel * CHBUF_SIZE; + dmap->buffsize = CHBUF_SIZE; + } + + return 0; +} + + /*ARGSUSED*/ static int +madi_free_buffer (int dev, dmap_t * dmap, int direction) +{ + dmap->dmabuf = NULL; + dmap->dmabuf_phys = 0; + dmap->buffsize = 0; + + return 0; +} + + /*ARGSUSED*/ static int +madi_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + unsigned int status; +#if 1 + /* + * Use only full/half buffer resolution. + */ + int bytes; + bytes = ((devc->cmd & MADI_LatencyMask) >> 1) + 8; + bytes = 1 << bytes; + bytes *= portc->channels; + + status = madi_read (devc, MADI_status); + return (status & MADI_BufferHalf) ? bytes : 0; +#else + /* + * Use full resolution + */ + status = madi_read (devc, MADI_status) & MADI_BufferPosMask; + + return status * portc->channels; +#endif +} + +/*ARGSUSED*/ +static void +madi_setup_fragments (int dev, dmap_t * dmap, int direction) +{ + madi_devc_t *devc = audio_engines[dev]->devc; + madi_portc_t *portc = audio_engines[dev]->portc; + int bytes; + + bytes = ((devc->cmd & MADI_LatencyMask) >> 1) + 8; + bytes = 1 << bytes; + + dmap->buffsize = portc->channels * CHBUF_SIZE; + +#if 1 + /* + * Use two fragment (ping-pong) buffer that is also used by the hardware. + */ + dmap->fragment_size = bytes * portc->channels; + dmap->nfrags = 2; +#else +/* + * Use 4 fragments instead of 2 to avoid clicking caused by accessing the + * DMA buffer too close to the active DMA position. + * + * This means that the DMA pointer will jump by 2 fregments every time there + * is a half/full bufferinterrupt. + */ + dmap->fragment_size = (bytes * portc->channels) / 2; + dmap->nfrags = 4; +#endif + + dmap->bytes_in_use = dmap->nfrags * dmap->fragment_size; +} + +static audiodrv_t madi_driver = { + madi_open, + madi_close, + madi_output_block, + madi_start_input, + madi_ioctl, + madi_prepare_for_input, + madi_prepare_for_output, + madi_halt, + NULL, // madi_local_qlen, + NULL, + NULL, // madi_halt_input, + NULL, // madi_halt_output, + madi_trigger, + madi_set_rate, + madi_set_format, + madi_set_channels, + NULL, + NULL, + NULL, + NULL, + madi_alloc_buffer, + madi_free_buffer, + NULL, + NULL, + madi_get_buffer_pointer, + NULL, + madi_sync_control, + NULL, + NULL, + NULL, + NULL, + madi_setup_fragments +}; + +static int +create_output_device (madi_devc_t * devc, char *name, int chn) +{ + madi_portc_t *portc; + adev_t *adev; + int n; + + if ((portc = PMALLOC (devc->osdev, sizeof (*portc))) == NULL) + { + cmn_err (CE_WARN, "Cannot allocate portc structure\n"); + return OSS_ENOMEM; + } + memset (portc, 0, sizeof (*portc)); + + n = devc->num_outputs++;; + portc->channel = chn; + portc->channels = 2; + portc->max_channels = 64 - chn; + + devc->out_portc[n] = portc; + + if ((portc->audio_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + name, + &madi_driver, + sizeof (audiodrv_t), + ADEV_NOINPUT | + ADEV_NONINTERLEAVED | + ADEV_NOMMAP, AFMT_S32_LE, + devc, -1)) < 0) + { + return portc->audio_dev; + } + + adev = audio_engines[portc->audio_dev]; + + if (devc->first_audiodev == -1) + devc->first_audiodev = portc->audio_dev; + adev->rate_source = devc->first_audiodev; + + adev->mixer_dev = devc->mixer_dev; + adev->portc = portc; + adev->min_rate = devc->rate; + adev->max_rate = devc->rate; + adev->min_channels = 1; + adev->max_channels = portc->max_channels; + adev->min_block = CHBUF_SIZE / 2; + adev->max_block = CHBUF_SIZE / 2; + + portc->direction = DIR_OUT; + + return portc->audio_dev; +} + +static int +create_input_device (madi_devc_t * devc, char *name, int chn) +{ + madi_portc_t *portc; + adev_t *adev; + int n; + + if ((portc = PMALLOC (devc->osdev, sizeof (*portc))) == NULL) + { + cmn_err (CE_WARN, "Cannot allocate portc structure\n"); + return OSS_ENOMEM; + } + memset (portc, 0, sizeof (*portc)); + + n = devc->num_inputs++;; + portc->channel = chn; + portc->channels = 2; + portc->max_channels = 64 - chn; + + devc->in_portc[n] = portc; + + if ((portc->audio_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + name, + &madi_driver, + sizeof (audiodrv_t), + ADEV_NOOUTPUT | + ADEV_NONINTERLEAVED | + ADEV_NOMMAP, AFMT_S32_LE, + devc, -1)) < 0) + { + return portc->audio_dev; + } + + adev = audio_engines[portc->audio_dev]; + + if (devc->first_audiodev == -1) + devc->first_audiodev = portc->audio_dev; + adev->rate_source = devc->first_audiodev; + + adev->mixer_dev = devc->mixer_dev; + adev->portc = portc; + adev->min_rate = devc->rate; + adev->max_rate = devc->rate; + adev->min_channels = 1; + adev->max_channels = portc->max_channels; + adev->min_block = CHBUF_SIZE / 2; + adev->max_block = CHBUF_SIZE / 2; + + portc->direction = DIR_IN; + + return portc->audio_dev; +} + +int +oss_madi_attach (oss_device_t * osdev) +{ + madi_devc_t *devc; + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int i; + int err; + int my_mixer; + + int chn, src; + + DDB (cmn_err (CE_NOTE, "Entered RME MADI detect routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != RME_VENDOR_ID || device != RME_MADI) + return 0; + + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &pci_ioaddr); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "BAR0 not initialized by BIOS\n"); + return 0; + } + + if ((devc = PMALLOC (osp, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Cannot allocate devc\n"); + return 0; + } + memset (devc, 0, sizeof (*devc)); + devc->osdev = osdev; + osdev->devc = devc; + devc->first_audiodev = -1; + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + + DDB (cmn_err (CE_CONT, "RME HDSPM revision %d\n", pci_revision)); + + if (pci_revision < 230) + { + devc->name = "RME MADI"; + devc->model = MDL_MADI; + } + else + { + devc->name = "RME AES32"; + devc->model = MDL_AES32; + } + + DDB (cmn_err (CE_CONT, "Card model is %s\n", devc->name)); + + devc->rate = devc->next_rate = 48000; // TODO: Also set the other rate control fields */ + + osdev->hw_info = PMALLOC (osdev, HWINFO_SIZE); /* Text buffer for additional device info */ + sprintf (osdev->hw_info, "PCI revision %d", pci_revision); + + oss_register_device (osdev, devc->name); + + devc->physaddr = pci_ioaddr; + devc->registers = MAP_PCI_MEM (devc->osdev, 0, devc->physaddr, 65536); + + if (devc->registers == NULL) + { + cmn_err (CE_WARN, "Can't map PCI registers (0x%08x)\n", devc->physaddr); + return 0; + } + + devc->playbuf = CONTIG_MALLOC (devc->osdev, DMABUF_SIZE, MEMLIMIT_32BITS, + &devc->playbuf_phys, devc->play_dma_handle); + if (devc->playbuf == NULL) + { + cmn_err (CE_WARN, "Cannot allocate play DMA buffers\n"); + return 0; + } + + devc->recbuf = CONTIG_MALLOC (devc->osdev, DMABUF_SIZE, MEMLIMIT_32BITS, + &devc->recbuf_phys, devc->rec_dma_handle); + if (devc->recbuf == NULL) + { + cmn_err (CE_WARN, "Cannot allocate rec DMA buffers\n"); + return 0; + } + + if ((err = oss_register_interrupts (devc->osdev, 0, madiintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + if (madi_maxchannels < 2) madi_maxchannels=2; + if (madi_maxchannels > MAX_CHANNELS)madi_maxchannels=MAX_CHANNELS; + + if (madi_devsize < 1) madi_devsize = 1; + + if (madi_devsize != 1 && madi_devsize != 2 && madi_devsize != 4) + madi_devsize = 2; + + /* + * Set the hw mixer shadow values to sane levels so that + * initialize_hardware() can write them to the actual registers. + */ + + for (chn = 0; chn < MAX_CHANNELS; chn++) + for (src = 0; src < 2 * MAX_CHANNELS; src++) + devc->mixer_values[chn][src] = MUTE_GAIN; /* Set everything off */ + +#if 0 + for (src = 0; src < MAX_CHANNELS; src += 2) + { + /* Setup playback monitoring to analog out */ + devc->mixer_values[MONITOR_CH][SRC_PLAY | src] = UNITY_GAIN / 10; + devc->mixer_values[MONITOR_CH + 1][SRC_PLAY | (src + 1)] = + UNITY_GAIN / 10; + } +#endif + + for (chn = 0; chn < MAX_CHANNELS; chn++) + devc->mixer_values[chn][SRC_PLAY | chn] = UNITY_GAIN; /* N->N outputs on */ + + initialize_hardware (devc); + + if ((my_mixer = madi_install_mixer (devc)) < 0) + { + devc->mixer_dev = -1; + return 0; + } + else + { + devc->mixer_dev = my_mixer; + } + + if (madi_devsize == 1) + { + for (i = 0; i < madi_maxchannels; i++) + { + char tmp[32]; + sprintf (tmp, "%s out%d", devc->name, i+1); + create_output_device (devc, tmp, i); + } + + for (i = 0; i < madi_maxchannels; i++) + { + char tmp[32]; + sprintf (tmp, "%s in%d", devc->name, i+1); + create_input_device (devc, tmp, i); + } + } + else + { + for (i = 0; i < madi_maxchannels; i += madi_devsize) + { + char tmp[32]; + sprintf (tmp, "%s out%d-%d", devc->name, i+1, i + madi_devsize); + create_output_device (devc, tmp, i); + } + + for (i = 0; i < madi_maxchannels; i += madi_devsize) + { + char tmp[32]; + sprintf (tmp, "%s in%d-%d", devc->name, i+1, i + madi_devsize); + create_input_device (devc, tmp, i); + } + } + + madi_activate_mixer (devc); + + return 1; +} + +int +oss_madi_detach (oss_device_t * osdev) +{ + madi_devc_t *devc = (madi_devc_t *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + stop_audio (devc); + + /* + * Shut up the hardware + */ + devc->cmd &= ~MADI_FreqMask; + madi_control (devc, devc->cmd); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + + if (devc->registers != NULL) + UNMAP_PCI_MEM (osdev, 0, devc->physaddr, devc->registers, 65536); + CONTIG_FREE (devc->osdev, devc->playbuf, DMABUF_SIZE, + devc->play_dma_handle); + CONTIG_FREE (devc->osdev, devc->recbuf, DMABUF_SIZE, devc->rec_dma_handle); + + oss_unregister_device (devc->osdev); + + return 1; +} diff --git a/kernel/drv/oss_madi/oss_madi.man b/kernel/drv/oss_madi/oss_madi.man new file mode 100644 index 0000000..70239fc --- /dev/null +++ b/kernel/drv/oss_madi/oss_madi.man @@ -0,0 +1,70 @@ +NAME +oss_madi - RME HDSP MADI and AES32 audio driver + +DESCRIPTION +Open Sound System driver for RME HDSP MADI and AES32 audio interfaces. + +This driver has been developed for RME HDSP MADI but it also supports +HDSP AES32. The driver has been tested under Linux and Solaris under x86 +and Sparc. + +The internal engine of the card supports 64 playback channels and 64 recording +channels. Only the first channels are connected to the actual input and +output ports of the card. + +The mixer section of the card has recording level settings for all inputs. +There is also an output mixer. Each output channel has mixer sliders for +corresponding input channel and corresponding audio playback channel. + +There is a full 64x(64+64) mixing matrix supported by the hardware. For +the time being this mixer matrix cannot be accessed directly by the +applications. However support for the SNDCTL_MIX_MATRIX_WRITE and +SNDCTL_MIX_MATRIX_READ ioctl calls can be added in the future. + +DEVICE FILES + +By default the driver will create input and output device files for +each 32 stereo pairs. This can be changed by editing the settings in +oss_madi.conf (see below). + +The application can set the devices to use 1, 2, 4, 8, 16, 32 or 64 channels. +The device file being used selects the first channel slot within the available +channels. For example pcm0 and pcmin0 sill select channel 0. Equally well +pcm1 and pcmin1 will select channel slot 2 (assuming that madi_devsize option +is set to 2). The first device (pcm0 and pcmin0) can be set to use up to 64 +channels. The last devices (pcm31 and pcmin31) only support 1 or 2 channel mode. +The other device files support channel configurations where the last channel +doesn't exceed the number of total channels (madi_maxchannels). Also the driver +will not let two device files to share any of the channels with some other +open device file. + +This channel allocation mechanism gives maximum flexibility to the user. It is +possible to use some output channels by multi channel application while the +others are available for other applications. This works as long the channel +allocations by different applications don't overlap. + +OPTIONS + +o madi_maxchannels Number of channels supported by the driver. The default + is 64 which is also the maximum. This parameter can + be set to a lower value if full 64 channels are not + required. With less channels the mixer/control panel + interface will require less space on screen. +o madi_devsize By default this parameter is set to 2 which means that + a device file will be created for each stereo channel + pair. Possible values are 1, 2, 4, 8, 16, 32 or 64. + +LIMITATIONS + +o The current driver doesn't support all control panel features of the card. +For example sampling rate is fixed to 48 kHz. More features will be added +on contract. + +o Use of mmap() is and will not be supported. +o Virtual mixer is not supported (yet). + +FILES +CONFIGFILEPATH/oss_madi.conf Device configuration file. + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_midiloop/.config b/kernel/drv/oss_midiloop/.config new file mode 100644 index 0000000..c10d582 --- /dev/null +++ b/kernel/drv/oss_midiloop/.config @@ -0,0 +1 @@ +bus=VIRTUAL diff --git a/kernel/drv/oss_midiloop/.devices b/kernel/drv/oss_midiloop/.devices new file mode 100644 index 0000000..9389c68 --- /dev/null +++ b/kernel/drv/oss_midiloop/.devices @@ -0,0 +1 @@ +oss_midiloop oss_midiloop OSS MIDI Loopback driver diff --git a/kernel/drv/oss_midiloop/.name b/kernel/drv/oss_midiloop/.name new file mode 100644 index 0000000..1b2e06b --- /dev/null +++ b/kernel/drv/oss_midiloop/.name @@ -0,0 +1 @@ +MIDI loopback pseudo device diff --git a/kernel/drv/oss_midiloop/.params b/kernel/drv/oss_midiloop/.params new file mode 100644 index 0000000..9e33e88 --- /dev/null +++ b/kernel/drv/oss_midiloop/.params @@ -0,0 +1,5 @@ +int midiloop_instances = 1; /* Number of loopback MIDI devs to install */ +/* + * midiloop_instances gives the number of MIDI loopback devices to be created. + * The default value is 1 + */ diff --git a/kernel/drv/oss_midiloop/oss_midiloop.c b/kernel/drv/oss_midiloop/oss_midiloop.c new file mode 100644 index 0000000..5c9082a --- /dev/null +++ b/kernel/drv/oss_midiloop/oss_midiloop.c @@ -0,0 +1,412 @@ +/* + * Purpose: MIDI loopback 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. + * + */ + +#include "oss_midiloop_cfg.h" +#include "midi_core.h" + +#define MIDI_SYNTH_NAME "OSS loopback MIDI" +#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT + +#define MAX_INSTANCES 8 +#define CLIENT_NAME "MIDI loopback" +#define SERVER_NAME "MIDI loopback server side" + +#define POLL_HZ (OSS_HZ/100) + +static int open_clients = 0; +static int open_servers = 0; + +typedef struct midiloop_devc +{ + oss_device_t *osdev; + oss_mutex_t mutex; + + int instance_no; + int side; +#define SIDE_SERVER 0 +#define SIDE_CLIENT 0 + int midi_dev; + struct midiloop_devc *client, *server, *peer; + + int open_mode; + oss_midi_inputbyte_t inputbyte_func; + oss_midi_inputbuf_t inputbuf_func; + oss_longname_t song_name; + +} midiloop_devc; + +static midiloop_devc midiloop_devs[2 * MAX_INSTANCES] = { {0} }; +static int ndevs = 0; + +static int +midiloop_open_server (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags; + midiloop_devc *devc, *client_devc; + char *cmd; + int client_dev; + + devc = midi_devs[dev]->devc; + + client_devc = devc->client; + + client_dev = client_devc->midi_dev; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + devc->open_mode = mode; + devc->inputbyte_func = inputbyte; + devc->inputbuf_func = inputbuf; + + open_servers++; + + if ((cmd = midi_devs[dev]->cmd) != NULL) + { + sprintf (midi_devs[client_dev]->name, CLIENT_NAME " (%s)", cmd); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +midiloop_close_server (int dev, int mode) +{ + oss_native_word flags; + midiloop_devc *devc, *client_devc; + int client_dev; + + devc = midi_devs[dev]->devc; + client_devc = devc->client; + client_dev = client_devc->midi_dev; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_mode = 0; + devc->inputbyte_func = NULL; + devc->inputbuf_func = NULL; + strcpy (midi_devs[client_dev]->name, CLIENT_NAME); + midi_devs[client_dev]->latency = -1; /* Not indicated */ + + open_servers--; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static int +midiloop_open_client (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags; + midiloop_devc *devc; + + devc = midi_devs[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + devc->open_mode = mode; + devc->inputbyte_func = inputbyte; + devc->inputbuf_func = inputbuf; + open_clients++; + + /* Notify the server */ + if (devc->server->open_mode & OPEN_READ) + { + if (devc->server->inputbyte_func != NULL) + devc->server->inputbyte_func (devc->server->midi_dev, 0xfa); /* Start */ + + /* Restart the MTC timer of the server side (if necessary) */ + if (midi_devs[devc->server->midi_dev]->mtc_timebase > -1) + { + int timebase = 25; + oss_midi_ioctl (devc->server->midi_dev, NULL, SNDCTL_MIDI_MTCINPUT, + (ioctl_arg) & timebase); + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +midiloop_close_client (int dev, int mode) +{ + oss_native_word flags; + midiloop_devc *devc; + + devc = midi_devs[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_mode = 0; + devc->inputbyte_func = NULL; + devc->inputbuf_func = NULL; + open_clients--; + + /* Notify the server */ + if (devc->server->open_mode & OPEN_READ) + if (devc->server->inputbyte_func != NULL) + devc->server->inputbyte_func (devc->server->midi_dev, 0xfc); /* Stop */ + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + /* Halt the MTC timer of the server side (if necessary) */ + if (midi_devs[devc->server->midi_dev]->mtc_timebase > 0) + { + int timebase = 0; + oss_midi_ioctl (devc->server->midi_dev, NULL, SNDCTL_MIDI_MTCINPUT, + (ioctl_arg) & timebase); + } +} + +static int +midiloop_out (int dev, unsigned char midi_byte) +{ + midiloop_devc *devc; + oss_native_word flags; + int ok = 0; + + devc = midi_devs[dev]->devc; + + if (devc->peer->open_mode == 0) + return 1; + MUTEX_ENTER_IRQDISABLE (devc->peer->mutex, flags); + if (devc->peer->inputbyte_func != NULL) + { + ok = devc->peer->inputbyte_func (devc->peer->midi_dev, midi_byte); + } + MUTEX_EXIT_IRQRESTORE (devc->peer->mutex, flags); + return ok; +} + +static int +midiloop_bulk_out (int dev, unsigned char *buf, int len) +{ + midiloop_devc *devc; + oss_native_word flags; + int ok = 0; + + devc = midi_devs[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->peer->mutex, flags); + if (devc->peer->open_mode == 0 || devc->peer->inputbuf_func == NULL) + { + MUTEX_EXIT_IRQRESTORE (devc->peer->mutex, flags); + return len; + } + + ok = devc->peer->inputbuf_func (devc->peer->midi_dev, buf, len); + MUTEX_EXIT_IRQRESTORE (devc->peer->mutex, flags); + return ok; +} + +static void +midiloop_timer_setup (int dev /* Client dev */ ) +{ + midiloop_devc *devc, *server_devc; + int client_dev; + int server_dev; + + devc = midi_devs[dev]->devc; + server_devc = devc->server; + client_dev = devc->midi_dev; + server_dev = devc->server->midi_dev; + + oss_midi_copy_timer (server_dev, client_dev); +} + +static int +midiloop_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + char *song_name; + oss_native_word flags; + midiloop_devc *devc, *client_devc; + int client_dev; + + devc = midi_devs[dev]->devc; + client_devc = devc->client; + client_dev = client_devc->midi_dev; + + switch (cmd) + { + case SNDCTL_SETSONG: + if (devc->side != SIDE_CLIENT) + return 0; + + song_name = (char *) arg; + song_name[OSS_LONGNAME_SIZE - 1] = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + strcpy (devc->song_name, song_name); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + break; + + case SNDCTL_SETNAME: + if (devc->side != SIDE_SERVER) + return 0; + + song_name = (char *) arg; + song_name[OSS_LONGNAME_SIZE - 1] = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + strcpy (midi_devs[devc->client->midi_dev]->name, song_name); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + break; + + case SNDCTL_GETSONG: + song_name = (char *) arg; + memset (song_name, 0, OSS_LONGNAME_SIZE); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->side == SIDE_SERVER) + strcpy (song_name, devc->peer->song_name); + else + strcpy (song_name, devc->song_name); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + break; + + case SNDCTL_MIDI_SET_LATENCY: + if (devc->side != SIDE_SERVER) + return OSS_EINVAL; + if (*arg < -1 || *arg > 10000000) + return OSS_EINVAL; + midi_devs[devc->client->midi_dev]->latency = *arg; + break; + } + return OSS_EINVAL; +} + +static midi_driver_t midiloop_client_driver = { + midiloop_open_client, + midiloop_close_client, + midiloop_ioctl, + midiloop_out, + midiloop_bulk_out, + MIDI_PAYLOAD_SIZE, + NULL, + NULL, + midiloop_timer_setup +}; + +static midi_driver_t midiloop_server_driver = { + midiloop_open_server, + midiloop_close_server, + midiloop_ioctl, + midiloop_out, + midiloop_bulk_out, + MIDI_PAYLOAD_SIZE +}; + +static void +attach_midiloop_dev (oss_device_t * osdev) +{ + midiloop_devc *server_devc = NULL, *client_devc = NULL; + + if (POLL_HZ < 1) + { + cmn_err (CE_CONT, "midiloop: Too low system timer resolution\n"); + return; + } + + if (ndevs >= MAX_INSTANCES) + { + cmn_err (CE_CONT, "MidiLoop: Too many instances\n"); + return; + } + + client_devc = &midiloop_devs[ndevs * 2]; + client_devc->osdev = osdev; + MUTEX_INIT (client_devc->osdev, client_devc->mutex, MH_DRV); + client_devc->instance_no = ndevs; + + client_devc->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "LOOP", CLIENT_NAME, + &midiloop_client_driver, sizeof (midi_driver_t), + MFLAG_VIRTUAL | MFLAG_CLIENT, client_devc, + client_devc->osdev); + + server_devc = &midiloop_devs[ndevs * 2 + 1]; + server_devc->osdev = osdev; + MUTEX_INIT (server_devc->osdev, server_devc->mutex, MH_DRV); + server_devc->instance_no = ndevs; + + midi_devs[client_devc->midi_dev]->latency = 1000000; + + server_devc->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "LOOP_S", SERVER_NAME, + &midiloop_server_driver, sizeof (midi_driver_t), + MFLAG_NOSEQUENCER | MFLAG_VIRTUAL | MFLAG_SERVER | + MFLAG_SELFTIMING, server_devc, server_devc->osdev); + + client_devc->server = client_devc->peer = server_devc; + client_devc->client = client_devc; + client_devc->side = SIDE_CLIENT; + + server_devc->client = server_devc->peer = client_devc; + server_devc->server = server_devc; + server_devc->side = SIDE_SERVER; + + ndevs++; +} + +int +oss_midiloop_attach (oss_device_t * osdev) +{ + extern int midiloop_instances; + int i; + + oss_register_device (osdev, "OSS MIDI loopback driver"); + + if (midiloop_instances > MAX_INSTANCES) + midiloop_instances = MAX_INSTANCES; + for (i = 0; i < midiloop_instances; i++) + { + attach_midiloop_dev (osdev); + } + + return 1; +} + +int +oss_midiloop_detach (oss_device_t * osdev) +{ + int i, err; + + if ((err = oss_disable_device (osdev)) < 0) + return 0; + + for (i = 0; i < 2 * ndevs; i++) + { + midiloop_devc *devc; + + devc = &midiloop_devs[i]; + } + + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_midiloop/oss_midiloop.man b/kernel/drv/oss_midiloop/oss_midiloop.man new file mode 100644 index 0000000..a3ee97d --- /dev/null +++ b/kernel/drv/oss_midiloop/oss_midiloop.man @@ -0,0 +1,44 @@ +NAME +oss_midiloop - Loopback MIDI driver. + +DESCRIPTION +The loopback midi driver makes it possible to create special purpose +virtual midi devices based on user land server processes. + +INTRODUCTION +MIDI loopback devices are like named pipes or pseudo terminals. They are +grouped in client and server device pairs. The server side device must be open +before the client side device can be opened. + + SERVER SIDE DEVICE +The server side device is used by some special application (such as a +software based MIDI synthesizer) to receice MIDI events from the applications +that want to play MIDI. + + CLIENT SIDE DEVICE +Client applications such as MIDI players open the client side device when they +need to play some MIDI stream (file). The client side device behaves like any +"ordinary" MIDI device. However it cannot be opened when there is no program +connected to the server side. + +COMPATIBILITY ISSUES +MIDI loopback devices differ from "normal" MIDI devices because an +application is needed at the both ends of the loop. The loop device +will return a "Connection reset by peer" error (ECONNRESET) error. Applications +designed to be used as loopback based server applications can/should use this +error (returned by read or write) as an end-of-stream indication. + +OPTIONS +o midiloop_instances: Specifies how many loopback client/server MIDI device + pairs to be created. + Values: 1-16 Default: 1 + +KNOWN PROBLEMS +None + +FILES +CONFIGFILEPATH/oss_midiloop.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_midimix/.config b/kernel/drv/oss_midimix/.config new file mode 100644 index 0000000..c10d582 --- /dev/null +++ b/kernel/drv/oss_midimix/.config @@ -0,0 +1 @@ +bus=VIRTUAL diff --git a/kernel/drv/oss_midimix/.name b/kernel/drv/oss_midimix/.name new file mode 100644 index 0000000..543ecb8 --- /dev/null +++ b/kernel/drv/oss_midimix/.name @@ -0,0 +1 @@ +MIDI mixer pseudo device. diff --git a/kernel/drv/oss_midimix/oss_midimix.c b/kernel/drv/oss_midimix/oss_midimix.c new file mode 100644 index 0000000..9f7cc4c --- /dev/null +++ b/kernel/drv/oss_midimix/oss_midimix.c @@ -0,0 +1,346 @@ +/* + * Purpose: MIDI mixer pseudo driver + * + * This driver creates a pseudo MIDI port device that can be used for + * real-time mixer volume changes. The pseudo MIDI device will return MIDI + * control change messages when a mixer setting changes. Application using the + * device may also do mixer changes (cross fading, etc) by sending (or + * playing back) control messages. + */ +/* + * + * 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_midimix_cfg.h" +#include "midi_core.h" +#include "midiparser.h" + +#define MAX_INSTANCES 1 + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + int midi_dev; + int open_mode; + oss_midi_inputbuf_t inputbuf; + midiparser_common_p parser; + int modify_counters[16]; + int update_counters[16][128]; + timeout_id_t timeout_id; +} midimix_devc; + +static midimix_devc midimix_devs[MAX_INSTANCES] = {{ 0 }}; +static int ndevs = 0; + +static void +midimix_close (int dev, int mode) +{ + midimix_devc *devc = midi_devs[dev]->devc; + oss_native_word flags; + + midiparser_unalloc (devc->parser); + devc->parser = NULL; + untimeout (devc->timeout_id); + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_mode = 0; + devc->inputbuf = NULL; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +void +parser_cb (void *context, int category, unsigned char msg, unsigned char ch, + unsigned char *parms, int len) +{ + + if (category == CAT_CHN && msg == MIDI_CTL_CHANGE) + { + oss_mixext *ext; + oss_mixer_value rec; + + int dev = ch; + int ctl = parms[0]; + int val = parms[1]; + + if ((ext = mixer_find_ext (dev, ctl)) == NULL) + return; /* Not found */ + + if (!(ext->flags & MIXF_READABLE) || !(ext->flags & MIXF_WRITEABLE)) + return; /* Not accessible */ + + if (ext->maxvalue > 127) + val = (val * ext->maxvalue + 63) / 127; + + if (val < 0 || val > ext->maxvalue) + return; /* Value out of range */ + + switch (ext->type) + { + case MIXT_MONOSLIDER: + case MIXT_STEREOSLIDER: + val = val & 0xff; + val = val | (val << 8); + break; + + case MIXT_ONOFF: + val = !!val; + break; + + case MIXT_ENUM: + if (val >= ext->maxvalue) + return; /* Out of range */ + break; + + case MIXT_VALUE: + case MIXT_HEXVALUE: + case MIXT_SLIDER: + /* Accept as-is */ + break; + + default: + return; /* Type not supported */ + } + + memset (&rec, 0, sizeof (rec)); + rec.dev = dev; + rec.ctrl = ctl; + rec.value = val; + rec.timestamp = ext->timestamp; + oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE, (ioctl_arg) & rec); + } + +} + +static void +check_for_updates (midimix_devc * devc, int force) +{ + int dev, ctl; + + for (dev = 0; dev < 16 && dev < num_mixers; dev++) + { + touch_mixer (dev); + + if (force + || (mixer_devs[dev]->modify_counter > devc->modify_counters[dev])) + { + devc->modify_counters[dev] = mixer_devs[dev]->modify_counter; + for (ctl = 0; ctl < 128; ctl++) + { + oss_mixext *ext; + oss_mixer_value rec; + int val; + unsigned char midibuf[3]; + + if ((ext = mixer_find_ext (dev, ctl)) == NULL) + break; /* All controls processed I think */ + if (!(ext->flags & MIXF_READABLE) + || !(ext->flags & MIXF_WRITEABLE)) + continue; /* Not accessible */ + + if (!force + && devc->update_counters[dev][ctl] == ext->update_counter) + continue; /* No change */ + devc->update_counters[dev][ctl] = ext->update_counter; + + switch (ext->type) + { + case MIXT_MONOSLIDER: + case MIXT_STEREOSLIDER: + case MIXT_ONOFF: + case MIXT_ENUM: + case MIXT_VALUE: + case MIXT_HEXVALUE: + case MIXT_SLIDER: + /* Type OK */ + break; + + default: + continue; /* Type not supported */ + } + + memset (&rec, 0, sizeof (rec)); + rec.dev = dev; + rec.ctrl = ctl; + rec.timestamp = ext->timestamp; + + if (oss_mixer_ext + (dev, OSS_DEV_MIXER, SNDCTL_MIX_READ, + (ioctl_arg) & rec) < 0) + { + continue; /* Read failed */ + } + + val = rec.value & 0xff; + if (ext->maxvalue > 127) + val = (val * 127 + (ext->maxvalue / 2)) / ext->maxvalue; + + if (val < 0) + val = 0; + if (val > 127) + val = 127; + + midibuf[0] = 0xb0 | dev; + midibuf[1] = ctl; + midibuf[2] = val; + + devc->inputbuf (devc->midi_dev, midibuf, 3); + } + } + } +} + +static void +timer_callback (void *arg) +{ + midimix_devc *devc = arg; + check_for_updates (devc, 0); + devc->timeout_id = timeout (timer_callback, devc, OSS_HZ / 10); /* 0.1s */ +} + +static int +midimix_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, oss_midi_outputintr_t outputintr) +{ + midimix_devc *devc = midi_devs[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (devc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + devc->open_mode = mode; + devc->inputbuf = inputbuf; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if ((devc->parser = midiparser_create (parser_cb, devc)) == NULL) + { + devc->open_mode = 0; + devc->inputbuf = NULL; + cmn_err (CE_WARN, "Cannot create MIDI parser\n"); + return OSS_ENOMEM; + } + + devc->timeout_id = timeout (timer_callback, devc, OSS_HZ / 10); /* 0.1s */ + return 0; +} + +static int +midimix_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static int +midimix_out (int dev, unsigned char midi_byte) +{ + midimix_devc *devc = midi_devs[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + midiparser_input (devc->parser, midi_byte); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 1; +} + +static int +midimix_bulk_out (int dev, unsigned char *buf, int len) +{ + midimix_devc *devc = midi_devs[dev]->devc; + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (i = 0; i < len; i++) + { + midiparser_input (devc->parser, buf[i]); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return len; +} + +static void +midimix_init_device (int dev) +{ + midimix_devc *devc = midi_devs[dev]->devc; + + if (devc->open_mode & OPEN_READ) + check_for_updates (devc, 1); +} + +static midi_driver_t midimix_driver = { + midimix_open, + midimix_close, + midimix_ioctl, + midimix_out, + midimix_bulk_out, + MIDI_PAYLOAD_SIZE, + NULL, + NULL, + NULL, + midimix_init_device +}; + +static void +attach_midimix_dev (oss_device_t * osdev) +{ + midimix_devc *devc = &midimix_devs[ndevs++]; + + devc->osdev = osdev; + + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + + devc->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "MIX", + "Mixer access MIDI device", &midimix_driver, + sizeof (midi_driver_t), + MFLAG_VIRTUAL | MFLAG_QUIET, devc, devc->osdev); +} + +int +oss_midimix_attach (oss_device_t * osdev) +{ + int midimix_instances = 1; + int i; + + oss_register_device (osdev, "OSS MIDI mixer driver"); + + if (midimix_instances > MAX_INSTANCES) + midimix_instances = MAX_INSTANCES; + for (i = 0; i < midimix_instances; i++) + { + attach_midimix_dev (osdev); + } + + return 1; +} + +int +oss_midimix_detach (oss_device_t * osdev) +{ + int i, err; + + if ((err = oss_disable_device (osdev)) < 0) + return 0; + + for (i = 0; i < ndevs; i++) + { + midimix_devc *devc; + + devc = &midimix_devs[i]; + } + + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_midimix/oss_midimix.man b/kernel/drv/oss_midimix/oss_midimix.man new file mode 100644 index 0000000..ac7e2ec --- /dev/null +++ b/kernel/drv/oss_midimix/oss_midimix.man @@ -0,0 +1,40 @@ +NAME +oss_midimix - Driver for controlling OSS mixer devices using MIDI messages + +DESCRIPTION +The MIDI mixer device can be used by MIDI sequencer programs to control +OSS mixer devices (volumes) in real time. A list of mixer devices available +in the system can be found using the ossinfo(1) program with the -x option. + + INTRODUCTION +This driver uses MIDI channel numbers to select the mixer device. The first MIDI +channel (#0) connects to the first mixer device in the system and so on. When +any of the mixer controls (such as volume sliders) change their value the +MIDI mixer device delivers a control change message to the application +listening it. An application (such as a MIDI sequencer program) can record +these mixer changes during recording and play them back during playback. In +this way it's possible to repeat mixer changes with precise timing during +playback. + +OPTIONS +None + +KNOWN PROBLEMS +o MIDI support is not included in OSS v4.0. It will be re-introduced in +some future version of OSS. +o The way how MIDI channel numbers are mapped to the mixer device numbers +is system dependednt and may change depending on the order of devices are +loaded in the system. The same is true with the MIDI controller numbers. For +this reason recorded mixer changes may become obsolete if new devices are +installed in the system or if the mixer layout changes in future OSS +versions. +o For the time being the MIDI controller numbers are mapped directly to +the mixer control numbers. This means that only the first 128 controls in large +mixers can be supported. This may change in future OSS versions. + +FILES +None + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_sadasupport/.config b/kernel/drv/oss_sadasupport/.config new file mode 100644 index 0000000..c8e8442 --- /dev/null +++ b/kernel/drv/oss_sadasupport/.config @@ -0,0 +1,3 @@ +bus=STREAMS +targetos=SunOS +depends=SADA diff --git a/kernel/drv/oss_sadasupport/.devices b/kernel/drv/oss_sadasupport/.devices new file mode 100644 index 0000000..236f38f --- /dev/null +++ b/kernel/drv/oss_sadasupport/.devices @@ -0,0 +1 @@ +oss_sadasupport OSSAUDIOS SADA emulation layer for OSS diff --git a/kernel/drv/oss_sadasupport/.name b/kernel/drv/oss_sadasupport/.name new file mode 100644 index 0000000..c311b6a --- /dev/null +++ b/kernel/drv/oss_sadasupport/.name @@ -0,0 +1 @@ +SADA emulation layer for OSS diff --git a/kernel/drv/oss_sadasupport/.params b/kernel/drv/oss_sadasupport/.params new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/kernel/drv/oss_sadasupport/.params diff --git a/kernel/drv/oss_sadasupport/oss_sadasupport.c b/kernel/drv/oss_sadasupport/oss_sadasupport.c new file mode 100644 index 0000000..43f5226 --- /dev/null +++ b/kernel/drv/oss_sadasupport/oss_sadasupport.c @@ -0,0 +1,1277 @@ +/* + * Purpose: Support for the legacy (SADA) /dev/audio interfaces of Solaris + * + * Description: + * This driver serves as a bridge between the OSS audio drivers and the + * native audio support framework of Solaris. + * + * **** This driver supports only one device instance **** + */ +/* + * + * 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_sadasupport_cfg.h" +#include <oss_pci.h> +#include <sys/note.h> +#include <sys/audioio.h> +#include <sys/audio.h> +#include <sys/audiovar.h> +#include <sys/audio/audio_trace.h> +#include <sys/audio/audio_support.h> +#include <sys/audio/audio_src.h> +#include <sys/mixer.h> +#include <sys/audio/audio_mixer.h> +#ifdef SOL9 +#include <sys/audio/am_src1.h> +#else +#include <sys/sunldi.h> +#endif + +int sadasupport_rate = 48000; + +static int do_byteswap = 0; + +#ifdef SOL9 +extern am_ad_src_entry_t am_src1; +#else +extern am_ad_src_entry_t am_src2; +#endif + +#define AUDIOS_DEV_NAME "SUNW,oss" +#define AUDIOS_DEV_CONFIG "onboard1" +#define AUDIOS_DEV_VERSION "a" +#define AUDIOS_NAME "oss" +#define AUDIOS_IDNUM (0x6175) +#define AUDIOS_MINPACKET (0) +#define AUDIOS_MAXPACKET (1*1024) +#define AUDIOS_HIWATER (64*1024) +#define AUDIOS_LOWATER (32*1024) +#define AUDIOS_BUFFSIZE (8*1024) + +#define AUDIOS_SAMPR5510 (5510) +#define AUDIOS_SAMPR6620 (6620) +#define AUDIOS_SAMPR8000 (8000) +#define AUDIOS_SAMPR9600 (9600) +#define AUDIOS_SAMPR11025 (11025) +#define AUDIOS_SAMPR12000 (12000) +#define AUDIOS_SAMPR16000 (16000) +#define AUDIOS_SAMPR18900 (18900) +#define AUDIOS_SAMPR22050 (22050) +#define AUDIOS_SAMPR24000 (24000) +#define AUDIOS_SAMPR27420 (27420) +#define AUDIOS_SAMPR32000 (32000) +#define AUDIOS_SAMPR33075 (33075) +#define AUDIOS_SAMPR37800 (37800) +#define AUDIOS_SAMPR44100 (44100) +#define AUDIOS_SAMPR48000 (48000) + +#define AUDIOS_DEFAULT_SR AUDIOS_SAMPR8000 +#define AUDIOS_DEFAULT_CH AUDIO_CHANNELS_MONO +#define AUDIOS_DEFAULT_PREC AUDIO_PRECISION_8 +#define AUDIOS_DEFAULT_ENC AUDIO_ENCODING_ULAW +#define AUDIOS_DEFAULT_PGAIN (AUDIO_MAX_GAIN * 3 / 4) +#define AUDIOS_DEFAULT_RGAIN (127) +#define AUDIOS_DEFAULT_MONITOR_GAIN (0) +#define AUDIOS_DEFAULT_BAL AUDIO_MID_BALANCE + +/* + * Entry point routine prototypes + */ +static int sadasupport_open (queue_t * q, dev_t * devp, int flag, int sflag, + cred_t * credp); +static int sadasupport_close (queue_t * q, int flag, cred_t * credp); +static int sadasupport_ad_set_config (audiohdl_t, int, int, int, int, int); +static int sadasupport_ad_set_format (audiohdl_t, int, int, int, int, int, + int); +static int sadasupport_ad_start_play (audiohdl_t, int); +static void sadasupport_ad_pause_play (audiohdl_t, int); +static void sadasupport_ad_stop_play (audiohdl_t, int); +static int sadasupport_ad_start_record (audiohdl_t, int); +static void sadasupport_ad_stop_record (audiohdl_t, int); + +/* now, only support stereo */ +static uint_t sadasupport_channels[] = { + AUDIO_CHANNELS_STEREO, + 0 +}; + +static am_ad_cap_comb_t sadasupport_combinations[] = { + {AUDIO_PRECISION_16, AUDIO_ENCODING_LINEAR}, + {0} +}; + +static uint_t sadasupport_mixer_srs[] = { + AUDIOS_SAMPR8000, AUDIOS_SAMPR48000, 0 +}; + +#ifdef SOL9 +/* don't filter the higher sample rates, this causes the high to be lost */ +static am_ad_src1_info_t sadasupport_play_sample_rates_info[] = { + {AUDIOS_SAMPR8000, AUDIOS_SAMPR48000, 2, /* up 6, down 1 */ + 3, (2 | AM_SRC1_FILTER), 0, 0, 1, 1, 0, 0, 3}, + {AUDIOS_SAMPR9600, AUDIOS_SAMPR48000, 1, /* up 5, down 1 */ + (5 | AM_SRC1_FILTER), 0, 0, 0, 1, 0, 0, 0, 3}, + {AUDIOS_SAMPR11025, AUDIOS_SAMPR48000, 3, /* up 640, down 147 */ + 10, 8, (8 | AM_SRC1_FILTER), 0, 7, 7, 3, 0, 3}, + {AUDIOS_SAMPR12000, AUDIOS_SAMPR48000, 1, /* up 4, down 1 */ + (4 | AM_SRC1_FILTER), 0, 0, 0, 1, 0, 0, 0, 3}, + {AUDIOS_SAMPR16000, AUDIOS_SAMPR48000, 1, /* up 3, down 1 */ + (3 | AM_SRC1_FILTER), 0, 0, 0, 1, 0, 0, 0, 3}, + {AUDIOS_SAMPR18900, AUDIOS_SAMPR48000, 3, /* up 160, down 63 */ + 8, 5, (4 | AM_SRC1_FILTER), 0, 7, 3, 3, 0, 3}, + {AUDIOS_SAMPR22050, AUDIOS_SAMPR48000, 3, /* up 320, down 147 */ + 10, 8, (4 | AM_SRC1_FILTER), 0, 7, 7, 3, 0, 3}, + {AUDIOS_SAMPR24000, AUDIOS_SAMPR48000, 1, /* up 2, down 1 */ + (2 | AM_SRC1_FILTER), 0, 0, 0, 1, 0, 0, 0, 3}, + {AUDIOS_SAMPR32000, AUDIOS_SAMPR48000, 1, /* up 3, down 2 */ + (3 | AM_SRC1_FILTER), 0, 0, 0, 2, 0, 0, 0, 3}, + {AUDIOS_SAMPR33075, AUDIOS_SAMPR48000, 4, /* up 640, down 441 */ + 8, 5, 4, 4, 7, 7, 3, 3, 3}, + {AUDIOS_SAMPR37800, AUDIOS_SAMPR48000, 3, /* up 80, down 63 */ + 5, 4, 4, 0, 7, 3, 3, 0, 3}, + {AUDIOS_SAMPR44100, AUDIOS_SAMPR48000, 3, /* up 160, down 147 */ + 8, 5, 4, 0, 7, 7, 3, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR48000, 1, /* up 1, down 1 */ + 1, 0, 0, 0, 1, 0, 0, 0, 3}, + {0} +}; + +static am_ad_src1_info_t sadasupport_record_sample_rates_info[] = { + {AUDIOS_SAMPR48000, AUDIOS_SAMPR8000, 1, /* up 1, down 6 */ + 1, 0, 0, 0, 6, 0, 0, 0, 0}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR9600, 1, /* up 1, down 5 */ + 1, 0, 0, 0, 5, 0, 0, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR11025, 3, /* up 147, down 640 */ + 7, 7, (3 | AM_SRC1_FILTER), 0, 10, 8, 8, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR12000, 1, /* up 1, down 4 */ + 1, 0, 0, 0, 4, 0, 0, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR16000, 1, /* up 1, down 3 */ + 1, 0, 0, 0, 3, 0, 0, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR18900, 3, /* up 63, down 160 */ + 7, 3, (3 | AM_SRC1_FILTER), 0, 8, 5, 4, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR22050, 3, /* up 147, down 320 */ + 7, 7, (3 | AM_SRC1_FILTER), 0, 10, 8, 4, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR24000, 1, /* up 1, down 2 */ + 1, 0, 0, 0, 2, 0, 0, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR32000, 1, /* up 2, down 3 */ + (2 | AM_SRC1_FILTER), 0, 0, 0, 3, 0, 0, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR33075, 4, /* up 441, down 640 */ + 7, 7, 3, 3, 8, 5, 4, 4, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR37800, 3, /* up 63, down 80 */ + 7, 3, 3, 0, 5, 4, 4, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR44100, 3, /* up 147, down 160 */ + 7, 7, 3, 0, 8, 5, 4, 0, 3}, + {AUDIOS_SAMPR48000, AUDIOS_SAMPR48000, 3, /* up 1, down 1 */ + 1, 0, 0, 0, 1, 0, 0, 0, 3}, + {0} +}; +#endif + +#if 0 +static uint_t sadasupport_compat_srs[] = { + AUDIOS_SAMPR5510, AUDIOS_SAMPR6620, AUDIOS_SAMPR8000, + AUDIOS_SAMPR9600, AUDIOS_SAMPR11025, AUDIOS_SAMPR12000, + AUDIOS_SAMPR16000, AUDIOS_SAMPR18900, AUDIOS_SAMPR22050, + AUDIOS_SAMPR24000, AUDIOS_SAMPR27420, AUDIOS_SAMPR32000, + AUDIOS_SAMPR33075, AUDIOS_SAMPR37800, AUDIOS_SAMPR44100, + AUDIOS_SAMPR48000, 0 +}; +#endif + +static am_ad_sample_rates_t sadasupport_mixer_sample_rates = { + MIXER_SRS_FLAG_SR_LIMITS, + sadasupport_mixer_srs +}; + +#if 0 +static am_ad_sample_rates_t sadasupport_compat_sample_rates = { + MIXER_SRS_FLAG_SR_NOT_LIMITS, + sadasupport_compat_srs +}; +#endif + +typedef struct +{ + oss_device_t *osdev; + kmutex_t inst_lock; + +/* + * Fields related with the OSS audio device + */ + + volatile int audio_busy; + int audio_mode; + int oss_audiodev; + int play_frag; + int rec_frag; + int start_flags; + int sample_rate; + int mute; /* Play silence if mute is set */ + +/* + * Fields related with the audiosup and mixer modules. + */ + audiohdl_t audio_handle; + am_ad_info_t ad_info; /* audio device info state */ + uint16_t vol_bits_mask; /* bits used to ctrl volume */ + + audio_info_t audios_defaults; /* default state for dev */ + audio_device_t audios_dev_info; /* audio device info state */ +#ifndef SOL9 + ldi_handle_t lh; + ldi_ident_t li; +#endif +} sadasupport_devc; + +static sadasupport_devc *devc = NULL; +static struct fileinfo tmp_file = { 0 }; + +static am_ad_entry_t sadasupport_entry = { + NULL, /* ad_setup() */ + NULL, /* ad_teardown() */ + sadasupport_ad_set_config, /* ad_set_config() */ + sadasupport_ad_set_format, /* ad_set_format() */ + sadasupport_ad_start_play, /* ad_start_play() */ + sadasupport_ad_pause_play, /* ad_pause_play() */ + sadasupport_ad_stop_play, /* ad_stop_play() */ + sadasupport_ad_start_record, /* ad_start_record() */ + sadasupport_ad_stop_record, /* ad_stop_record() */ + NULL, /* ad_ioctl() */ + NULL /* ad_iocdata() */ +}; + +/* + * STREAMS structures + */ + +/* STREAMS driver id and limit value struct */ +static struct module_info sadasupport_modinfo = { + AUDIOS_IDNUM, /* module ID number */ + AUDIOS_NAME, /* module name */ + AUDIOS_MINPACKET, /* minimum packet size */ + AUDIOS_MAXPACKET, /* maximum packet size */ + AUDIOS_HIWATER, /* high water mark */ + AUDIOS_LOWATER, /* low water mark */ +}; + +/* STREAMS queue processing procedures structures */ +/* read queue */ +static struct qinit sadasupport_rqueue = { + audio_sup_rput, /* put procedure */ + audio_sup_rsvc, /* service procedure */ + sadasupport_open, /* open procedure */ + sadasupport_close, /* close procedure */ + NULL, /* unused */ + &sadasupport_modinfo, /* module parameters */ + NULL /* module statistics */ +}; + +/* write queue */ +static struct qinit sadasupport_wqueue = { + audio_sup_wput, /* write procedure */ + audio_sup_wsvc, /* service procedure */ + NULL, /* open procedure */ + NULL, /* close procedure */ + NULL, /* unused */ + &sadasupport_modinfo, /* module parameters */ + NULL /* module statistics */ +}; + +/* STREAMS entity declaration structure */ +struct streamtab oss_sadasupport_str_info = { + &sadasupport_rqueue, /* read queue */ + &sadasupport_wqueue, /* write queue */ + NULL, /* mux lower read queue */ + NULL, /* mux lower write queue */ +}; + +/*ARGSUSED*/ +static void +input_callback (int dev, int parm) +{ + dmap_p dmap; + adev_p adev; + unsigned char *buf; + int samples, i; + oss_native_word flags; + + adev = audio_engines[dev]; + dmap = adev->dmap_in; + + if (dmap->dmabuf == NULL) + { + cmn_err (CE_WARN, "Dmabuf==NULL\n"); + return; + } + + MUTEX_ENTER (dmap->mutex, flags); + + samples = dmap->fragment_size / 2; /* Number of 16 bit samples */ + + buf = dmap->dmabuf + devc->rec_frag * dmap->fragment_size; + + if (dmap->nfrags == 0) + { + cmn_err (CE_WARN, "Nfrags==0\n"); + MUTEX_EXIT (dmap->mutex, flags); + return; + } + + devc->rec_frag = (devc->rec_frag + 1) % dmap->nfrags; + dmap->user_counter += dmap->fragment_size; + MUTEX_EXIT (dmap->mutex, flags); + + /* Perform byte swapping (if necessary) */ + if (do_byteswap) + for (i = 0; i < samples * 2; i += 2) + { + unsigned char tmp; + + tmp = buf[i]; + buf[i] = buf[i + 1]; + buf[i + 1] = tmp; + } + am_send_audio (devc->audio_handle, buf, AUDIO_NO_CHANNEL, samples); + +} + +static int fill_play_buf (sadasupport_devc * devc); + +/*ARGSUSED*/ +static void +output_callback (int dev, int parm) +{ + fill_play_buf (devc); +} + +static int +setup_device (sadasupport_devc * devc) +{ + int fmt = AFMT_S16_NE; + int ch = 2; + int rate = devc->sample_rate; + int mode; + + devc->mute = 0; /* Unmute every time the device gets opened */ + + mode = 0; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_COOKEDMODE, + (ioctl_arg) & mode); + +#if 0 + int frag; + + //frag=0x0002000d; /* Two 8k fragments */ + frag = 0x0008000a; /* 1k fragments */ + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETFRAGMENT, + (ioctl_arg) & frag); +#endif + + do_byteswap = 0; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETFMT, + (ioctl_arg) & fmt); + if (fmt != AFMT_S16_NE) + { + fmt = AFMT_S16_OE; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETFMT, + (ioctl_arg) & fmt); + if (fmt != AFMT_S16_OE) + { + cmn_err (CE_WARN, "Internal error (format=%x)\n", fmt); + return AUDIO_FAILURE; + } + do_byteswap = 1; + } + + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_CHANNELS, + (ioctl_arg) & ch); + if (ch != 2) + { + cmn_err (CE_WARN, "Internal error (channels=%d)\n", ch); + return AUDIO_FAILURE; + } + + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SPEED, + (ioctl_arg) & rate); + if (rate != devc->sample_rate) + { +/* + * Disabling SADA mixing/src may cause problems if the application wants + * to use rate that is not supported by the device itself. In that case + * we need to switch to the rate returned by the device. + */ + cmn_err (CE_WARN, "Returned sample rate %d is different than requested %d)\n", rate, + devc->sample_rate); + cmn_err (CE_CONT, "Switching to %d\n", rate); + devc->sample_rate = rate; + // return AUDIO_FAILURE; + } + + return AUDIO_SUCCESS; +} + +#ifndef SOL9 +static int +sadasupport_open (queue_t * q, dev_t * devp, int flag, int sflag, + cred_t * credp) +{ + int retval, i; + int devnum; + int dev = *devp; + char *cmd; + unsigned int bl_flags = 0; + int oss_mode = 0; + + DDB (cmn_err + (CE_CONT, "sadasupport_open(dev=%x, flag=%x, sflag=%x)\n", + dev, flag, sflag)); + + if (devc == NULL) + return EIO; + + oss_mode = OPEN_READWRITE; + + mutex_enter (&devc->inst_lock); + + if (devc->audio_busy++ == 0) + { + oss_audioinfo ai; + int err; + + mutex_exit (&devc->inst_lock); + + tmp_file.acc_flags = 0; + tmp_file.mode = oss_mode; + + devc->audio_mode = tmp_file.mode; + + DDB (cmn_err (CE_CONT, "Opening /dev/dsp (mode=%x)\n", tmp_file.mode)); + + if (ldi_ident_from_dev (dev, &devc->li) != 0) + { + cmn_err (CE_WARN, "ldi_ident_from_dev failed\n"); + devc->audio_busy--; + return EIO; + } + + if ((err = + ldi_open_by_name ("/dev/dsp", FWRITE | FREAD, credp, &devc->lh, + devc->li)) != 0) + { + cmn_err (CE_WARN, + "ldi_open_by_name(\"/dev/dsp\") failed, errno=%d\n", err); + devc->audio_busy--; + return -err; + } + + ai.dev = -1; + if ((err = + ldi_ioctl (devc->lh, SNDCTL_ENGINEINFO, (intptr_t) & ai, FKIOCTL, + credp, &retval)) != 0) + { + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + cmn_err (CE_WARN, "ldi_ioctl(SNDCTL_AUDIOINFO) failed, err=%d\n", + err); + devc->audio_busy--; + return err; + } + + devnum = ai.dev; + + DDB (cmn_err + (CE_CONT, "Opened OSS audio engine %d:%s\n", devnum, ai.name)); + + if (devnum < 0 || devnum >= num_audio_engines) + { + cmn_err (CE_WARN, "OSS audio engine number %d is out of range.\n", + devnum); + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + devc->audio_busy--; + return ENXIO; + } + + devc->oss_audiodev = devnum; + + if (tmp_file.mode & OPEN_READ) + audio_engines[devnum]->dmap_in->audio_callback = input_callback; + if (tmp_file.mode & OPEN_WRITE) + audio_engines[devnum]->dmap_out->audio_callback = output_callback; + strcpy (audio_engines[devnum]->cmd, "SADA"); + strcpy (audio_engines[devnum]->label, "SADA"); + audio_engines[devnum]->pid = 0; + + if ((retval = setup_device (devc)) != AUDIO_SUCCESS) + { + cmn_err (CE_NOTE, "setup_device failed\n"); + mutex_enter (&devc->inst_lock); + if (--devc->audio_busy == 0) + { + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + mutex_exit (&devc->inst_lock); + } + else + mutex_exit (&devc->inst_lock); + + return EIO; + } + } + else + { + if (oss_mode & ~devc->audio_mode) + { + cmn_err (CE_NOTE, "Conflicting access modes\n"); + + if (--devc->audio_busy == 0) + { + mutex_exit (&devc->inst_lock); + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + return EBUSY; + } + + mutex_exit (&devc->inst_lock); + return EBUSY; + } + + mutex_exit (&devc->inst_lock); + + } + + DDB (cmn_err (CE_CONT, "Open count %d\n", devc->audio_busy)); + + DDB (cmn_err + (CE_CONT, "audio_sup_open(q=%p, dev=%x, flag=%x, sflag=%x)\n", q, dev, + flag, sflag)); + if ((retval = audio_sup_open (q, devp, flag, sflag, credp)) != 0) + { + cmn_err (CE_NOTE, "audio_sup_open() returned %d\n", retval); + mutex_enter (&devc->inst_lock); + if (--devc->audio_busy == 0) + { + mutex_exit (&devc->inst_lock); + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + } + else + mutex_exit (&devc->inst_lock); + } + + return retval; +} + +static int +sadasupport_close (queue_t * q, int flag, cred_t * credp) +{ + int retval, count; + + DDB (cmn_err (CE_CONT, "sadasupport_close(q=%p, flag=%x)\n", q, flag)); + + if (!devc->audio_busy) + cmn_err (CE_WARN, "Close while not busy.\n"); + + retval = audio_sup_close (q, flag, credp); + + mutex_enter (&devc->inst_lock); + count = --devc->audio_busy; + mutex_exit (&devc->inst_lock); + + DDB (cmn_err (CE_CONT, "Open count (close) %d\n", count)); + if (count == 0) + { + DDB (cmn_err + (CE_CONT, "Closing OSS audiodev %d\n", devc->oss_audiodev)); + ldi_close (devc->lh, FREAD | FWRITE, credp); + ldi_ident_release (devc->li); + devc->audio_mode = 0; + } + + return retval; +} +#else +#include "sadasupport_sol9.h" +#endif + +static void +set_port (sadasupport_devc * devc, int dir, int port) +{ + int recdev = SOUND_MASK_MIC; + + if (dir == AUDIO_PLAY) /* Don't support this */ + return; + + switch (port) + { + case AUDIO_MICROPHONE: + recdev = SOUND_MASK_MIC; + break; + case AUDIO_LINE_IN: + recdev = SOUND_MASK_LINE; + break; + case AUDIO_CD: + recdev = SOUND_MASK_CD; + break; + } + + oss_audio_ioctl (devc->oss_audiodev, NULL, SOUND_MIXER_WRITE_RECSRC, + (ioctl_arg) & recdev); + /* Let's hope that worked */ +} + +static void +set_gain (sadasupport_devc * devc, int dir, int gain, int channel) +{ + int cmd; + int val; + + if (gain < 0) + gain = 0; + if (gain > 255) + gain = 255; + + gain = (gain * 100) / 255; + + if (dir == AUDIO_PLAY) + cmd = SNDCTL_DSP_GETPLAYVOL; + else + cmd = SNDCTL_DSP_GETRECVOL; + + if (oss_audio_ioctl (devc->oss_audiodev, NULL, cmd, (ioctl_arg) & val) < 0) + return; + + switch (channel) + { + case 0: /* Left channel */ + val = (val & 0xff00) | gain; + break; + + case 1: /* Right channel */ + val = (val & 0x00ff) | (gain << 8); + break; + } + + if (dir == AUDIO_PLAY) + cmd = SNDCTL_DSP_SETPLAYVOL; + else + cmd = SNDCTL_DSP_SETRECVOL; + + oss_audio_ioctl (devc->oss_audiodev, NULL, cmd, (ioctl_arg) & val); +} + +/*ARGSUSED*/ +static void +set_monitor_gain (sadasupport_devc * devc, int gain) +{ + /* NOP. SADA applications are not allowed to change monitor gain. */ +} + +/*ARGSUSED*/ +static int +sadasupport_ad_set_config (audiohdl_t ahandle, int stream, int command, + int dir, int arg1, int arg2) +{ +/* + * We do not support most gain settings. They are incompatible with the way + * how OSS 4.0 (and later) works. + */ + +#if 0 + typedef struct + { + uint_t cmd; + char *name; + } cmds_t; + + static const cmds_t cmds[] = { + {AM_SET_GAIN, "AM_SET_GAIN"}, + {AM_SET_GAIN_BAL, "AM_SET_GAIN_BAL"}, + {AM_SET_PORT, "AM_SET_PORT"}, + {AM_SET_MONITOR_GAIN, "AM_SET_MONITOR_GAIN"}, + {AM_OUTPUT_MUTE, "AM_OUTPUT_MUTE"}, + {AM_MONO_MIC, "AM_MONO_MIC"}, + {AM_MIC_BOOST, "AM_MIC_BOOST"}, + {AM_BASS_BOOST, "AM_BASS_BOOST"}, + {AM_MID_BOOST, "AM_MID_BOOST"}, + {AM_TREBLE_BOOST, "AM_TREBLE_BOOST"}, + {AM_LOUDNESS, "AM_LOUDNESS"}, + {AM_SET_DIAG_MODE, "AM_SET_DIAG_MODE"}, + {0, NULL} + }; +#endif + + if (devc->audio_mode == 0) + return AUDIO_SUCCESS; + + switch (command) + { + case AM_SET_PORT: + set_port (devc, dir, arg1); + break; + + case AM_SET_GAIN_BAL: + return AUDIO_FAILURE; + break; + + case AM_SET_GAIN: + set_gain (devc, dir, arg1, arg2); + break; + + case AM_SET_MONITOR_GAIN: + set_monitor_gain (devc, arg1); + break; + + case AM_OUTPUT_MUTE: + devc->mute = arg1; + break; + + default: +#if 0 + int i; + + cmn_err (CE_CONT, + "sadasupport_ad_set_config(stream=%d, cmd=%x, dir=%d, arg1=%x, arg2=%x)\n", + stream, command, dir, arg1, arg2); + + for (i = 0; cmds[i].cmd != 0; i++) + if (cmds[i].cmd == command) + { + cmn_err (CE_CONT, " Unsupported mixer command =%s\n", + cmds[i].name); + break; + } +#endif + break; + } + return AUDIO_SUCCESS; +} + +/*ARGSUSED*/ +static int +sadasupport_ad_set_format (audiohdl_t ahandle, int stream, int dir, + int sample_rate, int channels, int precision, + int encoding) +{ + + DDB (cmn_err (CE_CONT, + "sadasupport_ad_set_format(stream=%d, dir=%d, sr=%d, ch=%d, prec=%d, enc=%d)\n", + stream, dir, sample_rate, channels, precision, encoding)); + + if (precision != AUDIO_PRECISION_16) + { + cmn_err (CE_WARN, "Sample size must be 16 bits.\n"); + return AUDIO_FAILURE; + } + + if (channels != AUDIO_CHANNELS_STEREO) + { + cmn_err (CE_WARN, "Channels must be stereo.\n"); + return AUDIO_FAILURE; + } + + if (encoding != AUDIO_ENCODING_LINEAR) + { + cmn_err (CE_WARN, "Channels must be stereo.\n"); + return AUDIO_FAILURE; + } + + devc->sample_rate = sample_rate; + + return AUDIO_SUCCESS; +} + +static int +fill_play_buf (sadasupport_devc * devc) +{ + int rs; + int dev; + dmap_p dmap; + adev_p adev; + unsigned char *buf; + int samples, i; + oss_native_word flags; + + dev = devc->oss_audiodev; + + adev = audio_engines[dev]; + dmap = adev->dmap_out; + + if (dmap->dmabuf == NULL) + { + cmn_err (CE_WARN, "Dmabuf==NULL\n"); + return AUDIO_FAILURE; + } + + MUTEX_ENTER (dmap->mutex, flags); + + samples = dmap->fragment_size / 2; /* Number of 16 bit samples */ + + buf = dmap->dmabuf + devc->play_frag * dmap->fragment_size; + + if (dmap->nfrags == 0) + { + cmn_err (CE_WARN, "Nfrags==0\n"); + MUTEX_EXIT (dmap->mutex, flags); + return AUDIO_FAILURE; + } + + rs = am_get_audio (devc->audio_handle, buf, AUDIO_NO_CHANNEL, samples); + + if (devc->mute || rs == 0) /* Device paused or muted */ + { + memset (buf, 0, dmap->fragment_size); + } + else + { + /* Perform byte swapping (if necessary) */ + if (do_byteswap) + for (i = 0; i < samples * 2; i += 2) + { + unsigned char tmp; + + tmp = buf[i]; + buf[i] = buf[i + 1]; + buf[i + 1] = tmp; + } + } + + devc->play_frag = (devc->play_frag + 1) % dmap->nfrags; + dmap->user_counter += dmap->fragment_size; + MUTEX_EXIT (dmap->mutex, flags); + + return rs; +} + +/*ARGSUSED*/ +static int +sadasupport_ad_start_play (audiohdl_t ahandle, int stream) +{ + int dev; + dmap_p dmap; + adev_p adev; + + dev = devc->oss_audiodev; + + if (dev < 0 || dev >= num_audio_engines) + { + cmn_err (CE_CONT, "Bad oss_audiodev %d\n", dev); + return AUDIO_FAILURE; + } + + adev = audio_engines[dev]; + dmap = adev->dmap_out; + + mutex_enter (&devc->inst_lock); +/* + * Already playing? + */ + if (devc->start_flags & PCM_ENABLE_OUTPUT) + { + mutex_exit (&devc->inst_lock); + return 0; /* All buffers are full at this moment */ + } + + DDB (cmn_err (CE_CONT, "sadasupport_ad_start_play(stream=%d)\n", stream)); + +/* + * Skip the first fragment (fill with silence) to avoid underruns + */ + devc->play_frag = 1; + dmap->user_counter = dmap->fragment_size; + +/* + * Trigger the play engine + */ + dmap->dma_mode = PCM_ENABLE_OUTPUT; + devc->start_flags &= ~PCM_ENABLE_OUTPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + devc->start_flags |= PCM_ENABLE_OUTPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + + //dmap->user_counter += dmap->fragment_size; + devc->audios_defaults.play.buffer_size = dmap->fragment_size; + devc->ad_info.ad_play.ad_bsize = dmap->fragment_size; + + mutex_exit (&devc->inst_lock); + return fill_play_buf (devc); +} + +/*ARGSUSED*/ +static void +sadasupport_ad_stop_play (audiohdl_t ahandle, int stream) +{ + DDB (cmn_err (CE_CONT, "sadasupport_ad_stop_play (stream=%d)\n", stream)); + mutex_enter (&devc->inst_lock); + devc->start_flags &= ~PCM_ENABLE_OUTPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_HALT_OUTPUT, + (ioctl_arg) NULL); + mutex_exit (&devc->inst_lock); +} + +static void +sadasupport_ad_pause_play (audiohdl_t ahandle, int stream) +{ + DDB (cmn_err (CE_CONT, "sadasupport_ad_pause_play\n")); + + sadasupport_ad_stop_play (ahandle, stream); +} + +/*ARGSUSED*/ +static int +sadasupport_ad_start_record (audiohdl_t ahandle, int stream) +{ + int dev; + dmap_p dmap; + adev_p adev; + + dev = devc->oss_audiodev; + + if (dev < 0 || dev >= num_audio_engines) + { + cmn_err (CE_CONT, "Bad oss_audiodev %d\n", dev); + return AUDIO_FAILURE; + } + + mutex_enter (&devc->inst_lock); + adev = audio_engines[dev]; + dmap = adev->dmap_in; + +/* + * Already Recording? + */ + if (devc->start_flags & PCM_ENABLE_INPUT) + { + mutex_exit (&devc->inst_lock); + return AUDIO_SUCCESS; /* All buffers are full at this moment */ + } + + DDB (cmn_err (CE_CONT, "sadasupport_ad_start_record(stream=%d)\n", stream)); + +/* + * Skip the first fragment (fill with silence) to avoid underruns + */ + devc->rec_frag = 0; + dmap->user_counter = 0; + +/* + * Trigger the rec engine + */ + dmap->dma_mode = PCM_ENABLE_INPUT; + devc->start_flags &= ~PCM_ENABLE_INPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + devc->start_flags |= PCM_ENABLE_INPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + + devc->audios_defaults.record.buffer_size = dmap->fragment_size; + devc->ad_info.ad_record.ad_bsize = dmap->fragment_size; + + mutex_exit (&devc->inst_lock); + return AUDIO_SUCCESS; +} + +/*ARGSUSED*/ +static void +sadasupport_ad_stop_record (audiohdl_t ahandle, int stream) +{ + DDB (cmn_err (CE_CONT, "sadasupport_ad_stop_record(stream=%d)\n", stream)); + mutex_enter (&devc->inst_lock); + devc->start_flags &= ~PCM_ENABLE_INPUT; + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_SETTRIGGER, + (ioctl_arg) & devc->start_flags); + oss_audio_ioctl (devc->oss_audiodev, NULL, SNDCTL_DSP_HALT_INPUT, + (ioctl_arg) NULL); + mutex_exit (&devc->inst_lock); +} + +static int +sadasupport_init_state (sadasupport_devc * devc, dev_info_t * dip) +{ + int rints = 175; + int pints = 175; + int cdrom; + int mode; + + devc->vol_bits_mask = 5; + + cdrom = ddi_prop_get_int (DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + "cdrom", 0); + + /* get the mode from the .conf file */ + if (ddi_prop_get_int (DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + "mixer-mode", 1)) + { + mode = AM_MIXER_MODE; + } + else + { + mode = AM_COMPAT_MODE; + } + + /* fill in the device default state */ + devc->audios_defaults.play.sample_rate = AUDIOS_DEFAULT_SR; + devc->audios_defaults.play.channels = AUDIOS_DEFAULT_CH; + devc->audios_defaults.play.precision = AUDIOS_DEFAULT_PREC; + devc->audios_defaults.play.encoding = AUDIOS_DEFAULT_ENC; + devc->audios_defaults.play.gain = AUDIOS_DEFAULT_PGAIN; + devc->audios_defaults.play.port = AUDIO_SPEAKER | AUDIO_LINE_OUT; + devc->audios_defaults.play.avail_ports = AUDIO_SPEAKER | AUDIO_LINE_OUT; + devc->audios_defaults.play.mod_ports = AUDIO_SPEAKER | AUDIO_LINE_OUT; + devc->audios_defaults.play.buffer_size = AUDIOS_BUFFSIZE; + devc->audios_defaults.play.balance = AUDIOS_DEFAULT_BAL; + + devc->audios_defaults.record.sample_rate = AUDIOS_DEFAULT_SR; + devc->audios_defaults.record.channels = AUDIOS_DEFAULT_CH; + devc->audios_defaults.record.precision = AUDIOS_DEFAULT_PREC; + devc->audios_defaults.record.encoding = AUDIOS_DEFAULT_ENC; + devc->audios_defaults.record.gain = AUDIOS_DEFAULT_PGAIN; + devc->audios_defaults.record.port = AUDIO_MICROPHONE; + devc->audios_defaults.record.avail_ports = + AUDIO_MICROPHONE | AUDIO_LINE_IN | AUDIO_CD; + devc->audios_defaults.record.mod_ports = + AUDIO_MICROPHONE | AUDIO_LINE_IN | AUDIO_CD; + devc->audios_defaults.record.buffer_size = AUDIOS_BUFFSIZE; + devc->audios_defaults.record.balance = AUDIOS_DEFAULT_BAL; + + devc->audios_defaults.monitor_gain = AUDIOS_DEFAULT_MONITOR_GAIN; + devc->audios_defaults.output_muted = B_FALSE; + devc->audios_defaults.ref_cnt = B_FALSE; + devc->audios_defaults.hw_features = + AUDIO_HWFEATURE_DUPLEX | AUDIO_HWFEATURE_PLAY | + AUDIO_HWFEATURE_IN2OUT | AUDIO_HWFEATURE_RECORD; + devc->audios_defaults.sw_features = AUDIO_SWFEATURE_MIXER; + + if (cdrom) + { + devc->audios_defaults.record.avail_ports |= AUDIO_CD; + devc->audios_defaults.record.mod_ports |= AUDIO_CD; + } + +#if 0 + devc->audios_psample_rate = devc->audios_defaults.play.sample_rate; + devc->audios_pchannels = devc->audios_defaults.play.channels; + devc->audios_pprecision = devc->audios_defaults.play.precision; + devc->audios_csample_rate = devc->audios_defaults.record.sample_rate; + devc->audios_cchannels = devc->audios_defaults.record.channels; + devc->audios_cprecision = devc->audios_defaults.record.precision; +#endif + + /* + * fill in the ad_info structure + */ + devc->ad_info.ad_mode = mode; + devc->ad_info.ad_int_vers = AM_VERSION; + devc->ad_info.ad_add_mode = NULL; + devc->ad_info.ad_codec_type = AM_TRAD_CODEC; + devc->ad_info.ad_defaults = &devc->audios_defaults; + devc->ad_info.ad_play_comb = sadasupport_combinations; + devc->ad_info.ad_rec_comb = sadasupport_combinations; + devc->ad_info.ad_entry = &sadasupport_entry; + devc->ad_info.ad_dev_info = &devc->audios_dev_info; + devc->ad_info.ad_diag_flags = AM_DIAG_INTERNAL_LOOP; + devc->ad_info.ad_diff_flags = + AM_DIFF_SR | AM_DIFF_CH | AM_DIFF_PREC | AM_DIFF_ENC; + devc->ad_info.ad_assist_flags = AM_ASSIST_MIC; + devc->ad_info.ad_misc_flags = AM_MISC_RP_EXCL | AM_MISC_MONO_DUP; + devc->ad_info.ad_translate_flags = + AM_MISC_8_P_TRANSLATE | AM_MISC_8_R_TRANSLATE; + devc->ad_info.ad_num_mics = 1; + + /* play capabilities */ + devc->ad_info.ad_play.ad_mixer_srs = sadasupport_mixer_sample_rates; + + devc->ad_info.ad_play.ad_compat_srs = sadasupport_mixer_sample_rates; + +#ifdef SOL9 + devc->ad_info.ad_play.ad_conv = &am_src1; + devc->ad_info.ad_play.ad_sr_info = sadasupport_play_sample_rates_info; +#else + devc->ad_info.ad_play.ad_conv = &am_src2; + devc->ad_info.ad_play.ad_sr_info = NULL; +#endif + devc->ad_info.ad_play.ad_chs = sadasupport_channels; + devc->ad_info.ad_play.ad_int_rate = pints; + devc->ad_info.ad_play.ad_max_chs = 32; + devc->ad_info.ad_play.ad_bsize = AUDIOS_BUFFSIZE; + + /* record capabilities */ + devc->ad_info.ad_record.ad_mixer_srs = sadasupport_mixer_sample_rates; + devc->ad_info.ad_record.ad_compat_srs = sadasupport_mixer_sample_rates; +#ifdef SOL9 + devc->ad_info.ad_record.ad_conv = &am_src1; + devc->ad_info.ad_record.ad_sr_info = sadasupport_record_sample_rates_info; +#else + devc->ad_info.ad_record.ad_conv = &am_src2; + devc->ad_info.ad_record.ad_sr_info = NULL; +#endif + devc->ad_info.ad_record.ad_chs = sadasupport_channels; + devc->ad_info.ad_record.ad_int_rate = rints; + devc->ad_info.ad_record.ad_max_chs = 32; + devc->ad_info.ad_record.ad_bsize = AUDIOS_BUFFSIZE; + + /* fill in device info strings */ + (void) strcpy (devc->audios_dev_info.name, AUDIOS_DEV_NAME); + (void) strcpy (devc->audios_dev_info.config, AUDIOS_DEV_CONFIG); + (void) strcpy (devc->audios_dev_info.version, AUDIOS_DEV_VERSION); + +#if 0 + devc->play_buf_size = AUDIOS_SAMPR48000 * AUDIO_CHANNELS_STEREO * + (AUDIO_PRECISION_16 >> AUDIO_PRECISION_SHIFT) / pints; + devc->play_buf_size += AUDIOS_MOD_SIZE - + (devc->play_buf_size % AUDIOS_MOD_SIZE); + devc->record_buf_size = AUDIOS_SAMPR48000 * AUDIO_CHANNELS_STEREO * + (AUDIO_PRECISION_16 >> AUDIO_PRECISION_SHIFT) / rints; + devc->record_buf_size += AUDIOS_MOD_SIZE - + (devc->record_buf_size % AUDIOS_MOD_SIZE); +#endif + return (AUDIO_SUCCESS); + +} /* sadasupport_init_state */ + +int +oss_sadasupport_attach (oss_device_t * osdev) +{ +#ifndef SOL9 + audio_sup_reg_data_t data; +#endif + int instance; + /* extern struct cb_ops ossdrv_streams_cb_ops; */ + + sadasupport_mixer_srs[1] = sadasupport_rate; /* Set the maximum rate */ + + instance = ddi_get_instance (osdev->dip); + + DDB (cmn_err (CE_CONT, "sadasupport_attach\n")); + + if (devc != NULL) + { + cmn_err (CE_WARN, "Multiple instances are not permitted\n"); + return 0; + } + + devc = PMALLOC (osdev, sizeof (*devc)); + devc->osdev = osdev; + devc->oss_audiodev = -1; + devc->start_flags = 0; + mutex_init (&devc->inst_lock, NULL, MUTEX_DRIVER, NULL); + + osdev->devc = devc; + +#ifdef SOL9 + if ((devc->audio_handle = + audio_sup_attach (osdev->dip, DDI_ATTACH)) == NULL) + { + audio_sup_log (NULL, CE_WARN, + "!%s%d: attach() audio_sup_attach () failed", + DRIVER_NICK, instance); + return 0; + } + DDB (cmn_err (CE_CONT, "audio_sup_attach() OK, handle=%p\n", + devc->audio_handle)); +#else + data.asrd_version = AUDIOSUP_VERSION; + data.asrd_key = NULL; + + if ((devc->audio_handle = audio_sup_register (osdev->dip, &data)) == NULL) + { + audio_sup_log (NULL, CE_WARN, + "!%s%d: attach() audio_sup_register() failed", + DRIVER_NICK, instance); + return 0; + } + DDB (cmn_err (CE_CONT, "audio_sup_register() OK, handle=%x\n", + devc->audio_handle)); +#endif + /* Save private data */ + audio_sup_set_private (devc->audio_handle, devc); + + if ((sadasupport_init_state (devc, osdev->dip)) != AUDIO_SUCCESS) + { + audio_sup_log (devc->audio_handle, CE_WARN, + "!attach() init state structure failed"); + return 0; + } + + /* call the mixer attach() routine */ + if (am_attach (devc->audio_handle, DDI_ATTACH, &devc->ad_info) != + AUDIO_SUCCESS) + { + audio_sup_log (devc->audio_handle, CE_WARN, + "!attach() am_attach() failed"); + return 0; + } + + oss_register_device (osdev, "SADA compatibility layer"); + ddi_report_dev (osdev->dip); + +/* + * Take a copy of the callback options and replace the open/close + * entry points with our own version. + */ + + return 1; +} + +int +oss_sadasupport_detach (oss_device_t * osdev) +{ + /* int instance; */ + sadasupport_devc *devc = osdev->devc; + + if (devc != NULL && devc->audio_busy) + return 0; + + /* instance = ddi_get_instance (osdev->dip); */ + +#if 0 + /* stop DMA engines */ + mutex_enter (&devc->inst_lock); + sadasupport_stop_dma (devc); + mutex_exit (&devc->inst_lock); + + /* remove the interrupt handler */ + ddi_remove_intr (dip, 0, devc->intr_iblock); + + /* free DMA memory */ + sadasupport_free_sample_buf (devc, &devc->play_buf); + sadasupport_free_sample_buf (devc, &devc->record_buf); + + /* free the kernel statistics structure */ + if (devc->audios_ksp) + { + kstat_delete (devc->audios_ksp); + } +#endif + /* detach audio mixer */ + (void) am_detach (devc->audio_handle, DDI_DETACH); + + /* + * call the audio support module's detach routine to remove this + * driver completely from the audio driver architecture. + */ +#ifdef SOL9 + (void) audio_sup_detach (devc->audio_handle, DDI_DETACH); +#else + (void) audio_sup_unregister (devc->audio_handle); +#endif + mutex_destroy (&devc->inst_lock); + devc = NULL; + + return 1; +} diff --git a/kernel/drv/oss_sadasupport/oss_sadasupport.man b/kernel/drv/oss_sadasupport/oss_sadasupport.man new file mode 100644 index 0000000..4cce53e --- /dev/null +++ b/kernel/drv/oss_sadasupport/oss_sadasupport.man @@ -0,0 +1,26 @@ +NAME +oss_sadasupport - Open Sound System to Sun "devaudio" converter driver. + +DESCRIPTION +Open Sound System driver Solaris "devaudio" or "SADA" compatibility. +This driver is a shim driver between SADA's audio core and amsrc2 (mixer) +and the OSS audio core. Currently playback, recording and mixer controls +of SADA/devaudio are supported by this driver. This driver essentially +translates between SADA audio and OSS audio. It relies on SADA to keep +track of complete audio information and then takes that information and +translates it into OSS API. This way, OSS drivers can achieve a 99.9% +emulation of SADA APIs. + +OPTIONS +No configuration options defined for the current version. + +KNOWN PROBLEMS +Mixer volume control (/dev/audioctl) emulation is very limited. It is only +possible to change the playback volume. Use native OSS mixers such as +ossxmix(1) for volume control and control panel functions. + +FILES +CONFIGFILEPATH/oss_sadasupport.conf Device configuration file + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_sadasupport/sadasupport_sol9.h b/kernel/drv/oss_sadasupport/sadasupport_sol9.h new file mode 100644 index 0000000..6bf7518 --- /dev/null +++ b/kernel/drv/oss_sadasupport/sadasupport_sol9.h @@ -0,0 +1,187 @@ +/* + * Purpose: Solaris 9 compatible version of sadasupport_open/close + */ +/* + * + * 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. + * + */ + +static int +sadasupport_open (queue_t * q, dev_t * devp, int flag, int sflag, + cred_t * credp) +{ + int retval, i; + int tmpdev; + int dev = *devp; + char *cmd; + unsigned int bl_flags = 0; + int oss_mode = 0; +#ifndef SOL9 + extern void oss_forceload_drivers (int dev, cred_t * cred_p); +#endif + + DDB (cmn_err + (CE_CONT, "sadasupport_open(q=%x, dev=%x, flag=%x, sflag=%x)\n", q, + dev, flag, sflag)); + + cmd = oss_get_procname (); + DDB (cmn_err (CE_CONT, "Command %s\n", cmd)); + + if (devc == NULL) + return EIO; + + oss_mode = OPEN_READWRITE; + + mutex_enter (&devc->inst_lock); + + if (devc->audio_busy++ == 0) + { + mutex_exit (&devc->inst_lock); + + tmp_file.acc_flags = 0; + tmp_file.mode = oss_mode; + + tmpdev = 0; + devc->audio_mode = tmp_file.mode; +#if 0 + DDB (cmn_err (CE_CONT, "Opening OSS audio device file %d (mode=%x)\n", + devc->masterdev, tmp_file.mode)); + + if (devc->masterdev >= 0 && devc->masterdev < num_audio_devfiles) +#endif + { + /* Open /dev/dsp# */ + tmp_file.mode = oss_mode = OPEN_READ | OPEN_WRITE; + if ((retval = + oss_audio_open_devfile (0, OSS_DEV_DSP, + &tmp_file, 1, OF_DEVAUDIO, + &tmpdev)) < 0) + { + mutex_enter (&devc->inst_lock); + devc->audio_busy = 0; + mutex_exit (&devc->inst_lock); + return -retval; + } + } +#if 0 + else + + { + /* Open /dev/dsp */ + + if ((retval = + oss_open_vdsp (0, OSS_DEV_VDSP, &tmp_file, 1, OF_DEVAUDIO, + &tmpdev)) < 0) + { + mutex_enter (&devc->inst_lock); + devc->audio_busy = 0; + mutex_exit (&devc->inst_lock); + return -retval; + } + } +#endif + DDB (cmn_err + (CE_CONT, "Opened OSS audio engine %d, minor=%d\n", retval, + tmpdev)); + + devc->oss_audiodev = retval; + + if (tmp_file.mode & OPEN_READ) + audio_engines[retval]->dmap_in->audio_callback = input_callback; + if (tmp_file.mode & OPEN_WRITE) + audio_engines[retval]->dmap_out->audio_callback = output_callback; + strcpy (audio_engines[retval]->cmd, "SADA"); + strcpy (audio_engines[retval]->label, "SADA"); + audio_engines[retval]->pid = 0; + + if ((retval = setup_device (devc)) != AUDIO_SUCCESS) + { + cmn_err (CE_NOTE, "setup_device failed\n"); + mutex_enter (&devc->inst_lock); + if (--devc->audio_busy == 0) + { + mutex_exit (&devc->inst_lock); + oss_audio_release (devc->oss_audiodev, &tmp_file); + } + else + mutex_exit (&devc->inst_lock); + + return EIO; + } + } + else + { + if (oss_mode & ~devc->audio_mode) + { + cmn_err (CE_NOTE, "Conflicting access modes\n"); + + if (--devc->audio_busy == 0) + { + mutex_exit (&devc->inst_lock); + oss_audio_release (devc->oss_audiodev, &tmp_file); + return EBUSY; + } + + mutex_exit (&devc->inst_lock); + return EBUSY; + } + + mutex_exit (&devc->inst_lock); + + } + + DDB (cmn_err (CE_CONT, "Open count %d\n", devc->audio_busy)); + + DDB (cmn_err + (CE_CONT, "audio_sup_open(q=%x, dev=%x, flag=%x, sflag=%x)\n", q, dev, + flag, sflag)); + if ((retval = audio_sup_open (q, devp, flag, sflag, credp)) != 0) + { + cmn_err (CE_NOTE, "audio_sup_open() returned %d\n", retval); + mutex_enter (&devc->inst_lock); + if (--devc->audio_busy == 0) + { + mutex_exit (&devc->inst_lock); + oss_audio_release (devc->oss_audiodev, &tmp_file); + } + else + mutex_exit (&devc->inst_lock); + } + + return retval; +} + +static int +sadasupport_close (queue_t * q, int flag, cred_t * credp) +{ + int retval, count; + + DDB (cmn_err (CE_CONT, "sadasupport_close(q=%x, flag=%x)\n", q, flag)); + + if (!devc->audio_busy) + cmn_err (CE_WARN, "Close while not busy.\n"); + + retval = audio_sup_close (q, flag, credp); + + mutex_enter (&devc->inst_lock); + count = --devc->audio_busy; + mutex_exit (&devc->inst_lock); + + DDB (cmn_err (CE_CONT, "Open count (close) %d\n", count)); + if (count == 0) + { + DDB (cmn_err + (CE_CONT, "Closing OSS audiodev %d\n", devc->oss_audiodev)); + oss_audio_release (devc->oss_audiodev, &tmp_file); + devc->audio_mode = 0; + } + + return retval; +} diff --git a/kernel/drv/oss_sblive/.devices b/kernel/drv/oss_sblive/.devices new file mode 100644 index 0000000..56d10f0 --- /dev/null +++ b/kernel/drv/oss_sblive/.devices @@ -0,0 +1,7 @@ +oss_sblive pci1102,2 Creative Sound Blaster Live +oss_sblive pcs1102,8040 Creative Sound Blaster Live 1024/Platinum +oss_sblive pcs1102,8061 Creative Sound Blaster Live 5.1/Platinum IR +oss_sblive pci1102,4 Creative Sound Blaster Audigy/Audigy2 +oss_sblive pcs1102,51 Creative Sound Blaster Audigy Platinum +oss_sblive pci1102,8 Creative Sound Blaster Audigy2 Value/Audigy4 +oss_sblive pci1102,2001 Creative Sound Blaster Audigy2 ZS PCMCIA diff --git a/kernel/drv/oss_sblive/.name b/kernel/drv/oss_sblive/.name new file mode 100644 index 0000000..2bcb686 --- /dev/null +++ b/kernel/drv/oss_sblive/.name @@ -0,0 +1 @@ +Creative Sound Blaster Live/Audigy diff --git a/kernel/drv/oss_sblive/.params b/kernel/drv/oss_sblive/.params new file mode 100644 index 0000000..7720436 --- /dev/null +++ b/kernel/drv/oss_sblive/.params @@ -0,0 +1,25 @@ +int sblive_memlimit = 8; +/* + * Amount of memory allocated to SBLive Synth. + * Values: 4-4096 (in megabytes). Default: 8MB + */ + +int sblive_devices = 0; +/* + * Specifies number of audio output engines for SBLive/Audigy. + * Changing this setting is not recommanded. + * Values: 0, 5-32 + * Default: 0 (Use device dependent optimum value). + */ + +int sblive_digital_din = 0; +/* + * Sets the SPDIF/Analog combo output to audio or spdif mode + * Values: 1 = Digital, 0=Analog Default: 0 + */ + +int audigy_digital_din = 1; +/* + * Sets the SPDIF/Analog combo output to analog or spdif mode + * Values: 1 = Digital, 0 = Analog Default: 1 + */ diff --git a/kernel/drv/oss_sblive/emu10k1_dsp.h b/kernel/drv/oss_sblive/emu10k1_dsp.h new file mode 100644 index 0000000..87b4b3b --- /dev/null +++ b/kernel/drv/oss_sblive/emu10k1_dsp.h @@ -0,0 +1,989 @@ +/* + * Purpose: DSP firmware file for Live! + */ +/* + * + * 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. + * + */ +static unsigned char emu10k1_dsp[] = { + 0x01, 0x00, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, + 0x40, 0x18, 0x44, 0x00, 0x44, 0x04, 0x00, 0x00, 0x40, 0x1c, 0x44, 0x00, + 0x02, 0x19, 0x04, 0x00, + 0x40, 0x20, 0x04, 0x00, 0x03, 0x1d, 0x04, 0x00, 0x40, 0x24, 0x04, 0x00, + 0x44, 0x08, 0x00, 0x00, + 0x40, 0x28, 0x44, 0x00, 0x44, 0x0c, 0x00, 0x00, 0x40, 0x2c, 0x44, 0x00, + 0x02, 0x29, 0x04, 0x00, + 0x40, 0x28, 0x04, 0x00, 0x03, 0x2d, 0x04, 0x00, 0x40, 0x2c, 0x04, 0x00, + 0x36, 0x21, 0x04, 0x00, + 0x40, 0x30, 0x04, 0x00, 0x36, 0x25, 0x04, 0x00, 0x40, 0x34, 0x04, 0x00, + 0x40, 0x30, 0x04, 0x00, + 0x0c, 0x41, 0x94, 0x00, 0x10, 0xdd, 0x04, 0x00, 0x37, 0xdd, 0xa4, 0x00, + 0x40, 0x34, 0x04, 0x00, + 0x0d, 0x41, 0x94, 0x00, 0x10, 0xe1, 0x04, 0x00, 0x38, 0xe1, 0xa4, 0x00, + 0x30, 0x49, 0x00, 0x00, + 0x0c, 0x31, 0x04, 0x00, 0x30, 0x4d, 0x00, 0x00, 0x0d, 0x35, 0x04, 0x00, + 0x30, 0x49, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0xc5, 0x04, 0x00, + 0x31, 0xc5, 0xa4, 0x00, 0x30, 0x4d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0xc9, 0x04, 0x00, 0x32, 0xc9, 0xa4, 0x00, + 0x33, 0x41, 0x00, 0x00, + 0x0c, 0x31, 0x04, 0x00, 0x33, 0x45, 0x00, 0x00, 0x0d, 0x35, 0x04, 0x00, + 0x33, 0x41, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0xd1, 0x04, 0x00, + 0x34, 0xd1, 0xa4, 0x00, 0x33, 0x45, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0xd5, 0x04, 0x00, 0x35, 0xd5, 0xa4, 0x00, + 0x2d, 0x59, 0x00, 0x00, + 0x0c, 0x31, 0x04, 0x00, 0x2d, 0x5d, 0x00, 0x00, 0x0d, 0x35, 0x04, 0x00, + 0x2d, 0x59, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0xb9, 0x04, 0x00, + 0x2e, 0xb9, 0xa4, 0x00, 0x2d, 0x5d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0xbd, 0x04, 0x00, 0x2f, 0xbd, 0xa4, 0x00, + 0x2d, 0x59, 0x00, 0x00, + 0x0c, 0x31, 0x04, 0x00, 0x2d, 0x5d, 0x00, 0x00, 0x0d, 0x35, 0x04, 0x00, + 0x39, 0x71, 0x00, 0x00, + 0x0c, 0x31, 0x04, 0x00, 0x39, 0x75, 0x00, 0x00, 0x0d, 0x35, 0x04, 0x00, + 0x39, 0x71, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0xe9, 0x04, 0x00, + 0x3a, 0xe9, 0xa4, 0x00, 0x39, 0x75, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0xed, 0x04, 0x00, 0x3b, 0xed, 0xa4, 0x00, + 0x04, 0x31, 0x04, 0x00, + 0x40, 0x30, 0x04, 0x00, 0x05, 0x35, 0x04, 0x00, 0x40, 0x34, 0x04, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x0c, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x0c, 0xa1, 0x65, 0x00, + 0x16, 0xa5, 0x05, 0x00, + 0x40, 0xa4, 0x05, 0x00, 0x6e, 0xa5, 0x05, 0x00, 0x40, 0xa4, 0x05, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x82, 0x0d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x81, 0x09, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0x05, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x85, 0x19, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x84, 0x15, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x10, 0x66, 0x00, + 0x26, 0x05, 0x06, 0x00, + 0x40, 0x10, 0x06, 0x00, 0x27, 0x09, 0x06, 0x00, 0x84, 0x11, 0x06, 0x00, + 0x28, 0x15, 0x06, 0x00, + 0x84, 0x11, 0x06, 0x00, 0x29, 0x0d, 0x06, 0x00, 0x84, 0x11, 0x06, 0x00, + 0x2a, 0x19, 0x06, 0x00, + 0x84, 0x11, 0x06, 0x00, 0x6c, 0x11, 0x06, 0x00, 0x40, 0x10, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x84, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x7c, 0xf5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x7b, 0xf1, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0xed, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x7f, 0x01, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x7e, 0xfd, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0xf8, 0x65, 0x00, 0x21, 0xed, 0x05, 0x00, 0x40, 0xf8, 0x05, 0x00, + 0x22, 0xf1, 0x05, 0x00, + 0x7e, 0xf9, 0x05, 0x00, 0x23, 0xfd, 0x05, 0x00, 0x7e, 0xf9, 0x05, 0x00, + 0x24, 0xf5, 0x05, 0x00, + 0x7e, 0xf9, 0x05, 0x00, 0x25, 0x01, 0x06, 0x00, 0x7e, 0xf9, 0x05, 0x00, + 0x6c, 0xf9, 0x05, 0x00, + 0x40, 0xf8, 0x45, 0x00, 0x40, 0x00, 0x01, 0x00, 0x7e, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x76, 0xdd, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x75, 0xd9, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0xd5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x79, 0xe9, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x78, 0xe5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0xe0, 0x65, 0x00, + 0x1c, 0xd5, 0x05, 0x00, + 0x40, 0xe0, 0x05, 0x00, 0x1d, 0xd9, 0x05, 0x00, 0x78, 0xe1, 0x05, 0x00, + 0x1e, 0xe5, 0x05, 0x00, + 0x78, 0xe1, 0x05, 0x00, 0x1f, 0xdd, 0x05, 0x00, 0x78, 0xe1, 0x05, 0x00, + 0x20, 0xe9, 0x05, 0x00, + 0x78, 0xe1, 0x05, 0x00, 0x6c, 0xe1, 0x05, 0x00, 0x40, 0xe0, 0x45, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x78, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x70, 0xc5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x6f, 0xc1, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0xbd, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x73, 0xd1, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x72, 0xcd, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0xc8, 0x65, 0x00, 0x17, 0xbd, 0x05, 0x00, 0x40, 0xc8, 0x05, 0x00, + 0x18, 0xc1, 0x05, 0x00, + 0x72, 0xc9, 0x05, 0x00, 0x19, 0xcd, 0x05, 0x00, 0x72, 0xc9, 0x05, 0x00, + 0x1a, 0xc5, 0x05, 0x00, + 0x72, 0xc9, 0x05, 0x00, 0x1b, 0xd1, 0x05, 0x00, 0x72, 0xc9, 0x05, 0x00, + 0x6c, 0xc9, 0x05, 0x00, + 0x40, 0xc8, 0x45, 0x00, 0x40, 0x00, 0x01, 0x00, 0x72, 0xa5, 0x65, 0x00, + 0x6d, 0xa5, 0x05, 0x00, + 0x6b, 0xa5, 0x45, 0x00, 0x2c, 0xa5, 0x05, 0x00, 0x40, 0x30, 0x44, 0x00, + 0x2b, 0xa1, 0x05, 0x00, + 0x0c, 0x31, 0x44, 0x00, 0x40, 0x00, 0x01, 0x00, 0x0d, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x0d, 0xa1, 0x65, 0x00, 0x16, 0xa5, 0x05, 0x00, 0x40, 0xa4, 0x05, 0x00, + 0x6e, 0xa5, 0x05, 0x00, + 0x40, 0xa4, 0x05, 0x00, 0x40, 0x00, 0x01, 0x00, 0x9a, 0x6d, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x99, 0x69, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0x65, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x9d, 0x79, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x9c, 0x75, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x70, 0x66, 0x00, 0x26, 0x65, 0x06, 0x00, 0x40, 0x70, 0x06, 0x00, + 0x27, 0x69, 0x06, 0x00, + 0x9c, 0x71, 0x06, 0x00, 0x28, 0x75, 0x06, 0x00, 0x9c, 0x71, 0x06, 0x00, + 0x29, 0x6d, 0x06, 0x00, + 0x9c, 0x71, 0x06, 0x00, 0x2a, 0x79, 0x06, 0x00, 0x9c, 0x71, 0x06, 0x00, + 0x6c, 0x71, 0x06, 0x00, + 0x40, 0x70, 0x46, 0x00, 0x40, 0x00, 0x01, 0x00, 0x9c, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x94, 0x55, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x93, 0x51, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0x4d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x97, 0x61, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x96, 0x5d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x58, 0x66, 0x00, + 0x21, 0x4d, 0x06, 0x00, + 0x40, 0x58, 0x06, 0x00, 0x22, 0x51, 0x06, 0x00, 0x96, 0x59, 0x06, 0x00, + 0x23, 0x5d, 0x06, 0x00, + 0x96, 0x59, 0x06, 0x00, 0x24, 0x55, 0x06, 0x00, 0x96, 0x59, 0x06, 0x00, + 0x25, 0x61, 0x06, 0x00, + 0x96, 0x59, 0x06, 0x00, 0x6c, 0x59, 0x06, 0x00, 0x40, 0x58, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x96, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x8e, 0x3d, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x8d, 0x39, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0x35, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x91, 0x49, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x90, 0x45, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x40, 0x66, 0x00, 0x1c, 0x35, 0x06, 0x00, 0x40, 0x40, 0x06, 0x00, + 0x1d, 0x39, 0x06, 0x00, + 0x90, 0x41, 0x06, 0x00, 0x1e, 0x45, 0x06, 0x00, 0x90, 0x41, 0x06, 0x00, + 0x1f, 0x3d, 0x06, 0x00, + 0x90, 0x41, 0x06, 0x00, 0x20, 0x49, 0x06, 0x00, 0x90, 0x41, 0x06, 0x00, + 0x6c, 0x41, 0x06, 0x00, + 0x40, 0x40, 0x46, 0x00, 0x40, 0x00, 0x01, 0x00, 0x90, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x88, 0x25, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x87, 0x21, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0x1d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x8b, 0x31, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x8a, 0x2d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x28, 0x66, 0x00, + 0x17, 0x1d, 0x06, 0x00, + 0x40, 0x28, 0x06, 0x00, 0x18, 0x21, 0x06, 0x00, 0x8a, 0x29, 0x06, 0x00, + 0x19, 0x2d, 0x06, 0x00, + 0x8a, 0x29, 0x06, 0x00, 0x1a, 0x25, 0x06, 0x00, 0x8a, 0x29, 0x06, 0x00, + 0x1b, 0x31, 0x06, 0x00, + 0x8a, 0x29, 0x06, 0x00, 0x6c, 0x29, 0x06, 0x00, 0x40, 0x28, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x8a, 0xa5, 0x65, 0x00, 0x6d, 0xa5, 0x05, 0x00, 0x6b, 0xa5, 0x45, 0x00, + 0x2c, 0xa5, 0x05, 0x00, + 0x40, 0x34, 0x44, 0x00, 0x2b, 0xa1, 0x05, 0x00, 0x0d, 0x35, 0x44, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x0c, 0x89, 0x60, 0x00, 0x40, 0x00, 0x01, 0x00, 0x0d, 0x8d, 0x60, 0x00, + 0x40, 0x30, 0x04, 0x00, + 0x0c, 0x41, 0x94, 0x00, 0x10, 0x99, 0x05, 0x00, 0x66, 0x99, 0xa5, 0x00, + 0x40, 0x34, 0x04, 0x00, + 0x0d, 0x41, 0x94, 0x00, 0x10, 0x9d, 0x05, 0x00, 0x67, 0x9d, 0xa5, 0x00, + 0x3c, 0x31, 0x04, 0x00, + 0x40, 0x80, 0x00, 0x00, 0x3d, 0x35, 0x04, 0x00, 0x40, 0x84, 0x00, 0x00, + 0x3c, 0x31, 0x04, 0x00, + 0x40, 0x98, 0x00, 0x00, 0x3d, 0x35, 0x04, 0x00, 0x40, 0x9c, 0x00, 0x00, + 0x3c, 0x31, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0xf9, 0x04, 0x00, + 0x3e, 0xf9, 0xa4, 0x00, 0x3d, 0x35, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0xfd, 0x04, 0x00, 0x3f, 0xfd, 0xa4, 0x00, + 0x49, 0x29, 0x04, 0x00, + 0x40, 0x28, 0x04, 0x00, 0x49, 0x2d, 0x04, 0x00, 0x40, 0x2c, 0x04, 0x00, + 0x40, 0x28, 0x04, 0x00, + 0x0a, 0x41, 0x94, 0x00, 0x10, 0x29, 0x05, 0x00, 0x4a, 0x29, 0xa5, 0x00, + 0x40, 0x2c, 0x04, 0x00, + 0x0b, 0x41, 0x94, 0x00, 0x10, 0x2d, 0x05, 0x00, 0x4b, 0x2d, 0xa5, 0x00, + 0x43, 0x49, 0x00, 0x00, + 0x0a, 0x29, 0x04, 0x00, 0x43, 0x4d, 0x00, 0x00, 0x0b, 0x2d, 0x04, 0x00, + 0x43, 0x49, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x11, 0x05, 0x00, + 0x44, 0x11, 0xa5, 0x00, 0x43, 0x4d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x15, 0x05, 0x00, 0x45, 0x15, 0xa5, 0x00, + 0x46, 0x41, 0x00, 0x00, + 0x0a, 0x29, 0x04, 0x00, 0x46, 0x45, 0x00, 0x00, 0x0b, 0x2d, 0x04, 0x00, + 0x46, 0x41, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x1d, 0x05, 0x00, + 0x47, 0x1d, 0xa5, 0x00, 0x46, 0x45, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x21, 0x05, 0x00, 0x48, 0x21, 0xa5, 0x00, + 0x40, 0x59, 0x00, 0x00, + 0x0a, 0x29, 0x04, 0x00, 0x40, 0x5d, 0x00, 0x00, 0x0b, 0x2d, 0x04, 0x00, + 0x40, 0x59, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x05, 0x05, 0x00, + 0x41, 0x05, 0xa5, 0x00, 0x40, 0x5d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x09, 0x05, 0x00, 0x42, 0x09, 0xa5, 0x00, + 0x4c, 0x71, 0x00, 0x00, + 0x0a, 0x29, 0x04, 0x00, 0x4c, 0x75, 0x00, 0x00, 0x0b, 0x2d, 0x04, 0x00, + 0x4c, 0x71, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x35, 0x05, 0x00, + 0x4d, 0x35, 0xa5, 0x00, 0x4c, 0x75, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x39, 0x05, 0x00, 0x4e, 0x39, 0xa5, 0x00, + 0x04, 0x29, 0x04, 0x00, + 0x40, 0x18, 0x04, 0x00, 0x05, 0x2d, 0x04, 0x00, 0x40, 0x1c, 0x04, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x06, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0x06, 0xa1, 0x65, 0x00, + 0x16, 0xa5, 0x05, 0x00, + 0x40, 0xa4, 0x05, 0x00, 0x6e, 0xa5, 0x05, 0x00, 0x40, 0xa4, 0x05, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xb2, 0xcd, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xb1, 0xc9, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0xc5, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xb5, 0xd9, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xb4, 0xd5, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0xd0, 0x66, 0x00, + 0x26, 0xc5, 0x06, 0x00, + 0x40, 0xd0, 0x06, 0x00, 0x27, 0xc9, 0x06, 0x00, 0xb4, 0xd1, 0x06, 0x00, + 0x28, 0xd5, 0x06, 0x00, + 0xb4, 0xd1, 0x06, 0x00, 0x29, 0xcd, 0x06, 0x00, 0xb4, 0xd1, 0x06, 0x00, + 0x2a, 0xd9, 0x06, 0x00, + 0xb4, 0xd1, 0x06, 0x00, 0x6c, 0xd1, 0x06, 0x00, 0x40, 0xd0, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xb4, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0xac, 0xb5, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xab, 0xb1, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0xad, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xaf, 0xc1, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xae, 0xbd, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0xb8, 0x66, 0x00, 0x21, 0xad, 0x06, 0x00, 0x40, 0xb8, 0x06, 0x00, + 0x22, 0xb1, 0x06, 0x00, + 0xae, 0xb9, 0x06, 0x00, 0x23, 0xbd, 0x06, 0x00, 0xae, 0xb9, 0x06, 0x00, + 0x24, 0xb5, 0x06, 0x00, + 0xae, 0xb9, 0x06, 0x00, 0x25, 0xc1, 0x06, 0x00, 0xae, 0xb9, 0x06, 0x00, + 0x6c, 0xb9, 0x06, 0x00, + 0x40, 0xb8, 0x46, 0x00, 0x40, 0x00, 0x01, 0x00, 0xae, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xa6, 0x9d, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xa5, 0x99, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0x95, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xa9, 0xa9, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xa8, 0xa5, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0xa0, 0x66, 0x00, + 0x1c, 0x95, 0x06, 0x00, + 0x40, 0xa0, 0x06, 0x00, 0x1d, 0x99, 0x06, 0x00, 0xa8, 0xa1, 0x06, 0x00, + 0x1e, 0xa5, 0x06, 0x00, + 0xa8, 0xa1, 0x06, 0x00, 0x1f, 0x9d, 0x06, 0x00, 0xa8, 0xa1, 0x06, 0x00, + 0x20, 0xa9, 0x06, 0x00, + 0xa8, 0xa1, 0x06, 0x00, 0x6c, 0xa1, 0x06, 0x00, 0x40, 0xa0, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xa8, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0xa0, 0x85, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x9f, 0x81, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0x7d, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xa3, 0x91, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xa2, 0x8d, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x88, 0x66, 0x00, 0x17, 0x7d, 0x06, 0x00, 0x40, 0x88, 0x06, 0x00, + 0x18, 0x81, 0x06, 0x00, + 0xa2, 0x89, 0x06, 0x00, 0x19, 0x8d, 0x06, 0x00, 0xa2, 0x89, 0x06, 0x00, + 0x1a, 0x85, 0x06, 0x00, + 0xa2, 0x89, 0x06, 0x00, 0x1b, 0x91, 0x06, 0x00, 0xa2, 0x89, 0x06, 0x00, + 0x6c, 0x89, 0x06, 0x00, + 0x40, 0x88, 0x46, 0x00, 0x40, 0x00, 0x01, 0x00, 0xa2, 0xa5, 0x65, 0x00, + 0x6d, 0xa5, 0x05, 0x00, + 0x6b, 0xa5, 0x45, 0x00, 0x2c, 0xa5, 0x05, 0x00, 0x40, 0x18, 0x44, 0x00, + 0x2b, 0xa1, 0x05, 0x00, + 0x06, 0x19, 0x44, 0x00, 0x40, 0x00, 0x01, 0x00, 0x07, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x07, 0xa1, 0x65, 0x00, 0x16, 0xa5, 0x05, 0x00, 0x40, 0xa4, 0x05, 0x00, + 0x6e, 0xa5, 0x05, 0x00, + 0x40, 0xa4, 0x05, 0x00, 0x40, 0x00, 0x01, 0x00, 0xca, 0x2d, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xc9, 0x29, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0x25, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xcd, 0x39, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0xcc, 0x35, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x30, 0x67, 0x00, 0x26, 0x25, 0x07, 0x00, 0x40, 0x30, 0x07, 0x00, + 0x27, 0x29, 0x07, 0x00, + 0xcc, 0x31, 0x07, 0x00, 0x28, 0x35, 0x07, 0x00, 0xcc, 0x31, 0x07, 0x00, + 0x29, 0x2d, 0x07, 0x00, + 0xcc, 0x31, 0x07, 0x00, 0x2a, 0x39, 0x07, 0x00, 0xcc, 0x31, 0x07, 0x00, + 0x6c, 0x31, 0x07, 0x00, + 0x40, 0x30, 0x47, 0x00, 0x40, 0x00, 0x01, 0x00, 0xcc, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xc4, 0x15, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0xc3, 0x11, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0x0d, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0xc7, 0x21, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xc6, 0x1d, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x18, 0x67, 0x00, + 0x21, 0x0d, 0x07, 0x00, + 0x40, 0x18, 0x07, 0x00, 0x22, 0x11, 0x07, 0x00, 0xc6, 0x19, 0x07, 0x00, + 0x23, 0x1d, 0x07, 0x00, + 0xc6, 0x19, 0x07, 0x00, 0x24, 0x15, 0x07, 0x00, 0xc6, 0x19, 0x07, 0x00, + 0x25, 0x21, 0x07, 0x00, + 0xc6, 0x19, 0x07, 0x00, 0x6c, 0x19, 0x07, 0x00, 0x40, 0x18, 0x47, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xc6, 0xa5, 0x65, 0x00, 0x40, 0x00, 0x01, 0x00, 0xbe, 0xfd, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xbd, 0xf9, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x69, 0xf5, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xc1, 0x09, 0x67, 0x00, 0x40, 0x00, 0x01, 0x00, 0xc0, 0x05, 0x67, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x67, 0x00, 0x1c, 0xf5, 0x06, 0x00, 0x40, 0x00, 0x07, 0x00, + 0x1d, 0xf9, 0x06, 0x00, + 0xc0, 0x01, 0x07, 0x00, 0x1e, 0x05, 0x07, 0x00, 0xc0, 0x01, 0x07, 0x00, + 0x1f, 0xfd, 0x06, 0x00, + 0xc0, 0x01, 0x07, 0x00, 0x20, 0x09, 0x07, 0x00, 0xc0, 0x01, 0x07, 0x00, + 0x6c, 0x01, 0x07, 0x00, + 0x40, 0x00, 0x47, 0x00, 0x40, 0x00, 0x01, 0x00, 0xc0, 0xa5, 0x65, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xb8, 0xe5, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xb7, 0xe1, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x69, 0xdd, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0xbb, 0xf1, 0x66, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xba, 0xed, 0x66, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0xe8, 0x66, 0x00, + 0x17, 0xdd, 0x06, 0x00, + 0x40, 0xe8, 0x06, 0x00, 0x18, 0xe1, 0x06, 0x00, 0xba, 0xe9, 0x06, 0x00, + 0x19, 0xed, 0x06, 0x00, + 0xba, 0xe9, 0x06, 0x00, 0x1a, 0xe5, 0x06, 0x00, 0xba, 0xe9, 0x06, 0x00, + 0x1b, 0xf1, 0x06, 0x00, + 0xba, 0xe9, 0x06, 0x00, 0x6c, 0xe9, 0x06, 0x00, 0x40, 0xe8, 0x46, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0xba, 0xa5, 0x65, 0x00, 0x6d, 0xa5, 0x05, 0x00, 0x6b, 0xa5, 0x45, 0x00, + 0x2c, 0xa5, 0x05, 0x00, + 0x40, 0x1c, 0x44, 0x00, 0x2b, 0xa1, 0x05, 0x00, 0x07, 0x1d, 0x44, 0x00, + 0x4f, 0x19, 0x04, 0x00, + 0x40, 0xa0, 0x00, 0x00, 0x50, 0x1d, 0x04, 0x00, 0x40, 0xa4, 0x00, 0x00, + 0x4f, 0x19, 0x04, 0x00, + 0x40, 0xb4, 0x00, 0x00, 0x50, 0x1d, 0x04, 0x00, 0x40, 0xb8, 0x00, 0x00, + 0x41, 0x10, 0x00, 0x00, + 0x40, 0x48, 0x44, 0x00, 0x41, 0x14, 0x00, 0x00, 0x40, 0x4c, 0x44, 0x00, + 0x4f, 0x19, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x45, 0x05, 0x00, + 0x51, 0x45, 0xa5, 0x00, 0x50, 0x1d, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x49, 0x05, 0x00, 0x52, 0x49, 0xa5, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x12, 0x91, 0x60, 0x00, 0x40, 0x00, 0x01, 0x00, 0x13, 0x95, 0x60, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x12, 0xc5, 0x60, 0x00, 0x40, 0x00, 0x01, 0x00, 0x13, 0xc9, 0x60, 0x00, + 0x59, 0x41, 0x00, 0x00, + 0x40, 0x18, 0x04, 0x00, 0x59, 0x45, 0x00, 0x00, 0x40, 0x1c, 0x04, 0x00, + 0x59, 0x41, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x69, 0x05, 0x00, + 0x5a, 0x69, 0xa5, 0x00, 0x59, 0x45, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x6d, 0x05, 0x00, 0x5b, 0x6d, 0xa5, 0x00, + 0x53, 0x59, 0x00, 0x00, + 0x06, 0x19, 0x04, 0x00, 0x53, 0x5d, 0x00, 0x00, 0x07, 0x1d, 0x04, 0x00, + 0x53, 0x59, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x51, 0x05, 0x00, + 0x54, 0x51, 0xa5, 0x00, 0x53, 0x5d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x55, 0x05, 0x00, 0x55, 0x55, 0xa5, 0x00, + 0x56, 0x49, 0x00, 0x00, + 0x06, 0x19, 0x04, 0x00, 0x56, 0x4d, 0x00, 0x00, 0x07, 0x1d, 0x04, 0x00, + 0x56, 0x49, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x5d, 0x05, 0x00, + 0x57, 0x5d, 0xa5, 0x00, 0x56, 0x4d, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x61, 0x05, 0x00, 0x58, 0x61, 0xa5, 0x00, + 0x5c, 0x21, 0x04, 0x00, + 0x06, 0x19, 0x04, 0x00, 0x5c, 0x25, 0x04, 0x00, 0x07, 0x1d, 0x04, 0x00, + 0x5c, 0x21, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x75, 0x05, 0x00, + 0x5d, 0x75, 0xa5, 0x00, 0x5c, 0x25, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x79, 0x05, 0x00, 0x5e, 0x79, 0xa5, 0x00, + 0x5f, 0x71, 0x00, 0x00, + 0x06, 0x19, 0x04, 0x00, 0x5f, 0x75, 0x00, 0x00, 0x07, 0x1d, 0x04, 0x00, + 0x5f, 0x71, 0x00, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x81, 0x05, 0x00, + 0x60, 0x81, 0xa5, 0x00, 0x5f, 0x75, 0x00, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x85, 0x05, 0x00, 0x61, 0x85, 0xa5, 0x00, + 0x62, 0x19, 0x04, 0x00, + 0x40, 0xa8, 0x00, 0x00, 0x63, 0x1d, 0x04, 0x00, 0x40, 0xac, 0x00, 0x00, + 0x62, 0x19, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, 0x11, 0x41, 0x94, 0x00, + 0x10, 0x91, 0x05, 0x00, + 0x64, 0x91, 0xa5, 0x00, 0x63, 0x1d, 0x04, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x40, 0x44, 0x04, 0x00, + 0x11, 0x41, 0x94, 0x00, 0x10, 0x95, 0x05, 0x00, 0x65, 0x95, 0xa5, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x40, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, + 0x30, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x45, 0x51, 0x55, 0x41, + 0x4c, 0x49, 0x5a, 0x45, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x45, 0x53, 0x43, 0x41, 0x4c, 0x45, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, + 0x4c, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, + 0x4d, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x48, 0x49, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x00, 0x00, 0x58, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x00, 0x00, + 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x52, 0x4f, 0x4e, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x55, 0x52, 0x52, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x4d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4f, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x59, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, + 0x64, 0x64, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x6b, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x6d, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/kernel/drv/oss_sblive/emu10k1_dsp_be.h b/kernel/drv/oss_sblive/emu10k1_dsp_be.h new file mode 100644 index 0000000..ea8769b --- /dev/null +++ b/kernel/drv/oss_sblive/emu10k1_dsp_be.h @@ -0,0 +1,989 @@ +/* + * Purpose: DSP firmware file for Live! (big endian machines) + */ +/* + * + * 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. + * + */ +static unsigned char emu10k1_dsp[] = { + 0x00, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x96, + 0x00, 0x00, 0x00, 0x44, + 0x00, 0x44, 0x18, 0x40, 0x00, 0x00, 0x04, 0x44, 0x00, 0x44, 0x1c, 0x40, + 0x00, 0x04, 0x19, 0x02, + 0x00, 0x04, 0x20, 0x40, 0x00, 0x04, 0x1d, 0x03, 0x00, 0x04, 0x24, 0x40, + 0x00, 0x00, 0x08, 0x44, + 0x00, 0x44, 0x28, 0x40, 0x00, 0x00, 0x0c, 0x44, 0x00, 0x44, 0x2c, 0x40, + 0x00, 0x04, 0x29, 0x02, + 0x00, 0x04, 0x28, 0x40, 0x00, 0x04, 0x2d, 0x03, 0x00, 0x04, 0x2c, 0x40, + 0x00, 0x04, 0x21, 0x36, + 0x00, 0x04, 0x30, 0x40, 0x00, 0x04, 0x25, 0x36, 0x00, 0x04, 0x34, 0x40, + 0x00, 0x04, 0x30, 0x40, + 0x00, 0x94, 0x41, 0x0c, 0x00, 0x04, 0xdd, 0x10, 0x00, 0xa4, 0xdd, 0x37, + 0x00, 0x04, 0x34, 0x40, + 0x00, 0x94, 0x41, 0x0d, 0x00, 0x04, 0xe1, 0x10, 0x00, 0xa4, 0xe1, 0x38, + 0x00, 0x00, 0x49, 0x30, + 0x00, 0x04, 0x31, 0x0c, 0x00, 0x00, 0x4d, 0x30, 0x00, 0x04, 0x35, 0x0d, + 0x00, 0x00, 0x49, 0x30, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x04, 0xc5, 0x10, + 0x00, 0xa4, 0xc5, 0x31, 0x00, 0x00, 0x4d, 0x30, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x04, 0xc9, 0x10, 0x00, 0xa4, 0xc9, 0x32, + 0x00, 0x00, 0x41, 0x33, + 0x00, 0x04, 0x31, 0x0c, 0x00, 0x00, 0x45, 0x33, 0x00, 0x04, 0x35, 0x0d, + 0x00, 0x00, 0x41, 0x33, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x04, 0xd1, 0x10, + 0x00, 0xa4, 0xd1, 0x34, 0x00, 0x00, 0x45, 0x33, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x04, 0xd5, 0x10, 0x00, 0xa4, 0xd5, 0x35, + 0x00, 0x00, 0x59, 0x2d, + 0x00, 0x04, 0x31, 0x0c, 0x00, 0x00, 0x5d, 0x2d, 0x00, 0x04, 0x35, 0x0d, + 0x00, 0x00, 0x59, 0x2d, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x04, 0xb9, 0x10, + 0x00, 0xa4, 0xb9, 0x2e, 0x00, 0x00, 0x5d, 0x2d, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x04, 0xbd, 0x10, 0x00, 0xa4, 0xbd, 0x2f, + 0x00, 0x00, 0x59, 0x2d, + 0x00, 0x04, 0x31, 0x0c, 0x00, 0x00, 0x5d, 0x2d, 0x00, 0x04, 0x35, 0x0d, + 0x00, 0x00, 0x71, 0x39, + 0x00, 0x04, 0x31, 0x0c, 0x00, 0x00, 0x75, 0x39, 0x00, 0x04, 0x35, 0x0d, + 0x00, 0x00, 0x71, 0x39, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x04, 0xe9, 0x10, + 0x00, 0xa4, 0xe9, 0x3a, 0x00, 0x00, 0x75, 0x39, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x04, 0xed, 0x10, 0x00, 0xa4, 0xed, 0x3b, + 0x00, 0x04, 0x31, 0x04, + 0x00, 0x04, 0x30, 0x40, 0x00, 0x04, 0x35, 0x05, 0x00, 0x04, 0x34, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x0c, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa1, 0x0c, + 0x00, 0x05, 0xa5, 0x16, + 0x00, 0x05, 0xa4, 0x40, 0x00, 0x05, 0xa5, 0x6e, 0x00, 0x05, 0xa4, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x0d, 0x82, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x09, 0x81, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x05, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x19, 0x85, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x15, 0x84, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x10, 0x40, + 0x00, 0x06, 0x05, 0x26, + 0x00, 0x06, 0x10, 0x40, 0x00, 0x06, 0x09, 0x27, 0x00, 0x06, 0x11, 0x84, + 0x00, 0x06, 0x15, 0x28, + 0x00, 0x06, 0x11, 0x84, 0x00, 0x06, 0x0d, 0x29, 0x00, 0x06, 0x11, 0x84, + 0x00, 0x06, 0x19, 0x2a, + 0x00, 0x06, 0x11, 0x84, 0x00, 0x06, 0x11, 0x6c, 0x00, 0x46, 0x10, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x84, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xf5, 0x7c, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xf1, 0x7b, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xed, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x01, 0x7f, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xfd, 0x7e, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xf8, 0x40, 0x00, 0x05, 0xed, 0x21, 0x00, 0x05, 0xf8, 0x40, + 0x00, 0x05, 0xf1, 0x22, + 0x00, 0x05, 0xf9, 0x7e, 0x00, 0x05, 0xfd, 0x23, 0x00, 0x05, 0xf9, 0x7e, + 0x00, 0x05, 0xf5, 0x24, + 0x00, 0x05, 0xf9, 0x7e, 0x00, 0x06, 0x01, 0x25, 0x00, 0x05, 0xf9, 0x7e, + 0x00, 0x05, 0xf9, 0x6c, + 0x00, 0x45, 0xf8, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x7e, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xdd, 0x76, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xd9, 0x75, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xd5, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xe9, 0x79, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xe5, 0x78, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xe0, 0x40, + 0x00, 0x05, 0xd5, 0x1c, + 0x00, 0x05, 0xe0, 0x40, 0x00, 0x05, 0xd9, 0x1d, 0x00, 0x05, 0xe1, 0x78, + 0x00, 0x05, 0xe5, 0x1e, + 0x00, 0x05, 0xe1, 0x78, 0x00, 0x05, 0xdd, 0x1f, 0x00, 0x05, 0xe1, 0x78, + 0x00, 0x05, 0xe9, 0x20, + 0x00, 0x05, 0xe1, 0x78, 0x00, 0x05, 0xe1, 0x6c, 0x00, 0x45, 0xe0, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x78, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xc5, 0x70, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xc1, 0x6f, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xbd, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xd1, 0x73, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xcd, 0x72, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xc8, 0x40, 0x00, 0x05, 0xbd, 0x17, 0x00, 0x05, 0xc8, 0x40, + 0x00, 0x05, 0xc1, 0x18, + 0x00, 0x05, 0xc9, 0x72, 0x00, 0x05, 0xcd, 0x19, 0x00, 0x05, 0xc9, 0x72, + 0x00, 0x05, 0xc5, 0x1a, + 0x00, 0x05, 0xc9, 0x72, 0x00, 0x05, 0xd1, 0x1b, 0x00, 0x05, 0xc9, 0x72, + 0x00, 0x05, 0xc9, 0x6c, + 0x00, 0x45, 0xc8, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x72, + 0x00, 0x05, 0xa5, 0x6d, + 0x00, 0x45, 0xa5, 0x6b, 0x00, 0x05, 0xa5, 0x2c, 0x00, 0x44, 0x30, 0x40, + 0x00, 0x05, 0xa1, 0x2b, + 0x00, 0x44, 0x31, 0x0c, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x0d, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa1, 0x0d, 0x00, 0x05, 0xa5, 0x16, 0x00, 0x05, 0xa4, 0x40, + 0x00, 0x05, 0xa5, 0x6e, + 0x00, 0x05, 0xa4, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x6d, 0x9a, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x69, 0x99, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x65, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x79, 0x9d, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x75, 0x9c, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x70, 0x40, 0x00, 0x06, 0x65, 0x26, 0x00, 0x06, 0x70, 0x40, + 0x00, 0x06, 0x69, 0x27, + 0x00, 0x06, 0x71, 0x9c, 0x00, 0x06, 0x75, 0x28, 0x00, 0x06, 0x71, 0x9c, + 0x00, 0x06, 0x6d, 0x29, + 0x00, 0x06, 0x71, 0x9c, 0x00, 0x06, 0x79, 0x2a, 0x00, 0x06, 0x71, 0x9c, + 0x00, 0x06, 0x71, 0x6c, + 0x00, 0x46, 0x70, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x9c, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x55, 0x94, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x51, 0x93, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x4d, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x61, 0x97, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x5d, 0x96, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x58, 0x40, + 0x00, 0x06, 0x4d, 0x21, + 0x00, 0x06, 0x58, 0x40, 0x00, 0x06, 0x51, 0x22, 0x00, 0x06, 0x59, 0x96, + 0x00, 0x06, 0x5d, 0x23, + 0x00, 0x06, 0x59, 0x96, 0x00, 0x06, 0x55, 0x24, 0x00, 0x06, 0x59, 0x96, + 0x00, 0x06, 0x61, 0x25, + 0x00, 0x06, 0x59, 0x96, 0x00, 0x06, 0x59, 0x6c, 0x00, 0x46, 0x58, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x96, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x3d, 0x8e, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x39, 0x8d, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x35, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x49, 0x91, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x45, 0x90, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x40, 0x40, 0x00, 0x06, 0x35, 0x1c, 0x00, 0x06, 0x40, 0x40, + 0x00, 0x06, 0x39, 0x1d, + 0x00, 0x06, 0x41, 0x90, 0x00, 0x06, 0x45, 0x1e, 0x00, 0x06, 0x41, 0x90, + 0x00, 0x06, 0x3d, 0x1f, + 0x00, 0x06, 0x41, 0x90, 0x00, 0x06, 0x49, 0x20, 0x00, 0x06, 0x41, 0x90, + 0x00, 0x06, 0x41, 0x6c, + 0x00, 0x46, 0x40, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x90, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x25, 0x88, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x21, 0x87, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x1d, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x31, 0x8b, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x2d, 0x8a, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x28, 0x40, + 0x00, 0x06, 0x1d, 0x17, + 0x00, 0x06, 0x28, 0x40, 0x00, 0x06, 0x21, 0x18, 0x00, 0x06, 0x29, 0x8a, + 0x00, 0x06, 0x2d, 0x19, + 0x00, 0x06, 0x29, 0x8a, 0x00, 0x06, 0x25, 0x1a, 0x00, 0x06, 0x29, 0x8a, + 0x00, 0x06, 0x31, 0x1b, + 0x00, 0x06, 0x29, 0x8a, 0x00, 0x06, 0x29, 0x6c, 0x00, 0x46, 0x28, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x8a, 0x00, 0x05, 0xa5, 0x6d, 0x00, 0x45, 0xa5, 0x6b, + 0x00, 0x05, 0xa5, 0x2c, + 0x00, 0x44, 0x34, 0x40, 0x00, 0x05, 0xa1, 0x2b, 0x00, 0x44, 0x35, 0x0d, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x60, 0x89, 0x0c, 0x00, 0x01, 0x00, 0x40, 0x00, 0x60, 0x8d, 0x0d, + 0x00, 0x04, 0x30, 0x40, + 0x00, 0x94, 0x41, 0x0c, 0x00, 0x05, 0x99, 0x10, 0x00, 0xa5, 0x99, 0x66, + 0x00, 0x04, 0x34, 0x40, + 0x00, 0x94, 0x41, 0x0d, 0x00, 0x05, 0x9d, 0x10, 0x00, 0xa5, 0x9d, 0x67, + 0x00, 0x04, 0x31, 0x3c, + 0x00, 0x00, 0x80, 0x40, 0x00, 0x04, 0x35, 0x3d, 0x00, 0x00, 0x84, 0x40, + 0x00, 0x04, 0x31, 0x3c, + 0x00, 0x00, 0x98, 0x40, 0x00, 0x04, 0x35, 0x3d, 0x00, 0x00, 0x9c, 0x40, + 0x00, 0x04, 0x31, 0x3c, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x04, 0xf9, 0x10, + 0x00, 0xa4, 0xf9, 0x3e, 0x00, 0x04, 0x35, 0x3d, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x04, 0xfd, 0x10, 0x00, 0xa4, 0xfd, 0x3f, + 0x00, 0x04, 0x29, 0x49, + 0x00, 0x04, 0x28, 0x40, 0x00, 0x04, 0x2d, 0x49, 0x00, 0x04, 0x2c, 0x40, + 0x00, 0x04, 0x28, 0x40, + 0x00, 0x94, 0x41, 0x0a, 0x00, 0x05, 0x29, 0x10, 0x00, 0xa5, 0x29, 0x4a, + 0x00, 0x04, 0x2c, 0x40, + 0x00, 0x94, 0x41, 0x0b, 0x00, 0x05, 0x2d, 0x10, 0x00, 0xa5, 0x2d, 0x4b, + 0x00, 0x00, 0x49, 0x43, + 0x00, 0x04, 0x29, 0x0a, 0x00, 0x00, 0x4d, 0x43, 0x00, 0x04, 0x2d, 0x0b, + 0x00, 0x00, 0x49, 0x43, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x11, 0x10, + 0x00, 0xa5, 0x11, 0x44, 0x00, 0x00, 0x4d, 0x43, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x15, 0x10, 0x00, 0xa5, 0x15, 0x45, + 0x00, 0x00, 0x41, 0x46, + 0x00, 0x04, 0x29, 0x0a, 0x00, 0x00, 0x45, 0x46, 0x00, 0x04, 0x2d, 0x0b, + 0x00, 0x00, 0x41, 0x46, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x1d, 0x10, + 0x00, 0xa5, 0x1d, 0x47, 0x00, 0x00, 0x45, 0x46, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x21, 0x10, 0x00, 0xa5, 0x21, 0x48, + 0x00, 0x00, 0x59, 0x40, + 0x00, 0x04, 0x29, 0x0a, 0x00, 0x00, 0x5d, 0x40, 0x00, 0x04, 0x2d, 0x0b, + 0x00, 0x00, 0x59, 0x40, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x05, 0x10, + 0x00, 0xa5, 0x05, 0x41, 0x00, 0x00, 0x5d, 0x40, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x09, 0x10, 0x00, 0xa5, 0x09, 0x42, + 0x00, 0x00, 0x71, 0x4c, + 0x00, 0x04, 0x29, 0x0a, 0x00, 0x00, 0x75, 0x4c, 0x00, 0x04, 0x2d, 0x0b, + 0x00, 0x00, 0x71, 0x4c, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x35, 0x10, + 0x00, 0xa5, 0x35, 0x4d, 0x00, 0x00, 0x75, 0x4c, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x39, 0x10, 0x00, 0xa5, 0x39, 0x4e, + 0x00, 0x04, 0x29, 0x04, + 0x00, 0x04, 0x18, 0x40, 0x00, 0x04, 0x2d, 0x05, 0x00, 0x04, 0x1c, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0x06, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa1, 0x06, + 0x00, 0x05, 0xa5, 0x16, + 0x00, 0x05, 0xa4, 0x40, 0x00, 0x05, 0xa5, 0x6e, 0x00, 0x05, 0xa4, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xcd, 0xb2, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xc9, 0xb1, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xc5, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xd9, 0xb5, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xd5, 0xb4, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xd0, 0x40, + 0x00, 0x06, 0xc5, 0x26, + 0x00, 0x06, 0xd0, 0x40, 0x00, 0x06, 0xc9, 0x27, 0x00, 0x06, 0xd1, 0xb4, + 0x00, 0x06, 0xd5, 0x28, + 0x00, 0x06, 0xd1, 0xb4, 0x00, 0x06, 0xcd, 0x29, 0x00, 0x06, 0xd1, 0xb4, + 0x00, 0x06, 0xd9, 0x2a, + 0x00, 0x06, 0xd1, 0xb4, 0x00, 0x06, 0xd1, 0x6c, 0x00, 0x46, 0xd0, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0xb4, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xb5, 0xac, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xb1, 0xab, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xad, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xc1, 0xaf, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xbd, 0xae, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xb8, 0x40, 0x00, 0x06, 0xad, 0x21, 0x00, 0x06, 0xb8, 0x40, + 0x00, 0x06, 0xb1, 0x22, + 0x00, 0x06, 0xb9, 0xae, 0x00, 0x06, 0xbd, 0x23, 0x00, 0x06, 0xb9, 0xae, + 0x00, 0x06, 0xb5, 0x24, + 0x00, 0x06, 0xb9, 0xae, 0x00, 0x06, 0xc1, 0x25, 0x00, 0x06, 0xb9, 0xae, + 0x00, 0x06, 0xb9, 0x6c, + 0x00, 0x46, 0xb8, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0xae, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x9d, 0xa6, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x99, 0xa5, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x95, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xa9, 0xa9, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xa5, 0xa8, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xa0, 0x40, + 0x00, 0x06, 0x95, 0x1c, + 0x00, 0x06, 0xa0, 0x40, 0x00, 0x06, 0x99, 0x1d, 0x00, 0x06, 0xa1, 0xa8, + 0x00, 0x06, 0xa5, 0x1e, + 0x00, 0x06, 0xa1, 0xa8, 0x00, 0x06, 0x9d, 0x1f, 0x00, 0x06, 0xa1, 0xa8, + 0x00, 0x06, 0xa9, 0x20, + 0x00, 0x06, 0xa1, 0xa8, 0x00, 0x06, 0xa1, 0x6c, 0x00, 0x46, 0xa0, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0xa8, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x85, 0xa0, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x81, 0x9f, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x7d, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x91, 0xa3, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0x8d, 0xa2, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0x88, 0x40, 0x00, 0x06, 0x7d, 0x17, 0x00, 0x06, 0x88, 0x40, + 0x00, 0x06, 0x81, 0x18, + 0x00, 0x06, 0x89, 0xa2, 0x00, 0x06, 0x8d, 0x19, 0x00, 0x06, 0x89, 0xa2, + 0x00, 0x06, 0x85, 0x1a, + 0x00, 0x06, 0x89, 0xa2, 0x00, 0x06, 0x91, 0x1b, 0x00, 0x06, 0x89, 0xa2, + 0x00, 0x06, 0x89, 0x6c, + 0x00, 0x46, 0x88, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0xa2, + 0x00, 0x05, 0xa5, 0x6d, + 0x00, 0x45, 0xa5, 0x6b, 0x00, 0x05, 0xa5, 0x2c, 0x00, 0x44, 0x18, 0x40, + 0x00, 0x05, 0xa1, 0x2b, + 0x00, 0x44, 0x19, 0x06, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0x07, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa1, 0x07, 0x00, 0x05, 0xa5, 0x16, 0x00, 0x05, 0xa4, 0x40, + 0x00, 0x05, 0xa5, 0x6e, + 0x00, 0x05, 0xa4, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x2d, 0xca, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x29, 0xc9, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x25, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x39, 0xcd, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x35, 0xcc, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x30, 0x40, 0x00, 0x07, 0x25, 0x26, 0x00, 0x07, 0x30, 0x40, + 0x00, 0x07, 0x29, 0x27, + 0x00, 0x07, 0x31, 0xcc, 0x00, 0x07, 0x35, 0x28, 0x00, 0x07, 0x31, 0xcc, + 0x00, 0x07, 0x2d, 0x29, + 0x00, 0x07, 0x31, 0xcc, 0x00, 0x07, 0x39, 0x2a, 0x00, 0x07, 0x31, 0xcc, + 0x00, 0x07, 0x31, 0x6c, + 0x00, 0x47, 0x30, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0xcc, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x15, 0xc4, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x11, 0xc3, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x0d, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x21, 0xc7, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x1d, 0xc6, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x18, 0x40, + 0x00, 0x07, 0x0d, 0x21, + 0x00, 0x07, 0x18, 0x40, 0x00, 0x07, 0x11, 0x22, 0x00, 0x07, 0x19, 0xc6, + 0x00, 0x07, 0x1d, 0x23, + 0x00, 0x07, 0x19, 0xc6, 0x00, 0x07, 0x15, 0x24, 0x00, 0x07, 0x19, 0xc6, + 0x00, 0x07, 0x21, 0x25, + 0x00, 0x07, 0x19, 0xc6, 0x00, 0x07, 0x19, 0x6c, 0x00, 0x47, 0x18, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0xc6, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xfd, 0xbe, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xf9, 0xbd, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xf5, 0x69, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x09, 0xc1, 0x00, 0x01, 0x00, 0x40, 0x00, 0x67, 0x05, 0xc0, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x67, 0x00, 0x40, 0x00, 0x06, 0xf5, 0x1c, 0x00, 0x07, 0x00, 0x40, + 0x00, 0x06, 0xf9, 0x1d, + 0x00, 0x07, 0x01, 0xc0, 0x00, 0x07, 0x05, 0x1e, 0x00, 0x07, 0x01, 0xc0, + 0x00, 0x06, 0xfd, 0x1f, + 0x00, 0x07, 0x01, 0xc0, 0x00, 0x07, 0x09, 0x20, 0x00, 0x07, 0x01, 0xc0, + 0x00, 0x07, 0x01, 0x6c, + 0x00, 0x47, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x65, 0xa5, 0xc0, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xe5, 0xb8, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xe1, 0xb7, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xdd, 0x69, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xf1, 0xbb, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x66, 0xed, 0xba, 0x00, 0x01, 0x00, 0x40, 0x00, 0x66, 0xe8, 0x40, + 0x00, 0x06, 0xdd, 0x17, + 0x00, 0x06, 0xe8, 0x40, 0x00, 0x06, 0xe1, 0x18, 0x00, 0x06, 0xe9, 0xba, + 0x00, 0x06, 0xed, 0x19, + 0x00, 0x06, 0xe9, 0xba, 0x00, 0x06, 0xe5, 0x1a, 0x00, 0x06, 0xe9, 0xba, + 0x00, 0x06, 0xf1, 0x1b, + 0x00, 0x06, 0xe9, 0xba, 0x00, 0x06, 0xe9, 0x6c, 0x00, 0x46, 0xe8, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x65, 0xa5, 0xba, 0x00, 0x05, 0xa5, 0x6d, 0x00, 0x45, 0xa5, 0x6b, + 0x00, 0x05, 0xa5, 0x2c, + 0x00, 0x44, 0x1c, 0x40, 0x00, 0x05, 0xa1, 0x2b, 0x00, 0x44, 0x1d, 0x07, + 0x00, 0x04, 0x19, 0x4f, + 0x00, 0x00, 0xa0, 0x40, 0x00, 0x04, 0x1d, 0x50, 0x00, 0x00, 0xa4, 0x40, + 0x00, 0x04, 0x19, 0x4f, + 0x00, 0x00, 0xb4, 0x40, 0x00, 0x04, 0x1d, 0x50, 0x00, 0x00, 0xb8, 0x40, + 0x00, 0x00, 0x10, 0x41, + 0x00, 0x44, 0x48, 0x40, 0x00, 0x00, 0x14, 0x41, 0x00, 0x44, 0x4c, 0x40, + 0x00, 0x04, 0x19, 0x4f, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x45, 0x10, + 0x00, 0xa5, 0x45, 0x51, 0x00, 0x04, 0x1d, 0x50, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x49, 0x10, 0x00, 0xa5, 0x49, 0x52, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x60, 0x91, 0x12, 0x00, 0x01, 0x00, 0x40, 0x00, 0x60, 0x95, 0x13, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x60, 0xc5, 0x12, 0x00, 0x01, 0x00, 0x40, 0x00, 0x60, 0xc9, 0x13, + 0x00, 0x00, 0x41, 0x59, + 0x00, 0x04, 0x18, 0x40, 0x00, 0x00, 0x45, 0x59, 0x00, 0x04, 0x1c, 0x40, + 0x00, 0x00, 0x41, 0x59, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x69, 0x10, + 0x00, 0xa5, 0x69, 0x5a, 0x00, 0x00, 0x45, 0x59, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x6d, 0x10, 0x00, 0xa5, 0x6d, 0x5b, + 0x00, 0x00, 0x59, 0x53, + 0x00, 0x04, 0x19, 0x06, 0x00, 0x00, 0x5d, 0x53, 0x00, 0x04, 0x1d, 0x07, + 0x00, 0x00, 0x59, 0x53, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x51, 0x10, + 0x00, 0xa5, 0x51, 0x54, 0x00, 0x00, 0x5d, 0x53, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x55, 0x10, 0x00, 0xa5, 0x55, 0x55, + 0x00, 0x00, 0x49, 0x56, + 0x00, 0x04, 0x19, 0x06, 0x00, 0x00, 0x4d, 0x56, 0x00, 0x04, 0x1d, 0x07, + 0x00, 0x00, 0x49, 0x56, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x5d, 0x10, + 0x00, 0xa5, 0x5d, 0x57, 0x00, 0x00, 0x4d, 0x56, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x61, 0x10, 0x00, 0xa5, 0x61, 0x58, + 0x00, 0x04, 0x21, 0x5c, + 0x00, 0x04, 0x19, 0x06, 0x00, 0x04, 0x25, 0x5c, 0x00, 0x04, 0x1d, 0x07, + 0x00, 0x04, 0x21, 0x5c, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x75, 0x10, + 0x00, 0xa5, 0x75, 0x5d, 0x00, 0x04, 0x25, 0x5c, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x79, 0x10, 0x00, 0xa5, 0x79, 0x5e, + 0x00, 0x00, 0x71, 0x5f, + 0x00, 0x04, 0x19, 0x06, 0x00, 0x00, 0x75, 0x5f, 0x00, 0x04, 0x1d, 0x07, + 0x00, 0x00, 0x71, 0x5f, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x81, 0x10, + 0x00, 0xa5, 0x81, 0x60, 0x00, 0x00, 0x75, 0x5f, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x85, 0x10, 0x00, 0xa5, 0x85, 0x61, + 0x00, 0x04, 0x19, 0x62, + 0x00, 0x00, 0xa8, 0x40, 0x00, 0x04, 0x1d, 0x63, 0x00, 0x00, 0xac, 0x40, + 0x00, 0x04, 0x19, 0x62, + 0x00, 0x04, 0x44, 0x40, 0x00, 0x04, 0x44, 0x40, 0x00, 0x94, 0x41, 0x11, + 0x00, 0x05, 0x91, 0x10, + 0x00, 0xa5, 0x91, 0x64, 0x00, 0x04, 0x1d, 0x63, 0x00, 0x04, 0x44, 0x40, + 0x00, 0x04, 0x44, 0x40, + 0x00, 0x94, 0x41, 0x11, 0x00, 0x05, 0x95, 0x10, 0x00, 0xa5, 0x95, 0x65, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x40, + 0x00, 0x61, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x30, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, 0x45, 0x51, 0x55, 0x41, + 0x4c, 0x49, 0x5a, 0x45, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x45, 0x53, 0x43, 0x41, 0x4c, 0x45, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, + 0x4c, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x4d, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, + 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x49, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x10, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x80, 0x58, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x80, + 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x52, 0x4f, 0x4e, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x53, 0x55, 0x52, 0x52, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x43, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4f, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5a, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, + 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x64, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x6d, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x6e, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/kernel/drv/oss_sblive/emu10k2_dsp.h b/kernel/drv/oss_sblive/emu10k2_dsp.h new file mode 100644 index 0000000..233a7be --- /dev/null +++ b/kernel/drv/oss_sblive/emu10k2_dsp.h @@ -0,0 +1,989 @@ +/* + * Purpose: DSP firmware file for Audigy + */ +/* + * + * 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. + * + */ +static unsigned char emu10k2_dsp[] = { + 0x02, 0x00, 0xe1, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, + 0xc1, 0x00, 0x00, 0x00, + 0xc0, 0x60, 0x40, 0x04, 0xc1, 0x10, 0x00, 0x00, 0xc0, 0x70, 0x40, 0x04, + 0x02, 0x64, 0x40, 0x00, + 0xc0, 0x80, 0x40, 0x00, 0x03, 0x74, 0x40, 0x00, 0xc0, 0x90, 0x40, 0x00, + 0xc0, 0x00, 0x0c, 0x00, + 0x14, 0x60, 0x41, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x15, 0x70, 0x41, 0x06, + 0xc0, 0x60, 0x00, 0x00, + 0x02, 0xa0, 0x40, 0x06, 0xc0, 0x70, 0x00, 0x00, 0x03, 0xb0, 0x40, 0x06, + 0xc1, 0x40, 0x00, 0x00, + 0xc0, 0x20, 0x41, 0x04, 0xc1, 0x50, 0x00, 0x00, 0xc0, 0x30, 0x41, 0x04, + 0x02, 0xa4, 0x40, 0x00, + 0xc0, 0xa0, 0x40, 0x00, 0x03, 0xb4, 0x40, 0x00, 0xc0, 0xb0, 0x40, 0x00, + 0x38, 0x84, 0x40, 0x00, + 0xc0, 0xc0, 0x40, 0x00, 0x38, 0x94, 0x40, 0x00, 0xc0, 0xd0, 0x40, 0x00, + 0xc0, 0xc0, 0x40, 0x00, + 0x0c, 0x04, 0x41, 0x09, 0x10, 0x94, 0x43, 0x00, 0x39, 0x94, 0x43, 0x0a, + 0xc0, 0xd0, 0x40, 0x00, + 0x0d, 0x04, 0x41, 0x09, 0x10, 0xa4, 0x43, 0x00, 0x3a, 0xa4, 0x43, 0x0a, + 0x32, 0x24, 0x04, 0x00, + 0x0c, 0xc4, 0x40, 0x00, 0x32, 0x34, 0x04, 0x00, 0x0d, 0xd4, 0x40, 0x00, + 0x32, 0x24, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x34, 0x43, 0x00, + 0x33, 0x34, 0x43, 0x0a, 0x32, 0x34, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x44, 0x43, 0x00, 0x34, 0x44, 0x43, 0x0a, + 0x35, 0x04, 0x04, 0x00, + 0x0c, 0xc4, 0x40, 0x00, 0x35, 0x14, 0x04, 0x00, 0x0d, 0xd4, 0x40, 0x00, + 0x35, 0x04, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x64, 0x43, 0x00, + 0x36, 0x64, 0x43, 0x0a, 0x35, 0x14, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x74, 0x43, 0x00, 0x37, 0x74, 0x43, 0x0a, + 0x2f, 0x44, 0x04, 0x00, + 0x0c, 0xc4, 0x40, 0x00, 0x2f, 0x54, 0x04, 0x00, 0x0d, 0xd4, 0x40, 0x00, + 0x2f, 0x44, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x04, 0x43, 0x00, + 0x30, 0x04, 0x43, 0x0a, 0x2f, 0x54, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x14, 0x43, 0x00, 0x31, 0x14, 0x43, 0x0a, + 0x2f, 0x44, 0x04, 0x00, + 0x0c, 0xc4, 0x40, 0x00, 0x2f, 0x54, 0x04, 0x00, 0x0d, 0xd4, 0x40, 0x00, + 0x3b, 0xc4, 0x04, 0x00, + 0x0c, 0xc4, 0x40, 0x00, 0x3b, 0xd4, 0x04, 0x00, 0x0d, 0xd4, 0x40, 0x00, + 0x3b, 0xc4, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xc4, 0x43, 0x00, + 0x3c, 0xc4, 0x43, 0x0a, 0x3b, 0xd4, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xd4, 0x43, 0x00, 0x3d, 0xd4, 0x43, 0x0a, + 0x04, 0xc4, 0x40, 0x00, + 0xc0, 0xc0, 0x40, 0x00, 0x05, 0xd4, 0x40, 0x00, 0xc0, 0xd0, 0x40, 0x00, + 0x3e, 0x84, 0x04, 0x00, + 0x0e, 0xe4, 0x40, 0x00, 0x3e, 0x94, 0x04, 0x00, 0x0f, 0xf4, 0x40, 0x00, + 0x3e, 0x84, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xf4, 0x43, 0x00, + 0x3f, 0xf4, 0x43, 0x0a, 0x3e, 0x94, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x04, 0x44, 0x00, 0x40, 0x04, 0x44, 0x0a, + 0x04, 0xc4, 0x40, 0x00, + 0xc0, 0xe0, 0x40, 0x00, 0x05, 0xd4, 0x40, 0x00, 0xc0, 0xf0, 0x40, 0x00, + 0xc0, 0x00, 0x0c, 0x00, + 0x0c, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x0c, 0x54, 0x47, 0x06, + 0x18, 0x64, 0x47, 0x00, + 0xc0, 0x60, 0x47, 0x00, 0x7b, 0x64, 0x47, 0x00, 0xc0, 0x60, 0x47, 0x00, + 0xc0, 0x00, 0x0c, 0x00, + 0x8f, 0x04, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x8e, 0xf4, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0xe4, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x92, 0x34, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x91, 0x24, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x10, 0x49, 0x06, + 0x28, 0xe4, 0x48, 0x00, + 0xc0, 0x10, 0x49, 0x00, 0x29, 0xf4, 0x48, 0x00, 0x91, 0x14, 0x49, 0x00, + 0x2a, 0x24, 0x49, 0x00, + 0x91, 0x14, 0x49, 0x00, 0x2b, 0x04, 0x49, 0x00, 0x91, 0x14, 0x49, 0x00, + 0x2c, 0x34, 0x49, 0x00, + 0x91, 0x14, 0x49, 0x00, 0x79, 0x14, 0x49, 0x00, 0xc0, 0x10, 0x49, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0x91, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x89, 0xa4, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x88, 0x94, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0x84, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x8c, 0xd4, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x8b, 0xc4, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xb0, 0x48, 0x06, 0x23, 0x84, 0x48, 0x00, 0xc0, 0xb0, 0x48, 0x00, + 0x24, 0x94, 0x48, 0x00, + 0x8b, 0xb4, 0x48, 0x00, 0x25, 0xc4, 0x48, 0x00, 0x8b, 0xb4, 0x48, 0x00, + 0x26, 0xa4, 0x48, 0x00, + 0x8b, 0xb4, 0x48, 0x00, 0x27, 0xd4, 0x48, 0x00, 0x8b, 0xb4, 0x48, 0x00, + 0x79, 0xb4, 0x48, 0x00, + 0xc0, 0xb0, 0x48, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0x8b, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x83, 0x44, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x82, 0x34, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x24, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x86, 0x74, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x85, 0x64, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x50, 0x48, 0x06, + 0x1e, 0x24, 0x48, 0x00, + 0xc0, 0x50, 0x48, 0x00, 0x1f, 0x34, 0x48, 0x00, 0x85, 0x54, 0x48, 0x00, + 0x20, 0x64, 0x48, 0x00, + 0x85, 0x54, 0x48, 0x00, 0x21, 0x44, 0x48, 0x00, 0x85, 0x54, 0x48, 0x00, + 0x22, 0x74, 0x48, 0x00, + 0x85, 0x54, 0x48, 0x00, 0x79, 0x54, 0x48, 0x00, 0xc0, 0x50, 0x48, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0x85, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x7d, 0xe4, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x7c, 0xd4, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0xc4, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x80, 0x14, 0x48, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x7f, 0x04, 0x48, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xf0, 0x47, 0x06, 0x19, 0xc4, 0x47, 0x00, 0xc0, 0xf0, 0x47, 0x00, + 0x1a, 0xd4, 0x47, 0x00, + 0x7f, 0xf4, 0x47, 0x00, 0x1b, 0x04, 0x48, 0x00, 0x7f, 0xf4, 0x47, 0x00, + 0x1c, 0xe4, 0x47, 0x00, + 0x7f, 0xf4, 0x47, 0x00, 0x1d, 0x14, 0x48, 0x00, 0x7f, 0xf4, 0x47, 0x00, + 0x79, 0xf4, 0x47, 0x00, + 0xc0, 0xf0, 0x47, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0x7f, 0x64, 0x47, 0x06, + 0x7a, 0x64, 0x47, 0x00, + 0x78, 0x64, 0x47, 0x04, 0x2e, 0x64, 0x47, 0x00, 0xc0, 0xc0, 0x40, 0x04, + 0x2d, 0x54, 0x47, 0x00, + 0x0c, 0xc4, 0x40, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0x0d, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x0d, 0x54, 0x47, 0x06, 0x18, 0x64, 0x47, 0x00, 0xc0, 0x60, 0x47, 0x00, + 0x7b, 0x64, 0x47, 0x00, + 0xc0, 0x60, 0x47, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xa7, 0x84, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xa6, 0x74, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0x64, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xaa, 0xb4, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xa9, 0xa4, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x90, 0x4a, 0x06, 0x28, 0x64, 0x4a, 0x00, 0xc0, 0x90, 0x4a, 0x00, + 0x29, 0x74, 0x4a, 0x00, + 0xa9, 0x94, 0x4a, 0x00, 0x2a, 0xa4, 0x4a, 0x00, 0xa9, 0x94, 0x4a, 0x00, + 0x2b, 0x84, 0x4a, 0x00, + 0xa9, 0x94, 0x4a, 0x00, 0x2c, 0xb4, 0x4a, 0x00, 0xa9, 0x94, 0x4a, 0x00, + 0x79, 0x94, 0x4a, 0x00, + 0xc0, 0x90, 0x4a, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0xa9, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xa1, 0x24, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xa0, 0x14, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x04, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xa4, 0x54, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xa3, 0x44, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x30, 0x4a, 0x06, + 0x23, 0x04, 0x4a, 0x00, + 0xc0, 0x30, 0x4a, 0x00, 0x24, 0x14, 0x4a, 0x00, 0xa3, 0x34, 0x4a, 0x00, + 0x25, 0x44, 0x4a, 0x00, + 0xa3, 0x34, 0x4a, 0x00, 0x26, 0x24, 0x4a, 0x00, 0xa3, 0x34, 0x4a, 0x00, + 0x27, 0x54, 0x4a, 0x00, + 0xa3, 0x34, 0x4a, 0x00, 0x79, 0x34, 0x4a, 0x00, 0xc0, 0x30, 0x4a, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0xa3, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x9b, 0xc4, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x9a, 0xb4, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0xa4, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x9e, 0xf4, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x9d, 0xe4, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xd0, 0x49, 0x06, 0x1e, 0xa4, 0x49, 0x00, 0xc0, 0xd0, 0x49, 0x00, + 0x1f, 0xb4, 0x49, 0x00, + 0x9d, 0xd4, 0x49, 0x00, 0x20, 0xe4, 0x49, 0x00, 0x9d, 0xd4, 0x49, 0x00, + 0x21, 0xc4, 0x49, 0x00, + 0x9d, 0xd4, 0x49, 0x00, 0x22, 0xf4, 0x49, 0x00, 0x9d, 0xd4, 0x49, 0x00, + 0x79, 0xd4, 0x49, 0x00, + 0xc0, 0xd0, 0x49, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0x9d, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x95, 0x64, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x94, 0x54, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x44, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x98, 0x94, 0x49, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x97, 0x84, 0x49, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x70, 0x49, 0x06, + 0x19, 0x44, 0x49, 0x00, + 0xc0, 0x70, 0x49, 0x00, 0x1a, 0x54, 0x49, 0x00, 0x97, 0x74, 0x49, 0x00, + 0x1b, 0x84, 0x49, 0x00, + 0x97, 0x74, 0x49, 0x00, 0x1c, 0x64, 0x49, 0x00, 0x97, 0x74, 0x49, 0x00, + 0x1d, 0x94, 0x49, 0x00, + 0x97, 0x74, 0x49, 0x00, 0x79, 0x74, 0x49, 0x00, 0xc0, 0x70, 0x49, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0x97, 0x64, 0x47, 0x06, 0x7a, 0x64, 0x47, 0x00, 0x78, 0x64, 0x47, 0x04, + 0x2e, 0x64, 0x47, 0x00, + 0xc0, 0xd0, 0x40, 0x04, 0x2d, 0x54, 0x47, 0x00, 0x0d, 0xd4, 0x40, 0x04, + 0x74, 0xc4, 0x40, 0x00, + 0xc0, 0x00, 0x06, 0x04, 0x74, 0xd4, 0x40, 0x00, 0xc0, 0x10, 0x06, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0x16, 0x04, 0x4e, 0x06, 0xc1, 0xc0, 0x4d, 0x00, 0xd7, 0x70, 0x0d, 0x0f, + 0xe0, 0x94, 0x0c, 0x00, + 0xc0, 0x00, 0x4e, 0x06, 0xc0, 0xd0, 0x4d, 0x00, 0xe0, 0x04, 0x4e, 0x08, + 0x73, 0x04, 0x4e, 0x00, + 0xc0, 0xe0, 0x4d, 0x04, 0xc1, 0x10, 0x0c, 0x00, 0x73, 0xf4, 0x4d, 0x08, + 0xdf, 0xc4, 0x40, 0x00, + 0xc0, 0xf0, 0x4d, 0x04, 0xc0, 0xf0, 0x4d, 0x00, 0xde, 0x04, 0x06, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x17, 0x04, 0x4e, 0x06, 0xc1, 0xc0, 0x4d, 0x00, 0xd7, 0x70, 0x0d, 0x0f, + 0xe0, 0x94, 0x0c, 0x00, + 0xc0, 0x00, 0x4e, 0x06, 0xc0, 0xd0, 0x4d, 0x00, 0xe0, 0x04, 0x4e, 0x08, + 0x73, 0x04, 0x4e, 0x00, + 0xc0, 0xe0, 0x4d, 0x04, 0xc1, 0x10, 0x0c, 0x00, 0x73, 0xf4, 0x4d, 0x08, + 0xdf, 0xd4, 0x40, 0x00, + 0xc0, 0xf0, 0x4d, 0x04, 0xc0, 0xf0, 0x4d, 0x00, 0xde, 0x14, 0x06, 0x06, + 0xc0, 0xc0, 0x40, 0x00, + 0x0c, 0x04, 0x41, 0x09, 0x10, 0x14, 0x47, 0x00, 0x71, 0x14, 0x47, 0x0a, + 0xc0, 0xd0, 0x40, 0x00, + 0x0d, 0x04, 0x41, 0x09, 0x10, 0x24, 0x47, 0x00, 0x72, 0x24, 0x47, 0x0a, + 0x41, 0xc4, 0x40, 0x00, + 0xc0, 0x80, 0x06, 0x00, 0x42, 0xd4, 0x40, 0x00, 0xc0, 0x90, 0x06, 0x00, + 0x41, 0xc4, 0x40, 0x00, + 0xc0, 0x40, 0x06, 0x00, 0x42, 0xd4, 0x40, 0x00, 0xc0, 0x50, 0x06, 0x00, + 0x41, 0xc4, 0x40, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x34, 0x44, 0x00, + 0x43, 0x34, 0x44, 0x0a, 0x42, 0xd4, 0x40, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x44, 0x44, 0x00, 0x44, 0x44, 0x44, 0x0a, + 0x4e, 0xa4, 0x40, 0x00, + 0xc0, 0xa0, 0x40, 0x00, 0x4e, 0xb4, 0x40, 0x00, 0xc0, 0xb0, 0x40, 0x00, + 0xc0, 0xa0, 0x40, 0x00, + 0x0a, 0x04, 0x41, 0x09, 0x10, 0xf4, 0x44, 0x00, 0x4f, 0xf4, 0x44, 0x0a, + 0xc0, 0xb0, 0x40, 0x00, + 0x0b, 0x04, 0x41, 0x09, 0x10, 0x04, 0x45, 0x00, 0x50, 0x04, 0x45, 0x0a, + 0x48, 0x24, 0x04, 0x00, + 0x0a, 0xa4, 0x40, 0x00, 0x48, 0x34, 0x04, 0x00, 0x0b, 0xb4, 0x40, 0x00, + 0x48, 0x24, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x94, 0x44, 0x00, + 0x49, 0x94, 0x44, 0x0a, 0x48, 0x34, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xa4, 0x44, 0x00, 0x4a, 0xa4, 0x44, 0x0a, + 0x4b, 0x04, 0x04, 0x00, + 0x0a, 0xa4, 0x40, 0x00, 0x4b, 0x14, 0x04, 0x00, 0x0b, 0xb4, 0x40, 0x00, + 0x4b, 0x04, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xc4, 0x44, 0x00, + 0x4c, 0xc4, 0x44, 0x0a, 0x4b, 0x14, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xd4, 0x44, 0x00, 0x4d, 0xd4, 0x44, 0x0a, + 0x45, 0x44, 0x04, 0x00, + 0x0a, 0xa4, 0x40, 0x00, 0x45, 0x54, 0x04, 0x00, 0x0b, 0xb4, 0x40, 0x00, + 0x45, 0x44, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x64, 0x44, 0x00, + 0x46, 0x64, 0x44, 0x0a, 0x45, 0x54, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x74, 0x44, 0x00, 0x47, 0x74, 0x44, 0x0a, + 0x51, 0xc4, 0x04, 0x00, + 0x0a, 0xa4, 0x40, 0x00, 0x51, 0xd4, 0x04, 0x00, 0x0b, 0xb4, 0x40, 0x00, + 0x51, 0xc4, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x24, 0x45, 0x00, + 0x52, 0x24, 0x45, 0x0a, 0x51, 0xd4, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x34, 0x45, 0x00, 0x53, 0x34, 0x45, 0x0a, + 0x54, 0x84, 0x04, 0x00, + 0x0a, 0xa4, 0x40, 0x00, 0x54, 0x94, 0x04, 0x00, 0x0b, 0xb4, 0x40, 0x00, + 0x54, 0x84, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x54, 0x45, 0x00, + 0x55, 0x54, 0x45, 0x0a, 0x54, 0x94, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x64, 0x45, 0x00, 0x56, 0x64, 0x45, 0x0a, + 0x04, 0xa4, 0x40, 0x00, + 0xc0, 0x60, 0x40, 0x00, 0x05, 0xb4, 0x40, 0x00, 0xc0, 0x70, 0x40, 0x00, + 0xc0, 0x00, 0x0c, 0x00, + 0x06, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x06, 0x54, 0x47, 0x06, + 0x18, 0x64, 0x47, 0x00, + 0xc0, 0x60, 0x47, 0x00, 0x7b, 0x64, 0x47, 0x00, 0xc0, 0x60, 0x47, 0x00, + 0xc0, 0x00, 0x0c, 0x00, + 0xbf, 0x04, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xbe, 0xf4, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0xe4, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc2, 0x34, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc1, 0x24, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x10, 0x4c, 0x06, + 0x28, 0xe4, 0x4b, 0x00, + 0xc0, 0x10, 0x4c, 0x00, 0x29, 0xf4, 0x4b, 0x00, 0xc1, 0x14, 0x4c, 0x00, + 0x2a, 0x24, 0x4c, 0x00, + 0xc1, 0x14, 0x4c, 0x00, 0x2b, 0x04, 0x4c, 0x00, 0xc1, 0x14, 0x4c, 0x00, + 0x2c, 0x34, 0x4c, 0x00, + 0xc1, 0x14, 0x4c, 0x00, 0x79, 0x14, 0x4c, 0x00, 0xc0, 0x10, 0x4c, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0xc1, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xb9, 0xa4, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xb8, 0x94, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0x84, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xbc, 0xd4, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xbb, 0xc4, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xb0, 0x4b, 0x06, 0x23, 0x84, 0x4b, 0x00, 0xc0, 0xb0, 0x4b, 0x00, + 0x24, 0x94, 0x4b, 0x00, + 0xbb, 0xb4, 0x4b, 0x00, 0x25, 0xc4, 0x4b, 0x00, 0xbb, 0xb4, 0x4b, 0x00, + 0x26, 0xa4, 0x4b, 0x00, + 0xbb, 0xb4, 0x4b, 0x00, 0x27, 0xd4, 0x4b, 0x00, 0xbb, 0xb4, 0x4b, 0x00, + 0x79, 0xb4, 0x4b, 0x00, + 0xc0, 0xb0, 0x4b, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0xbb, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xb3, 0x44, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xb2, 0x34, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x24, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xb6, 0x74, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xb5, 0x64, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x50, 0x4b, 0x06, + 0x1e, 0x24, 0x4b, 0x00, + 0xc0, 0x50, 0x4b, 0x00, 0x1f, 0x34, 0x4b, 0x00, 0xb5, 0x54, 0x4b, 0x00, + 0x20, 0x64, 0x4b, 0x00, + 0xb5, 0x54, 0x4b, 0x00, 0x21, 0x44, 0x4b, 0x00, 0xb5, 0x54, 0x4b, 0x00, + 0x22, 0x74, 0x4b, 0x00, + 0xb5, 0x54, 0x4b, 0x00, 0x79, 0x54, 0x4b, 0x00, 0xc0, 0x50, 0x4b, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0xb5, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xad, 0xe4, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xac, 0xd4, 0x4a, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0xc4, 0x4a, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xb0, 0x14, 0x4b, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xaf, 0x04, 0x4b, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xf0, 0x4a, 0x06, 0x19, 0xc4, 0x4a, 0x00, 0xc0, 0xf0, 0x4a, 0x00, + 0x1a, 0xd4, 0x4a, 0x00, + 0xaf, 0xf4, 0x4a, 0x00, 0x1b, 0x04, 0x4b, 0x00, 0xaf, 0xf4, 0x4a, 0x00, + 0x1c, 0xe4, 0x4a, 0x00, + 0xaf, 0xf4, 0x4a, 0x00, 0x1d, 0x14, 0x4b, 0x00, 0xaf, 0xf4, 0x4a, 0x00, + 0x79, 0xf4, 0x4a, 0x00, + 0xc0, 0xf0, 0x4a, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0xaf, 0x64, 0x47, 0x06, + 0x7a, 0x64, 0x47, 0x00, + 0x78, 0x64, 0x47, 0x04, 0x2e, 0x64, 0x47, 0x00, 0xc0, 0x60, 0x40, 0x04, + 0x2d, 0x54, 0x47, 0x00, + 0x06, 0x64, 0x40, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0x07, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x07, 0x54, 0x47, 0x06, 0x18, 0x64, 0x47, 0x00, 0xc0, 0x60, 0x47, 0x00, + 0x7b, 0x64, 0x47, 0x00, + 0xc0, 0x60, 0x47, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xd7, 0x84, 0x4d, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xd6, 0x74, 0x4d, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0x64, 0x4d, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xda, 0xb4, 0x4d, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xd9, 0xa4, 0x4d, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x90, 0x4d, 0x06, 0x28, 0x64, 0x4d, 0x00, 0xc0, 0x90, 0x4d, 0x00, + 0x29, 0x74, 0x4d, 0x00, + 0xd9, 0x94, 0x4d, 0x00, 0x2a, 0xa4, 0x4d, 0x00, 0xd9, 0x94, 0x4d, 0x00, + 0x2b, 0x84, 0x4d, 0x00, + 0xd9, 0x94, 0x4d, 0x00, 0x2c, 0xb4, 0x4d, 0x00, 0xd9, 0x94, 0x4d, 0x00, + 0x79, 0x94, 0x4d, 0x00, + 0xc0, 0x90, 0x4d, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0xd9, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xd1, 0x24, 0x4d, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xd0, 0x14, 0x4d, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x04, 0x4d, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xd4, 0x54, 0x4d, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xd3, 0x44, 0x4d, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x30, 0x4d, 0x06, + 0x23, 0x04, 0x4d, 0x00, + 0xc0, 0x30, 0x4d, 0x00, 0x24, 0x14, 0x4d, 0x00, 0xd3, 0x34, 0x4d, 0x00, + 0x25, 0x44, 0x4d, 0x00, + 0xd3, 0x34, 0x4d, 0x00, 0x26, 0x24, 0x4d, 0x00, 0xd3, 0x34, 0x4d, 0x00, + 0x27, 0x54, 0x4d, 0x00, + 0xd3, 0x34, 0x4d, 0x00, 0x79, 0x34, 0x4d, 0x00, 0xc0, 0x30, 0x4d, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0xd3, 0x64, 0x47, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xcb, 0xc4, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xca, 0xb4, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x76, 0xa4, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xce, 0xf4, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xcd, 0xe4, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0xd0, 0x4c, 0x06, 0x1e, 0xa4, 0x4c, 0x00, 0xc0, 0xd0, 0x4c, 0x00, + 0x1f, 0xb4, 0x4c, 0x00, + 0xcd, 0xd4, 0x4c, 0x00, 0x20, 0xe4, 0x4c, 0x00, 0xcd, 0xd4, 0x4c, 0x00, + 0x21, 0xc4, 0x4c, 0x00, + 0xcd, 0xd4, 0x4c, 0x00, 0x22, 0xf4, 0x4c, 0x00, 0xcd, 0xd4, 0x4c, 0x00, + 0x79, 0xd4, 0x4c, 0x00, + 0xc0, 0xd0, 0x4c, 0x04, 0xc0, 0x00, 0x0c, 0x00, 0xcd, 0x64, 0x47, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc5, 0x64, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc4, 0x54, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x76, 0x44, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc8, 0x94, 0x4c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc7, 0x84, 0x4c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x70, 0x4c, 0x06, + 0x19, 0x44, 0x4c, 0x00, + 0xc0, 0x70, 0x4c, 0x00, 0x1a, 0x54, 0x4c, 0x00, 0xc7, 0x74, 0x4c, 0x00, + 0x1b, 0x84, 0x4c, 0x00, + 0xc7, 0x74, 0x4c, 0x00, 0x1c, 0x64, 0x4c, 0x00, 0xc7, 0x74, 0x4c, 0x00, + 0x1d, 0x94, 0x4c, 0x00, + 0xc7, 0x74, 0x4c, 0x00, 0x79, 0x74, 0x4c, 0x00, 0xc0, 0x70, 0x4c, 0x04, + 0xc0, 0x00, 0x0c, 0x00, + 0xc7, 0x64, 0x47, 0x06, 0x7a, 0x64, 0x47, 0x00, 0x78, 0x64, 0x47, 0x04, + 0x2e, 0x64, 0x47, 0x00, + 0xc0, 0x70, 0x40, 0x04, 0x2d, 0x54, 0x47, 0x00, 0x07, 0x74, 0x40, 0x04, + 0x57, 0x64, 0x40, 0x00, + 0xc0, 0xe0, 0x06, 0x00, 0x58, 0x74, 0x40, 0x00, 0xc0, 0xf0, 0x06, 0x00, + 0x57, 0x64, 0x40, 0x00, + 0xc0, 0x60, 0x06, 0x00, 0x58, 0x74, 0x40, 0x00, 0xc0, 0x70, 0x06, 0x00, + 0x57, 0x64, 0x40, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x94, 0x45, 0x00, + 0x59, 0x94, 0x45, 0x0a, 0x58, 0x74, 0x40, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xa4, 0x45, 0x00, 0x5a, 0xa4, 0x45, 0x0a, + 0xc0, 0x00, 0x0c, 0x00, + 0x12, 0x24, 0x06, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x13, 0x34, 0x06, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0x12, 0xa4, 0x06, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0x13, 0xb4, 0x06, 0x06, + 0x61, 0x04, 0x04, 0x00, + 0xc0, 0x60, 0x40, 0x00, 0x61, 0x14, 0x04, 0x00, 0xc0, 0x70, 0x40, 0x00, + 0x61, 0x04, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x24, 0x46, 0x00, + 0x62, 0x24, 0x46, 0x0a, 0x61, 0x14, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x34, 0x46, 0x00, 0x63, 0x34, 0x46, 0x0a, + 0x5b, 0x44, 0x04, 0x00, + 0x06, 0x64, 0x40, 0x00, 0x5b, 0x54, 0x04, 0x00, 0x07, 0x74, 0x40, 0x00, + 0x5b, 0x44, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xc4, 0x45, 0x00, + 0x5c, 0xc4, 0x45, 0x0a, 0x5b, 0x54, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xd4, 0x45, 0x00, 0x5d, 0xd4, 0x45, 0x0a, + 0x5e, 0x24, 0x04, 0x00, + 0x06, 0x64, 0x40, 0x00, 0x5e, 0x34, 0x04, 0x00, 0x07, 0x74, 0x40, 0x00, + 0x5e, 0x24, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xf4, 0x45, 0x00, + 0x5f, 0xf4, 0x45, 0x0a, 0x5e, 0x34, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x04, 0x46, 0x00, 0x60, 0x04, 0x46, 0x0a, + 0x64, 0x84, 0x40, 0x00, + 0x06, 0x64, 0x40, 0x00, 0x64, 0x94, 0x40, 0x00, 0x07, 0x74, 0x40, 0x00, + 0x64, 0x84, 0x40, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x54, 0x46, 0x00, + 0x65, 0x54, 0x46, 0x0a, 0x64, 0x94, 0x40, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x64, 0x46, 0x00, 0x66, 0x64, 0x46, 0x0a, + 0x67, 0xc4, 0x04, 0x00, + 0x06, 0x64, 0x40, 0x00, 0x67, 0xd4, 0x04, 0x00, 0x07, 0x74, 0x40, 0x00, + 0x67, 0xc4, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0x84, 0x46, 0x00, + 0x68, 0x84, 0x46, 0x0a, 0x67, 0xd4, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x94, 0x46, 0x00, 0x69, 0x94, 0x46, 0x0a, + 0x6a, 0x84, 0x04, 0x00, + 0x06, 0x64, 0x40, 0x00, 0x6a, 0x94, 0x04, 0x00, 0x07, 0x74, 0x40, 0x00, + 0x6a, 0x84, 0x04, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xb4, 0x46, 0x00, + 0x6b, 0xb4, 0x46, 0x0a, 0x6a, 0x94, 0x04, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0xc4, 0x46, 0x00, 0x6c, 0xc4, 0x46, 0x0a, + 0x6d, 0x64, 0x40, 0x00, + 0xc0, 0x60, 0x07, 0x00, 0x6e, 0x74, 0x40, 0x00, 0xc0, 0x70, 0x07, 0x00, + 0x6d, 0x64, 0x40, 0x00, + 0xc0, 0x10, 0x41, 0x00, 0xc0, 0x10, 0x41, 0x00, 0x11, 0x04, 0x41, 0x09, + 0x10, 0xf4, 0x46, 0x00, + 0x6f, 0xf4, 0x46, 0x0a, 0x6e, 0x74, 0x40, 0x00, 0xc0, 0x10, 0x41, 0x00, + 0xc0, 0x10, 0x41, 0x00, + 0x11, 0x04, 0x41, 0x09, 0x10, 0x04, 0x47, 0x00, 0x70, 0x04, 0x47, 0x0a, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0xc0, 0x00, 0x0c, 0x00, + 0xc0, 0x00, 0x0c, 0x06, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x06, + 0x37, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x45, 0x51, 0x55, 0x41, + 0x4c, 0x49, 0x5a, 0x45, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x45, 0x53, 0x43, 0x41, 0x4c, 0x45, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, + 0x4c, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, + 0x4d, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x48, 0x49, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x00, 0x00, 0x58, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x10, + 0x80, 0x00, 0x00, 0x00, + 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x52, 0x4f, 0x4e, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x39, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x4d, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, + 0x64, 0x64, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x55, 0x52, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4b, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x57, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x5b, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x43, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6f, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x50, 0x41, 0x53, + 0x53, 0x54, 0x48, 0x52, + 0x4f, 0x55, 0x47, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x7a, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0xdc, 0x00, 0x00, 0x00, + 0x08, 0x10, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/kernel/drv/oss_sblive/emu10k2_dsp_be.h b/kernel/drv/oss_sblive/emu10k2_dsp_be.h new file mode 100644 index 0000000..95447fa --- /dev/null +++ b/kernel/drv/oss_sblive/emu10k2_dsp_be.h @@ -0,0 +1,989 @@ +/* + * Purpose: DSP firmware file for Audigy (big endian machines) + */ +/* + * + * 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. + * + */ +static unsigned char emu10k2_dsp[] = { + 0x00, 0xe1, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0xc2, + 0x00, 0x00, 0x00, 0xc1, + 0x04, 0x40, 0x60, 0xc0, 0x00, 0x00, 0x10, 0xc1, 0x04, 0x40, 0x70, 0xc0, + 0x00, 0x40, 0x64, 0x02, + 0x00, 0x40, 0x80, 0xc0, 0x00, 0x40, 0x74, 0x03, 0x00, 0x40, 0x90, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x41, 0x60, 0x14, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x41, 0x70, 0x15, + 0x00, 0x00, 0x60, 0xc0, + 0x06, 0x40, 0xa0, 0x02, 0x00, 0x00, 0x70, 0xc0, 0x06, 0x40, 0xb0, 0x03, + 0x00, 0x00, 0x40, 0xc1, + 0x04, 0x41, 0x20, 0xc0, 0x00, 0x00, 0x50, 0xc1, 0x04, 0x41, 0x30, 0xc0, + 0x00, 0x40, 0xa4, 0x02, + 0x00, 0x40, 0xa0, 0xc0, 0x00, 0x40, 0xb4, 0x03, 0x00, 0x40, 0xb0, 0xc0, + 0x00, 0x40, 0x84, 0x38, + 0x00, 0x40, 0xc0, 0xc0, 0x00, 0x40, 0x94, 0x38, 0x00, 0x40, 0xd0, 0xc0, + 0x00, 0x40, 0xc0, 0xc0, + 0x09, 0x41, 0x04, 0x0c, 0x00, 0x43, 0x94, 0x10, 0x0a, 0x43, 0x94, 0x39, + 0x00, 0x40, 0xd0, 0xc0, + 0x09, 0x41, 0x04, 0x0d, 0x00, 0x43, 0xa4, 0x10, 0x0a, 0x43, 0xa4, 0x3a, + 0x00, 0x04, 0x24, 0x32, + 0x00, 0x40, 0xc4, 0x0c, 0x00, 0x04, 0x34, 0x32, 0x00, 0x40, 0xd4, 0x0d, + 0x00, 0x04, 0x24, 0x32, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x43, 0x34, 0x10, + 0x0a, 0x43, 0x34, 0x33, 0x00, 0x04, 0x34, 0x32, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x43, 0x44, 0x10, 0x0a, 0x43, 0x44, 0x34, + 0x00, 0x04, 0x04, 0x35, + 0x00, 0x40, 0xc4, 0x0c, 0x00, 0x04, 0x14, 0x35, 0x00, 0x40, 0xd4, 0x0d, + 0x00, 0x04, 0x04, 0x35, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x43, 0x64, 0x10, + 0x0a, 0x43, 0x64, 0x36, 0x00, 0x04, 0x14, 0x35, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x43, 0x74, 0x10, 0x0a, 0x43, 0x74, 0x37, + 0x00, 0x04, 0x44, 0x2f, + 0x00, 0x40, 0xc4, 0x0c, 0x00, 0x04, 0x54, 0x2f, 0x00, 0x40, 0xd4, 0x0d, + 0x00, 0x04, 0x44, 0x2f, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x43, 0x04, 0x10, + 0x0a, 0x43, 0x04, 0x30, 0x00, 0x04, 0x54, 0x2f, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x43, 0x14, 0x10, 0x0a, 0x43, 0x14, 0x31, + 0x00, 0x04, 0x44, 0x2f, + 0x00, 0x40, 0xc4, 0x0c, 0x00, 0x04, 0x54, 0x2f, 0x00, 0x40, 0xd4, 0x0d, + 0x00, 0x04, 0xc4, 0x3b, + 0x00, 0x40, 0xc4, 0x0c, 0x00, 0x04, 0xd4, 0x3b, 0x00, 0x40, 0xd4, 0x0d, + 0x00, 0x04, 0xc4, 0x3b, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x43, 0xc4, 0x10, + 0x0a, 0x43, 0xc4, 0x3c, 0x00, 0x04, 0xd4, 0x3b, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x43, 0xd4, 0x10, 0x0a, 0x43, 0xd4, 0x3d, + 0x00, 0x40, 0xc4, 0x04, + 0x00, 0x40, 0xc0, 0xc0, 0x00, 0x40, 0xd4, 0x05, 0x00, 0x40, 0xd0, 0xc0, + 0x00, 0x04, 0x84, 0x3e, + 0x00, 0x40, 0xe4, 0x0e, 0x00, 0x04, 0x94, 0x3e, 0x00, 0x40, 0xf4, 0x0f, + 0x00, 0x04, 0x84, 0x3e, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x43, 0xf4, 0x10, + 0x0a, 0x43, 0xf4, 0x3f, 0x00, 0x04, 0x94, 0x3e, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x44, 0x04, 0x10, 0x0a, 0x44, 0x04, 0x40, + 0x00, 0x40, 0xc4, 0x04, + 0x00, 0x40, 0xe0, 0xc0, 0x00, 0x40, 0xd4, 0x05, 0x00, 0x40, 0xf0, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0x0c, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x54, 0x0c, + 0x00, 0x47, 0x64, 0x18, + 0x00, 0x47, 0x60, 0xc0, 0x00, 0x47, 0x64, 0x7b, 0x00, 0x47, 0x60, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0x04, 0x8f, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0xf4, 0x8e, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0xe4, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0x34, 0x92, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0x24, 0x91, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0x10, 0xc0, + 0x00, 0x48, 0xe4, 0x28, + 0x00, 0x49, 0x10, 0xc0, 0x00, 0x48, 0xf4, 0x29, 0x00, 0x49, 0x14, 0x91, + 0x00, 0x49, 0x24, 0x2a, + 0x00, 0x49, 0x14, 0x91, 0x00, 0x49, 0x04, 0x2b, 0x00, 0x49, 0x14, 0x91, + 0x00, 0x49, 0x34, 0x2c, + 0x00, 0x49, 0x14, 0x91, 0x00, 0x49, 0x14, 0x79, 0x04, 0x49, 0x10, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0x91, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0xa4, 0x89, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0x94, 0x88, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0x84, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0xd4, 0x8c, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0xc4, 0x8b, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0xb0, 0xc0, 0x00, 0x48, 0x84, 0x23, 0x00, 0x48, 0xb0, 0xc0, + 0x00, 0x48, 0x94, 0x24, + 0x00, 0x48, 0xb4, 0x8b, 0x00, 0x48, 0xc4, 0x25, 0x00, 0x48, 0xb4, 0x8b, + 0x00, 0x48, 0xa4, 0x26, + 0x00, 0x48, 0xb4, 0x8b, 0x00, 0x48, 0xd4, 0x27, 0x00, 0x48, 0xb4, 0x8b, + 0x00, 0x48, 0xb4, 0x79, + 0x04, 0x48, 0xb0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0x8b, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0x44, 0x83, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0x34, 0x82, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0x24, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0x74, 0x86, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0x64, 0x85, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0x50, 0xc0, + 0x00, 0x48, 0x24, 0x1e, + 0x00, 0x48, 0x50, 0xc0, 0x00, 0x48, 0x34, 0x1f, 0x00, 0x48, 0x54, 0x85, + 0x00, 0x48, 0x64, 0x20, + 0x00, 0x48, 0x54, 0x85, 0x00, 0x48, 0x44, 0x21, 0x00, 0x48, 0x54, 0x85, + 0x00, 0x48, 0x74, 0x22, + 0x00, 0x48, 0x54, 0x85, 0x00, 0x48, 0x54, 0x79, 0x04, 0x48, 0x50, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0x85, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0xe4, 0x7d, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0xd4, 0x7c, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0xc4, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x48, 0x14, 0x80, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x48, 0x04, 0x7f, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0xf0, 0xc0, 0x00, 0x47, 0xc4, 0x19, 0x00, 0x47, 0xf0, 0xc0, + 0x00, 0x47, 0xd4, 0x1a, + 0x00, 0x47, 0xf4, 0x7f, 0x00, 0x48, 0x04, 0x1b, 0x00, 0x47, 0xf4, 0x7f, + 0x00, 0x47, 0xe4, 0x1c, + 0x00, 0x47, 0xf4, 0x7f, 0x00, 0x48, 0x14, 0x1d, 0x00, 0x47, 0xf4, 0x7f, + 0x00, 0x47, 0xf4, 0x79, + 0x04, 0x47, 0xf0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0x7f, + 0x00, 0x47, 0x64, 0x7a, + 0x04, 0x47, 0x64, 0x78, 0x00, 0x47, 0x64, 0x2e, 0x04, 0x40, 0xc0, 0xc0, + 0x00, 0x47, 0x54, 0x2d, + 0x04, 0x40, 0xc4, 0x0c, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0x0d, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x54, 0x0d, 0x00, 0x47, 0x64, 0x18, 0x00, 0x47, 0x60, 0xc0, + 0x00, 0x47, 0x64, 0x7b, + 0x00, 0x47, 0x60, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0x84, 0xa7, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0x74, 0xa6, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0x64, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0xb4, 0xaa, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0xa4, 0xa9, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0x90, 0xc0, 0x00, 0x4a, 0x64, 0x28, 0x00, 0x4a, 0x90, 0xc0, + 0x00, 0x4a, 0x74, 0x29, + 0x00, 0x4a, 0x94, 0xa9, 0x00, 0x4a, 0xa4, 0x2a, 0x00, 0x4a, 0x94, 0xa9, + 0x00, 0x4a, 0x84, 0x2b, + 0x00, 0x4a, 0x94, 0xa9, 0x00, 0x4a, 0xb4, 0x2c, 0x00, 0x4a, 0x94, 0xa9, + 0x00, 0x4a, 0x94, 0x79, + 0x04, 0x4a, 0x90, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0xa9, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0x24, 0xa1, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0x14, 0xa0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0x04, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0x54, 0xa4, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0x44, 0xa3, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0x30, 0xc0, + 0x00, 0x4a, 0x04, 0x23, + 0x00, 0x4a, 0x30, 0xc0, 0x00, 0x4a, 0x14, 0x24, 0x00, 0x4a, 0x34, 0xa3, + 0x00, 0x4a, 0x44, 0x25, + 0x00, 0x4a, 0x34, 0xa3, 0x00, 0x4a, 0x24, 0x26, 0x00, 0x4a, 0x34, 0xa3, + 0x00, 0x4a, 0x54, 0x27, + 0x00, 0x4a, 0x34, 0xa3, 0x00, 0x4a, 0x34, 0x79, 0x04, 0x4a, 0x30, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0xa3, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0xc4, 0x9b, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0xb4, 0x9a, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0xa4, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0xf4, 0x9e, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0xe4, 0x9d, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0xd0, 0xc0, 0x00, 0x49, 0xa4, 0x1e, 0x00, 0x49, 0xd0, 0xc0, + 0x00, 0x49, 0xb4, 0x1f, + 0x00, 0x49, 0xd4, 0x9d, 0x00, 0x49, 0xe4, 0x20, 0x00, 0x49, 0xd4, 0x9d, + 0x00, 0x49, 0xc4, 0x21, + 0x00, 0x49, 0xd4, 0x9d, 0x00, 0x49, 0xf4, 0x22, 0x00, 0x49, 0xd4, 0x9d, + 0x00, 0x49, 0xd4, 0x79, + 0x04, 0x49, 0xd0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0x9d, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0x64, 0x95, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0x54, 0x94, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0x44, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0x94, 0x98, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x49, 0x84, 0x97, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x49, 0x70, 0xc0, + 0x00, 0x49, 0x44, 0x19, + 0x00, 0x49, 0x70, 0xc0, 0x00, 0x49, 0x54, 0x1a, 0x00, 0x49, 0x74, 0x97, + 0x00, 0x49, 0x84, 0x1b, + 0x00, 0x49, 0x74, 0x97, 0x00, 0x49, 0x64, 0x1c, 0x00, 0x49, 0x74, 0x97, + 0x00, 0x49, 0x94, 0x1d, + 0x00, 0x49, 0x74, 0x97, 0x00, 0x49, 0x74, 0x79, 0x04, 0x49, 0x70, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0x97, 0x00, 0x47, 0x64, 0x7a, 0x04, 0x47, 0x64, 0x78, + 0x00, 0x47, 0x64, 0x2e, + 0x04, 0x40, 0xd0, 0xc0, 0x00, 0x47, 0x54, 0x2d, 0x04, 0x40, 0xd4, 0x0d, + 0x00, 0x40, 0xc4, 0x74, + 0x04, 0x06, 0x00, 0xc0, 0x00, 0x40, 0xd4, 0x74, 0x04, 0x06, 0x10, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4e, 0x04, 0x16, 0x00, 0x4d, 0xc0, 0xc1, 0x0f, 0x0d, 0x70, 0xd7, + 0x00, 0x0c, 0x94, 0xe0, + 0x06, 0x4e, 0x00, 0xc0, 0x00, 0x4d, 0xd0, 0xc0, 0x08, 0x4e, 0x04, 0xe0, + 0x00, 0x4e, 0x04, 0x73, + 0x04, 0x4d, 0xe0, 0xc0, 0x00, 0x0c, 0x10, 0xc1, 0x08, 0x4d, 0xf4, 0x73, + 0x00, 0x40, 0xc4, 0xdf, + 0x04, 0x4d, 0xf0, 0xc0, 0x00, 0x4d, 0xf0, 0xc0, 0x06, 0x06, 0x04, 0xde, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4e, 0x04, 0x17, 0x00, 0x4d, 0xc0, 0xc1, 0x0f, 0x0d, 0x70, 0xd7, + 0x00, 0x0c, 0x94, 0xe0, + 0x06, 0x4e, 0x00, 0xc0, 0x00, 0x4d, 0xd0, 0xc0, 0x08, 0x4e, 0x04, 0xe0, + 0x00, 0x4e, 0x04, 0x73, + 0x04, 0x4d, 0xe0, 0xc0, 0x00, 0x0c, 0x10, 0xc1, 0x08, 0x4d, 0xf4, 0x73, + 0x00, 0x40, 0xd4, 0xdf, + 0x04, 0x4d, 0xf0, 0xc0, 0x00, 0x4d, 0xf0, 0xc0, 0x06, 0x06, 0x14, 0xde, + 0x00, 0x40, 0xc0, 0xc0, + 0x09, 0x41, 0x04, 0x0c, 0x00, 0x47, 0x14, 0x10, 0x0a, 0x47, 0x14, 0x71, + 0x00, 0x40, 0xd0, 0xc0, + 0x09, 0x41, 0x04, 0x0d, 0x00, 0x47, 0x24, 0x10, 0x0a, 0x47, 0x24, 0x72, + 0x00, 0x40, 0xc4, 0x41, + 0x00, 0x06, 0x80, 0xc0, 0x00, 0x40, 0xd4, 0x42, 0x00, 0x06, 0x90, 0xc0, + 0x00, 0x40, 0xc4, 0x41, + 0x00, 0x06, 0x40, 0xc0, 0x00, 0x40, 0xd4, 0x42, 0x00, 0x06, 0x50, 0xc0, + 0x00, 0x40, 0xc4, 0x41, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x44, 0x34, 0x10, + 0x0a, 0x44, 0x34, 0x43, 0x00, 0x40, 0xd4, 0x42, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x44, 0x44, 0x10, 0x0a, 0x44, 0x44, 0x44, + 0x00, 0x40, 0xa4, 0x4e, + 0x00, 0x40, 0xa0, 0xc0, 0x00, 0x40, 0xb4, 0x4e, 0x00, 0x40, 0xb0, 0xc0, + 0x00, 0x40, 0xa0, 0xc0, + 0x09, 0x41, 0x04, 0x0a, 0x00, 0x44, 0xf4, 0x10, 0x0a, 0x44, 0xf4, 0x4f, + 0x00, 0x40, 0xb0, 0xc0, + 0x09, 0x41, 0x04, 0x0b, 0x00, 0x45, 0x04, 0x10, 0x0a, 0x45, 0x04, 0x50, + 0x00, 0x04, 0x24, 0x48, + 0x00, 0x40, 0xa4, 0x0a, 0x00, 0x04, 0x34, 0x48, 0x00, 0x40, 0xb4, 0x0b, + 0x00, 0x04, 0x24, 0x48, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x44, 0x94, 0x10, + 0x0a, 0x44, 0x94, 0x49, 0x00, 0x04, 0x34, 0x48, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x44, 0xa4, 0x10, 0x0a, 0x44, 0xa4, 0x4a, + 0x00, 0x04, 0x04, 0x4b, + 0x00, 0x40, 0xa4, 0x0a, 0x00, 0x04, 0x14, 0x4b, 0x00, 0x40, 0xb4, 0x0b, + 0x00, 0x04, 0x04, 0x4b, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x44, 0xc4, 0x10, + 0x0a, 0x44, 0xc4, 0x4c, 0x00, 0x04, 0x14, 0x4b, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x44, 0xd4, 0x10, 0x0a, 0x44, 0xd4, 0x4d, + 0x00, 0x04, 0x44, 0x45, + 0x00, 0x40, 0xa4, 0x0a, 0x00, 0x04, 0x54, 0x45, 0x00, 0x40, 0xb4, 0x0b, + 0x00, 0x04, 0x44, 0x45, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x44, 0x64, 0x10, + 0x0a, 0x44, 0x64, 0x46, 0x00, 0x04, 0x54, 0x45, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x44, 0x74, 0x10, 0x0a, 0x44, 0x74, 0x47, + 0x00, 0x04, 0xc4, 0x51, + 0x00, 0x40, 0xa4, 0x0a, 0x00, 0x04, 0xd4, 0x51, 0x00, 0x40, 0xb4, 0x0b, + 0x00, 0x04, 0xc4, 0x51, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x45, 0x24, 0x10, + 0x0a, 0x45, 0x24, 0x52, 0x00, 0x04, 0xd4, 0x51, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x45, 0x34, 0x10, 0x0a, 0x45, 0x34, 0x53, + 0x00, 0x04, 0x84, 0x54, + 0x00, 0x40, 0xa4, 0x0a, 0x00, 0x04, 0x94, 0x54, 0x00, 0x40, 0xb4, 0x0b, + 0x00, 0x04, 0x84, 0x54, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x45, 0x54, 0x10, + 0x0a, 0x45, 0x54, 0x55, 0x00, 0x04, 0x94, 0x54, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x45, 0x64, 0x10, 0x0a, 0x45, 0x64, 0x56, + 0x00, 0x40, 0xa4, 0x04, + 0x00, 0x40, 0x60, 0xc0, 0x00, 0x40, 0xb4, 0x05, 0x00, 0x40, 0x70, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0x06, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x54, 0x06, + 0x00, 0x47, 0x64, 0x18, + 0x00, 0x47, 0x60, 0xc0, 0x00, 0x47, 0x64, 0x7b, 0x00, 0x47, 0x60, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0x04, 0xbf, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0xf4, 0xbe, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0xe4, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0x34, 0xc2, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0x24, 0xc1, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0x10, 0xc0, + 0x00, 0x4b, 0xe4, 0x28, + 0x00, 0x4c, 0x10, 0xc0, 0x00, 0x4b, 0xf4, 0x29, 0x00, 0x4c, 0x14, 0xc1, + 0x00, 0x4c, 0x24, 0x2a, + 0x00, 0x4c, 0x14, 0xc1, 0x00, 0x4c, 0x04, 0x2b, 0x00, 0x4c, 0x14, 0xc1, + 0x00, 0x4c, 0x34, 0x2c, + 0x00, 0x4c, 0x14, 0xc1, 0x00, 0x4c, 0x14, 0x79, 0x04, 0x4c, 0x10, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0xc1, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0xa4, 0xb9, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0x94, 0xb8, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0x84, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0xd4, 0xbc, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0xc4, 0xbb, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0xb0, 0xc0, 0x00, 0x4b, 0x84, 0x23, 0x00, 0x4b, 0xb0, 0xc0, + 0x00, 0x4b, 0x94, 0x24, + 0x00, 0x4b, 0xb4, 0xbb, 0x00, 0x4b, 0xc4, 0x25, 0x00, 0x4b, 0xb4, 0xbb, + 0x00, 0x4b, 0xa4, 0x26, + 0x00, 0x4b, 0xb4, 0xbb, 0x00, 0x4b, 0xd4, 0x27, 0x00, 0x4b, 0xb4, 0xbb, + 0x00, 0x4b, 0xb4, 0x79, + 0x04, 0x4b, 0xb0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0xbb, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0x44, 0xb3, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0x34, 0xb2, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0x24, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0x74, 0xb6, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0x64, 0xb5, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0x50, 0xc0, + 0x00, 0x4b, 0x24, 0x1e, + 0x00, 0x4b, 0x50, 0xc0, 0x00, 0x4b, 0x34, 0x1f, 0x00, 0x4b, 0x54, 0xb5, + 0x00, 0x4b, 0x64, 0x20, + 0x00, 0x4b, 0x54, 0xb5, 0x00, 0x4b, 0x44, 0x21, 0x00, 0x4b, 0x54, 0xb5, + 0x00, 0x4b, 0x74, 0x22, + 0x00, 0x4b, 0x54, 0xb5, 0x00, 0x4b, 0x54, 0x79, 0x04, 0x4b, 0x50, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0xb5, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0xe4, 0xad, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0xd4, 0xac, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4a, 0xc4, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4b, 0x14, 0xb0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4b, 0x04, 0xaf, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4a, 0xf0, 0xc0, 0x00, 0x4a, 0xc4, 0x19, 0x00, 0x4a, 0xf0, 0xc0, + 0x00, 0x4a, 0xd4, 0x1a, + 0x00, 0x4a, 0xf4, 0xaf, 0x00, 0x4b, 0x04, 0x1b, 0x00, 0x4a, 0xf4, 0xaf, + 0x00, 0x4a, 0xe4, 0x1c, + 0x00, 0x4a, 0xf4, 0xaf, 0x00, 0x4b, 0x14, 0x1d, 0x00, 0x4a, 0xf4, 0xaf, + 0x00, 0x4a, 0xf4, 0x79, + 0x04, 0x4a, 0xf0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0xaf, + 0x00, 0x47, 0x64, 0x7a, + 0x04, 0x47, 0x64, 0x78, 0x00, 0x47, 0x64, 0x2e, 0x04, 0x40, 0x60, 0xc0, + 0x00, 0x47, 0x54, 0x2d, + 0x04, 0x40, 0x64, 0x06, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0x07, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x54, 0x07, 0x00, 0x47, 0x64, 0x18, 0x00, 0x47, 0x60, 0xc0, + 0x00, 0x47, 0x64, 0x7b, + 0x00, 0x47, 0x60, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0x84, 0xd7, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0x74, 0xd6, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0x64, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0xb4, 0xda, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0xa4, 0xd9, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0x90, 0xc0, 0x00, 0x4d, 0x64, 0x28, 0x00, 0x4d, 0x90, 0xc0, + 0x00, 0x4d, 0x74, 0x29, + 0x00, 0x4d, 0x94, 0xd9, 0x00, 0x4d, 0xa4, 0x2a, 0x00, 0x4d, 0x94, 0xd9, + 0x00, 0x4d, 0x84, 0x2b, + 0x00, 0x4d, 0x94, 0xd9, 0x00, 0x4d, 0xb4, 0x2c, 0x00, 0x4d, 0x94, 0xd9, + 0x00, 0x4d, 0x94, 0x79, + 0x04, 0x4d, 0x90, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0xd9, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0x24, 0xd1, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0x14, 0xd0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0x04, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0x54, 0xd4, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4d, 0x44, 0xd3, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4d, 0x30, 0xc0, + 0x00, 0x4d, 0x04, 0x23, + 0x00, 0x4d, 0x30, 0xc0, 0x00, 0x4d, 0x14, 0x24, 0x00, 0x4d, 0x34, 0xd3, + 0x00, 0x4d, 0x44, 0x25, + 0x00, 0x4d, 0x34, 0xd3, 0x00, 0x4d, 0x24, 0x26, 0x00, 0x4d, 0x34, 0xd3, + 0x00, 0x4d, 0x54, 0x27, + 0x00, 0x4d, 0x34, 0xd3, 0x00, 0x4d, 0x34, 0x79, 0x04, 0x4d, 0x30, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0xd3, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0xc4, 0xcb, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0xb4, 0xca, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0xa4, 0x76, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0xf4, 0xce, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0xe4, 0xcd, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0xd0, 0xc0, 0x00, 0x4c, 0xa4, 0x1e, 0x00, 0x4c, 0xd0, 0xc0, + 0x00, 0x4c, 0xb4, 0x1f, + 0x00, 0x4c, 0xd4, 0xcd, 0x00, 0x4c, 0xe4, 0x20, 0x00, 0x4c, 0xd4, 0xcd, + 0x00, 0x4c, 0xc4, 0x21, + 0x00, 0x4c, 0xd4, 0xcd, 0x00, 0x4c, 0xf4, 0x22, 0x00, 0x4c, 0xd4, 0xcd, + 0x00, 0x4c, 0xd4, 0x79, + 0x04, 0x4c, 0xd0, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x47, 0x64, 0xcd, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0x64, 0xc5, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0x54, 0xc4, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0x44, 0x76, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0x94, 0xc8, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x4c, 0x84, 0xc7, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x4c, 0x70, 0xc0, + 0x00, 0x4c, 0x44, 0x19, + 0x00, 0x4c, 0x70, 0xc0, 0x00, 0x4c, 0x54, 0x1a, 0x00, 0x4c, 0x74, 0xc7, + 0x00, 0x4c, 0x84, 0x1b, + 0x00, 0x4c, 0x74, 0xc7, 0x00, 0x4c, 0x64, 0x1c, 0x00, 0x4c, 0x74, 0xc7, + 0x00, 0x4c, 0x94, 0x1d, + 0x00, 0x4c, 0x74, 0xc7, 0x00, 0x4c, 0x74, 0x79, 0x04, 0x4c, 0x70, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x47, 0x64, 0xc7, 0x00, 0x47, 0x64, 0x7a, 0x04, 0x47, 0x64, 0x78, + 0x00, 0x47, 0x64, 0x2e, + 0x04, 0x40, 0x70, 0xc0, 0x00, 0x47, 0x54, 0x2d, 0x04, 0x40, 0x74, 0x07, + 0x00, 0x40, 0x64, 0x57, + 0x00, 0x06, 0xe0, 0xc0, 0x00, 0x40, 0x74, 0x58, 0x00, 0x06, 0xf0, 0xc0, + 0x00, 0x40, 0x64, 0x57, + 0x00, 0x06, 0x60, 0xc0, 0x00, 0x40, 0x74, 0x58, 0x00, 0x06, 0x70, 0xc0, + 0x00, 0x40, 0x64, 0x57, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x45, 0x94, 0x10, + 0x0a, 0x45, 0x94, 0x59, 0x00, 0x40, 0x74, 0x58, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x45, 0xa4, 0x10, 0x0a, 0x45, 0xa4, 0x5a, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x06, 0x24, 0x12, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x06, 0x34, 0x13, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x06, 0xa4, 0x12, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x06, 0xb4, 0x13, + 0x00, 0x04, 0x04, 0x61, + 0x00, 0x40, 0x60, 0xc0, 0x00, 0x04, 0x14, 0x61, 0x00, 0x40, 0x70, 0xc0, + 0x00, 0x04, 0x04, 0x61, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x46, 0x24, 0x10, + 0x0a, 0x46, 0x24, 0x62, 0x00, 0x04, 0x14, 0x61, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x46, 0x34, 0x10, 0x0a, 0x46, 0x34, 0x63, + 0x00, 0x04, 0x44, 0x5b, + 0x00, 0x40, 0x64, 0x06, 0x00, 0x04, 0x54, 0x5b, 0x00, 0x40, 0x74, 0x07, + 0x00, 0x04, 0x44, 0x5b, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x45, 0xc4, 0x10, + 0x0a, 0x45, 0xc4, 0x5c, 0x00, 0x04, 0x54, 0x5b, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x45, 0xd4, 0x10, 0x0a, 0x45, 0xd4, 0x5d, + 0x00, 0x04, 0x24, 0x5e, + 0x00, 0x40, 0x64, 0x06, 0x00, 0x04, 0x34, 0x5e, 0x00, 0x40, 0x74, 0x07, + 0x00, 0x04, 0x24, 0x5e, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x45, 0xf4, 0x10, + 0x0a, 0x45, 0xf4, 0x5f, 0x00, 0x04, 0x34, 0x5e, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x46, 0x04, 0x10, 0x0a, 0x46, 0x04, 0x60, + 0x00, 0x40, 0x84, 0x64, + 0x00, 0x40, 0x64, 0x06, 0x00, 0x40, 0x94, 0x64, 0x00, 0x40, 0x74, 0x07, + 0x00, 0x40, 0x84, 0x64, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x46, 0x54, 0x10, + 0x0a, 0x46, 0x54, 0x65, 0x00, 0x40, 0x94, 0x64, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x46, 0x64, 0x10, 0x0a, 0x46, 0x64, 0x66, + 0x00, 0x04, 0xc4, 0x67, + 0x00, 0x40, 0x64, 0x06, 0x00, 0x04, 0xd4, 0x67, 0x00, 0x40, 0x74, 0x07, + 0x00, 0x04, 0xc4, 0x67, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x46, 0x84, 0x10, + 0x0a, 0x46, 0x84, 0x68, 0x00, 0x04, 0xd4, 0x67, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x46, 0x94, 0x10, 0x0a, 0x46, 0x94, 0x69, + 0x00, 0x04, 0x84, 0x6a, + 0x00, 0x40, 0x64, 0x06, 0x00, 0x04, 0x94, 0x6a, 0x00, 0x40, 0x74, 0x07, + 0x00, 0x04, 0x84, 0x6a, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x46, 0xb4, 0x10, + 0x0a, 0x46, 0xb4, 0x6b, 0x00, 0x04, 0x94, 0x6a, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x46, 0xc4, 0x10, 0x0a, 0x46, 0xc4, 0x6c, + 0x00, 0x40, 0x64, 0x6d, + 0x00, 0x07, 0x60, 0xc0, 0x00, 0x40, 0x74, 0x6e, 0x00, 0x07, 0x70, 0xc0, + 0x00, 0x40, 0x64, 0x6d, + 0x00, 0x41, 0x10, 0xc0, 0x00, 0x41, 0x10, 0xc0, 0x09, 0x41, 0x04, 0x11, + 0x00, 0x46, 0xf4, 0x10, + 0x0a, 0x46, 0xf4, 0x6f, 0x00, 0x40, 0x74, 0x6e, 0x00, 0x41, 0x10, 0xc0, + 0x00, 0x41, 0x10, 0xc0, + 0x09, 0x41, 0x04, 0x11, 0x00, 0x47, 0x04, 0x10, 0x0a, 0x47, 0x04, 0x70, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x0c, 0x00, 0xc0, + 0x06, 0x0c, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xc0, 0x06, 0x0c, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x37, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, 0x45, 0x51, 0x55, 0x41, + 0x4c, 0x49, 0x5a, 0x45, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x45, 0x53, 0x43, 0x41, 0x4c, 0x45, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, + 0x4c, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x19, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x4d, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e, + 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x49, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0x10, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x80, 0x58, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x10, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x80, + 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x52, 0x4f, 0x4e, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x33, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x4d, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x64, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x55, 0x52, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, + 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4b, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x57, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x53, 0x50, 0x44, 0x49, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x47, 0x43, + 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x64, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x43, 0x39, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x62, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x50, 0x43, 0x4d, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x41, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x68, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x43, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, + 0x56, 0x4f, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x64, 0x64, + 0x2d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6f, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x50, 0x41, 0x53, + 0x53, 0x54, 0x48, 0x52, + 0x4f, 0x55, 0x47, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x7a, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xdc, + 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0xdd, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; diff --git a/kernel/drv/oss_sblive/oss_sblive.c b/kernel/drv/oss_sblive/oss_sblive.c new file mode 100644 index 0000000..b516746 --- /dev/null +++ b/kernel/drv/oss_sblive/oss_sblive.c @@ -0,0 +1,3985 @@ +/* + * Purpose: Driver for Creative SB Live/Audigy/2/4. Audio, MIDI and mixer services. + */ +/* + * + * 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_sblive_cfg.h" +#include "midi_core.h" +#include "oss_pci.h" +#include "remux.h" + +/* + * Include the DSP files for emu10k1 (Live!) and emu10k2 (Audigy) + * These headers have been generated using the emu10k tools (by 4Front). + * The _be.h files have been generated in a big endian system and the others + * in a litle endian (intel) system. + */ +#ifdef OSS_BIG_ENDIAN +# include "emu10k1_dsp_be.h" +# include "emu10k2_dsp_be.h" +#else +# include "emu10k1_dsp.h" +# include "emu10k2_dsp.h" +#endif + +#define NO_EMU10K1_SYNTH +#undef TEST_3D + +#define BOGUS_MIXER_CONTROLS ( \ + SOUND_MASK_SPEAKER | \ + SOUND_MASK_ALTPCM | \ + SOUND_MASK_VIDEO | \ + SOUND_MASK_DEPTH | \ + SOUND_MASK_MONO \ + ) + +#ifndef linux +#define NO_EMU10K1_SYNTH +#endif + +#include "ac97.h" +#include "sblive.h" +#include "eq1.h" + +#define MAX_SENDS 4 + +#define SEND_L 0 +#define SEND_R 1 +#define SEND_SL 2 +#define SEND_SR 3 +#define SEND_C 4 +#define SEND_W 5 +#define SEND_RL 6 +#define SEND_RR 7 + +#define SPDIF_L 20 +#define SPDIF_R 21 + +static unsigned char default_routing[MAX_SENDS] = + { SEND_L, SEND_R, SEND_SL, SEND_SR }; +static unsigned char front_routing[MAX_SENDS] = + { SEND_L, SEND_R, 0x3f, 0x3f }; +static unsigned char surr_routing[MAX_SENDS] = + { SEND_SL, SEND_SR, 0x3f, 0x3f }; +static unsigned char center_lfe_routing[MAX_SENDS] = + { SEND_C, SEND_W, 0x3f, 0x3f }; +static unsigned char rear_routing[MAX_SENDS] = + { SEND_RL, SEND_RR, 0x3f, 0x3f }; +static unsigned char spdif_routing[MAX_SENDS] = + { SPDIF_L, SPDIF_R, 0x3f, 0x3f }; + +typedef struct +{ + int speed; + int pitch; + int recbits; + int audigy_recbits; + int rom; +} +speed_ent; + +/* Note! with audigy speedsel=7 means 12 kHz */ + +static speed_ent speed_tab[] = { + {8000, 0xb6a41b, 7, 8, ROM7}, + {11025, 0xbe0b64, 6, 6, ROM6}, + {16000, 0xc6a41b, 5, 5, ROM5}, + {22050, 0xce0b64, 4, 3, ROM4}, + {24000, 0xd00000, 3, 3, ROM3}, + {32000, 0xd6a41b, 2, 2, ROM2}, + {44100, 0xde0b64, 1, 1, ROM1}, + {48000, 0xe00000, 0, 0, ROM0}, + {0} +}; + +#define PCI_VENDOR_ID_CREATIVE 0x1102 +#define PCI_DEVICE_ID_SBLIVE 0x0002 +#define PCI_DEVICE_ID_AUDIGY 0x0004 +#define PCI_DEVICE_ID_AUDIGYVALUE 0x0008 +#define PCI_DEVICE_ID_AUDIGY_CARDBUS 0x2001 + +#define LEFT_CH 0 +#define RIGHT_CH 1 + +void sblive_init_voice (sblive_devc * devc, int chn); +static void audigyuartintr (sblive_devc * devc); + +static int +ac97_read (void *devc_, int wAddr) +{ + sblive_devc *devc = devc_; + int dtemp = 0, i; + + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + if (i == 1000) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; /* Timeout */ + } + dtemp = INW (devc->osdev, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dtemp & 0xffff; +} + +static int +ac97_write (void *devc_, int wAddr, int wData) +{ + sblive_devc *devc = devc_; + oss_native_word flags; + int i; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, wAddr, devc->base + 0x1e); + for (i = 0; i < 10000; i++) + if (INB (devc->osdev, devc->base + 0x1e) & 0x80) + break; + OUTW (devc->osdev, wData, devc->base + 0x1c); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + +unsigned int +sblive_read_reg (sblive_devc * devc, int reg, int chn) +{ + oss_native_word flags; + unsigned int ptr, ptr_addr_mask, val, mask, size, offset; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ptr_addr_mask = (devc->feature_mask & SB_AUDIGY) ? 0x0fff0000 : 0x07ff0000; + ptr = ((reg << 16) & ptr_addr_mask) | (chn & 0x3f); + OUTL (devc->osdev, ptr, devc->base + 0x00); /* Pointer */ + val = INL (devc->osdev, devc->base + 0x04); /* Data */ + if (reg & 0xff000000) + { + size = (reg >> 24) & 0x3f; + offset = (reg >> 16) & 0x1f; + mask = ((1 << size) - 1) << offset; + val &= mask; + val >>= offset; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return val; +} + +void +sblive_write_reg (sblive_devc * devc, int reg, int chn, unsigned int value) +{ + oss_native_word flags; + unsigned int ptr, ptr_addr_mask, mask, size, offset; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + ptr_addr_mask = (devc->feature_mask & SB_AUDIGY) ? 0x0fff0000 : 0x07ff0000; + ptr = ((reg << 16) & ptr_addr_mask) | (chn & 0x3f); + OUTL (devc->osdev, ptr, devc->base + 0x00); /* Pointer */ + if (reg & 0xff000000) + { + size = (reg >> 24) & 0x3f; + offset = (reg >> 16) & 0x1f; + mask = ((1 << size) - 1) << offset; + value <<= offset; + value &= mask; + value |= INL (devc->osdev, devc->base + 0x04) & ~mask; /* data */ + } + OUTL (devc->osdev, value, devc->base + 0x04); /* Data */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +static void +write_efx (sblive_devc * devc, int reg, unsigned int value) +{ + sblive_write_reg (devc, reg, 0, value); +} + +static void +update_vu (sblive_devc * devc, sblive_portc * portc, dmap_p dmap, int frag) +{ + int left = 0, right = 0; + int i, l; + + frag %= dmap->nfrags; + l = dmap->fragment_size / 2; + + if (portc->format == AFMT_AC3) /* Raw S/PDIF mode */ + { + if (devc->vu_tmp2 == 0) + devc->vu_tmp2 = 2; + + portc->vu_left = devc->vu_tmp; + portc->vu_right = 144 - devc->vu_tmp; + devc->vu_tmp = devc->vu_tmp + devc->vu_tmp2; + + if (devc->vu_tmp >= 144) + { + devc->vu_tmp2 = -2; + devc->vu_tmp = 144; + } + + if (devc->vu_tmp <= 0) + { + devc->vu_tmp2 = 2; + devc->vu_tmp = 0; + } + + return; + } + + if (portc->format == AFMT_U8) + { + unsigned char *p; + int v; + + p = dmap->dmabuf + (frag * dmap->fragment_size); + + if (dmap->dmabuf != NULL) + for (i = 0; i < l; i++) + { + v = *p; + p++; + v -= 128; + if (v < 0) + v = -v; + if (v > left) + left = v; + + v = *p; + p++; + v -= 128; + if (v < 0) + v = -v; + if (v > right) + right = v; + } + } + else + { + short *p; + int v; + + l /= 2; + p = (short *) (dmap->dmabuf + (frag * dmap->fragment_size)); + + if (dmap->dmabuf != NULL) + for (i = 0; i < l; i++) + { + v = SSWAP (*p++) >> 8; + if (v < 0) + v = -v; + if (v > left) + left = v; + + v = *p++ >> 8; + if (v < 0) + v = -v; + if (v > right) + right = v; + } + } + + if (portc->channels == 1) /* Mono */ + { + if (right > left) + left = right; + right = left; + } + + if (left > portc->vu_left) + portc->vu_left = left; + if (right > portc->vu_right) + portc->vu_right = right; +} + +static int +sbliveintr (oss_device_t * osdev) +{ + int p; + unsigned int status; +#ifndef NO_EMU10K1_SYNTH + extern int sblive_synth_enable; +#endif + + sblive_devc *devc = osdev->devc; + + /* + * TODO: Fix mutexes and move the inputintr/outputintr calls outside the + * mutex block. + */ + /* oss_native_word flags; */ + /* MUTEX_ENTER (devc->mutex, flags); */ + + status = INL (devc->osdev, devc->base + 0x08); + +#if !defined(sparc) + if (status == 0) + { + /* MUTEX_EXIT (devc->mutex, flags); */ + return 0; + } +#endif + + if (status & 0x00000080) /* MIDI RX interrupt */ + { + if (devc->feature_mask & SB_AUDIGY) + audigyuartintr (devc); + else + uart401_irq (&devc->uart401devc); + } + + if (status & 0x00008000) /* ADC buffer full intr */ + { + /* Force the starting position to match this moment */ + unsigned int pos; + pos = (INL (devc->osdev, devc->base + 0x10) >> 6) & 0xfffff; + devc->portc[0].rec_starttime = pos; + } + + if (status & 0x00000240) /* Interval timer or channel loop interrupt */ + { + for (p = 0; p < devc->n_audiodevs; p++) + { + sblive_portc *portc = &devc->portc[p]; + + if (portc->audiodev >= 0 && portc->audiodev < num_audio_engines + && portc->trigger_bits & PCM_ENABLE_OUTPUT) + { + int pos, n; + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_out; + + pos = sblive_read_reg (devc, QKBCA, portc->voice_chn) & 0x00ffffff; /* Curr pos */ + pos <<= portc->out_sz; + pos -= dmap->driver_use_value; + + if (dmap->fragment_size == 0) + { + cmn_err (CE_WARN, "dmap->fragment_size == 0\n"); + continue; + } + + pos /= dmap->fragment_size; + if (pos < 0 || pos >= dmap->nfrags) + pos = 0; + + /* + * If this was a full/half loop interrupt then use forced pointer + */ + if (sblive_get_voice_loopintr (devc, portc->voice_chn)) + pos = 0; /* Full loop boundary */ + else if (sblive_get_voice_halfloopintr (devc, portc->voice_chn)) + pos = dmap->nfrags / 2; /* Half loop boundary */ + + n = 0; + while (dmap_get_qhead (dmap) != pos && n++ < dmap->nfrags) + { + update_vu (devc, portc, dmap, dmap_get_qhead (dmap)); + oss_audio_outputintr (portc->audiodev, 0); + } + } + + if (num_audio_engines > 0 && portc->audiodev < num_audio_engines + && portc->trigger_bits & PCM_ENABLE_INPUT) + { + int n; + unsigned int pos; + + dmap_t *dmap = audio_engines[portc->audiodev]->dmap_in; + + /* Compute current pos based on the wall clock register */ + pos = (INL (devc->osdev, devc->base + 0x10) >> 6) & 0xfffff; + if (pos > portc->rec_starttime) + pos = pos - portc->rec_starttime; + else + pos = 0xfffff - (portc->rec_starttime - pos); + pos = (pos * (portc->speed / 25)) / (48000 / 25); + pos *= 2; /* 16 bit->bytes */ + pos *= portc->channels; + pos = pos % dmap->bytes_in_use; + if (dmap->fragment_size == 0) + cmn_err (CE_WARN, "dmap->fragment_size==0\n"); + else + { + pos /= dmap->fragment_size; + if (pos >= dmap->nfrags) + pos = 0; + n = 0; + while (dmap_get_qtail (dmap) != pos && n++ < dmap->nfrags) + { + oss_audio_inputintr (devc->recording_dev, 0); + } + } + } + } + +#ifndef NO_EMU10K1_SYNTH + if (sblive_synth_enable) + sblive_synth_interrupt (devc); +#endif + } + + OUTL (devc->osdev, status, devc->base + 0x08); /* Acknowledge them */ + + /* MUTEX_EXIT (devc->mutex, flags); */ + + return 1; +} + +static int +setup_passthrough (sblive_devc * devc, sblive_portc * portc, int pass) +{ + int ctrl = devc->passthrough_gpr; + + if (ctrl < 0) + return 0; + + if (pass == portc->uses_spdif) + return 1; + + if (pass && devc->spdif_busy) + return 0; + + portc->uses_spdif = pass; + + sblive_write_reg (devc, ctrl + GPR0, 0, pass); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, !pass); + if (pass) + { + devc->spdif_busy = 1; + } + else + { + devc->spdif_busy = 0; + } + + return 1; +} + +static int +sblive_audio_set_rate (int dev, int arg) +{ + sblive_portc *portc = audio_engines[dev]->portc; + int i, n = -1, dif, best = -1, bestdif = 0x7fffffff; + + if (arg == 0) + return portc->speed; + + for (i = 0; speed_tab[i].speed != 0 && n == -1; i++) + { + if (speed_tab[i].speed == arg) /* Exact match */ + { + n = i; + break; + } + + dif = arg - speed_tab[i].speed; + if (dif < 0) + dif = -dif; + + if (dif < bestdif) + { + best = i; + bestdif = dif; + } + } + + if (n == -1) + n = best; + + if (n == -1) + n = 0; + + portc->speed = speed_tab[n].speed; + portc->speedsel = n; + + return portc->speed; +} + +static short +sblive_audio_set_channels (int dev, short arg) +{ + sblive_portc *portc = audio_engines[dev]->portc; + + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +sblive_audio_set_format (int dev, unsigned int arg) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->format; + + if (portc->mode & OPEN_READ) + arg = AFMT_S16_LE; + + if (arg != AFMT_U8 && arg != AFMT_S16_LE && arg != AFMT_AC3) + return portc->format; + + /* Enforce stereo mode with AC3 */ + if (arg == AFMT_AC3) + { + if (!setup_passthrough (devc, portc, 1)) + return portc->format; + portc->channels = 2; + portc->speed = 48000; + } + else + if (portc->input_type != ITYPE_SPDIF && portc->uses_spdif + && arg != AFMT_AC3) + { + setup_passthrough (devc, portc, 0); + } + + portc->format = arg; + + return portc->format; +} + +static int mixer_ext_init (int dev); +static int create_efx_mixer (int dev); +static int sblive_set_gpr (int dev, int ctrl, unsigned int cmd, int value); + +static int +is_special_gpr (int gpr) +{ + if (gpr >= NEXT_FREE_GPR) + return 0; + + if (SPECIAL_GPRS & (1 << gpr)) + { + return 1; + } + + if (gpr > 0) + if (SPECIAL_GPRS & (1 << (gpr - 1))) + { + return 1; + } + return 0; +} + +static void update_output_device (sblive_devc * devc, sblive_portc * portc); + +static int +sblive_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + sblive_reg *reg = (sblive_reg *) arg; + gpr_info *gpr = (gpr_info *) arg; + const_info *consts = (const_info *) arg; + unsigned int *code = (unsigned int *) arg; + int i; + + switch (cmd) + { + case SNDCTL_DSP_GETCHANNELMASK: + return *arg = + DSP_BIND_FRONT | DSP_BIND_REAR | DSP_BIND_SURR | DSP_BIND_CENTER_LFE; + break; + + case SNDCTL_DSP_BIND_CHANNEL: + { + int val; + + val = *arg; + portc->speaker_mode = SMODE_BIND; + portc->binding = val; + return *arg = val; + } + break; + + case SNDCTL_DSP_SETPLAYVOL: + { + int left, right, val; + + val = *arg; + + left = val & 0xff; + right = (val >> 8) & 0xff; + if (left < 0) + left = 0; + if (right < 0) + right = 0; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + +#if 0 + if (right > left) + left = right; +#endif + portc->playvol = left; + update_output_device (devc, portc); + + return *arg = left | (left << 8); + } + break; + + case SNDCTL_DSP_GETPLAYVOL: + { + int vol; + vol = (portc->playvol << 8) | portc->playvol; + return *arg = vol; + } + break; + + case SBLIVE_READREG: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + reg->value = sblive_read_reg (devc, reg->reg, reg->chn); + return 0; + break; + + case SBLIVE_WRITEREG: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + sblive_write_reg (devc, reg->reg, reg->chn, reg->value); + return 0; + break; + + case SBLIVE_READGPIO: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + return *arg = INW (devc->osdev, devc->base + 0x18); + break; + + case SBLIVE_WRITEGPIO: + { + int val; + val = *arg; + +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + OUTW (devc->osdev, val, devc->base + 0x18); + + } + return 0; + + case SBLIVE_WRITEPARMS: + { + +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + if (gpr->ngpr >= MAX_GPR_PARMS) + return OSS_EIO; + + for (i = 0; i < gpr->ngpr; i++) + { + gpr->gpr[i].name[GPR_NAME_SIZE - 1] = 0; /* Overflow protection */ + if (strlen (gpr->gpr[i].name) >= 32) /* Name may be bad */ + { + return OSS_EIO; + } + + if (gpr->gpr[i].num >= MAX_GPR) + { + return OSS_EIO; + } + +/* cmn_err(CE_CONT, "Gpr %d = %s (vol %x) type=%x\n", gpr->gpr[i].num, gpr->gpr[i].name, gpr->gpr[i].def, gpr->gpr[i].type); */ + if (gpr->gpr[i].type != MIXT_GROUP) + { + if (is_special_gpr (gpr->gpr[i].num)) + sblive_set_gpr (devc->mixer_dev, gpr->gpr[i].num, + SNDCTL_MIX_WRITE, + devc->gpr_values[gpr->gpr[i].num]); + else + sblive_set_gpr (devc->mixer_dev, gpr->gpr[i].num, + SNDCTL_MIX_WRITE, gpr->gpr[i].def); + } + } + + + if (devc->gpr == NULL) + { + devc->gpr = PMALLOC (devc->osdev, sizeof (gpr_info)); + if (devc->gpr == NULL) + { + cmn_err (CE_WARN, "Out of memory (gpr)\n"); + return OSS_ENOSPC; + } + memset (devc->gpr, 0, sizeof (gpr_info)); + } + memcpy (devc->gpr, gpr, sizeof (gpr_info)); + create_efx_mixer (devc->mixer_dev); + } + return 0; + break; + + case SBLIVE_WRITECONST: + { + +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + if (consts->nconst >= MAX_CONST_PARMS) + return OSS_EIO; + + for (i = 0; i < consts->nconst; i++) + { + if (consts->consts[i].gpr >= MAX_GPR) + { + return OSS_EIO; + } + + sblive_write_reg (devc, consts->consts[i].gpr + GPR0, 0, + consts->consts[i].value); + } + + } + return 0; + break; + + case SBLIVE_WRITECODE1: + { + int pc; + +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + for (pc = 0; pc < 512; pc++) + { + write_efx (devc, UC0 + pc, code[pc]); + } + + } + sblive_write_reg (devc, DBG, 0, 0); + return 0; + break; + + case SBLIVE_WRITECODE2: + { + int pc; + +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + for (pc = 0; pc < 512; pc++) + { + write_efx (devc, UC0 + 512 + pc, code[pc]); + } + } + sblive_write_reg (devc, DBG, 0, 0); + return 0; + break; + + case SBLIVE_GETCHIPTYPE: +#ifdef GET_PROCESS_UID + if (GET_PROCESS_UID () != 0) /* Not root */ + return OSS_EINVAL; +#endif + return *arg = devc->feature_mask & ~SB_AUDIGY2; + break; + + } + return OSS_EINVAL; +} + +static void sblive_audio_trigger (int dev, int state); + +static void +sblive_audio_reset (int dev) +{ + sblive_audio_trigger (dev, 0); +} + +static void +sblive_audio_reset_input (int dev) +{ + sblive_portc *portc = audio_engines[dev]->portc; + sblive_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +sblive_audio_reset_output (int dev) +{ + sblive_portc *portc = audio_engines[dev]->portc; + sblive_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +static int sblive_set_vol (int dev, int ctrl, unsigned int cmd, int value); + +static void +reset_portc_volume (sblive_devc * devc, sblive_portc * portc) +{ + int v; +#ifdef TEST_3D + v = 100 | (50 << 8) | (0 << 16); /* vol=100, dist=50, angle=0 */ +#else + v = 100 | (100 < 8); +#endif + sblive_set_vol (devc->mixer_dev, portc->port_number, SNDCTL_MIX_WRITE, v); +} + +#if MAX_ADEV == 2 +static const unsigned int binding_map[MAX_ADEV] = + { DSP_BIND_FRONT, DSP_BIND_SURR }; +#else +static const unsigned int binding_map[MAX_ADEV] = { + DSP_BIND_FRONT, + DSP_BIND_FRONT, + DSP_BIND_SURR, + DSP_BIND_CENTER_LFE, + DSP_BIND_REAR +}; +#endif + +/*ARGSUSED*/ +static int +sblive_audio_open (int dev, int mode, int open_flags) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->mode = mode; + portc->audio_active &= ~mode; + + portc->resetvol = 0; + + portc->speaker_mode = devc->speaker_mode; + portc->binding = binding_map[portc->port_number]; + if (portc->binding == 0) + portc->binding = DSP_BIND_FRONT; + mixer_devs[devc->mixer_dev]->modify_counter++; /* Force update of mixer */ + + audio_engines[dev]->flags &= ~ADEV_FIXEDRATE; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (devc->autoreset || portc->resetvol) + reset_portc_volume (devc, portc); + + if (portc->input_type == ITYPE_SPDIF) + { + if (!setup_passthrough (devc, portc, 1)) + { + portc->mode = 0; + return OSS_EBUSY; + } + } + else + { + /* Enable AC3 format if possible */ + if (!devc->spdif_busy) + audio_engines[dev]->oformat_mask |= AFMT_AC3; + else + audio_engines[dev]->oformat_mask &= ~AFMT_AC3; + } + return 0; +} + +static void +sblive_audio_close (int dev, int mode) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + + sblive_audio_reset (dev); + portc->mode = 0; + portc->audio_active &= ~mode; + mixer_devs[devc->mixer_dev]->modify_counter++; + setup_passthrough (devc, portc, 0); + audio_engines[dev]->oformat_mask |= AFMT_AC3; +} + +#ifdef TEST_3D +/* Sin table for Q1 (*10000) */ +static const int sincos[] = { + 0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, + 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, + 3420, 3583, 3746, 3907, 4067, 4226, 4383, 4539, 4694, 4848, + 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, + 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, + 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, + 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, + 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, + 9848, 9876, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, + 10000, +}; + +static __inline__ int +oss_sin (int angle) +{ + int a; + int f; + + a = angle % 90; + + if ((angle / 90) & 1) + a = 90 - a; + + f = sincos[a]; + if (angle >= 180) + f = -f; + return f; +} + +static __inline__ int +oss_cos (int angle) +{ + int a, q; + int f; + + a = angle % 90; + q = angle / 90; + + if (!(q & 1)) + a = 90 - a; + + f = sincos[a]; + if (angle >= 90 && angle < 270) + f = -f; + return f; +} + +static void +compute_3d (sblive_devc * devc, sblive_portc * portc, int voice, int chn, + int *send) +{ + int angle = portc->playangle; + int dist, opening = 45; + int i; + + /* left, right, rear_right, rear_left */ + static int spk_angles[4] = { 315, 45, 135, 225 }; + int gain = 50, leak = 0; + int v[4]; + + dist = portc->playdist; + + if (dist < 0) + dist = 0; + if (dist > 100) + dist = 100; + portc->playdist = dist; + + dist = 100 - dist; /* Invert distance */ + opening = (90 * dist) / 100; + + if (dist < 50) + { /* Attenuate distant sounds */ + gain = dist; + } + else + { + /* "Expand" close sounds by leaking signal to silent channels */ + leak = dist - 50; + } + + if (portc->channels == 2) + { + if (chn == LEFT_CH) + angle -= opening; + else + angle += opening; + } + + if (angle < 0) + angle += 360; + + angle %= 360; + + for (i = 0; i < 4; i++) + v[i] = (gain * portc->playvol * 255 + 25) / 50; + + for (i = 0; i < 4; i++) + { + int a = spk_angles[i] - angle; + + if (a < 0) + a = -a; /* ABS */ + if (a > 180) + a = 360 - a; + + if (a >= 90) /* Too far */ + { + v[i] = 0; /* Muted speaker */ + continue; + } + else + v[i] = ((v[i] * oss_cos (a) + 5000) / 10000) / 100; + } + + if (leak > 0) + { + leak = (255 * portc->playvol * leak + 2500) / 5000; + + for (i = 0; i < 4; i++) + if (v[i] < leak) + v[i] = leak; + } + + send[0] = v[0]; /* Left */ + send[1] = v[1]; /* Right */ + send[2] = v[3]; /* Rear left */ + send[3] = v[2]; /* Rear right */ +} +#endif + +static void +write_routing (sblive_devc * devc, int voice, unsigned char *routing) +{ + int i; + + if (routing == NULL) + routing = default_routing; + + if (devc->feature_mask & SB_AUDIGY) + { + unsigned int srda = 0; + + for (i = 0; i < 4; i++) + srda |= routing[i] << (i * 8); + + sblive_write_reg (devc, SRDA, voice, srda); + } + else + { + int fxrt = 0; + + for (i = 0; i < 4; i++) + fxrt |= routing[i] << ((i * 4) + 16); + sblive_write_reg (devc, FXRT, voice, fxrt); + } +} + +/*ARGSUSED*/ +static void +compute_bind (sblive_devc * devc, sblive_portc * portc, unsigned char *send, + int chn) +{ + memset (send, 0, MAX_SENDS); + + if (chn == LEFT_CH) + send[0] = (0xff * portc->playvol + 50) / 100; + else + send[1] = (0xff * portc->playvol + 50) / 100; + + switch (portc->binding) + { + case DSP_BIND_FRONT: + portc->routing = front_routing; + break; + case DSP_BIND_SURR: + portc->routing = surr_routing; + break; + case DSP_BIND_CENTER_LFE: + portc->routing = center_lfe_routing; + break; + case DSP_BIND_REAR: + portc->routing = rear_routing; + break; + default: + portc->routing = default_routing; + } +} + +static void +update_output_volume (int dev, int voice, int chn) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + int left, right; + unsigned int loop_start, loop_end, tmp; + unsigned char send[MAX_SENDS]; + + send[0] = 0xff; /* Max */ + send[1] = 0xff; /* Max */ + send[2] = 0xff; /* Max */ + send[3] = 0xff; /* Max */ + + if (portc->input_type == ITYPE_SPDIF || portc->format == AFMT_AC3) + { + /* Digital voice */ + send[2] = 0; /* Muted */ + send[3] = 0; /* Muted */ + + /* sends are revered between Audigy2 and Audigy */ + left = (devc->feature_mask & SB_AUDIGY2) ? 1 : 0; + right = !left; + + if (portc->channels > 1) + { + if (chn == LEFT_CH) + { + send[left] = 0; + } + else + { + send[right] = 0; + } + } + } + else + { + /* Analog voice */ + + if (portc->channels > 1) + { + if (chn == LEFT_CH) + { + send[1] = 0; + } + else + { + send[0] = 0; + } + } + send[2] = send[0]; + send[3] = send[1]; + +#ifdef TEST_3D + if (portc->speaker_mode == SMODE_3D) + compute_3d (devc, portc, voice, chn, send); + else +#endif + { + send[0] = (send[0] * portc->playvol + 50) / 100; + send[1] = (send[1] * portc->playvol + 50) / 100; + send[2] = (send[2] * portc->playvol + 50) / 100; + send[3] = (send[3] * portc->playvol + 50) / 100; + + switch (portc->speaker_mode) + { + case SMODE_FRONT: + send[2] = send[3] = 0; + break; + + case SMODE_SURR: + send[0] = send[1] = 0; + break; + + case SMODE_FRONTREAR: + break; + + case SMODE_BIND: + compute_bind (devc, portc, send, chn); + break; + } + } + + /* Analog voice */ + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + loop_end = sblive_read_reg (devc, SDL, voice) & 0xffffff; + sblive_write_reg (devc, SDL, voice, loop_end | (send[3] << 24)); + loop_start = sblive_read_reg (devc, SCSA, voice) & 0xffffff; + sblive_write_reg (devc, SCSA, voice, loop_start | (send[2] << 24)); + tmp = sblive_read_reg (devc, PTAB, voice) & 0xffff0000; + sblive_write_reg (devc, PTAB, voice, tmp | (send[0] << 8) | send[1]); + write_routing (devc, voice, portc->routing); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +setup_audio_voice (int dev, int voice, int chn) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + unsigned int nCRA = 0; + + unsigned int loop_start, loop_end; + + int sz = 1; + int start_pos; + + sblive_write_reg (devc, VEDS, voice, 0x0); /* OFF */ + sblive_write_reg (devc, VTFT, voice, 0xffff); + sblive_write_reg (devc, CVCF, voice, 0xffff); + + if (devc->feature_mask & SB_AUDIGY) + sblive_write_reg (devc, SRDA, voice, 0x03020100); + else + sblive_write_reg (devc, FXRT, voice, 0x32100000); + + + sz = + (((portc->format == AFMT_S16_LE + || portc->format == AFMT_AC3)) ? 1 : 0) + ((portc->channels == + 2) ? 1 : 0); + + loop_start = dmap->driver_use_value >> sz; + loop_end = (dmap->driver_use_value + dmap->bytes_in_use) >> sz; + + /* set mono/stereo */ + sblive_write_reg (devc, CPF, voice, (portc->channels > 1) ? 0x8000 : 0); + + nCRA = (portc->channels > 1) ? 28 : 30; + nCRA *= (portc->format == AFMT_S16_LE || portc->format == AFMT_AC3) ? 1 : 2; + start_pos = loop_start + nCRA; + + /* SDL, ST, CA */ + portc->out_sz = sz; + + sblive_write_reg (devc, SDL, voice, loop_end); + sblive_write_reg (devc, SCSA, voice, loop_start); + sblive_write_reg (devc, PTAB, voice, 0); + + update_output_volume (dev, voice, chn); /* Set volume */ + + if (portc->format == AFMT_S16_LE || portc->format == AFMT_AC3) + sblive_write_reg (devc, QKBCA, voice, start_pos); + else + sblive_write_reg (devc, QKBCA, voice, start_pos | BYTESIZE); + + sblive_write_reg (devc, Z1, voice, 0); + sblive_write_reg (devc, Z2, voice, 0); + + sblive_write_reg (devc, MAPA, voice, 0x1fff | (devc->silent_page_phys << 1)); /* This is really a physical address */ + sblive_write_reg (devc, MAPB, voice, 0x1fff | (devc->silent_page_phys << 1)); /* This is really a physical address */ + + sblive_write_reg (devc, VTFT, voice, 0x0000ffff); + sblive_write_reg (devc, CVCF, voice, 0x0000ffff); + sblive_write_reg (devc, MEHA, voice, 0); + sblive_write_reg (devc, MEDS, voice, 0x7f); + sblive_write_reg (devc, MLV, voice, 0x8000); + sblive_write_reg (devc, VLV, voice, 0x8000); + sblive_write_reg (devc, VFM, voice, 0); + sblive_write_reg (devc, TMFQ, voice, 0); + sblive_write_reg (devc, VVFQ, voice, 0); + sblive_write_reg (devc, MEV, voice, 0x8000); + sblive_write_reg (devc, VEHA, voice, 0x7f7f); /* OK */ + sblive_write_reg (devc, VEV, voice, 0x8000); /* No volume envelope delay (OK) */ + sblive_write_reg (devc, PEFE_FILTERAMOUNT, voice, 0x7f); + sblive_write_reg (devc, PEFE_PITCHAMOUNT, voice, 0x00); +} + +/*ARGSUSED*/ +static void +update_output_device (sblive_devc * devc, sblive_portc * portc) +{ + int voiceL = portc->voice_chn, voiceR = portc->voice_chn + 1; + + if (!(portc->audio_active & PCM_ENABLE_OUTPUT)) + return; + + update_output_volume (portc->audiodev, voiceL, LEFT_CH); + update_output_volume (portc->audiodev, voiceR, RIGHT_CH); +} + + +/*ARGSUSED*/ +static void +sblive_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + sblive_portc *portc = audio_engines[dev]->portc; + + portc->audio_active |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +sblive_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + sblive_portc *portc = audio_engines[dev]->portc; + + portc->audio_active |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +void +sblive_set_loop_stop (sblive_devc * devc, int voice, int s) +{ + unsigned int tmp; + int offs, bit; + + offs = voice / 32; + bit = voice % 32; + s = !!s; + + tmp = sblive_read_reg (devc, SOLL + offs, 0); + tmp &= ~(1 << bit); + + if (s) + tmp |= (1 << bit); + sblive_write_reg (devc, SOLL + offs, 0, tmp); +} + +int +sblive_get_voice_loopintr (sblive_devc * devc, int voice) +{ + unsigned int tmp; + int offs, bit; + + offs = voice / 32; + bit = voice % 32; + + tmp = sblive_read_reg (devc, CLIPL + offs, 0); + tmp &= 1 << bit; + sblive_write_reg (devc, CLIPL + offs, 0, tmp); /* Ack the interrupt */ + + return !!tmp; +} + +int +sblive_get_voice_halfloopintr (sblive_devc * devc, int voice) +{ + unsigned int tmp; + int offs, bit; + + offs = voice / 32; + bit = voice % 32; + + tmp = sblive_read_reg (devc, HLIPL + offs, 0); + tmp &= 1 << bit; + sblive_write_reg (devc, HLIPL + offs, 0, tmp); /* Ack the interrupt */ + + return !!tmp; +} + +void +sblive_set_voice_intr (sblive_devc * devc, int voice, int s) +{ + unsigned int tmp; + int offs, bit; + + offs = voice / 32; + bit = voice % 32; + s = !!s; + + tmp = sblive_read_reg (devc, CLIEL + offs, 0); + tmp &= ~(1 << bit); + if (s) + tmp |= (1 << bit); + sblive_write_reg (devc, CLIEL + offs, 0, tmp); + sblive_write_reg (devc, HLIEL + offs, 0, tmp); +} + +static unsigned int +emu_rate_to_pitch (unsigned int rate) +{ + static unsigned int logMagTable[128] = { + 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, + 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, + 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, + 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, + 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, + 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, + 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, + 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, + 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, + 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, + 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, + 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, + 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, + 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, + 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, + 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df + }; + static char logSlopeTable[128] = { + 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, + 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, + 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, + 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, + 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, + 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, + 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, + 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, + 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, + 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, + 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, + 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f + }; + int i; + + if (rate == 0) + return 0; /* Bail out if no leading "1" */ + rate *= 11185; /* Scale 48000 to 0x20002380 */ + for (i = 31; i > 0; i--) + { + if (rate & 0x80000000) + { /* Detect leading "1" */ + return (((unsigned int) (i - 15) << 20) + + logMagTable[0x7f & (rate >> 24)] + + (0x7f & (rate >> 17)) * logSlopeTable[0x7f & (rate >> 24)]); + } + rate <<= 1; + } + + return 0; /* Should never reach this point */ +} + +static unsigned int +emu_rate_to_linearpitch (unsigned int rate) +{ + rate = (rate << 8) / 375; + return (rate >> 1) + (rate & 1); +} + +static void +start_audio_voice (int dev, int voice, int chn) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + unsigned int sample, initial_pitch, pitch_target; + unsigned int cra, cs, ccis, i; + + /* setup CCR regs */ + cra = 64; + cs = (portc->channels > 1) ? 4 : 2; + ccis = (portc->channels > 1) ? 28 : 30; + ccis *= (portc->format == AFMT_S16_LE || portc->format == AFMT_AC3) ? 1 : 2; + sample = (portc->format == AFMT_S16_LE + || portc->format == AFMT_AC3) ? 0x00000000 : 0x80808080; + + for (i = 0; i < cs; i++) + sblive_write_reg (devc, CD0 + i, voice, sample); + + sblive_write_reg (devc, CCR_CACHEINVALIDSIZE, voice, 0); + sblive_write_reg (devc, CCR_READADDRESS, voice, cra); + sblive_write_reg (devc, CCR_CACHEINVALIDSIZE, voice, ccis); + + /* Set current pitch */ + sblive_write_reg (devc, IFA, voice, 0xff00); + sblive_write_reg (devc, VTFT, voice, 0xffffffff); + sblive_write_reg (devc, CVCF, voice, 0xffffffff); + sblive_set_loop_stop (devc, voice, 0); + + pitch_target = emu_rate_to_linearpitch (portc->speed); + initial_pitch = emu_rate_to_pitch (portc->speed) >> 8; + sblive_write_reg (devc, PTRX_PITCHTARGET, voice, pitch_target); + sblive_write_reg (devc, CPF_CURRENTPITCH, voice, pitch_target); + sblive_write_reg (devc, IP, voice, initial_pitch); + + if (chn == LEFT_CH) + { + sblive_get_voice_loopintr (devc, voice); + sblive_get_voice_halfloopintr (devc, voice); + sblive_set_voice_intr (devc, voice, 1); + } + sblive_write_reg (devc, VEDS, voice, /*0x80 | */ 0x7f7f); /* Trigger (OK) */ +} + +/*ARGSUSED*/ +static void +stop_audio_voice (int dev, int voice, int chn) +{ + sblive_devc *devc = audio_engines[dev]->devc; + + sblive_write_reg (devc, IFA, voice, 0xffff); + sblive_write_reg (devc, VTFT, voice, 0xffff); + sblive_write_reg (devc, PTRX_PITCHTARGET, voice, 0); + sblive_write_reg (devc, CPF_CURRENTPITCH, voice, 0); + sblive_write_reg (devc, IP, voice, 0); + sblive_set_loop_stop (devc, voice, 1); + sblive_set_voice_intr (devc, voice, 0); +} + +static void +sblive_audio_trigger (int dev, int state) +{ + sblive_portc *portc = audio_engines[dev]->portc; + sblive_devc *devc = audio_engines[dev]->devc; + int voiceL = portc->voice_chn, voiceR = portc->voice_chn + 1; + + if (portc->mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + { + if ((portc->audio_active & PCM_ENABLE_OUTPUT) && + !(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + start_audio_voice (dev, voiceL, LEFT_CH); + /* sblive_dump_regs(devc, voiceL); */ + if (portc->channels > 1) + start_audio_voice (dev, voiceR, RIGHT_CH); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_active & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + portc->audio_active &= ~PCM_ENABLE_OUTPUT; + stop_audio_voice (dev, voiceL, LEFT_CH); + stop_audio_voice (dev, voiceR, RIGHT_CH); + } + } + } + + if (portc->mode & OPEN_READ && !(audio_engines[dev]->flags & ADEV_NOINPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_active & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + int tmp = sblive_read_reg (devc, ADCSR, 0); + unsigned int pos; + + if (portc->input_type == ITYPE_SPDIF) + { + /* Start recording from S/PDIF input A */ + sblive_write_reg (devc, SPRC, 0, portc->in_szbits | 0x00); + } + else + { + if (devc->feature_mask & SB_AUDIGY) + { + tmp |= 0x10; /* Left channel enable */ + if (portc->channels > 1) + tmp |= 0x20; /* Right channel enable */ + } + else + { + tmp |= 0x08; /* Left channel enable */ + if (portc->channels > 1) + tmp |= 0x10; /* Right channel enable */ + } + sblive_write_reg (devc, ADCBS, 0, portc->in_szbits); + sblive_write_reg (devc, ADCSR, 0, tmp); /* GO */ + } + + pos = (INL (devc->osdev, devc->base + 0x10) >> 6) & 0xfffff; + portc->rec_starttime = pos; + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_active & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + if (portc->input_type == ITYPE_SPDIF) + sblive_write_reg (devc, SPRC, 0, 0); + else + sblive_write_reg (devc, ADCSR, 0, 0); + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + portc->audio_active &= ~PCM_ENABLE_INPUT; + } + } + } + +} + +/*ARGSUSED*/ +static int +sblive_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int sz = -1; + + if (audio_engines[dev]->flags & ADEV_NOINPUT) + { + cmn_err (CE_WARN, "Audio device %d is output only\n", dev); + return OSS_EIO; + } + + if (dmap->buffsize > 65536) + { + cmn_err (CE_WARN, "Recording buffer bigger than 64k\n"); + dmap->buffsize = 65536; + } + +#ifdef sun1 + if (dmap->buffsize == 36864) + { + dmap->buffsize = 32768; + } +#endif + + switch (dmap->buffsize) + { + case 4096: + sz = 15; + break; + case 8192: + sz = 19; + break; + case 16384: + sz = 23; + break; + case 32768: + sz = 27; + break; + case 65536: + sz = 31; + break; + + default: + cmn_err (CE_WARN, "Unsupported input buffer size %d\n", dmap->buffsize); + return OSS_ENOSPC; + } + + if (portc->input_type == ITYPE_SPDIF) + { + sblive_write_reg (devc, SPRA, 0, dmap->dmabuf_phys); + sblive_write_reg (devc, SPRC, 0, 0); + } + else + { + sblive_write_reg (devc, ADCBA, 0, dmap->dmabuf_phys); + sblive_write_reg (devc, ADCBS, 0, 0); + } + portc->in_szbits = sz; + + sblive_write_reg (devc, ADCSR, 0, 0x0); + + if (portc->input_type == ITYPE_ANALOG) + { + if (devc->feature_mask & SB_AUDIGY) + sblive_write_reg (devc, ADCSR, 0, + speed_tab[portc->speedsel].audigy_recbits); + else + sblive_write_reg (devc, ADCSR, 0, speed_tab[portc->speedsel].recbits); + } + + devc->recording_dev = dev; + + portc->audio_active |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + return 0; +} + +/*ARGSUSED*/ +static int +sblive_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + + int voiceL = portc->voice_chn, voiceR = portc->voice_chn + 1; + + if (audio_engines[dev]->flags & ADEV_NOOUTPUT) + return OSS_EIO; + + /* AC3 needs stereo too */ + if (portc->format == AFMT_AC3 || portc->input_type == ITYPE_SPDIF) + { + portc->channels = 2; + portc->speed = 48000; + portc->routing = spdif_routing; + } + else + portc->routing = default_routing; + + /* Left channel */ + sblive_write_reg (devc, IFA, voiceL, 0xffff); /* Intial filter cutoff and attenuation */ + sblive_write_reg (devc, VEDS, voiceL, 0x0); /* Volume envelope decay and sustain */ + sblive_write_reg (devc, VTFT, voiceL, 0xffff); /* Volume target and Filter cutoff target */ + sblive_write_reg (devc, PTAB, voiceL, 0x0); /* Pitch target and sends A and B */ + /* The same for right channel */ + sblive_write_reg (devc, IFA, voiceR, 0xffff); + sblive_write_reg (devc, VEDS, voiceR, 0x0); + sblive_write_reg (devc, VTFT, voiceR, 0xffff); + sblive_write_reg (devc, PTAB, voiceR, 0x0); + + /* now setup the voices and go! */ + setup_audio_voice (dev, voiceL, LEFT_CH); + if (portc->channels == 2) + setup_audio_voice (dev, voiceR, RIGHT_CH); + + portc->audio_active |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + if (portc->uses_spdif) + { + if (portc->format == AFMT_AC3) + { + sblive_write_reg (devc, SCS0, 0, 0x2109206); + } + else + { + sblive_write_reg (devc, SCS0, 0, 0x2108504); + } + } + return 0; +} + +static int +sblive_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + int err, i, n; + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + + if (dmap->dmabuf != NULL) + return 0; + + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + { + cmn_err (CE_WARN, "Cannot allocate DMA buffer\n"); + return err; + } + + if (dmap->buffsize > DMABUF_SIZE) + { + cmn_err (CE_NOTE, "DMA buffer was too large - truncated\n"); + dmap->buffsize = DMABUF_SIZE; + } + + if (devc->feature_mask & SB_LIVE) + if (dmap->dmabuf_phys & 0x80000000) + { + cmn_err (CE_CONT, "Got DMA buffer address beyond 2G limit.\n"); + oss_free_dmabuf (dev, dmap); + dmap->dmabuf = NULL; + + return OSS_ENOSPC; + } + + if (direction == PCM_ENABLE_OUTPUT) + { + dmap->driver_use_value = portc->memptr; + n = portc->memptr / 4096; + +/* + * Fill the page table + */ + for (i = 0; i < dmap->buffsize / 4096; i++) + { + FILL_PAGE_MAP_ENTRY (n + i, dmap->dmabuf_phys + i * 4096); + } + } + + return 0; +} + +/*ARGSUSED*/ +static int +sblive_free_buffer (int dev, dmap_t * dmap, int direction) +{ + if (dmap->dmabuf == NULL) + return 0; + oss_free_dmabuf (dev, dmap); + + dmap->dmabuf = NULL; + return 0; +} + +/*ARGSUSED*/ +static int +sblive_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + sblive_devc *devc = audio_engines[dev]->devc; + sblive_portc *portc = audio_engines[dev]->portc; + int pos; + + if (!(portc->trigger_bits & direction)) + return 0; + + if (direction == OPEN_WRITE) + { + pos = sblive_read_reg (devc, QKBCA, portc->voice_chn) & 0x00ffffff; /* Curr pos */ + pos <<= portc->out_sz; + pos -= dmap->driver_use_value; + } + else + { + /* Compute current pos based on the wall clock register */ + pos = (INL (devc->osdev, devc->base + 0x10) >> 6) & 0xfffff; + if (pos > portc->rec_starttime) + pos = pos - portc->rec_starttime; + else + pos = 0xfffff - (portc->rec_starttime - pos); + pos = (pos * (portc->speed / 25)) / (48000 / 25); + pos *= 2; /* 16 bit->bytes */ + pos *= portc->channels; + pos = pos % dmap->bytes_in_use; + } + + if (pos < 0) + pos = 0; + + return pos; +} + +static audiodrv_t sblive_audio_driver = { + sblive_audio_open, + sblive_audio_close, + sblive_audio_output_block, + sblive_audio_start_input, + sblive_audio_ioctl, + sblive_audio_prepare_for_input, + sblive_audio_prepare_for_output, + sblive_audio_reset, + NULL, + NULL, + sblive_audio_reset_input, + sblive_audio_reset_output, + sblive_audio_trigger, + sblive_audio_set_rate, + sblive_audio_set_format, + sblive_audio_set_channels, + NULL, + NULL, + NULL, /* sblive_check_input, */ + NULL, /* sblive_check_output, */ + sblive_alloc_buffer, + sblive_free_buffer, + NULL, + NULL, + sblive_get_buffer_pointer, + NULL, + NULL, + NULL, + NULL, + NULL, + sblive_audio_ioctl /* bind */ +}; + +#define DATAPORT (devc->base) +#define COMDPORT (devc->base+1) +#define STATPORT (devc->base+1) + +static __inline__ int +audigyuart_status (sblive_devc * devc) +{ + return sblive_read_reg (devc, MUASTAT, 0); +} + +#define input_avail(devc) (!(audigyuart_status(devc)&INPUT_AVAIL)) +#define output_ready(devc) (!(audigyuart_status(devc)&OUTPUT_READY)) +static void +audigyuart_cmd (sblive_devc * devc, unsigned char cmd) +{ + sblive_write_reg (devc, MUACMD, 0, cmd); +} + +static __inline__ int +audigyuart_read (sblive_devc * devc) +{ + return sblive_read_reg (devc, MUADAT, 0); +} + +static __inline__ void +audigyuart_write (sblive_devc * devc, unsigned char byte) +{ + sblive_write_reg (devc, MUADAT, 0, byte); +} + +#define OUTPUT_READY 0x40 +#define INPUT_AVAIL 0x80 +#define MPU_ACK 0xFE +#define MPU_RESET 0xFF +#define UART_MODE_ON 0x3F + +static int reset_audigyuart (sblive_devc * devc); +static void enter_uart_mode (sblive_devc * devc); + +typedef struct +{ + int keycode; + int action; + int local_action; +} ir_code_t; + +static void +sblive_key_action (sblive_devc * devc, ir_code_t * code) +{ + int value, left, right, dev; + + dev = devc->mixer_dev; + + switch (code->local_action) + { + case 1: /* Volume- */ + value = sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_READ, 0); + left = value & 0xff; + right = (value >> 8) & 0xff; + left -= 5; + if (left < 0) + left = 0; + right -= 5; + if (right < 0) + right = 0; + value = left | (right << 8); + sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_WRITE, value); + mixer_devs[dev]->modify_counter++; + return; + break; + + case 2: /* Volume+ */ + value = sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_READ, 0); + left = value & 0xff; + right = (value >> 8) & 0xff; + left += 5; + if (left > 100) + left = 100; + right += 5; + if (right > 100) + right = 100; + value = left | (right << 8); + sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_WRITE, value); + mixer_devs[dev]->modify_counter++; + return; + break; + } +} + +static void +sblive_handle_ir (sblive_devc * devc, unsigned char c) +{ +/* + * Receive a MIDI SysEx message and check if it's an IR remote command + */ +#if 1 + +/* + * Sysex code sent by the Live!DRIVE IR unit + */ + static unsigned char remote_id[] = + { 0xf0, 0x00, 0x20, 0x21, 0x60, 0x00, 0x02, 0x00, 0xf7 }; + + static ir_code_t codes[] = { + /* Creative RM-900B remote control unit */ + {0x09017e}, /* 0 */ + {0x0a512e}, /* 1 */ + {0x0a710e}, /* 2 */ + {0x090976}, /* 3 */ + {0x09512e}, /* 4 */ + {0x09215e}, /* 5 */ + {0x091e61}, /* 6 */ + {0x0a116e}, /* 7 */ + {0x0a413e}, /* 8 */ + {0x0a6e11}, /* 9 */ + {0x0a1e61}, /* Play/Pause */ + {0x0a215e}, /* Stop/Eject */ + {0x0a3e41}, /* Slow */ + {0x0a7e01}, /* Prev */ + {0x095e21}, /* Next */ + {0x097e01}, /* Step */ + {0x097609}, /* Mute */ + {0x0a4639, 0, 1}, /* Vol- */ + {0x094639, 0, 2}, /* Vol+ */ + /* Speaker ??? */ + {0x09314e}, /* EAX */ + {0x09413e}, /* Options */ + {0x096e11}, /* Display */ + {0x09710e}, /* Return */ + {0x09116e}, /* Start */ + {0x093e41}, /* Cancel */ + {0x0a5e21}, /* Up */ + {0x0a611e}, /* << */ + {0x0a017e}, /* Select/OK */ + {0x0a2e51}, /* >> */ + {0x0a314e}, /* Down */ + +/* Creative RM-1000 remote control unit */ + {0x0a0679}, /* Power */ + {0x0a0e71}, /* CMSS */ + {0x0a4e31}, /* Rec */ + +/* Creative Inspire 5.1 Digital 5700 remote */ + {0x0a0778}, /* Power */ + {0x097708}, /* Mute */ + {0x0a7708}, /* Test */ + {0x0a4738}, /* Vol- */ + {0x094738}, /* Vol+ */ + {0x0a0f70}, /* Effect */ + {0x0a5728}, /* Analog */ + {0x0a2758}, /* Pro logic */ + {0x094f30}, /* Dynamic mode */ + {0x093748}, /* Digital/PCM audio */ + {0} + }; +#endif + if (c == 0xf0) /* Sysex start */ + { + devc->sysex_buf[0] = c; + devc->sysex_p = 1; + return; + } + + if (devc->sysex_p <= 0) + return; + + if (devc->sysex_p >= 20) /* Too long */ + { + devc->sysex_p = 0; + return; + } + + if (c == 0xf7) /* Sysex end */ + { + int i, l, v; + unsigned char *buf; + + devc->sysex_buf[devc->sysex_p] = c; + devc->sysex_p++; + l = devc->sysex_p; + + devc->sysex_p = 0; + buf = devc->sysex_buf; + + if (l == 9) + { + int ok = 1; + + for (i = 0; i < sizeof (remote_id); i++) + if (buf[i] != remote_id[i]) + ok = 0; + + if (ok) + { + /* cmn_err (CE_CONT, "Live!DRIVE IR detected\n"); */ + return; + } + + return; + } + + if (l != 13) /* Wrong length */ + return; + + if (buf[0] != 0xf0 || buf[12] != 0xf7) /* Not sysex */ + return; + + /* Verify that this is an IR receiver sysex */ + if (buf[1] != 0x00 || buf[2] != 0x20 || buf[3] != 0x21) + return; + if (buf[4] != 0x60 || buf[5] != 0x00 || buf[6] != 0x01) + return; +#if 0 + if (buf[7] != 0x09 && buf[7] != 0x0a) /* Remote ID */ + return; +#endif + if (buf[8] != 0x41 || buf[9] != 0x44) + return; + + v = (buf[7] << 16) | (buf[10] << 8) | buf[11]; + + for (i = 0; codes[i].keycode != 0; i++) + if (codes[i].keycode == v) + { + sblive_key_action (devc, &codes[i]); + return; + } + + return; + } + + /* Ordinary byte */ + devc->sysex_buf[devc->sysex_p] = c; + devc->sysex_p++; +} + +static void +sblive_ir_callback (int dev, unsigned char c) +{ + sblive_devc *devc; + oss_device_t *osdev = midi_devs[dev]->osdev; + devc = osdev->devc; + + if (devc->midi_dev != dev) + return; + + sblive_handle_ir (devc, c); +} + +static void +audigyuart_input_loop (sblive_devc * devc) +{ + int t = 0; + + while (input_avail (devc) && t++ < 1000) + { + unsigned char c = audigyuart_read (devc); + + sblive_handle_ir (devc, c); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, c); + } +} + +static void +audigyuartintr (sblive_devc * devc) +{ + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + audigyuart_input_loop (devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +audigyuart_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + sblive_devc *devc = (sblive_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + while (input_avail (devc)) + audigyuart_read (devc); + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + enter_uart_mode (devc); + devc->midi_disabled = 0; + + return 0; +} + +/*ARGSUSED*/ +static void +audigyuart_close (int dev, int mode) +{ + sblive_devc *devc = (sblive_devc *) midi_devs[dev]->devc; + + reset_audigyuart (devc); + oss_udelay (10); + enter_uart_mode (devc); + reset_audigyuart (devc); + devc->midi_opened = 0; +} + +static int +audigyuart_out (int dev, unsigned char midi_byte) +{ + sblive_devc *devc = (sblive_devc *) midi_devs[dev]->devc; + + if (devc->midi_disabled) + return 1; + + if (!output_ready (devc)) + { + return 0; + } + + audigyuart_write (devc, midi_byte); + return 1; +} + +/*ARGSUSED*/ +static int +audigyuart_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t audigy_midi_driver = { + audigyuart_open, + audigyuart_close, + audigyuart_ioctl, + audigyuart_out +}; + +static void +enter_uart_mode (sblive_devc * devc) +{ + int ok, timeout; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + audigyuart_cmd (devc, UART_MODE_ON); + + ok = 0; + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) + ok = 1; + else if (input_avail (devc)) + if (audigyuart_read (devc) == MPU_ACK) + ok = 1; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +void +attach_audigyuart (sblive_devc * devc) +{ + enter_uart_mode (devc); + + devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "AUDIGY", "Audigy UART", &audigy_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev); + devc->midi_opened = 0; +} + +static int +reset_audigyuart (sblive_devc * devc) +{ + int ok, timeout, n; + oss_native_word flags; + + /* + * Send the RESET command. Try again if no success at the first time. + */ + + ok = 0; + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + for (n = 0; n < 2 && !ok; n++) + { + for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--); + + devc->input_byte = 0; + audigyuart_cmd (devc, MPU_RESET); + + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail (devc)) + if (audigyuart_read (devc) == MPU_ACK) + ok = 1; + + } + + + + if (ok) + audigyuart_input_loop (devc); /* + * Flush input before enabling interrupts + */ + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return ok; +} + +int +probe_audigyuart (sblive_devc * devc) +{ + int ok = 0; + + DDB (cmn_err (CE_CONT, "Entered probe_audigyuart\n")); + + devc->midi_input_intr = NULL; + devc->midi_opened = 0; + devc->input_byte = 0; + + ok = reset_audigyuart (devc); + + if (ok) + { + DDB (cmn_err (CE_CONT, "Reset UART401 OK\n")); + } + else + { + DDB (cmn_err + (CE_CONT, "Reset UART401 failed (no hardware present?).\n")); + DDB (cmn_err + (CE_CONT, "mpu401 status %02x\n", audigyuart_status (devc))); + } + + DDB (cmn_err (CE_CONT, "audigyuart detected OK\n")); + return ok; +} + +void +unload_audigyuart (sblive_devc * devc) +{ + reset_audigyuart (devc); +} + +static void +attach_mpu (sblive_devc * devc) +{ + char tmp[128]; + int ndevs = num_mididevs; + oss_native_word flags; + + sprintf (tmp, "%s external MIDI", devc->card_name); + + if (devc->feature_mask & SB_AUDIGY) + { + if (!probe_audigyuart (devc)) + { + cmn_err (CE_NOTE, "MIDI UART was not detected\n"); + return; + } + DDB (cmn_err (CE_CONT, "SB Audigy: MIDI UART detected - Good\n")); + devc->mpu_attached = 1; + attach_audigyuart (devc); + } + else + { + MUTEX_ENTER (devc->mutex, flags); + if (uart401_init (&devc->uart401devc, devc->osdev, devc->base + 0x18, + tmp) >= 0) + devc->mpu_attached = 1; + MUTEX_EXIT (devc->mutex, flags); + + if (ndevs != num_mididevs) + { + devc->midi_dev = ndevs; + midi_devs[ndevs]->input_callback = sblive_ir_callback; + } + } +} + +static void +load_dsp (sblive_devc * devc, unsigned char *buf, int len) +{ + emu10k1_file *code; + int pc, i; + + if (len != sizeof (*code)) + { + cmn_err (CE_NOTE, "DSP file size mismatch\n"); + return; + } + + code = (emu10k1_file *) buf; + + for (pc = 0; pc < 1024; pc++) + { + write_efx (devc, UC0 + pc, code->code[pc]); + } + + if (code->parms.ngpr < MAX_GPR_PARMS) + for (i = 0; i < code->parms.ngpr; i++) + { + code->parms.gpr[i].name[GPR_NAME_SIZE - 1] = 0; /* Overflow protection */ + if (strlen (code->parms.gpr[i].name) >= 32) /* Name may be bad */ + { + return; + } + +/* cmn_err(CE_CONT, "Gpr %d = %s (vol %x) type=%x\n", gpr->gpr[i].num, gpr->gpr[i].name, gpr->gpr[i].def, gpr->gpr[i].type); */ + if (code->parms.gpr[i].num < MAX_GPR) + if (code->parms.gpr[i].type != MIXT_GROUP) + { + if (is_special_gpr (code->parms.gpr[i].num)) + sblive_set_gpr (devc->mixer_dev, code->parms.gpr[i].num, + SNDCTL_MIX_WRITE, + devc->gpr_values[code->parms.gpr[i].num]); + else + sblive_set_gpr (devc->mixer_dev, code->parms.gpr[i].num, + SNDCTL_MIX_WRITE, code->parms.gpr[i].def); + } + } + + + if (devc->gpr == NULL) + { + devc->gpr = PMALLOC (devc->osdev, sizeof (gpr_info)); + if (devc->gpr == NULL) + { + cmn_err (CE_WARN, "Out of memory (gpr)\n"); + return; + } + memset (devc->gpr, 0, sizeof (gpr_info)); + } + memcpy (devc->gpr, &code->parms, sizeof (gpr_info)); + create_efx_mixer (devc->mixer_dev); + + if (code->consts.nconst >= MAX_CONST_PARMS) + return; + + for (i = 0; i < code->consts.nconst; i++) + { + if (code->consts.consts[i].gpr >= MAX_GPR) + { + return; + } + + sblive_write_reg (devc, code->consts.consts[i].gpr + GPR0, 0, + code->consts.consts[i].value); + } +} + +#define LIVE_NOP() \ + write_efx(devc, UC0+(pc*2), 0x10040); \ + write_efx(devc, UC0+(pc*2+1), 0x610040);pc++ +#define LIVE_ACC3(r, a, x, y) /* z=w+x+y */ \ + write_efx(devc, UC0+(pc*2), (x << 10) | y); \ + write_efx(devc, UC0+(pc*2+1), (6 << 20) | (r << 10) | a);pc++ + +#define AUDIGY_ACC3(r, a, x, y) /* z=w+x+y */ \ + write_efx(devc, UC0+(pc*2), (x << 12) | y); \ + write_efx(devc, UC0+(pc*2+1), (6 << 24) | (r << 12) | a);pc++ +#define AUDIGY_NOP() AUDIGY_ACC3(0xc0, 0xc0, 0xc0, 0xc0) + +static int +init_effects (sblive_devc * devc) +{ + int i; + unsigned short pc; + + if (devc->feature_mask & SB_AUDIGY) + { + pc = 0; + for (i = 0; i < 512; i++) + { + AUDIGY_NOP (); + } + + for (i = 0; i < 256; i++) + write_efx (devc, GPR0 + i, 0); + sblive_write_reg (devc, AUDIGY_DBG, 0, 0); + load_dsp (devc, emu10k2_dsp, sizeof (emu10k2_dsp)); + } + else + { + pc = 0; + for (i = 0; i < 512; i++) + { + LIVE_NOP (); + } + + for (i = 0; i < 256; i++) + write_efx (devc, GPR0 + i, 0); + sblive_write_reg (devc, DBG, 0, 0); + load_dsp (devc, emu10k1_dsp, sizeof (emu10k1_dsp)); + } + + return 1; +} + +static void +init_emu10k1 (sblive_devc * devc) +{ + unsigned int tmp, i; + extern int sblive_memlimit; +#ifndef NO_EMU10K1_SYNTH + extern int sblive_synth_enable; +#endif + int xmem_mode = 0; + unsigned int reg, val; + extern int sblive_digital_din; + extern int audigy_digital_din; + oss_native_word phaddr; + unsigned int memlimit = MEMLIMIT_31BITS; + + OUTL (devc->osdev, 0x00000000, devc->base + 0x0c); /* Intr disable */ + OUTL (devc->osdev, + HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, + devc->base + 0x14); + + sblive_write_reg (devc, MBS, 0, 0x0); + sblive_write_reg (devc, MBA, 0, 0x0); + sblive_write_reg (devc, FXBS, 0, 0x0); + sblive_write_reg (devc, FXBA, 0, 0x0); + sblive_write_reg (devc, ADCBS, 0, 0x0); + sblive_write_reg (devc, ADCBA, 0, 0x0); + + sblive_write_reg (devc, CLIEL, 0, 0x0); + sblive_write_reg (devc, CLIEH, 0, 0x0); + sblive_write_reg (devc, SOLL, 0, 0xffffffff); + sblive_write_reg (devc, SOLH, 0, 0xffffffff); + + + if (devc->feature_mask & SB_AUDIGY) + { + memlimit=MEMLIMIT_32BITS; + sblive_write_reg (devc, 0x5e, 0, 0xf00); /* ?? */ + sblive_write_reg (devc, 0x5f, 0, 0x3); /* ?? */ + } + +#ifndef NO_EMU10K1_SYNTH + if (!sblive_synth_enable) + sblive_memlimit = 0; +#endif + + if (sblive_memlimit < 4096) /* Given in megabytes */ + sblive_memlimit *= (1024 * 1024); + + devc->max_mem = sblive_memlimit; + if (devc->max_mem < 1024 * 1024) + devc->max_mem = 1024 * 1024; + + devc->max_mem += AUDIO_MEMSIZE; + + /* SB Live/Audigy supports at most 32M of memory) */ + if (devc->max_mem > 32 * 1024 * 1024) + devc->max_mem = 32 * 1024 * 1024; + + devc->max_pages = devc->max_mem / 4096; + if (devc->max_pages < 1024) + devc->max_pages = 1024; + devc->page_map = + (int *) CONTIG_MALLOC (devc->osdev, devc->max_pages * 4, memlimit, + &phaddr, devc->page_map_dma_handle); + devc->vpage_map = + KERNEL_MALLOC (devc->max_pages * sizeof (unsigned char *)); + if (devc->page_map == NULL || devc->vpage_map == NULL) + { + cmn_err (CE_WARN, "Can't allocate the PTBA table\n"); + return; + } + memset (devc->vpage_map, 0, devc->max_pages * 4); + + tmp = phaddr; + if (devc->feature_mask & SB_LIVE) + { + if (tmp & 0x80000000) + { + cmn_err (CE_CONT, + "SB Live Error: Page table is beyond the 2G limit\n"); + } + } + else + { + if (tmp & 0x80000000) + { + DDB (cmn_err (CE_CONT, "Audigy: Using 4G PCI addressing mode\n")); + xmem_mode = 1; + devc->emu_page_shift = 0; + if (devc->max_mem > 16 * 1024 * 1034) + { + devc->max_mem = 16 * 1024 * 1024; + + DDB (cmn_err + (CE_NOTE, + "Max memory dropped to 16M due to need for extended PCI address mode.\n")); + } + } + } + + devc->synth_memlimit = devc->max_mem - AUDIO_MEMSIZE; + devc->synth_membase = SYNTH_MEMBASE; + devc->synth_memtop = devc->synth_membase; + devc->synth_memptr = devc->synth_membase; + + devc->silent_page = + (int *) CONTIG_MALLOC (devc->osdev, 4096, memlimit, &phaddr, devc->silent_page_dma_handle); + if (devc->silent_page == NULL) + { + cmn_err (CE_WARN, "Can't allocate a silent page\n"); + return; + } + + devc->silent_page_phys = phaddr; + if (devc->feature_mask & SB_LIVE) + if (devc->silent_page_phys & 0x80000000) + { + cmn_err (CE_CONT, + "SB Live warning: Silent page is beyond the 2G limit\n"); + } + + devc->audio_memptr = 4096; /* Skip the silence page */ + memset (devc->silent_page, 0, 4096); + + for (i = 0; i < devc->max_pages; i++) + { + FILL_PAGE_MAP_ENTRY (i, devc->silent_page_phys); + devc->vpage_map[i] = NULL; + } + + for (i = 0; i < 64; i++) + sblive_init_voice (devc, i); + + if (devc->feature_mask & SB_AUDIGY) + { + sblive_write_reg (devc, SCS0, 0, 0x2108504); + sblive_write_reg (devc, SCS1, 0, 0x2108504); + sblive_write_reg (devc, SCS2, 0, 0x2108504); + } + else + { + sblive_write_reg (devc, SCS0, 0, 0x2109204); + sblive_write_reg (devc, SCS1, 0, 0x2109204); + sblive_write_reg (devc, SCS2, 0, 0x2109204); + } + + sblive_write_reg (devc, PTBA, 0, tmp); + tmp = sblive_read_reg (devc, PTBA, 0); + + sblive_write_reg (devc, TCBA, 0, 0x0); + sblive_write_reg (devc, TCBS, 0, 0x4); + + OUTL (devc->osdev, IE_RXA | IE_AB | IE_IT, devc->base + IE); /* Intr enable */ + +/* + * SB Live 5.1 support. Turn on S/PDIF output + */ + if (devc->subvendor == 0x80611102) /* Live 5.1 */ + { + tmp = INL (devc->osdev, devc->base + 0x14); + tmp |= 0x00001000; /* Turn GPO0 pin on to enable S/PDIF outputs */ + OUTL (devc->osdev, tmp, devc->base + 0x14); + } + + if (devc->subvendor == 0x80661102) + { + sblive_write_reg (devc, AC97SLOT, 0, + AC97SLOT_CENTER | AC97SLOT_LFE | AC97SLOT_REAR_LEFT | + AC97SLOT_REAR_RIGHT); + } + + if (devc->feature_mask & SB_AUDIGY2) + { + /* Enable analog outputs on Audigy2 */ + int tmp; + + /* Setup SRCMulti_I2S SamplingRate */ + tmp = sblive_read_reg (devc, EHC, 0); + tmp &= 0xfffff1ff; + tmp |= (0x2 << 9); + sblive_write_reg (devc, EHC, 0, tmp); + /* sblive_write_reg (devc, SOC, 0, 0x00000000); */ + + /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ + OUTL (devc->osdev, 0x600000, devc->base + 0x20); + OUTL (devc->osdev, 0x14, devc->base + 0x24); + + /* Setup SRCMulti Input Audio Enable */ + /* Setup SRCMulti Input Audio Enable */ + if (devc->feature_mask & SB_AUDIGY2VAL) + OUTL (devc->osdev, 0x7B0000, devc->base + 0x20); + else + OUTL (devc->osdev, 0x6E0000, devc->base + 0x20); + + OUTL (devc->osdev, 0xFF00FF00, devc->base + 0x24); + + /* Setup I2S ASRC Enable (HC register) */ + tmp = INL (devc->osdev, devc->base + 0x14); + tmp |= 0x00000070; + OUTL (devc->osdev, tmp, devc->base + 0x14); + + /* + * Unmute Analog now. Set GPO6 to 1 for Apollo. + * This has to be done after init ALice3 I2SOut beyond 48KHz. + * So, sequence is important + */ + tmp = INL (devc->osdev, devc->base + 0x18); + tmp |= 0x0040; + if (devc->feature_mask & SB_AUDIGY2VAL) + tmp |= 0x0060; + + OUTL (devc->osdev, tmp, devc->base + 0x18); + } + + sblive_write_reg (devc, SOLL, 0, 0xffffffff); + sblive_write_reg (devc, SOLH, 0, 0xffffffff); + + if (devc->feature_mask & SB_AUDIGY) + { + unsigned int mode = 0; + + if (devc->feature_mask & SB_AUDIGY2) + mode |= HCFG_AC3ENABLE_GPSPDIF | HCFG_AC3ENABLE_CDSPDIF; + if (xmem_mode) + { + OUTL (devc->osdev, + HCFG_AUDIOENABLE | HCFG_AUTOMUTE | HCFG_JOYENABLE | + A_HCFG_VMUTE | A_HCFG_AUTOMUTE | A_HCFG_XM | mode, + devc->base + 0x14); + } + else + OUTL (devc->osdev, + HCFG_AUDIOENABLE | HCFG_AUTOMUTE | HCFG_JOYENABLE | A_HCFG_VMUTE + | A_HCFG_AUTOMUTE | mode, devc->base + 0x14); + + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x18) | 0x0004, devc->base + 0x18); /* GPIO (S/PDIF enable) */ + + + /* enable IR port */ + tmp = INL (devc->osdev, devc->base + 0x18); + OUTL (devc->osdev, tmp | A_IOCFG_GPOUT2, devc->base + 0x18); + oss_udelay (500); + OUTL (devc->osdev, tmp | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, + devc->base + 0x18); + oss_udelay (100); + OUTL (devc->osdev, tmp, devc->base + 0x18); + } + else + OUTL (devc->osdev, + HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | + HCFG_JOYENABLE, devc->base + 0x14); + + + /* enable IR port */ + tmp = INL (devc->osdev, devc->base + 0x14); + OUTL (devc->osdev, tmp | HCFG_GPOUT2, devc->base + 0x14); + oss_udelay (500); + OUTL (devc->osdev, tmp | HCFG_GPOUT1 | HCFG_GPOUT2, devc->base + 0x14); + oss_udelay (100); + OUTL (devc->osdev, tmp, devc->base + 0x14); + + /* Switch the shared SPDIF/OUT3 to DIGITAL or ANALOG mode */ + /* depending on whether the port is SPDIF or analog */ + + if ((devc->feature_mask == SB_AUDIGY) || + ((devc->feature_mask & SB_AUDIGY2) && (audigy_digital_din == 0))) + { + reg = INL (devc->osdev, devc->base + 0x18) & ~A_IOCFG_GPOUT0; + val = (audigy_digital_din) ? 0x4 : 0; + reg |= val; + OUTL (devc->osdev, reg, devc->base + 0x18); + } + if (devc->feature_mask & SB_LIVE) /* SBLIVE */ + { + reg = INL (devc->osdev, devc->base + 0x14) & ~HCFG_GPOUT0; + val = (sblive_digital_din) ? HCFG_GPOUT0 : 0; + reg |= val; + OUTL (devc->osdev, reg, devc->base + 0x14); + } + +} + +void +sblive_init_voice (sblive_devc * devc, int voice) +{ + sblive_set_loop_stop (devc, voice, 1); + + sblive_write_reg (devc, VEDS, voice, 0x0); + sblive_write_reg (devc, IP, voice, 0x0); + sblive_write_reg (devc, VTFT, voice, 0xffff); + sblive_write_reg (devc, CVCF, voice, 0xffff); + sblive_write_reg (devc, PTAB, voice, 0x0); + sblive_write_reg (devc, CPF, voice, 0x0); + sblive_write_reg (devc, CCR, voice, 0x0); + sblive_write_reg (devc, SCSA, voice, 0x0); + sblive_write_reg (devc, SDL, voice, 0x10); + sblive_write_reg (devc, QKBCA, voice, 0x0); + sblive_write_reg (devc, Z1, voice, 0x0); + sblive_write_reg (devc, Z2, voice, 0x0); + + if (devc->feature_mask & SB_AUDIGY) + sblive_write_reg (devc, SRDA, voice, 0x03020100); + sblive_write_reg (devc, FXRT, voice, 0x32100000); + + sblive_write_reg (devc, MEHA, voice, 0x0); + sblive_write_reg (devc, MEDS, voice, 0x0); + sblive_write_reg (devc, IFA, voice, 0xffff); + sblive_write_reg (devc, PEFE, voice, 0x0); + sblive_write_reg (devc, VFM, voice, 0x0); + sblive_write_reg (devc, TMFQ, voice, 24); + sblive_write_reg (devc, VVFQ, voice, 24); + sblive_write_reg (devc, TMPE, voice, 0x0); + sblive_write_reg (devc, VLV, voice, 0x0); + sblive_write_reg (devc, MLV, voice, 0x0); + sblive_write_reg (devc, VEHA, voice, 0x0); + sblive_write_reg (devc, VEV, voice, 0x0); + sblive_write_reg (devc, MEV, voice, 0x0); + + if (devc->feature_mask & SB_AUDIGY) + { + sblive_write_reg (devc, CSBA, voice, 0x0); + sblive_write_reg (devc, CSDC, voice, 0x0); + sblive_write_reg (devc, CSFE, voice, 0x0); + sblive_write_reg (devc, CSHG, voice, 0x0); + sblive_write_reg (devc, SRHE, voice, 0x3f3f3f3f); + } +} + +#ifndef NO_EMU10K1_SYNTH +extern void sblive_install_synth (sblive_devc * devc); +extern void sblive_remove_synth (sblive_devc * devc); +#endif + +static const unsigned char peak_cnv[256] = { + 0, 18, 29, 36, 42, 47, 51, 54, 57, 60, 62, 65, 67, 69, 71, 72, + 74, 75, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 89, 90, + 91, 92, 93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, + 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, + 108, + 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, + 114, + 115, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, + 119, + 119, 119, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, + 123, + 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 125, 126, 126, 126, 126, + 126, + 127, 127, 127, 127, 127, 128, 128, 128, 128, 128, 129, 129, 129, 129, 129, + 130, + 130, 130, 130, 130, 130, 131, 131, 131, 131, 131, 131, 132, 132, 132, 132, + 132, + 132, 133, 133, 133, 133, 133, 133, 134, 134, 134, 134, 134, 134, 134, 135, + 135, + 135, 135, 135, 135, 135, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, + 139, + 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, + 141, + 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 142, 142, 142, 143, 143, + 143, + 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, +}; + +static void +set_equalizer (sblive_devc * devc, int ctrl, int band, int value) +{ + const unsigned int *row; + int i; + + switch (band) + { + case 0: + row = (unsigned int *) &eq_band1_data[value][0]; + break; + case 1: + row = (unsigned int *) &eq_band2_data[value][0]; + break; + case 2: + row = (unsigned int *) &eq_band3_data[value][0]; + break; + case 3: + row = (unsigned int *) &eq_band4_data[value][0]; + break; + + default: + cmn_err (CE_CONT, "%s: bad equalizer band %d\n", devc->card_name, band); + return; + } + + for (i = 0; i < 5; i++) + { + sblive_write_reg (devc, ctrl + GPR0 + i, 0, row[i]); + } +} + +static const int db2lin_101[101] = { 0x00000000, + 0x0024B53A, 0x002750CA, 0x002A1BC6, 0x002D198D, 0x00304DBA, 0x0033BC2A, + 0x00376901, 0x003B58AF, 0x003F8FF1, 0x004413DF, 0x0048E9EA, 0x004E17E9, + 0x0053A419, 0x0059952C, 0x005FF24E, 0x0066C32A, 0x006E0FFB, 0x0075E18D, + 0x007E414F, 0x0087395B, 0x0090D482, 0x009B1E5B, 0x00A6234F, 0x00B1F0A7, + 0x00BE94A1, 0x00CC1E7C, 0x00DA9E8D, 0x00EA2650, 0x00FAC881, 0x010C9931, + 0x011FADDC, 0x01341D87, 0x014A00D8, 0x01617235, 0x017A8DE6, 0x01957233, + 0x01B23F8D, 0x01D118B1, 0x01F222D4, 0x021585D1, 0x023B6C57, 0x0264041D, + 0x028F7E19, 0x02BE0EBD, 0x02EFEE33, 0x032558A2, 0x035E8E7A, 0x039BD4BC, + 0x03DD7551, 0x0423BF61, 0x046F07B5, 0x04BFA91B, 0x051604D5, 0x0572830D, + 0x05D59354, 0x063FAD27, 0x06B15080, 0x072B0673, 0x07AD61CD, 0x0838FFCA, + 0x08CE88D3, 0x096EB147, 0x0A1A3A53, 0x0AD1F2E0, 0x0B96B889, 0x0C6978A5, + 0x0D4B316A, 0x0E3CF31B, 0x0F3FE155, 0x10553469, 0x117E3AD9, 0x12BC5AEA, + 0x14111457, 0x157E0219, 0x1704DC5E, 0x18A77A97, 0x1A67D5B6, 0x1C480A87, + 0x1E4A5C45, 0x2071374D, 0x22BF3412, 0x25371A37, 0x27DBE3EF, 0x2AB0C18F, + 0x2DB91D6F, 0x30F89FFD, 0x34733433, 0x382D0C46, 0x3C2AA6BD, 0x4070D3D9, + 0x4504BB66, 0x49EBE2F1, 0x4F2C346F, 0x54CC0565, 0x5AD21E86, 0x6145C3E7, + 0x682EBDBD, 0x6F9561C4, 0x77829D4D, + 0x7fffffff +}; + +static __inline__ int +convert_fixpoint (int val) +{ + if (val < 0) + val = 0; + if (val > 100) + val = 100; + return db2lin_101[val]; +} + +static int +sblive_set_gpr (int dev, int ctrl, unsigned int cmd, int value) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + int typ, i; + + if (devc == NULL) + return 0; + + if (devc->gpr == NULL) + { + int left, right; + + if (ctrl >= NEXT_FREE_GPR) + return 0; + + if (cmd != SNDCTL_MIX_WRITE) + return 0; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + value = left | (right << 8); + devc->gpr_values[ctrl] = value; + + left = convert_fixpoint (left); + sblive_write_reg (devc, ctrl + GPR0, 0, left); + right = convert_fixpoint (right); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, right); + return value; + } + + if (ctrl < 0 || ctrl >= MAX_GPR) + return OSS_EIO; + + typ = MIXT_SLIDER; + for (i = 0; i < devc->gpr->ngpr; i++) + if (devc->gpr->gpr[i].num == ctrl && devc->gpr->gpr[i].type != MIXT_GROUP) + typ = devc->gpr->gpr[i].type; + + if (typ == MIXT_GROUP) + { + return OSS_EIO; + } + + if (cmd == SNDCTL_MIX_READ) + { + if (typ == MIXT_STEREOPEAK || typ == MIXT_STEREOVU) + { + int v, l, r; + + /* Get the sample values and scale them to 0-144 dB range */ + v = sblive_read_reg (devc, ctrl + GPR0, 0); + l = v >> 23; + + v = sblive_read_reg (devc, ctrl + GPR0 + 1, 0); + r = v >> 23; + + if (l < 0) + l = -l; + if (r < 0) + r = -r; + l = peak_cnv[l]; + r = peak_cnv[r]; + + /* Reset values back to 0 */ + sblive_write_reg (devc, ctrl + GPR0, 0, 0); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, 0); + + return l | (r << 8); + } + return devc->gpr_values[ctrl]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (typ) + { + case MIXT_STEREOSLIDER: + { + int left, right; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + value = left | (right << 8); + devc->gpr_values[ctrl] = value; + + left = convert_fixpoint (left); + sblive_write_reg (devc, ctrl + GPR0, 0, left); + right = convert_fixpoint (right); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, right); + } + break; + + case MIXT_ONOFF: + { + value = !!value; + devc->gpr_values[ctrl] = value; + + sblive_write_reg (devc, ctrl + GPR0, 0, value); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, !value); + } + break; + + case EMU_MIXT_EQ1: + case EMU_MIXT_EQ2: + case EMU_MIXT_EQ3: + case EMU_MIXT_EQ4: + { + int band; + + band = typ & 3; + value = value & 0xff; + set_equalizer (devc, ctrl, band, value); + devc->gpr_values[ctrl] = value; + } + break; + + default: + { + int tmp; + + value = value & 0xff; + if (value > 100) + value = 100; + + devc->gpr_values[ctrl] = value; + + tmp = convert_fixpoint (value); + sblive_write_reg (devc, ctrl + GPR0, 0, tmp); + } + } + + return value; + } + + return OSS_EINVAL; +} + +static int +sblive_set_vol (int dev, int ctrl, unsigned int cmd, int value) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + sblive_portc *portc; + + if (ctrl < 0 || ctrl >= devc->n_audiodevs) + return OSS_EINVAL; + + portc = &devc->portc[ctrl]; + + if (portc->input_type == ITYPE_SPDIF) + { + mixer_devs[dev]->modify_counter++; + return 100 | (100 << 8); + } + + if (cmd == SNDCTL_MIX_READ) + { +#ifdef TEST_3D + return (devc->portc[ctrl].playvol & 0x00ff) | + ((devc->portc[ctrl].playangle & 0xffff) << 16) | + ((devc->portc[ctrl].playdist & 0xff) << 8); +#else + return devc->portc[ctrl].playvol & 0xff; +#endif + } + + if (cmd == SNDCTL_MIX_WRITE) + { +#ifdef TEST_3D + int angle, dist; + angle = (value >> 16) & 0xffff; /* Rotation angle */ + dist = (value >> 8) & 0xff; /* Distance */ + value &= 0x00ff; /* Volume */ + + if (value < 0) + value = 0; + if (value > 100) + value = 100; + + switch (portc->speaker_mode) + { + case SMODE_FRONT: + angle = 0; + dist = 50; + break; + + case SMODE_SURR: + angle = 180; + dist = 50; + break; + + case SMODE_FRONTREAR: + angle = 0; + dist = 50; + break; + + case SMODE_3D: + break; + } + devc->portc[ctrl].playvol = value; + devc->portc[ctrl].playdist = dist; + devc->portc[ctrl].playangle = angle; + + update_output_device (devc, &devc->portc[ctrl]); + return (value & 0x00ff) | (angle << 16) | ((dist & 0xff) << 8); +#else + value &= 0xff; /* Only left channel */ + + if (value < 0) + value = 0; + if (value > 100) + value = 100; + devc->portc[ctrl].playvol = value; + + update_output_device (devc, &devc->portc[ctrl]); + return value; + +#endif + } + + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +sblive_get_peak (int dev, int ctrl, unsigned int cmd, int value) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + + if (ctrl < 0 || ctrl >= devc->n_audiodevs) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + int l, r, vol; + + l = devc->portc[ctrl].vu_left & 0xff; + r = devc->portc[ctrl].vu_right & 0xff; +#if 1 + vol = devc->portc[ctrl].playvol; + /* if (vol<1) vol=5; */ + l = (l * vol + 50) / 100; + r = (r * vol + 50) / 100; +#endif + devc->portc[ctrl].vu_left = 0; + devc->portc[ctrl].vu_right = 0; + + return peak_cnv[l] | (peak_cnv[r] << 8); + } + + return OSS_EINVAL; +} + +static int +sblive_set_parm (int dev, int ctrl, unsigned int cmd, int value) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + switch (ctrl) + { + case 1: + return devc->autoreset; + case 2: + return devc->speaker_mode; + } + } + + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: + return devc->autoreset = !!(value); + case 2: + if (devc->speaker_mode != value) + { + int i; + for (i = 0; i < devc->n_audiodevs; i++) + devc->portc[i].resetvol = 1; + } + return devc->speaker_mode = value; + break; + + } + } + + return OSS_EINVAL; +} + +static int +create_soft_mixer (int dev) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + int group = 0, err, i, n; + char tmp[100]; + + if ((err = mixer_ext_create_control (dev, 0, + 1, + sblive_set_parm, + MIXT_ONOFF, + "SBLIVE_AUTORESET", + 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + +#ifdef TEST_3D + n = 5; +#else + n = 4; +#endif + if ((err = mixer_ext_create_control (dev, 0, + 2, + sblive_set_parm, + MIXT_ENUM, + "SBLIVE_SPKMODE", + n, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + for (i = 0; i < devc->n_audiodevs; i++) + { + if (devc->n_audiodevs > devc->min_audiodevs) + { + /* + * Use the traditional dspN naming system for sliders. + */ + if ((i % 8) == 0) + if ((group = mixer_ext_create_group (dev, 0, "/dev")) < 0) + return group; + + sprintf (tmp, "@pcm%d", devc->portc[i].audiodev); + } + else + { + /* + * Use front/rear/etc naming style + */ + if ((i % 8) == 0) + if ((group = mixer_ext_create_group (dev, 0, "pcm")) < 0) + return group; + + switch (i) + { + case 0: + strcpy (tmp, "main"); + break; /* Duplex device */ + case 1: + strcpy (tmp, "front"); + break; + case 2: + strcpy (tmp, "side"); + break; + case 3: + strcpy (tmp, "C/L"); + break; + case 4: + strcpy (tmp, "rear"); + break; + } + } + + + if ((err = mixer_ext_create_control (dev, group, i, sblive_set_vol, +#ifdef TEST_3D + MIXT_3D, +#else + MIXT_SLIDER, +#endif + tmp, + 100, + MIXF_PCMVOL | MIXF_READABLE | MIXF_WRITEABLE)) < + 0) + return err; + if ((err = mixer_ext_create_control (dev, group, + i, + sblive_get_peak, + MIXT_STEREOPEAK, + "-", 144, MIXF_READABLE)) < 0) + return err; + } + + return 0; +} + +static int +create_efx_mixer (int dev) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + int group = 0, err = 0, i, mode; + int group_created = 0; + int typ, maxval; + + if (!devc->extinfo_loaded) + { + return 0; + } + + if (devc->gpr == NULL) + { + return 0; + } + + if (devc->mixer_group >= 0) + mixer_ext_truncate (dev, devc->mixer_group); + devc->mixer_group = -1; + + if (devc->gpr->ngpr >= MAX_GPR_PARMS) + return OSS_EINVAL; + + for (i = 0; i < devc->gpr->ngpr; i++) + { + if (devc->gpr->gpr[i].num >= MAX_GPR) + continue; + + typ = devc->gpr->gpr[i].type; + + if (typ == MIXT_GROUP) + { + if ((group = + mixer_ext_create_group (dev, 0, devc->gpr->gpr[i].name)) < 0) + return group; + + if (!group_created) + devc->mixer_group = group; + group_created = 1; + continue; + } + +#if 0 + if (!group_created) + { + cmn_err (CE_WARN, "Mixer initialization sequence error\n"); + return OSS_EINVAL; + } +#endif + mode = MIXF_READABLE; + maxval = 144; + + switch (typ) + { + case EMU_MIXT_EQ1: + case EMU_MIXT_EQ2: + case EMU_MIXT_EQ3: + case EMU_MIXT_EQ4: + { + mode |= MIXF_WRITEABLE; + maxval = 255; + typ = MIXT_SLIDER; + } + break; + + case MIXT_STEREOSLIDER: + case MIXT_SLIDER: + case MIXT_MONOSLIDER: + { + mode |= MIXF_WRITEABLE; + maxval = 100; + } + break; + + case MIXT_STEREOVU: + typ = MIXT_STEREOPEAK; + break; + + case MIXT_ONOFF: + { + mode |= MIXF_WRITEABLE; + maxval = 1; + } + break; + } + + if (devc->gpr->gpr[i].name[0] == '_') + { + /* Hidden control */ + if (strcmp (devc->gpr->gpr[i].name, "_PASSTHROUGH") == 0) + { + int ctrl = devc->gpr->gpr[i].num; + devc->passthrough_gpr = ctrl; + + sblive_write_reg (devc, ctrl + GPR0, 0, 1); + sblive_write_reg (devc, ctrl + GPR0 + 1, 0, 0); + } + } + else + { + /* Visible control */ + if ((err = mixer_ext_create_control (dev, group, + devc->gpr->gpr[i].num, + sblive_set_gpr, typ, + devc->gpr->gpr[i].name, + maxval, mode)) < 0) + return err; + } + + if (!group_created) + devc->mixer_group = err; + group_created = 1; + + if (is_special_gpr (devc->gpr->gpr[i].num)) + { + sblive_set_gpr (dev, devc->gpr->gpr[i].num, SNDCTL_MIX_WRITE, + devc->gpr_values[devc->gpr->gpr[i].num]); + } + else + { + sblive_set_gpr (dev, devc->gpr->gpr[i].num, SNDCTL_MIX_WRITE, + devc->gpr->gpr[i].def); + } + } + return 0; +} + +static int +mixer_ext_init (int dev) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + + devc->extinfo_loaded = 1; + create_soft_mixer (dev); + create_efx_mixer (dev); + return 0; +} + +static int +mixer_override (int dev, int audiodev, unsigned int cmd, int val) +{ + sblive_devc *devc = mixer_devs[dev]->hw_devc; + switch (cmd) + { + case SOUND_MIXER_READ_VOLUME: + return sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_READ, 0); + break; + + case SOUND_MIXER_WRITE_VOLUME: + return sblive_set_gpr (dev, GPR_VOLUME, SNDCTL_MIX_WRITE, val); + break; + + case SOUND_MIXER_READ_PCM: + if (audiodev >= 0 && audiodev < num_audio_engines) + { + sblive_portc *portc = NULL; + int i; + + for (i = 0; i < devc->n_audiodevs && portc == NULL; i++) + if (devc->portc[i].audiodev == audiodev) + portc = &devc->portc[i]; + + if (portc == NULL) + return OSS_EIO; + + return portc->playvol | (portc->playvol << 8); + } + return sblive_set_gpr (dev, GPR_PCM, SNDCTL_MIX_READ, 0); + break; + + case SOUND_MIXER_WRITE_PCM: + if (audiodev >= 0 && audiodev < num_audio_engines) + { + sblive_portc *portc = NULL; + int i, left, right; + + for (i = 0; i < devc->n_audiodevs && portc == NULL; i++) + if (devc->portc[i].audiodev == audiodev) + portc = &devc->portc[i]; + + if (portc == NULL) + return OSS_EIO; + + left = val & 0xff; + right = (val >> 8) & 0xff; + + if (left < 0) + left = 0; + if (right < 0) + right = 0; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + + if (right > left) + left = right; + portc->playvol = left; + mixer_devs[devc->mixer_dev]->modify_counter++; /* Force update of mixer */ + update_output_device (devc, portc); + + return portc->playvol | (portc->playvol << 8); + } + return sblive_set_gpr (dev, GPR_PCM, SNDCTL_MIX_WRITE, val); + break; + } + + return 0; +} + +static const char *port_names[] = + { "front out", "side out", "center/lfe out", "rear out" }; + +static const __inline__ char * +get_port_name (sblive_devc * devc, int n) +{ + int max_names = 3; + + if (devc->feature_mask & SB_AUDIGY) + max_names = 3; + if (devc->feature_mask & SB_LIVE) + max_names = 2; + + n = n - 1; + + if (n > max_names) + return "extra out"; + + return port_names[n]; +} + +static void +unload_mpu (sblive_devc * devc) +{ + if (devc == NULL) + return; + + if (devc->feature_mask & SB_AUDIGY) + unload_audigyuart (devc); + else + uart401_disable (&devc->uart401devc); +} + +int +oss_sblive_attach (oss_device_t * osdev) +{ + sblive_devc *devc; + int i, err; + int frontdev = -1, ndevs = 0; + int first_dev = -1; + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + unsigned int subvendor; + adev_p adev; + extern int sblive_devices; + + int audiodevs_to_create = sblive_devices; + + char tmp[64]; + + DDB (cmn_err (CE_CONT, "sblive_attach entered\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != PCI_VENDOR_ID_CREATIVE) + { + cmn_err (CE_WARN, "Unrecognized SB live vendor %x\n", vendor); + return 0; + } + + if (device != PCI_DEVICE_ID_SBLIVE + && device != PCI_DEVICE_ID_AUDIGY + && device != PCI_DEVICE_ID_AUDIGY_CARDBUS + && device != PCI_DEVICE_ID_AUDIGYVALUE) + { + cmn_err (CE_WARN, "Unrecognized SB live device %x:%x\n", vendor, + device); + return 0; + } + +#ifdef AUDIGY_ONLY + if (device == PCI_DEVICE_ID_SBLIVE) + { + cmn_err (CE_CONT, + "Error: Due to hardware limitations SB Live is not\n"); + cmn_err (CE_CONT, "supported under this hardware architecture.\n"); + cmn_err (CE_CONT, + "Consider upgrading to SB Audigy which is supported.\n"); + return 0; + } +#endif + + pci_read_config_dword (osdev, 0x2c, &subvendor); + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_command &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + + 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.\n"); + return 0; + } + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + + memset (devc, 0, sizeof (*devc)); + devc->osdev = osdev; + osdev->devc = devc; + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + MUTEX_INIT (osdev, devc->low_mutex, MH_DRV + 1); + + devc->emu_page_shift = 1; /* Default page shift */ + + devc->card_name = "Generic SB Live!"; + devc->subvendor = subvendor; + + devc->min_audiodevs = 5; /* Audigy supports 7.1 */ + + if (device == PCI_DEVICE_ID_AUDIGYVALUE) + { + /* SOLWAY subvendor id is 0x10211103 */ + if ((devc->subvendor == 0x10211102) || (devc->subvendor == 0x10211103)) + devc->card_name = "SB Audigy4"; + else + devc->card_name = "SB Audigy2 Value"; + devc->feature_mask = SB_AUDIGY | SB_AUDIGY2 | SB_AUDIGY2VAL; + } + else if (device == PCI_DEVICE_ID_AUDIGY) + { + if (devc->subvendor >= 0x10021102 && devc->subvendor <= 0x20051102) + { + devc->card_name = "SB Audigy2"; + devc->feature_mask = SB_AUDIGY | SB_AUDIGY2; + } + else + { + devc->card_name = "SB Audigy"; + devc->feature_mask = SB_AUDIGY; + } + } + else if (device == PCI_DEVICE_ID_AUDIGY_CARDBUS) + { + if (devc->subvendor >= 0x10021102 && devc->subvendor <= 0x20051102) + { + devc->card_name = "SB Audigy2 ZS Notebook"; + devc->feature_mask = SB_AUDIGY | SB_AUDIGY2; + } + else + { + devc->card_name = "SB Audigy"; + devc->feature_mask = SB_AUDIGY; + } + DDB (cmn_err (CE_CONT, + "emu10k2 chip rev %d, pcb rev %d\n", pci_revision, + sblive_read_reg (devc, 0x5f, 0))); + } + else + { + devc->card_name = "SB Live"; + devc->feature_mask = SB_LIVE; + devc->min_audiodevs = 4; /* Just 5.1 */ + } + + if (audiodevs_to_create < devc->min_audiodevs) + audiodevs_to_create = devc->min_audiodevs; + if (audiodevs_to_create > MAX_ADEV) + audiodevs_to_create = MAX_ADEV; + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + devc->base &= ~0x3; + + devc->gpr = NULL; + oss_register_device (osdev, devc->card_name); + + devc->irq = pci_irq_line; + + devc->page_map = NULL; + devc->vpage_map = NULL; + devc->nr_pages = 0; + devc->max_pages = 0; + devc->max_mem = 0; + devc->silent_page = NULL; + devc->subvendor = subvendor; + devc->passthrough_gpr = -1; + + if ((err = oss_register_interrupts (devc->osdev, 0, sbliveintr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't register interrupt handler, err=%d\n", err); + return 0; + } + + devc->mixer_group = -1; + devc->extinfo_loaded = 0; + devc->autoreset = 1; + devc->speaker_mode = SMODE_FRONTREAR; + +/* + * Init mixer + */ + devc->mixer_dev = + ac97_install (&devc->ac97devc, devc->card_name, ac97_read, ac97_write, + devc, devc->osdev); + if (devc->mixer_dev < 0) + { + cmn_err (CE_WARN, "Mixer install failed - cannot continue\n"); + return 0; + } + + devc->ac97devc.mixer_ext = 0; + devc->ac97devc.spdifout_support = 0; + devc->ac97devc.spdifin_support = 0; + if (ac97_init_ext + (devc->mixer_dev, &devc->ac97devc, mixer_ext_init, 100) < 0) + { + cmn_err (CE_WARN, "Mixer ext install failed\n"); + } + + /* first set the AC97 PCM to max - otherwise sound is too low */ + ac97_mixer_set (&devc->ac97devc, SOUND_MIXER_PCM, 100 | (100 << 8)); + + ac97_remove_control (&devc->ac97devc, BOGUS_MIXER_CONTROLS, 0); + ac97_override_control (&devc->ac97devc, SOUND_MIXER_VOLUME, + mixer_override, 100 | (100 << 8)); + ac97_override_control (&devc->ac97devc, SOUND_MIXER_PCM, + mixer_override, 100 | (100 << 8)); + + attach_mpu (devc); + +/* + * Audio initialization + */ + init_emu10k1 (devc); + + for (i = 0; i < audiodevs_to_create; i++) + { + sblive_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + int fmts = 0; + devc->n_audiodevs = i + 1; + + portc->memptr = devc->audio_memptr; + devc->audio_memptr += (DMABUF_SIZE + 4095) & ~4095; + + if (devc->audio_memptr > AUDIO_MEMSIZE) + { + cmn_err (CE_WARN, "Audio memory block exhausted (%d/%d)\n", + devc->audio_memptr, AUDIO_MEMSIZE); + return OSS_ENOSPC; + } + + if (i == 0) + { + strcpy (tmp, devc->card_name); + sprintf (tmp, "%s main", devc->card_name); + caps |= ADEV_DUPLEX; + } + else + { + sprintf (tmp, "%s %s", devc->card_name, get_port_name (devc, i)); + caps |= ADEV_NOINPUT; +#if 0 + if (i >= devc->min_audiodevs) + caps |= ADEV_HWMIX; +#endif + if (i >= devc->min_audiodevs + 1) + caps |= ADEV_SHADOW; + } + if ((devc->feature_mask & SB_AUDIGY) && i == audiodevs_to_create - 1) + { + sprintf (tmp, "%s raw S/PDIF (output only)", devc->card_name); + caps &= ~(ADEV_SHADOW /* | ADEV_HWMIX*/); + caps |= ADEV_SPECIAL; + fmts |= AFMT_AC3; + } +#if 0 + if (devc->feature_mask & SB_AUDIGY) + caps |= ADEV_COLD; +#endif + if ((portc->audiodev = + oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &sblive_audio_driver, + sizeof (audiodrv_t), caps, + fmts | AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0) + { + portc->audiodev = -1; + return (i > 0); + } + else + { + int x; + + adev = audio_engines[portc->audiodev]; + adev->nrates=0; + for (x = 0; speed_tab[x].speed != 0; x++) + adev->rates[adev->nrates++] = speed_tab[x].speed; + + if (i == 0) + first_dev = portc->audiodev; + adev->devc = devc; + adev->portc = portc; + adev->rate_source = first_dev; + adev->mixer_dev = devc->mixer_dev; + adev->min_rate = 8000; + adev->max_rate = 48000; + + if (!(devc->feature_mask & SB_AUDIGY)) + { + /* + * SB Live supports only 31 PCI address bits + */ + adev->dmabuf_maxaddr = MEMLIMIT_31BITS; + } + + portc->mode = 0; + adev->oformat_mask |= AFMT_AC3; + portc->input_type = ITYPE_ANALOG; + if ((devc->feature_mask & SB_AUDIGY) && i == audiodevs_to_create - 1) + portc->input_type = ITYPE_SPDIF; + if (i == 1) + frontdev = portc->audiodev; + if (i > 0) + ndevs++; + + portc->playvol = 100; + portc->playangle = 0; + portc->playdist = 50; + portc->vu_left = 0; + portc->vu_right = 0; + portc->audio_active = 0; + portc->voice_chn = i * 2; + portc->port_number = i; + devc->voice_busy[i * 2] = 1; + devc->voice_busy[i * 2 + 1] = 1; + portc->resetvol = 0; + if (devc->feature_mask & SB_LIVE) + { +/* + * Do not enable vmix by default on Live! It would cause enormous + * latencies because emu10k1 doesn't have working full/half buffer DMA + * interrupts. + */ + adev->vmix_flags = VMIX_MULTIFRAG; + adev->max_intrate = 50; + adev->min_block = 4096; + } + else + { + adev->max_fragments = 2; + } + + /* + * Hide vmix main volume control and peak meters if no + * real HW mixing devices are enabled. + */ +#if 0 + if (audiodevs_to_create <= devc->min_audiodevs) + adev->vmix_flags |= VMIX_NOMAINVOL; +#endif + adev->iformat_mask = AFMT_S16_LE; /* No 8 bit recording */ + + if (i == 0) + { + if (devc->feature_mask & SB_LIVE) + adev->magic = EMU10K1_MAGIC; + else + adev->magic = EMU10K2_MAGIC; + } +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, first_dev, -1, 0); +#endif + } + adev->mixer_dev = devc->mixer_dev; + } + +#ifdef USE_REMUX + /* Install Remux (only 5.1 support for the time being) */ + sprintf (tmp, "%s 5.1 output device", devc->card_name); + if (frontdev > 0 && ndevs >= 3) /* Have enough devices for 5.1 */ + remux_install (tmp, devc->osdev, frontdev, frontdev + 1, frontdev + 2, + -1); +#endif + +#ifndef NO_EMU10K1_SYNTH + sblive_install_synth (devc); +#endif + + touch_mixer (devc->mixer_dev); + init_effects (devc); + + return 1; +} + +int +oss_sblive_detach (oss_device_t * osdev) +{ + sblive_devc *devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + devc = osdev->devc; + + OUTL (devc->osdev, 0, devc->base + 0x0c); /* Intr enable (all off) */ + OUTL (devc->osdev, + HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | + HCFG_MUTEBUTTONENABLE, devc->base + 0x14); + + sblive_write_reg (devc, ADCSR, 0, 0x0); + sblive_write_reg (devc, ADCBA, 0, 0x0); + sblive_write_reg (devc, ADCBA, 0, 0x0); + + sblive_write_reg (devc, PTBA, 0, 0); + +#ifndef NO_EMU10K1_SYNTH + sblive_remove_synth (devc); +#endif + if (devc->page_map != NULL) + CONTIG_FREE (devc->osdev, devc->page_map, devc->max_pages * 4, devc->page_map_dma_handle); + if (devc->vpage_map != NULL) + KERNEL_FREE (devc->vpage_map); + if (devc->silent_page != NULL) + CONTIG_FREE (devc->osdev, devc->silent_page, 4096, devc->silent_page_dma_handle); + devc->max_pages = 0; + devc->max_mem = 0; + devc->page_map = NULL; + devc->vpage_map = NULL; + devc->silent_page = NULL; + unload_mpu (devc); + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + UNMAP_PCI_IOADDR (devc->osdev, 0); + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_sblive/oss_sblive.man b/kernel/drv/oss_sblive/oss_sblive.man new file mode 100644 index 0000000..067a341 --- /dev/null +++ b/kernel/drv/oss_sblive/oss_sblive.man @@ -0,0 +1,226 @@ +NAME + oss_sblive - Creative Labs Sound Blaster Live/Audigy family driver. + +DESCRIPTION + Open Sound System driver for Creative Labs Sound Blaster Live!, Audigy, + Audigy2, Audigy2-Value and sound cards. + + The sblive driver supports: + + o 8-48Khz Playback/Recording + o 8 or 16 bits + o SPDIF digital output and Input + o Multi channel 5.1 (Live!) and 7.1 (Audigy) output. + + AC3 passthrough is only supported on Audigy series of the soundcards. + +OTHER SIMILAR CARDS +There are several Sound Blaster cards that are also called as Live or +Audigy. However these cards are based on entirely different hardware design +and they are not compatible with this driver. + +o Sound Blaster Live 5.1 card is used in some Dell machines but it's + driven by the emu10k1x driver. +o Sound Blaster AudigyLS and Live 7.1 models are driven by the audigyls + driver of OSS. + + SBLIVE COMBO SPDIF AND AUDIO JACKS +Most models of Live! and Audigy cards have an orange combo jack that is +used both for the analog center/LFE output and for digital DIN (S/PDIF) +output. The output mode is selected by a driver configuration option +(seel below) which should be set to proper value depending on the actual +speaker configuration. + +o Noisy analog center/LFE output. The orange combo jack at the rear plate + of the Live/Audigy card is shared between the digital DIN and the analog + center/LFE outputs. In digital DIN mode (default) you will hear very noisy + output from the speakers connected to this output jack. If you have analog + center/LFE (subwoofer) speakers connected then you need to turn off the + sblive_digital_din (or audigy_digital_din) option. + +o There is a new configuration option to enable/disable the "digital DIN" + output. By default the digital DIN interface is enabled which disables the + center/LFE analog output (uses the same combo jack). By setting the + sblive_digital_din (or audigy_digital_din) option to 0 you can enable the + analog C/LFE output feature. When digital DIN is disabled you can still get + S/PDIF (or AC3) output from the digital (optical/coax) outputs of the + optional livedrive unit. + + SBLIVE MIXER +SB Live cards have actually two mixer chips. In OSS both of them are +controlled together. However only limited set of features can be controlled +using ordinary mixer programs (such as the mixer applet included in OSS). +Majority of features can only be accessed using the ossmix and ossxmix +programs included in OSS. + +The AC97 mixer is used to control volumes of the back bracket inputs (mic and +line in) and the _analog_ CD input connector on the soundcard. The 'mic' +volume controls the level of the rear bracket microphone input sent directly +to the front (only front) speakers. The 'line' and 'cd' controls do the same +for the back bracket line in connector and the on board analog CD input +connector. It's usually recommended to set these volumes to 0. + +Another function of the AC97 mixer is selecting the signal that is passed to +the master mixer (for example for recording). One of the 'mic', 'line' or +'cd' signals can be routed to the master mixer by selecting that device as +the recording source in the AC97 mixer. The 'rec' volume control slider can +be used to adjust the signal strength. The 'igain' control doesn't usually +have any effect but some hardware revisions may use it for controlling the +microphone recording level. + + + SBLIVE MASTER MIXER +Other mixer functions are handled by the DSP engine of the EMU 10k1 chip. +Most input signals (including all digital signals and LiveDrive inputs). + +There are only two master mixer settings that can be controlled using all +mixer programs. The 'vol' setting is the master output volume that affects +both the front and rear speakers and the headphone output (digital output +volumes are not affected). The 'pcm' setting controls volumes of all PCM +playback channels (/dev/dsp#). + +In addition to volume sliders most inputs have a stereo VU meter pair +(only in ossxmix) that can be used to monitor the input and to adjust the +input levels properly. + +The master mixer consists of several sections that are: + +o Primary section: This section has two settings. The "spkmode" setting + selects how front/rear speakers are used for PCM playback (outputs from + programs using /dev/dsp#). The possible settings are FRONT, REAR and + FRONT+REAR. The default is FRONT+REAR. Change this setting if you like to + get PCM playback only from front or rear speakers. The "autoreset" flag is + used to control the "/dev" section. + +o "/dev" section: This section controls the volumes of each /dev/dsp# device + file supported by the device (there are 8 of them at this moment). These + volumes will return back to maximum every time the device is opened. However + this can be disabled by setting the 'autoreset' option to OFF. The ossxmix + program has special ability to show the application using the particular + /dev/dsp device (for layout reasons only the first 4 characters of the + program name are shown). + +o The equalizer section: This section controls the graphic equalizer for + front speakers only. + +o The front rear, and record sections: These three identical sections control + the levels of external inputs and PCM playback (/dev/dsp# devices) to be + sent to the front/rear speakers and to the recording device. + The CD Analog audio will only be heard from the FRONT speakers. + + SBLIVE RECORDING +Before recording anything you need to set the volumes in the recording +section properly. To enable recording from the AC97 connected inputs +(mic, line in and analog CD) use the AC97 mixer to select the desired input +and then tune the input level using the rec (and igain) setting. + +Finally set the 'ac97' slider in the record section of the master mixer so +that the recording level is suitable. + +The OSS drivers permit recording any application that's currently playing. + +To record audio that's playing on any of the SB Live channels: + +o Turn down the AC97 control in the "record" section. This prevents any audio + being fed to the soundcard from MIC/Line-in/CD-in from getting mixed with + the audio produced by the application that's currently playing. + +o Type ossrecord -s<sampling rate> -b<bits/sample> -c<channels> test.wav + +o To stop recording press <Ctrl-c> and then you can play back the test.wav + file using ossplay command. + + + RECORDING ISSUES: +In most cases noise is caused by the microphone input or some other +(unused) input. Use the ossxmix program to turn off all unused inputs and +finally save the current mixer settings (see below). + +Hint: Look at the VU meter panels of ossxmix. It's usually very easy to +locate the noise source by looking which input has some signal coming from +it. + +WARNING! If you turn off some of the signals in recording section or the +AC97 mixer section this affects all subsequent recordings. Remember +to raise the volume prior doing any recording. After that decrease +the volumes again if necessary. + + + SBLIVE HARDWARE MIXING +You can use /dev/oss/oss_sblive0/ pcm0-pcm7 to play multiple audio programs +using the hardware mixing. +Simply specify the device name with the application. A simple test is +to do the following: + ossplay -d/dev/oss/oss_sblive0/pcm0 <file1.wav> & + ossplay -d/dev/oss/oss_sblive0/pcm1 <file2.wav> & + ossplay -d/dev/oss/oss_sblive0/pcm2 <file3.wav> & + +You should hear all three wav files playing simultaneously. + +NOTE: Some apps may desire the old /dev/dspN names. e.g. /dev/dsp0 - /dev/dsp7. + +NOTE: You can increase the number of output devices from the standard 8 devices +to 32 device. For this, run soundconf, select Set configuration options and +look for the entry "sblive_device", now type any number between 1 and 32 +for the number of channels you wish. You can also do this manually by editing +oss_sblive.conf and inserting sblive_devices=XX entry, + e.g.: sblive_devices=27 + + CDROM CONNNECTIONS +There are two alternative ways to connect audio signal from a CD-ROM drive tor +the SB Live soundcard. You can use a (three wire) analog cable or a (2 wire) +digital cable. OSS now supports both of these choices. Note that there are +separate mixer settings for both of these connections. + +The analog CD-ROM wire is connected to the AC97 code chip and this method +works in most cases. To route the analog CD -input to the (front) speakers +you need to raise the volume of the 'cd' control in mixer. However if you +like to hear the analog CD input both from the front and rears speakers you +need to do this in slightly different way (please read the description of +the mixer above). + +The digital connection works only with CD-ROM drives that has support for it. +Note that some CD-ROM drives having this digital output connector use a +different signal level than the one required by SB Live. This means that the +digital connection doesn't work with all CD-ROM drives (no sound). If you +have problems with the digital connection you should use the analog one. +When using the the digital CD input you may need to adjust the 'digcd' +volumes using ossxmix (or ossmix). + +It should be noted that SB Live works internally at 48 kHz. This means that +all S/PDIF input signals are automatically sample rate converted to 48 kHz. +If you record from a 44.1 kHz (CD-ROM) and save the result to a 44.1 kHz +file the signal will be sample rate converted twice. First from the 44.1 kHz +input to internal 48 kHz and then back to 44.1 kHz. While the sample rate +converter of SB Live is very precise this will cause some change. This should +not be any problem when doing audio recordings but it may cause unwanted +results when transferring digital data (such as AC3/DTS) using the S/PDIF +the interface. + +CONFIGURATION OPTIONS +o sblive_digital_din=<0|1> - This option is to enable/disable the "digital DIN" + output of SB Live. By default the digital DIN interface is disabled which + enables the center/LFE analog output (uses the same combo jack). By + setting the sblive_digital_din option to 0 you can enable the analog + Center/LFE output feature. When digital DIN is disabled you can still + get S/PDIF (or AC3) output from the digital (optical/coax) outputs of the + optional livedrive unit. Default: 0=analog output. + +o audigy_digital_din=<0|1> - same as "sblive_digital_din" option except for + the Audigy soundcards. Default: 1=digital output. + +o sblive_devices=<1..32> - Number of audio devices to be configured. + + +LIMITATION +o SB Live! devices will not work in Sparc systems due to PCI addressing + limitations. Only Audigy/Audigy2 models work under Sparc. +o EMU Wavetable MIDI synthesizer is not supported +o AC3 passthrough only supported on Audigy/Audigy but not on SB Live! devices. + +FILES +CONFIGFILEPATH/oss_sblive.conf Device configuration file + +AUTHOR + 4Front Technologies + diff --git a/kernel/drv/oss_sblive/sblive.h b/kernel/drv/oss_sblive/sblive.h new file mode 100644 index 0000000..a6a2ca7 --- /dev/null +++ b/kernel/drv/oss_sblive/sblive.h @@ -0,0 +1,535 @@ +/* + * Purpose: Global definitions for the SB Live/Audigy 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. + * + */ + +#ifndef USERLAND +#include "uart401.h" +#endif + +#define EMU10K1_MAGIC 0xe10001 +#define EMU10K2_MAGIC 0xe10002 + +/* Audio */ + +#if defined(OSR5) || defined(__bsdi__) +#define MAX_ADEV 2 +#else +#define MAX_ADEV 32 /* How many devices */ +#endif + +#define DMABUF_SIZE (64*1024) /* Maximum DMA buffer size supported */ +#define AUDIO_MAXVOICE (2*MAX_ADEV) +#define AUDIO_MEMSIZE (MAX_ADEV*DMABUF_SIZE+4096) /* Audio buffer + silent page */ +#define SYNTH_MEMBASE AUDIO_MEMSIZE + +/* Synth */ +#define MAX_PATCH 256 +#define MAX_SAMPLE 512 +#define MAX_VOICE 64 + +#define SYNTH_FIRSTVOICE AUDIO_MAXVOICE +#define SYNTH_LASTVOICE (MAX_VOICE-1) + +/* Synth memory allocation */ +#define SBLIVE_MEMBLOCK_SIZE (128*1024) /* Default synth mem alloc chunk size */ +#define MIN_BLOCK_SIZE (8*1024) +#define SBLIVE_MAX_MEMBLOCKS 1024 /* Max number of mem chunks to allocate */ + +/* Hardware config register */ + +#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */ +#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ +#define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */ +#define HCFG_GPINPUT0 0x00004000 /* External pin112 */ +#define HCFG_GPINPUT1 0x00002000 /* External pin110 */ +#define HCFG_GPOUTPUT_MASK 0x00001c00 /* External pins which may be controlled */ +#define HCFG_GPOUT0 0x00001000 /* set to enable digital out on 5.1 cards */ +#define HCFG_GPOUT1 0x00000800 /* IR */ +#define HCFG_GPOUT2 0x00000400 /* IR */ +#define HCFG_JOYENABLE 0x00000200 /* Internal joystick enable */ +#define HCFG_PHASETRACKENABLE 0x00000100 /* Phase tracking enable */ + /* 1 = Force all 3 async digital inputs to use */ + /* the same async sample rate tracker (ZVIDEO) */ +#define HCFG_AC3ENABLE_MASK 0x0x0000e0 /* AC3 async input control - Not implemented */ +#define HCFG_AC3ENABLE_ZVIDEO 0x00000080 /* Channels 0 and 1 replace ZVIDEO */ +#define HCFG_AC3ENABLE_CDSPDIF 0x00000040 /* Channels 0 and 1 replace CDSPDIF */ +#define HCFG_AC3ENABLE_GPSPDIF 0x00000020 /* Channels 0 and 1 replace GPSPDIF */ +#define HCFG_AUTOMUTE 0x00000010 /* When set, the async sample rate convertors */ + /* will automatically mute their output when */ + /* they are not rate-locked to the external */ + /* async audio source */ +#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */ + /* NOTE: This should generally never be used. */ +#define HCFG_LOCKTANKCACHE_MASK 0x00000004 /* 1 = Cancel bustmaster accesses to tankcache */ + /* NOTE: This should generally never be used. */ +#define HCFG_LOCKTANKCACHE 0x01020014 +#define HCFG_MUTEBUTTONENABLE 0x00000002 /* 1 = Master mute button sets AUDIOENABLE = 0. */ + /* NOTE: This is a 'cheap' way to implement a */ + /* master mute function on the mute button, and */ + /* in general should not be used unless a more */ + /* sophisticated master mute function has not */ + /* been written. */ +#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ + /* Should be set to 1 when the EMU10K1 is */ + /* completely initialized. */ +#define A_HCFG_VMUTE 0x00004000 +#define A_HCFG_AUTOMUTE 0x00008000 +#define A_HCFG_XM 0x00040000 /* Xtended address mode */ + +/* + * GPIO bit definitions (global register 0x18) for Audigy. + */ + +#define A_IOCFG_GPOUT0 0x0044 /* analog/digital? */ +#define A_IOCFG_GPOUT1 0x0002 /* IR */ +#define A_IOCFG_GPOUT2 0x0001 /* IR */ + +/* Status bits (read only) */ +#define GPIO_VERSAPLUGGED 0x2000 /* Center/LFE/digital */ +#define GPIO_FRONTPLUGGED 0x4000 +#define GPIO_REARPLUGGED 0x8000 +#define GPIO_HEADPHPLUGGED 0x0100 +#define GPIO_ANALOG_MUTE 0x0040 +#define GPIO_DIGITAL_ENABLE 0x0004 /* Center/lfe (0) or digital (1) switch */ + +#define FILL_PAGE_MAP_ENTRY(e, v) devc->page_map[e] = LSWAP (((v) << devc->emu_page_shift) | (e)); +/* + * Audio block registers + */ + +#define CPF 0x000 /* DW:cnl Current pitch and fraction */ +#define CPF_CURRENTPITCH_MASK 0xffff0000 /* Current pitch (linear, 0x4000 == unity pitch shift) */ +#define CPF_CURRENTPITCH 0x10100000 +#define CPF_STEREO_MASK 0x00008000 /* 1 = Even channel interleave, odd channel locked */ +#define CPF_STOP_MASK 0x00004000 /* 1 = Current pitch forced to 0 */ +#define CPF_FRACADDRESS_MASK 0x00003fff /* Linear fractional address of the current channel */ + + +#define PTAB 0x001 /* DW:cnl Pitch target and sends A and B */ +#define PTRX_PITCHTARGET_MASK 0xffff0000 /* Pitch target of specified channel */ +#define PTRX_PITCHTARGET 0x10100001 +#define PTRX_FXSENDAMOUNT_A_MASK 0x0000ff00 /* Linear level of channel output sent to FX send bus A */ +#define PTRX_FXSENDAMOUNT_A 0x08080001 +#define PTRX_FXSENDAMOUNT_B_MASK 0x000000ff /* Linear level of channel output sent to FX send bus B */ +#define PTRX_FXSENDAMOUNT_B 0x08000001 + + +#define CVCF 0x002 /* DW:cnl Curr vol and curr filter cutoff */ +#define VTFT 0x003 /* DW:cnl Volume tgt and filter cutoff tgt */ +#define Z2 0x004 /* DW:cnl Filter delay memory 2 */ +#define Z1 0x005 /* DW:cnl Filter delay memory 1 */ +#define SCSA 0x006 /* DW:cnl Send C and Start addr */ +#define SDL 0x007 /* DW:cnl Send D and Loop addr */ +#define QKBCA 0x008 /* DW:cnl Filter Q, ROM, etc */ +#undef CCR +#define CCR 0x009 +#define CCR_CACHEINVALIDSIZE 0x07190009 +#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */ +#define CCR_CACHELOOPFLAG 0x01000000 /* 1 = Cache has a loop service pending */ +#define CCR_INTERLEAVEDSAMPLES 0x00800000 /* 1 = A cache service will fetch interleaved samples */ +#define CCR_WORDSIZEDSAMPLES 0x00400000 /* 1 = A cache service will fetch word sized samples */ +#define CCR_READADDRESS 0x06100009 +#define CCR_READADDRESS_MASK 0x003f0000 /* Location of cache just beyond current cache service */ +#define CCR_LOOPINVALSIZE 0x0000fe00 /* Number of invalid samples in cache prior to loop */ + /* NOTE: This is valid only if CACHELOOPFLAG is set */ +#define CCR_LOOPFLAG 0x00000100 /* Set for a single sample period when a loop occurs */ +#define CCR_CACHELOOPADDRHI 0x000000ff /* DSL_LOOPSTARTADDR's hi byte if CACHELOOPFLAG is set */ + +#define CLP 0x00a +#define SRHE 0x07c +#define STHE 0x07d +#define SRDA 0x07e +#define STDA 0x07f +#define L_FXRT 0x00b +#define FXRT ((devc->feature_mask&SB_AUDIGY)? 0x7d:0x00b) /* W:cnl */ +#define MAPA 0x00c +#define MAPB 0x00d +#define VEV 0x010 /* W:cnl */ +#define VEHA 0x011 /* W:cnl */ +#define VEDS 0x012 /* W:cnl */ +#define MLV 0x013 /* W:cnl */ +#define MEV 0x014 /* W:cnl */ +#define MEHA 0x015 /* W:cnl */ +#define MEDS 0x016 /* W:cnl */ +#define VLV 0x017 /* W:cnl */ +#define IP 0x018 /* W:cnl */ +#define IFA 0x019 /* W:cnl */ +#define PEFE 0x01a /* W:cnl */ +#define PEFE_PITCHAMOUNT_MASK 0x0000ff00 /* Pitch envlope amount */ +#define PEFE_PITCHAMOUNT 0x0808001a +#define PEFE_FILTERAMOUNT_MASK 0x000000ff /* Filter envlope amount */ +#define PEFE_FILTERAMOUNT 0x0800001a + +#define VFM 0x01b /* W:cnl */ +#define TMFQ 0x01c /* W:cnl */ +#define VVFQ 0x01d /* W:cnl */ +#define TMPE 0x01e /* W:cnl */ +#define CD0 0x020 /* DW:cnl (16 registers) */ +#define PTBA 0x040 /* DW:nocnl */ +#define TCBA 0x041 /* DW:nocnl */ +#define ADCSR 0x042 /* B:nocnl */ +#define FXWC 0x043 /* DW:nocnl */ +#define TCBS 0x044 /* B:nocnl */ +#define MBA 0x045 /* DW:nocnl */ +#define ADCBA 0x046 /* DW:nocnl */ +#define FXBA 0x047 /* DW:nocnl */ + +#define MBS 0x049 /* B:nocnl */ +#define ADCBS 0x04a /* B:nocnl */ +#define FXBS 0x04b /* B:nocnl */ +#define CSBA 0x4c +#define CSDC 0x4d +#define CSFE 0x4e +#define CSHG 0x4f +#define CDCS 0x050 /* DW:nocnl */ +#define GPSCS 0x051 /* DW:nocnl */ +#define DBG 0x052 /* DW:nocnl */ +#define AUDIGY_DBG 0x053 /* DW:nocnl */ +#define SCS0 0x054 /* DW:nocnl */ +#define SCS1 0x055 /* DW:nocnl */ +#define SCS2 0x056 /* DW:nocnl */ +#define CLIEL 0x058 /* DW:nocnl */ +#define CLIEH 0x059 /* DW:nocnl */ +#define CLIPL 0x05a /* DW:nocnl */ +#define CLIPH 0x05b /* DW:nocnl */ +#define SOLL 0x05c /* DW:nocnl */ +#define SOLH 0x05d /* DW:nocnl */ +#define SOC 0x05e /* DW:nocnl */ +#define AC97SLOT 0x05f +#define AC97SLOT_REAR_RIGHT 0x01 +#define AC97SLOT_REAR_LEFT 0x02 +#define AC97SLOT_CENTER 0x10 +#define AC97SLOT_LFE 0x20 +#define CDSRCS 0x060 /* DW:nocnl */ +#define GPSRCS 0x061 /* DW:nocnl */ +#define ZVSRCS 0x062 /* DW:nocnl */ +#define ADCIDX 0x063 /* W:nocnl */ +#define MIDX 0x064 /* W:nocnl */ +#define FXIDX 0x065 /* W:nocnl */ + +/* Half loop interrupt registers (audigy only) */ +#define HLIEL 0x066 /* DW:nocnl */ +#define HLIEH 0x067 /* DW:nocnl */ +#define HLIPL 0x068 /* DW:nocnl */ +#define HLIPH 0x069 /* DW:nocnl */ +#define GPR0 ((devc->feature_mask&SB_LIVE)? 0x100:0x400) /* DW:nocnl */ +#define TMA0 0x300 /* Tank memory */ +#define UC0 ((devc->feature_mask&SB_LIVE) ? 0x400:0x600) /* DSM microcode memory */ + +/* Interrupt enable register */ +#define IE 0x0c +# define IE_RXA 0x00000001 +# define IE_IT 0x00000004 +# define IE_AB 0x00000040 + +/* EMU10K2 MIDI UART */ +#define MUADAT 0x070 +#define MUACMD 0x071 +#define MUASTAT MUACMD + +/* EMU10K2 S/PDIF recording buffer */ +#define SPRI 0x6a +#define SPRA 0x6b +#define SPRC 0x6c + +#define EHC 0x76 /* Audigy 2 */ + +#define SRHE 0x07c +#define STHE 0x07d +#define SRDA 0x07e + +#define HCFG_GPOUT0 0x00001000 /* set to enable digital out on 5.1 cards */ +#define HCFG_GPOUT1 0x00000800 /* IR on SBLive */ +#define HCFG_GPOUT2 0x00000400 /* IR on SBLive */ +#define HCFG_JOYENABLE 0x00000200 /* Internal joystick enable */ + +#define A_IOCFG_GPOUT0 0x0044 /* analog/digital? */ +#define A_IOCFG_GPOUT1 0x0002 /* IR on Audigy */ +#define A_IOCFG_GPOUT2 0x0001 /* IR on Audigy */ + +#define ROM0 0x00000000 /* interpolation ROM 0 */ +#define ROM1 0x02000000 /* interpolation ROM 1 */ +#define ROM2 0x04000000 /* interpolation ROM 2 */ +#define ROM3 0x06000000 /* interpolation ROM 3 */ +#define ROM4 0x08000000 /* interpolation ROM 4 */ +#define ROM5 0x0A000000 /* interpolation ROM 5 */ +#define ROM6 0x0C000000 /* interpolation ROM 6 */ +#define ROM7 0x0E000000 /* interpolation ROM 7 */ +#define BYTESIZE 0x01000000 /* byte sound memory */ + +#define MAX_GPR 256 +#define MAX_GPR_PARMS 60 +#define MAX_CONST_PARMS 128 +#define GPR_NAME_SIZE 32 +typedef struct +{ + char name[GPR_NAME_SIZE]; + unsigned int num; + int type; + int def; +} +gpr_t; + +typedef struct +{ + unsigned int gpr; + int value; +} +const_t; + +typedef struct +{ + unsigned int ngpr; + + gpr_t gpr[MAX_GPR_PARMS]; +} +gpr_info; + +typedef struct +{ + unsigned int nconst; + + const_t consts[MAX_CONST_PARMS]; +} +const_info; + +typedef struct sblive_portc +{ + int audiodev; + int mode; + int input_type; +#define ITYPE_ANALOG 0 +#define ITYPE_SPDIF 1 + int uses_spdif; /* This device uses the S/PDIF passthrough channel */ + int audio_active; + volatile int trigger_bits; + int format, speed, channels; + int speedsel; + + int voice_chn; + int port_number; + int out_sz; /* Output sample size */ + int in_szbits; + unsigned long rec_starttime; + + /* 3D soft mixer */ + int playvol, playangle, playdist; + int vu_left, vu_right; + int speaker_mode; +#define SMODE_FRONT 0 /* Front speakers only */ +#define SMODE_SURR 1 /* Rear speakers only */ +#define SMODE_FRONTREAR 2 /* Front and rear speakers */ +#define SMODE_BIND 3 /* Use channel bindings */ +#define SMODE_3D 4 /* 3D positioning */ + int binding; + unsigned char *routing; + int resetvol; + int memptr; +} +sblive_portc; + +typedef struct +{ + int active; + int program; + int sample; + int note_num, note_freq, orig_freq; + int velosity; + struct patch_info *patch; + int sample_ptr; + int fixed_pitch; + int main_vol, expression_vol, panning, frontrear, bender, bender_range; +} +sblive_voice_t; + +typedef struct sblive_devc +{ + oss_native_word base; + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + oss_device_t *osdev; + char *card_name; + + /* + * Device feature mask tells which kind of features are suported by the + * hardware. Audigy2/2val have multiple bits set while Live! has just + * the SB_LIVE bits. So Features of Audigy will be reported by Audigy2/val + * too. + */ + int feature_mask; +#define SB_LIVE 1 +#define SB_AUDIGY 2 +#define SB_AUDIGY2 4 +#define SB_AUDIGY2VAL 8 + int mpu_attached; + + int *page_map; /* Table for up to 8k pointers to pages of 4k */ + unsigned char **vpage_map; /* Virtual address map */ + oss_dma_handle_t page_map_dma_handle; + int emu_page_shift; + int max_mem, max_pages, nr_pages; + unsigned int subvendor; +/* + * Mixer + */ + int mixer_dev; + ac97_devc ac97devc; + int input_routing_pc; + int input_sel; /* 0=AC97 */ + gpr_info *gpr; + int mixer_group; + int gpr_values[MAX_GPR]; + int extinfo_loaded; + int passthrough_gpr; + int vu_tmp, vu_tmp2; + +/* + * Audio + */ + + int n_audiodevs; + int min_audiodevs; + int audio_memptr; + int *silent_page; + oss_dma_handle_t silent_page_dma_handle; + oss_native_word silent_page_phys; + + sblive_portc portc[MAX_ADEV + 2]; + int recording_dev; + int spdif_busy; + + int autoreset; + int speaker_mode; + +/* + * Wave table RAM alloc structures + */ + int memblock_size; /* Size of blocks to be allocated */ + int num_memblocks; + void *memblocks[SBLIVE_MAX_MEMBLOCKS]; + int memblock_sizes[SBLIVE_MAX_MEMBLOCKS]; + int total_memblock_size; + +/* + * Audigy UART + */ + oss_midi_inputbyte_t midi_input_intr; + int midi_opened, midi_disabled; + volatile unsigned char input_byte; + int midi_dev; + int sysex_p; + unsigned char sysex_buf[20]; + uart401_devc uart401devc; + +/* + * Wave table + */ + + int synthdev; + int synth_open; + int synth_membase, synth_memlimit, synth_memptr, synth_memtop; + unsigned int voice_busy[2]; + int free_sample; + struct patch_info *samples; + long sample_ptrs[MAX_SAMPLE + 1]; + int programs[MAX_PATCH]; + + sblive_voice_t voices[MAX_VOICE]; + +} +sblive_devc; + +/* + * Private ioctl() interface + */ + +typedef struct +{ + unsigned int reg; + unsigned int chn; + unsigned int value; +} +sblive_reg; + +typedef struct +{ + int magic; + int feature_mask; + int size; /* # of instructions */ + unsigned int code[1024]; + gpr_info parms; + const_info consts; +} +emu10k1_file; + +typedef unsigned int sblive_code[512]; + +#define SBLIVE_READREG __SIOWR('L', 1, sblive_reg) +#define SBLIVE_WRITEREG __SIOW ('L', 2, sblive_reg) +#define SBLIVE_WRITECODE1 __SIOW ('L', 3, sblive_code) +#define SBLIVE_WRITECODE2 __SIOW ('L', 4, sblive_code) +#define SBLIVE_WRITEPARMS __SIOW ('L', 5, gpr_info) +#define SBLIVE_WRITECONST __SIOW ('L', 6, const_info) +#define SBLIVE_GETCHIPTYPE __SIOR ('L', 7, int) +#define SBLIVE_WRITEGPIO __SIOW ('L', 8, int) +#define SBLIVE_READGPIO __SIOR ('L', 9, int) + +#define EMU_MIXT_EQ1 0x10000000 +#define EMU_MIXT_EQ2 0x10000001 +#define EMU_MIXT_EQ3 0x10000002 +#define EMU_MIXT_EQ4 0x10000003 + +/* + * Overridden mixer controls (GPR registers) + * Note that these definitions heve to be kept in sync with + * init_compiler() routine of sndkit/sblive/asm10k1.c and the + * mixer_override() routine of sblive.c. + */ +#define GPR_DUMMY 0 /* 2 locations reserved for NULL control */ +#define GPR_PCM 2 /* 2 locations required for stereo slider */ +#define GPR_VOLUME 4 /* 2 locations required for stereo slider */ +#define NEXT_FREE_GPR 6 /* Needs to be 32 or below so that SPECIAL_GPRS works */ +#define SPECIAL_GPRS ((1<<GPR_PCM) | (1<<GPR_VOLUME)) + +#ifdef OSS_BIG_ENDIAN +static __inline__ unsigned int +swap_int (unsigned int x) +{ + return ((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24); +} + +static __inline__ unsigned short +swap_short (unsigned short x) +{ + return ((x | 0xff) << 8) | ((x >> 8) & 0xff); +} + +#define LSWAP(x) swap_int(x) +#define SSWAP(x) swap_short(x) +#else +#define LSWAP(x) x +#define SSWAP(x) x +#endif +extern void sblive_set_loop_stop (sblive_devc * devc, int voice, int s); +extern void sblive_set_voice_intr (sblive_devc * devc, int voice, int s); +extern void sblive_write_reg (sblive_devc * devc, int reg, int chn, + unsigned int value); +extern unsigned int sblive_read_reg (sblive_devc * devc, int reg, int chn); +extern void sblive_init_voice (sblive_devc * devc, int chn); +extern void sblive_synth_interrupt (sblive_devc * devc); +extern int sblive_get_voice_loopintr (sblive_devc * devc, int voice); +extern int sblive_get_voice_halfloopintr (sblive_devc * devc, int voice); diff --git a/kernel/drv/oss_sbpci/.devices b/kernel/drv/oss_sbpci/.devices new file mode 100644 index 0000000..4a38255 --- /dev/null +++ b/kernel/drv/oss_sbpci/.devices @@ -0,0 +1,5 @@ +oss_sbpci pci1102,8938 Creative Ectiva EV1938 +oss_sbpci pci1274,1371 Creative AudioPCI97 (ES1371/ES1373) +oss_sbpci pci1274,5880 Creative Sound Blaster PCI128 (5880B) +oss_sbpci pci1274,8001 Creative Sound Blaster PCI128 (CT5880) +oss_sbpci pci1274,8002 Creative Sound Blaster PCI128 (5880A) diff --git a/kernel/drv/oss_sbpci/.name b/kernel/drv/oss_sbpci/.name new file mode 100644 index 0000000..36ff069 --- /dev/null +++ b/kernel/drv/oss_sbpci/.name @@ -0,0 +1 @@ +Creative AudioPCI97 (ES1371/ES1373/EV1938) diff --git a/kernel/drv/oss_sbpci/.params b/kernel/drv/oss_sbpci/.params new file mode 100644 index 0000000..5d4d7b5 --- /dev/null +++ b/kernel/drv/oss_sbpci/.params @@ -0,0 +1,12 @@ +int apci_latency=0; +/* + * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit + * garbled audio in some cases and setting the latency to higer values fixes it + * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios) + */ + +int apci_spdif=0; +/* + * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models + * Values: 1=Enable 0=Disable Default: 0 + */ diff --git a/kernel/drv/oss_sbpci/oss_sbpci.c b/kernel/drv/oss_sbpci/oss_sbpci.c new file mode 100644 index 0000000..c4bea9f --- /dev/null +++ b/kernel/drv/oss_sbpci/oss_sbpci.c @@ -0,0 +1,1404 @@ +/* + * Purpose: Creative/Ensoniq AudioPCI97 driver (ES1371/ES1373) + * + * This driver is used with the original Ensoniq AudioPCI97 card and many + * PCI based Sound Blaster cards by Creative Technologies. For example + * Sound Blaster PCI128 and Creative/Ectiva EV1938. + */ +/* + * + * 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_sbpci_cfg.h" +#include "midi_core.h" +#include "sbpci.h" +#include "ac97.h" +#include "oss_pci.h" + + +extern int apci_latency; +extern int apci_spdif; + +#define ENSONIQ_VENDOR_ID 0x1274 +#define ECTIVA_VENDOR_ID 0x1102 +#define ENSONIQ_ES1371 0x1371 +#define ENSONIQ_ES5880 0x8001 +#define ENSONIQ_ES5880A 0x8002 +#define ENSONIQ_ES5880B 0x5880 +#define ECTIVA_ES1938 0x8938 + +#define MAX_PORTC 2 + +typedef struct apci97_portc +{ + + /* Audio parameters */ + int audiodev; + int open_mode; + int trigger_bits; + int audio_enabled; + int speed, bits, channels; + int atype; /* 0=DAC/ADC, 1=Synth */ +} +apci97_portc; + +typedef struct apci97_devc +{ + oss_device_t *osdev; + oss_mutex_t mutex, low_mutex; + oss_native_word base; + int irq; + char *chip_name; + int revision; + + apci97_portc portc[MAX_PORTC]; +/* + * Mixer + */ + ac97_devc ac97devc; + +/* + * MIDI + */ + int midi_opened; + int midi_dev; + oss_midi_inputbyte_t midi_input_intr; +} +apci97_devc; + + +void SRCRegWrite (apci97_devc * devc, unsigned short reg, unsigned short val); +void SRCSetRate (apci97_devc * devc, unsigned char base, unsigned short rate); + + +static int +ac97_read (void *devc_, int wAddr) +{ + apci97_devc *devc = devc_; + int i, dtemp, dinit; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + dtemp = INL (devc->osdev, devc->base + CONC_dCODECCTL_OFF); + /* wait for WIP to go away saving the current state for later */ + for (i = 0; i < 0x100UL; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dCODECCTL_OFF) & (1UL << 30))) + break; + + /* write addr w/data=0 and assert read request ... */ + + /* save the current state for later */ + dinit = INL (devc->osdev, devc->base + CONC_dSRCIO_OFF); + + /* enable SRC state data in SRC mux */ + for (i = 0; i < 0x100UL; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + OUTL (devc->osdev, (dtemp & SRC_CTLMASK) | 0x00010000UL, + devc->base + CONC_dSRCIO_OFF); + + /* wait for a SAFE time to write a read request and then do it, dammit */ + + for (i = 0; i < 0x100UL; ++i) + { + if ((INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & 0x00070000UL) == + 0x00010000UL) + break; + } + + OUTL (devc->osdev, + ((int) wAddr << 16) | (1UL << 23), devc->base + CONC_dCODECCTL_OFF); + + /* restore SRC reg */ + for (i = 0; i < 0x100UL; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + OUTL (devc->osdev, dinit, devc->base + CONC_dSRCIO_OFF); + + /* now wait for the stinkin' data (RDY) */ + for (i = 0; i < 0x100UL; ++i) + if (INL (devc->osdev, devc->base + CONC_dCODECCTL_OFF) & (1UL << 31)) + break; + dtemp = INL (devc->osdev, devc->base + CONC_dCODECCTL_OFF); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dtemp & 0xffff; +} + +static int +ac97_write (void *devc_, int wAddr, int wData) +{ + apci97_devc *devc = devc_; + int i, dtemp, dinit; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + /* wait for WIP to go away */ + for (i = 0; i < 0x100UL; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dCODECCTL_OFF) & (1UL << 30))) + break; + + /* save the current state for later */ + dinit = INL (devc->osdev, devc->base + CONC_dSRCIO_OFF); + + dtemp = INL (devc->osdev, devc->base + CONC_dSRCIO_OFF); + /* enable SRC state data in SRC mux */ + for (i = 0; i < 0x100UL; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + OUTL (devc->osdev, (dtemp & SRC_CTLMASK) | 0x00010000UL, + devc->base + CONC_dSRCIO_OFF); + + /* wait for a SAFE time to write addr/data and then do it, dammit */ + for (i = 0; i < 0x100UL; ++i) + { + if ((INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & 0x00070000UL) == + 0x00010000UL) + break; + } + + OUTL (devc->osdev, ((int) wAddr << 16) | wData, + devc->base + CONC_dCODECCTL_OFF); + + /* restore SRC reg */ + for (i = 0; i < 0x100UL; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_BUSY)) + break; + OUTL (devc->osdev, dinit, devc->base + CONC_dSRCIO_OFF); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return 0; +} + + +void +SRCInit (apci97_devc * devc) +{ + int i; + + /* Clear all SRC RAM then init - keep SRC disabled until done */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_BUSY)) + break; + OUTL (devc->osdev, SRC_DISABLE, devc->base + CONC_dSRCIO_OFF); + + for (i = 0; i < 0x80; ++i) + SRCRegWrite (devc, (unsigned short) i, 0U); + + SRCRegWrite (devc, SRC_SYNTH_BASE + SRC_TRUNC_N_OFF, 16 << 4); + SRCRegWrite (devc, SRC_SYNTH_BASE + SRC_INT_REGS_OFF, 16 << 10); + SRCRegWrite (devc, SRC_DAC_BASE + SRC_TRUNC_N_OFF, 16 << 4); + SRCRegWrite (devc, SRC_DAC_BASE + SRC_INT_REGS_OFF, 16 << 10); + SRCRegWrite (devc, SRC_SYNTH_VOL_L, 1 << 12); + SRCRegWrite (devc, SRC_SYNTH_VOL_R, 1 << 12); + SRCRegWrite (devc, SRC_DAC_VOL_L, 1 << 12); + SRCRegWrite (devc, SRC_DAC_VOL_R, 1 << 12); + SRCRegWrite (devc, SRC_ADC_VOL_L, 1 << 12); + SRCRegWrite (devc, SRC_ADC_VOL_R, 1 << 12); + + /* default some rates */ + SRCSetRate (devc, SRC_SYNTH_BASE, 8000); + SRCSetRate (devc, SRC_DAC_BASE, 8000); + SRCSetRate (devc, SRC_ADC_BASE, 8000); + + /* now enable the whole deal */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_BUSY)) + break; + OUTL (devc->osdev, 0, devc->base + CONC_dSRCIO_OFF); + + return; +} + +unsigned short +SRCRegRead (apci97_devc * devc, unsigned short reg) +{ + int i, dtemp; + + dtemp = INL (devc->osdev, devc->base + CONC_dSRCIO_OFF); + /* wait for ready */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + + /* assert a read request */ + OUTL (devc->osdev, + (dtemp & SRC_CTLMASK) | ((int) reg << 25), + devc->base + CONC_dSRCIO_OFF); + + /* now wait for the data */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + + return (unsigned short) dtemp; +} + + +void +SRCRegWrite (apci97_devc * devc, unsigned short reg, unsigned short val) +{ + int i, dtemp; + int writeval; + + dtemp = INL (devc->osdev, devc->base + CONC_dSRCIO_OFF); + /* wait for ready */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (! + ((dtemp = + INL (devc->osdev, devc->base + CONC_dSRCIO_OFF)) & SRC_BUSY)) + break; + + /* assert the write request */ + writeval = (dtemp & SRC_CTLMASK) | SRC_WENABLE | ((int) reg << 25) | val; + OUTL (devc->osdev, writeval, devc->base + CONC_dSRCIO_OFF); + + return; +} + +typedef struct +{ + unsigned char base; + unsigned short rate; +} +SRC_RATE_REC; + +#define SRC_RATE_RECS (3) +SRC_RATE_REC theSRCRates[SRC_RATE_RECS] = { + {SRC_SYNTH_BASE, 0}, + {SRC_DAC_BASE, 0}, + {SRC_ADC_BASE, 0} +}; + +/*ARGSUSED*/ +unsigned short +SRCGetRate (apci97_devc * devc, unsigned char base) +{ + unsigned short i; + + for (i = 0; i < SRC_RATE_RECS; i++) + if (theSRCRates[i].base == base) + return theSRCRates[i].rate; + + return 0; +} + +void +SRCSetRate (apci97_devc * devc, unsigned char base, unsigned short rate) +{ + int i, freq, dtemp; + unsigned short N, truncM, truncStart; + + + for (i = 0; i < SRC_RATE_RECS; i++) + if (theSRCRates[i].base == base) + { + theSRCRates[i].rate = rate; + break; + } + + if (base != SRC_ADC_BASE) + { + /* freeze the channel */ + dtemp = base == SRC_SYNTH_BASE ? SRC_SYNTHFREEZE : SRC_DACFREEZE; + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_BUSY)) + break; + OUTL (devc->osdev, + (INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_CTLMASK) | + dtemp, devc->base + CONC_dSRCIO_OFF); + + /* calculate new frequency and write it - preserve accum */ + freq = ((int) rate << 16) / 3000U; + SRCRegWrite (devc, (unsigned short) base + SRC_INT_REGS_OFF, + (SRCRegRead + (devc, + (unsigned short) base + + SRC_INT_REGS_OFF) & 0x00ffU) | ((unsigned short) (freq >> + 6) & + 0xfc00)); + SRCRegWrite (devc, (unsigned short) base + SRC_VFREQ_FRAC_OFF, + (unsigned short) freq >> 1); + + /* un-freeze the channel */ + for (i = 0; i < SRC_IOPOLL_COUNT; ++i) + if (!(INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_BUSY)) + break; + OUTL (devc->osdev, + (INL (devc->osdev, devc->base + CONC_dSRCIO_OFF) & SRC_CTLMASK) & + ~dtemp, devc->base + CONC_dSRCIO_OFF); + } + else + { + /* derive oversample ratio */ + N = rate / 3000U; + if (N == 15 || N == 13 || N == 11 || N == 9) + --N; + + /* truncate the filter and write n/trunc_start */ + truncM = (21 * N - 1) | 1; + if (rate >= 24000U) + { + if (truncM > 239) + truncM = 239; + truncStart = (239 - truncM) >> 1; + + SRCRegWrite (devc, base + SRC_TRUNC_N_OFF, + (truncStart << 9) | (N << 4)); + } + else + { + if (truncM > 119) + truncM = 119; + truncStart = (119 - truncM) >> 1; + + SRCRegWrite (devc, base + SRC_TRUNC_N_OFF, + 0x8000U | (truncStart << 9) | (N << 4)); + } + + /* calculate new frequency and write it - preserve accum */ + freq = ((48000UL << 16) / rate) * N; + SRCRegWrite (devc, base + SRC_INT_REGS_OFF, + (SRCRegRead + (devc, + (unsigned short) base + + SRC_INT_REGS_OFF) & 0x00ff) | ((unsigned short) (freq >> + 6) & + 0xfc00)); + SRCRegWrite (devc, base + SRC_VFREQ_FRAC_OFF, + (unsigned short) freq >> 1); + + SRCRegWrite (devc, SRC_ADC_VOL_L, N << 8); + SRCRegWrite (devc, SRC_ADC_VOL_R, N << 8); + + } + + return; +} + +static void +apci97_writemem (apci97_devc * devc, int page, int offs, int data) +{ + int tmp; + + tmp = INL (devc->osdev, devc->base + 0xc); + OUTL (devc->osdev, page, devc->base + 0xc); /* Select memory page */ + OUTL (devc->osdev, data, devc->base + offs); + OUTL (devc->osdev, tmp, devc->base + 0xc); /* Select the original memory page */ +} + +static unsigned int +apci97_readmem (apci97_devc * devc, int page, int offs) +{ + unsigned int val; + + OUTL (devc->osdev, page, devc->base + 0xc); /* Select memory page */ + val = INL (devc->osdev, devc->base + offs); + return val; +} + +static int +apci97intr (oss_device_t * osdev) +{ + int stats, i; + int tmp; + unsigned char ackbits = 0; + unsigned char uart_stat; + apci97_devc *devc = (apci97_devc *) osdev->devc; + apci97_portc *portc; + int served = 0; + + stats = INL (devc->osdev, devc->base + 0x04); + /*cmn_err (CE_WARN, "AudioPCI97 intr status %08x\n", stats); */ + + if (!(stats & 0x80000000)) /* No interrupt pending */ + return served; + + served = 1; + + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if (stats & 0x00000010) /* CCB interrupt */ + { + cmn_err (CE_WARN, "CCB interrupt\n"); + } + + if ((stats & 0x00000004) && (portc->atype)) /* DAC1 (synth) interrupt */ + { + ackbits |= CONC_SERCTL_DAC1IE; + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + oss_audio_outputintr (portc->audiodev, 0); + + } + + if ((stats & 0x00000002) && (!portc->atype)) /* DAC2 interrupt */ + { + ackbits |= CONC_SERCTL_DAC2IE; + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + oss_audio_outputintr (portc->audiodev, 0); + } + + if ((stats & 0x00000001) && (!portc->atype)) /* ADC interrupt */ + { + ackbits |= CONC_SERCTL_ADCIE; + if (portc->trigger_bits & PCM_ENABLE_INPUT) + { + oss_audio_inputintr (portc->audiodev, 0); + } + } + + if (stats & 0x00000008) /* UART interrupt */ + { + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + + while (uart_stat & CONC_UART_RXRDY) + { + unsigned char d; + d = INB (devc->osdev, devc->base + CONC_bUARTDATA_OFF); + + if (devc->midi_opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr (devc->midi_dev, d); + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + } + + } + /* Ack the interrupt */ + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + OUTB (devc->osdev, (tmp & ~ackbits), devc->base + CONC_bSERCTL_OFF); /* Clear bits */ + OUTB (devc->osdev, tmp | ackbits, devc->base + CONC_bSERCTL_OFF); /* Return them back on */ + } + + return served; +} + +/* + * Audio routines + */ + +static int +apci97_audio_set_rate (int dev, int arg) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +apci97_audio_set_channels (int dev, short arg) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +apci97_audio_set_format (int dev, unsigned int arg) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +apci97_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void apci97_audio_trigger (int dev, int state); + +static void +apci97_audio_reset (int dev) +{ + apci97_audio_trigger (dev, 0); +} + +static void +apci97_audio_reset_input (int dev) +{ + apci97_portc *portc = audio_engines[dev]->portc; + apci97_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +apci97_audio_reset_output (int dev) +{ + apci97_portc *portc = audio_engines[dev]->portc; + apci97_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +apci97_audio_open (int dev, int mode, int open_flags) +{ + apci97_portc *portc = audio_engines[dev]->portc; + apci97_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; + } + portc->open_mode = mode; + portc->audio_enabled = ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +apci97_audio_close (int dev, int mode) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + apci97_audio_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +apci97_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + +} + +/*ARGSUSED*/ +static void +apci97_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + apci97_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +apci97_audio_trigger (int dev, int state) +{ + apci97_devc *devc = audio_engines[dev]->devc; + apci97_portc *portc = audio_engines[dev]->portc; + int tmp; + oss_native_word flags; + + 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->atype) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_DAC1_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + } + else + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_DAC2_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + } + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + if (portc->atype) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_DAC1_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_DAC1IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + else + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_DAC2_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_DAC2IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + + } + } + } + } + + if ((portc->open_mode & OPEN_READ) + && !(audio_engines[dev]->flags & ADEV_NOINPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp |= CONC_DEVCTL_ADC_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF); + tmp &= ~CONC_DEVCTL_ADC_EN; + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF); + tmp &= ~CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +apci97_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + dmap_t *dmap = audio_engines[dev]->dmap_in; + apci97_devc *devc = audio_engines[dev]->devc; + apci97_portc *portc = audio_engines[dev]->portc; + int tmp = 0x00; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + /* Set physical address of the DMA buffer */ + + apci97_writemem (devc, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF, + dmap->dmabuf_phys); + + /* Set ADC rate */ + SRCSetRate (devc, SRC_ADC_BASE, portc->speed); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~(CONC_PCM_ADC_STEREO | CONC_PCM_ADC_16BIT); + if (portc->channels == 2) + tmp |= CONC_PCM_ADC_STEREO; + if (portc->bits == 16) + { + tmp |= CONC_PCM_ADC_16BIT; + OUTB (devc->osdev, 0x10, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + else + { + OUTB (devc->osdev, 0x08, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + /* Set the frame count */ + apci97_writemem (devc, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wADCIC_OFF); + + /* Enable the wave interrupt */ + tmp = INB (devc->osdev, devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_ADCIE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +apci97_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + dmap_t *dmap = audio_engines[dev]->dmap_out; + apci97_devc *devc = audio_engines[dev]->devc; + apci97_portc *portc = audio_engines[dev]->portc; + int tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (devc->revision >= 4) + { + /* set SPDIF to PCM mode */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x1c) & ~0x2, + devc->base + 0x1c); + if (portc->bits & AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + portc->speed = 48000; + /* set S/PDIF to AC3 Mode */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x1c) | 0x2, + devc->base + 0x1c); + } + } + + if (portc->atype) + { + /* Set physical address of the DMA buffer */ + apci97_writemem (devc, CONC_SYNCTL_PAGE, CONC_dSYNPADDR_OFF, + dmap->dmabuf_phys); + + /* Set DAC1 rate */ + SRCSetRate (devc, SRC_SYNTH_BASE, portc->speed); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~((CONC_PCM_DAC_STEREO | CONC_PCM_DAC_16BIT) >> 2); + if (portc->channels == 2) + tmp |= (CONC_PCM_DAC_STEREO >> 2); + if (portc->bits == 16) + { + tmp |= (CONC_PCM_DAC_16BIT >> 2); + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + /* Set the frame count */ + apci97_writemem (devc, CONC_SYNCTL_PAGE, CONC_wSYNFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wSYNIC_OFF); + + /* Enable the wave interrupt */ + tmp = + INB (devc->osdev, + devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_DAC1IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_DAC1IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + + } + else + { + /* Set physical address of the DMA buffer */ + apci97_writemem (devc, CONC_DACCTL_PAGE, CONC_dDACPADDR_OFF, + dmap->dmabuf_phys); + + /* Set DAC rate */ + SRCSetRate (devc, SRC_DAC_BASE, portc->speed); + + /* Set format */ + tmp = INB (devc->osdev, devc->base + CONC_bSERFMT_OFF); + tmp &= ~(CONC_PCM_DAC_STEREO | CONC_PCM_DAC_16BIT); + if (portc->channels == 2) + tmp |= CONC_PCM_DAC_STEREO; + if (portc->bits == 16) + { + tmp |= CONC_PCM_DAC_16BIT; + OUTB (devc->osdev, 0x10, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + else + { + OUTB (devc->osdev, 0x08, devc->base + CONC_bSKIPC_OFF); /* Skip count register */ + } + OUTB (devc->osdev, tmp, devc->base + CONC_bSERFMT_OFF); + + + /* Set the frame count */ + apci97_writemem (devc, CONC_DACCTL_PAGE, CONC_wDACFC_OFF, + (dmap->bytes_in_use / 4) - 1); + + /* Set # of samples between interrupts */ + OUTW (devc->osdev, + (dmap->fragment_size / ((portc->channels * portc->bits) / 8)) - 1, + devc->base + CONC_wDACIC_OFF); + + /* Enable the wave interrupt */ + tmp = + INB (devc->osdev, + devc->base + CONC_bSERCTL_OFF) & ~CONC_SERCTL_DAC2IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + tmp |= CONC_SERCTL_DAC2IE; + OUTB (devc->osdev, tmp, devc->base + CONC_bSERCTL_OFF); + } + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +apci97_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + apci97_devc *devc = audio_engines[dev]->devc; + apci97_portc *portc = audio_engines[dev]->portc; + int ptr = 0, port = 0, page = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + if (portc->atype) + { + port = CONC_wSYNFC_OFF; + page = CONC_SYNCTL_PAGE; + } + else + { + port = CONC_wDACFC_OFF; + page = CONC_DACCTL_PAGE; + } + } + + if (direction == PCM_ENABLE_INPUT) + { + port = CONC_wADCFC_OFF; + page = CONC_ADCCTL_PAGE; + } + + ptr = apci97_readmem (devc, page, port); + ptr >>= 16; + ptr <<= 2; /* count is in dwords */ + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return ptr; +} + +audiodrv_t apci97_audio_driver = { + apci97_audio_open, + apci97_audio_close, + apci97_audio_output_block, + apci97_audio_start_input, + apci97_audio_ioctl, + apci97_audio_prepare_for_input, + apci97_audio_prepare_for_output, + apci97_audio_reset, + NULL, + NULL, + apci97_audio_reset_input, + apci97_audio_reset_output, + apci97_audio_trigger, + apci97_audio_set_rate, + apci97_audio_set_format, + apci97_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* apci97_alloc_buffer */ + NULL, /* apci97_free_buffer */ + NULL, + NULL, + apci97_get_buffer_pointer +}; + +/*ARGSUSED*/ +static int +apci97_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + apci97_devc *devc = (apci97_devc *) midi_devs[dev]->devc; + + if (devc->midi_opened) + { + return OSS_EBUSY; + } + + devc->midi_input_intr = inputbyte; + devc->midi_opened = mode; + + if (mode & OPEN_READ) + { + OUTB (devc->osdev, CONC_UART_RXINTEN, devc->base + CONC_bUARTCSTAT_OFF); + } + + return 0; +} + +/*ARGSUSED*/ +static void +apci97_midi_close (int dev, int mode) +{ + apci97_devc *devc = (apci97_devc *) midi_devs[dev]->devc; + + OUTB (devc->osdev, 0x00, devc->base + CONC_bUARTCSTAT_OFF); + devc->midi_opened = 0; +} + +static int +apci97_midi_out (int dev, unsigned char midi_byte) +{ + apci97_devc *devc = (apci97_devc *) midi_devs[dev]->devc; + int i; + + unsigned char uart_stat = + INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + + i = 0; + while (i < 1000000 && !(uart_stat & CONC_UART_TXRDY)) + { + uart_stat = INB (devc->osdev, devc->base + CONC_bUARTCSTAT_OFF); + i++; + } + + if (!(uart_stat & CONC_UART_TXRDY)) + return 0; + + + OUTB (devc->osdev, midi_byte, devc->base + CONC_bUARTDATA_OFF); + + return 1; +} + +/*ARGSUSED*/ +static int +apci97_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t apci97_midi_driver = { + apci97_midi_open, + apci97_midi_close, + apci97_midi_ioctl, + apci97_midi_out +}; + +static int +apci97_control (int dev, int ctrl, unsigned int cmd, int value) +{ + apci97_devc *devc = mixer_devs[dev]->hw_devc; + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case 1: /* Speaker Mode */ + value = (INL (devc->osdev, devc->base + 4) & (1 << 26) ? 1 : 0); + break; + + case 2: /* Dual Dac Mode */ + value = INL (devc->osdev, devc->base + 4) & (1 << 27) ? 1 : 0; + break; + } + } + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: /* Front/Rear Mirror */ + if (value) + { + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 4) | (1 << 26), + devc->base + 4); + } + else + { + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 4) & ~(1 << 26), + devc->base + 4); + } + break; + + case 2: /* DAC1->Front DAC2->REAR */ + if (value) + { + /* disable front/rear mirroring */ + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 4) & ~(1 << 26), + devc->base + 4); + /* Enable Dual Dac mode */ + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 4) | (1 << 27) | (1 << 24), + devc->base + 4); + } + else + { + /* enable mirror */ + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 4) | (1 << 26), + devc->base + 4); + /* disable dual dac */ + OUTL (devc->osdev, + INL (devc->osdev, + devc->base + 4) & ~((1 << 27) | (1 << 24)), + devc->base + 4); + } + break; + } + } + return value; +} + +static int +apci97_mix_init (int dev) +{ + int group, err; + + if ((group = mixer_ext_create_group (dev, 0, "MIXEXT")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 1, apci97_control, + MIXT_ENUM, "SPKMODE", 2, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 2, apci97_control, + MIXT_ONOFF, "DUALDAC", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + return 0; + +} + +static int +init_apci97 (apci97_devc * devc, int device_id) +{ + int my_mixer; + int tmp, i; + int first_dev = 0; + + if ((device_id == ENSONIQ_ES5880) || (device_id == ENSONIQ_ES5880A) || + (device_id == ENSONIQ_ES5880B) || + (device_id == 0x1371 && devc->revision == 7) || + (device_id == 0x1371 && devc->revision >= 9)) + { + int i; + + /* Have a ES5880 so enable the codec manually */ + tmp = INB (devc->osdev, devc->base + CONC_bINTSUMM_OFF) & 0xff; + tmp |= 0x20; + OUTB (devc->osdev, tmp, devc->base + CONC_bINTSUMM_OFF); /* OUTB? */ + for (i = 0; i < 2000; i++) + oss_udelay (10); + } + + SRCInit (devc); +#if 0 + OUTB (devc->osdev, 0x00, devc->base + CONC_bSERCTL_OFF); + OUTB (devc->osdev, 0x00, devc->base + CONC_bNMIENA_OFF); /* NMI off */ + OUTB (devc->osdev, 0x00, devc->base + CONC_wNMISTAT_OFF); /* OUTB? */ +#endif +/* + * Turn on UART and CODEC + */ + tmp = INL (devc->osdev, devc->base + CONC_bDEVCTL_OFF) & 0xff; + tmp &= ~(CONC_DEVCTL_PCICLK_DS | CONC_DEVCTL_XTALCLK_DS); + OUTB (devc->osdev, tmp | CONC_DEVCTL_UART_EN | CONC_DEVCTL_JSTICK_EN, + devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, 0x00, devc->base + CONC_bUARTCSTAT_OFF); + + /* Perform AC97 codec warm reset */ + tmp = INB (devc->osdev, devc->base + CONC_bMISCCTL_OFF) & 0xff; + OUTB (devc->osdev, tmp | CONC_MISCCTL_SYNC_RES, + devc->base + CONC_bMISCCTL_OFF); + oss_udelay (200); + OUTB (devc->osdev, tmp, devc->base + CONC_bMISCCTL_OFF); + oss_udelay (200); + +/* + * Enable S/PDIF + */ + if (devc->revision >= 4) + { + if (apci_spdif) + { + /* enable SPDIF */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x04) | (1 << 18), + devc->base + 0x04); + /* SPDIF out = data from DAC */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 0x00) | (1 << 26), + devc->base + 0x00); + } + else + { + /* disable spdif out */ + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 0x04) & ~(1 << 18), + devc->base + 0x04); + OUTL (devc->osdev, + INL (devc->osdev, devc->base + 0x00) & ~(1 << 26), + devc->base + 0x00); + } + } + +/* + * Init mixer + */ + my_mixer = + ac97_install (&devc->ac97devc, "AC97 Mixer", ac97_read, ac97_write, devc, + devc->osdev); + + if (my_mixer < 0) + return 0; + + if (devc->revision >= 4) + { + /* enable 4 speaker mode */ + OUTL (devc->osdev, INL (devc->osdev, devc->base + 4) | (1 << 26), + devc->base + 4); + mixer_ext_set_init_fn (my_mixer, apci97_mix_init, 5); + } + + for (i = 0; i < MAX_PORTC; i++) + { + + int adev; + char tmp_name[100]; + apci97_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + int fmts = AFMT_U8 | AFMT_S16_LE; + + if (devc->revision >= 4) + fmts |= AFMT_AC3; + + if (i == 0) + { + sprintf (tmp_name, "%s (rev %d)", devc->chip_name, devc->revision); + caps |= ADEV_DUPLEX; + } + else + { + sprintf (tmp_name, "%s (playback only)", devc->chip_name); + caps |= ADEV_NOINPUT; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &apci97_audio_driver, + sizeof (audiodrv_t), + caps, fmts, devc, -1)) < 0) + { + adev = -1; + return 0; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + 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->atype = i; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + + audio_engines[adev]->mixer_dev = my_mixer; + } + + if ((devc->midi_dev = oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "APCI97", "APCI97 UART", &apci97_midi_driver, sizeof (midi_driver_t), + 0, devc, devc->osdev)) < 0) + { + cmn_err (CE_WARN, "Couldn't install MIDI device\n"); + return 0; + } + + devc->midi_opened = 0; + return 1; +} + +int +oss_sbpci_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + apci97_devc *devc; + int err; + + DDB (cmn_err (CE_WARN, "Entered AudioPCI97 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if ((vendor != ENSONIQ_VENDOR_ID && vendor != ECTIVA_VENDOR_ID) || + (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 && + device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 && + device != ENSONIQ_ES5880B)) + + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr); + + + if (pci_irq_line == 0) + { + cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d). Can't continue\n", + pci_irq_line); + return 0; + } + + if (pci_ioaddr == 0) + { + cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n"); + 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; + + switch (device) + { + case ENSONIQ_ES1371: + devc->chip_name = "Creative AudioPCI97 (ES1371)"; + break; + case ECTIVA_ES1938: + devc->chip_name = "Ectiva AudioPCI"; + break; + case ENSONIQ_ES5880: + case ENSONIQ_ES5880A: + case ENSONIQ_ES5880B: + devc->chip_name = "Sound Blaster PCI128"; + break; + default: + devc->chip_name = "AudioPCI97"; + } + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + /* Remove I/O space marker in bit 0. */ + devc->base &= ~3; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + /* set the PCI latency to 32 */ + if ((apci_latency == 32) || (apci_latency == 64) || (apci_latency == 96) || + (apci_latency == 128)) + pci_write_config_byte (osdev, 0x0d, apci_latency); + + + + oss_register_device (osdev, devc->chip_name); + + if ((err = oss_register_interrupts (osdev, 0, apci97intr, NULL)) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err); + return 0; + } + + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1); + + + devc->revision = pci_revision; + return init_apci97 (devc, device); /* Detected */ +} + +int +oss_sbpci_detach (oss_device_t * osdev) +{ + apci97_devc *devc = (apci97_devc *) osdev->devc; + int tmp; + + if (oss_disable_device (osdev) < 0) + return 0; + + tmp = INB (devc->osdev, devc->base + CONC_bDEVCTL_OFF) & + ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + OUTB (devc->osdev, tmp, devc->base + CONC_bDEVCTL_OFF); + + 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/kernel/drv/oss_sbpci/oss_sbpci.man b/kernel/drv/oss_sbpci/oss_sbpci.man new file mode 100644 index 0000000..2e03556 --- /dev/null +++ b/kernel/drv/oss_sbpci/oss_sbpci.man @@ -0,0 +1,39 @@ +NAME +oss_sbpci - Creative Labs ES1371 audio driver. + +DESCRIPTION +Open Sound System driver for Creative Labs ES1371/ES1373/5880, Ectiva 1938 +audio controllers. + +APCI97 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate + + APCI97 MIXER EXTENSIONS + +Dual Dac mode: This feature turns the APCI97 into two output devices with +the output going to front and rear speakers independantly (however volume +control is global). + +Speaker Mode: This feature allows you to either have the audio coming out +the front speakers or you can have audio duplicated on rear speakers. This +mode is disabled when Dual Dac mode is enabled. + +SPDIF: This button enables or disables SPDIF output. + +OPTIONS +o apci97_latency=<NNN> +Certain models of the ES1371 sound devices will sound distorted playing stereo +audio and setting the PCI latency fixes the problem + +o apci_spdif=0|1 +Certain models like the SB 4.1D/SB PCI128D have SPDIF output jacks and +this setting enables the output device. + +FILES +CONFIGFILEPATH/oss_sbpci.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_sbpci/sbpci.h b/kernel/drv/oss_sbpci/sbpci.h new file mode 100644 index 0000000..4c2803a --- /dev/null +++ b/kernel/drv/oss_sbpci/sbpci.h @@ -0,0 +1,181 @@ +/* + * Purpose: Definitions for the Creative/Ensoniq AudioPCI97 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. + * + */ + +#ifndef ES1371_H +#define ES1371_H + +/* CONCERT PCI-SIG defines */ +#define CONC_PCI_VENDID 0x1274U +#define CONC_PCI_DEVID 0x1371U + + +/* Concert97 direct register offset defines */ +#define CONC_bDEVCTL_OFF 0x00 /* Device control/enable */ +#define CONC_bMISCCTL_OFF 0x01 /* Miscellaneous control */ +#define CONC_bGPIO_OFF 0x02 /* General purpose I/O control */ +#define CONC_bJOYCTL_OFF 0x03 /* Joystick control (decode) */ +#define CONC_dSTATUS_OFF 0x04 /* long status register */ +#define CONC_bINTSTAT_OFF 0x04 /* Device interrupt status */ +#define CONC_bCODECSTAT_OFF 0x05 /* CODEC interface status */ +#define CONC_bINTSUMM_OFF 0x07 /* Interrupt summary status */ +#define CONC_bUARTDATA_OFF 0x08 /* UART data R/W - read clears RX int */ +#define CONC_bUARTCSTAT_OFF 0x09 /* UART control and status */ +#define CONC_bUARTTEST_OFF 0x0a /* UART test control reg */ +#define CONC_bMEMPAGE_OFF 0x0c /* Memory page select */ +#define CONC_dSRCIO_OFF 0x10 /* I/O ctl/stat/data for SRC RAM */ +#define CONC_dCODECCTL_OFF 0x14 /* CODEC control - dword read/write */ +#define CONC_wNMISTAT_OFF 0x18 /* Legacy NMI status */ +#define CONC_bNMIENA_OFF 0x1a /* Legacy NMI enable */ +#define CONC_bNMICTL_OFF 0x1b /* Legacy control */ +#define CONC_bSERFMT_OFF 0x20 /* Serial device control */ +#define CONC_bSERCTL_OFF 0x21 /* Serial device format */ +#define CONC_bSKIPC_OFF 0x22 /* DAC skip count reg */ +#define CONC_wSYNIC_OFF 0x24 /* Synth int count in sample frames */ +#define CONC_wSYNCIC_OFF 0x26 /* Synth current int count */ +#define CONC_wDACIC_OFF 0x28 /* DAC int count in sample frames */ +#define CONC_wDACCIC_OFF 0x2a /* DAC current int count */ +#define CONC_wADCIC_OFF 0x2c /* ADC int count in sample frames */ +#define CONC_wADCCIC_OFF 0x2e /* ADC current int count */ +#define CONC_MEMBASE_OFF 0x30 /* Memory window base - 16 byte window */ + +/* Concert memory page-banked register offset defines */ +#define CONC_dSYNPADDR_OFF 0x30 /* Synth host frame PCI phys addr */ +#define CONC_wSYNFC_OFF 0x34 /* Synth host frame count in DWORDS */ +#define CONC_wSYNCFC_OFF 0x36 /* Synth host current frame count */ +#define CONC_dDACPADDR_OFF 0x38 /* DAC host frame PCI phys addr */ +#define CONC_wDACFC_OFF 0x3c /* DAC host frame count in DWORDS */ +#define CONC_wDACCFC_OFF 0x3e /* DAC host current frame count */ +#define CONC_dADCPADDR_OFF 0x30 /* ADC host frame PCI phys addr */ +#define CONC_wADCFC_OFF 0x34 /* ADC host frame count in DWORDS */ +#define CONC_wADCCFC_OFF 0x36 /* ADC host current frame count */ + +/* Concert memory page number defines */ +#define CONC_SYNRAM_PAGE 0x00 /* Synth host/serial I/F RAM */ +#define CONC_DACRAM_PAGE 0x04 /* DAC host/serial I/F RAM */ +#define CONC_ADCRAM_PAGE 0x08 /* ADC host/serial I/F RAM */ +#define CONC_SYNCTL_PAGE 0x0c /* Page bank for synth host control */ +#define CONC_DACCTL_PAGE 0x0c /* Page bank for DAC host control */ +#define CONC_ADCCTL_PAGE 0x0d /* Page bank for ADC host control */ +#define CONC_FIFO0_PAGE 0x0e /* page 0 of UART "FIFO" (rx stash) */ +#define CONC_FIFO1_PAGE 0x0f /* page 1 of UART "FIFO" (rx stash) */ + +/* PCM format defines */ +#define CONC_PCM_DAC_STEREO 0x04 +#define CONC_PCM_DAC_16BIT 0x08 +#define CONC_PCM_DAC_MASK 0xf3 +#define CONC_PCM_ADC_STEREO 0x10 +#define CONC_PCM_ADC_16BIT 0x20 +#define CONC_PCM_ADC_MASK 0xcf + +/* Device Control defines */ +#define CONC_DEVCTL_PCICLK_DS 0x01 /* PCI Clock Disable */ +#define CONC_DEVCTL_XTALCLK_DS 0x02 /* Crystal Clock Disable */ +#define CONC_DEVCTL_JSTICK_EN 0x04 /* Joystick Enable */ +#define CONC_DEVCTL_UART_EN 0x08 /* UART Enable */ +#define CONC_DEVCTL_ADC_EN 0x10 /* ADC Enable (record) */ +#define CONC_DEVCTL_DAC2_EN 0x20 /* DAC2 Enable (playback) */ +#define CONC_DEVCTL_DAC1_EN 0x40 /* DAC1 Enabale (synth) */ + +/* Misc Control defines */ +#define CONC_MISCCTL_PDLEV_D0 0x00 /* These bits reflect the */ +#define CONC_MISCCTL_PDLEV_D1 0x01 /* power down state of */ +#define CONC_MISCCTL_PDLEV_D2 0x02 /* the part */ +#define CONC_MISCCTL_PDLEV_D3 0x03 /* */ +#define CONC_MISCCTL_CCBINTRM_EN 0x04 /* CCB module interrupt mask */ + +#define CONC_MISCCTL_SYNC_RES 0x40 /* for AC97 warm reset */ + +/* Serial Control defines */ +#define CONC_SERCTL_DAC1IE 0x01 /* playback interrupt enable P1_INT_EN */ +#define CONC_SERCTL_DAC2IE 0x02 /* playback interrupt enable P2_INT_EN */ +#define CONC_SERCTL_ADCIE 0x04 /* record interrupt enable R1_INT_EN */ +#define CONC_SERCTL_DACPAUSE 0x10 /* playback pause */ +#define CONC_SERCTL_R1LOOP 0x80 +#define CONC_SERCTL_P2LOOP 0x40 +#define CONC_SERCTL_P1LOOP 0x20 + +/* Interrupt Status defines */ +#define CONC_INTSTAT_ADCINT 0x01 /* A/D interrupt pending bit */ +#define CONC_INTSTAT_DAC2INT 0x02 /* DAC2 interrupt pending bit */ +#define CONC_INTSTAT_DAC1INT 0x04 /* DAC1 interrupt pending bit */ +#define CONC_INTSTAT_UARTINT 0x08 /* UART interrupt pending bit */ +#define CONC_INTSTAT_PENDING 0x80000000 /* this bit set high while'st we have an interrupt */ +/* DEVCTL register masks */ +/*#define CONC_DEVCTL_D1EN 0x40 */ +/*#define CONC_DEVCTL_D2EN 0x20 */ +/*#define CONC_DEVCTL_ADEN 0x10 */ + +/* SERCTL register masks */ +/*#define CONC_SERCTL_P1_INT_EN 0x01 */ +/*#define CONC_SERCTL_P2_INT_EN 0x02 */ +/*#define CONC_SERCTL_R1_INT_EN 0x04 */ + +/* JOYCTL register defines */ +#define CONC_JOYCTL_200 0x00 +#define CONC_JOYCTL_208 0x01 +#define CONC_JOYCTL_210 0x02 +#define CONC_JOYCTL_218 0x03 + + +/* UARTCSTAT register masks */ +#define CONC_UART_RXRDY 0x01 +#define CONC_UART_TXRDY 0x02 +#define CONC_UART_TXINT 0x04 +#define CONC_UART_RXINT 0x80 + +#define CONC_UART_CTL 0x03 +#define CONC_UART_TXINTEN 0x20 +#define CONC_UART_RXINTEN 0x80 + +/* Logical index for each DMA controller on chip - used for */ +/* generic routines that access all DMA controllers */ +#define CONC_SYNTH_DAC 0 +#define CONC_WAVE_DAC 1 +#define CONC_WAVE_ADC 2 + +/* defines for the CONCERT97 Sample Rate Converters */ + +/* register/base equates for the SRC RAM */ +#define SRC_SYNTH_FIFO 0x00 +#define SRC_DAC_FIFO 0x20 +#define SRC_ADC_FIFO 0x40 +#define SRC_ADC_VOL_L 0x6c +#define SRC_ADC_VOL_R 0x6d +#define SRC_SYNTH_BASE 0x70 +#define SRC_DAC_BASE 0x74 +#define SRC_ADC_BASE 0x78 +#define SRC_SYNTH_VOL_L 0x7c +#define SRC_SYNTH_VOL_R 0x7d +#define SRC_DAC_VOL_L 0x7e +#define SRC_DAC_VOL_R 0x7f + +#define SRC_TRUNC_N_OFF 0x00 +#define SRC_INT_REGS_OFF 0x01 +#define SRC_ACCUM_FRAC_OFF 0x02 +#define SRC_VFREQ_FRAC_OFF 0x03 + + +/* miscellaneous control defines */ +/*#define SRC_IOPOLL_COUNT 0x1000UL */ +#define SRC_IOPOLL_COUNT 0x20000UL +#define SRC_WENABLE (1UL << 24) +#define SRC_BUSY (1UL << 23) +#define SRC_DISABLE (1UL << 22) +#define SRC_SYNTHFREEZE (1UL << 21) +#define SRC_DACFREEZE (1UL << 20) +#define SRC_ADCFREEZE (1UL << 19) +#define SRC_CTLMASK 0x00780000UL + +#endif /* ES1371_H */ diff --git a/kernel/drv/oss_sbxfi/.config b/kernel/drv/oss_sbxfi/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_sbxfi/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_sbxfi/.devices b/kernel/drv/oss_sbxfi/.devices new file mode 100644 index 0000000..01f85a4 --- /dev/null +++ b/kernel/drv/oss_sbxfi/.devices @@ -0,0 +1,3 @@ +oss_sbxfi pci1102,5 Creative SB X-Fi 20K1 *EARLY BETA* +oss_sbxfi pci1102,b Creative SB X-Fi 20K2 *EARLY BETA* +#oss_sbxfi pci1102,9 Creative SB X-Fi PCI-e *EARLY BETA* diff --git a/kernel/drv/oss_sbxfi/.name b/kernel/drv/oss_sbxfi/.name new file mode 100644 index 0000000..d63384d --- /dev/null +++ b/kernel/drv/oss_sbxfi/.name @@ -0,0 +1 @@ +Creative Sound Blaster X-Fi diff --git a/kernel/drv/oss_sbxfi/.params b/kernel/drv/oss_sbxfi/.params new file mode 100644 index 0000000..d9df108 --- /dev/null +++ b/kernel/drv/oss_sbxfi/.params @@ -0,0 +1,15 @@ +int sbxfi_type=0; +/* + * Override sbxfi autodetection. + * Values: 0-4. Default: 0 + * 0 - Autodetect + * 1 - Sound Blaster X-Fi (SB046x/067x/076x) + * 2 - Sound Blaster X-Fi (SB073x) + * 3 - Sound Blaster X-Fi (SB055x) + * 4 - Sound Blaster X-Fi (UAA) + * 5 - Sound Blaster X-Fi (SB0760) + * 6 - Sound Blaster X-Fi (SB0880-1) + * 7 - Sound Blaster X-Fi (SB0880-2) + * 8 - Sound Blaster X-Fi (SB0880-3) + */ + diff --git a/kernel/drv/oss_sbxfi/20k1reg.h b/kernel/drv/oss_sbxfi/20k1reg.h new file mode 100644 index 0000000..051c5a0 --- /dev/null +++ b/kernel/drv/oss_sbxfi/20k1reg.h @@ -0,0 +1,911 @@ +/** +******************************************************************************* +Confidential & Proprietary +Private & Confidential +Creative Confidential +******************************************************************************* +*/ +/** +******************************************************************************* +Copyright (C) Creative Technology, Ltd., 2007. All rights reserved. +******************************************************************************* +**/ +#ifndef _201kreg_H +#define _20k1reg_H + + +// PCI config registers +#define PCI_CFGHDR_VENDORID 0x00 +#define PCI_CFGHDR_DEVICEID 0x02 +#define PCI_CFGHDR_CMDREG 0x04 +#define PCI_CFGHDR_STATUSREG 0x06 +#define PCI_CFGHDR_REVID 0x08 +#define PCI_CFGHDR_DEVCLASS 0x09 +#define PCI_CFGHDR_CACHESIZE 0x0C +#define PCI_CFGHDR_LATENCY 0x0D +#define PCI_CFGHDR_HEADERTYPE 0x0E +#define PCI_CFGHDR_BIST 0x0F + +#define PCI_CFGHDR_BASEREG0 0x10 +#define PCI_CFGHDR_BASEREG1 0x14 +#define PCI_CFGHDR_BASEREG2 0x18 +#define PCI_CFGHDR_BASEREG3 0x1C +#define PCI_CFGHDR_BASEREG4 0x20 +#define PCI_CFGHDR_BASEREG5 0x24 + +#define PCI_CFGHDR_RESERVED1 0x28 +#define PCI_CFGHDR_SUBVENDORID 0x2C +#define PCI_CFGHDR_SUBSYSTEMID 0x2E +#define PCI_CFGHDR_EXPANDROM 0x30 +#define PCI_CFGHDR_RESERVED2 0x34 +#define PCI_CFGHDR_CAPS_PTR 0x34 + +#define PCI_CFGHDR_IRQLINE 0x3C +#define PCI_CFGHDR_IRQPIN 0x3D +#define PCI_CFGHDR_MINGRANT 0x3E +#define PCI_CFGHDR_MAXLATENCY 0x3F +#define PCI_CFGHDR_LACR1 0x40 +#define PCI_CFGHDR_LACR2 0x41 +#define PCI_CFGHDR_LACR3 0x42 +#define PCI_CFGHDR_LACR4 0x43 + + +// 20k1 registers + +#define DSPXRAM_START 0x000000 +#define DSPXRAM_END 0x013FFC +#define DSPAXRAM_START 0x020000 +#define DSPAXRAM_END 0x023FFC +#define DSPYRAM_START 0x040000 +#define DSPYRAM_END 0x04FFFC +#define DSPAYRAM_START 0x020000 +#define DSPAYRAM_END 0x063FFC +#define DSPMICRO_START 0x080000 +#define DSPMICRO_END 0x0B3FFC +#define DSP0IO_START 0x100000 +#define DSP0IO_END 0x101FFC +#define AUDIORINGIPDSP0_START 0x100000 +#define AUDIORINGIPDSP0_END 0x1003FC +#define AUDIORINGOPDSP0_START 0x100400 +#define AUDIORINGOPDSP0_END 0x1007FC +#define AUDPARARINGIODSP0_START 0x100800 +#define AUDPARARINGIODSP0_END 0x100BFC +#define DSP0LOCALHWREG_START 0x100C00 +#define DSP0LOCALHWREG_END 0x100C3C +#define DSP0XYRAMAGINDEX_START 0x100C40 +#define DSP0XYRAMAGINDEX_END 0x100C5C +#define DSP0XYRAMAGMDFR_START 0x100C60 +#define DSP0XYRAMAGMDFR_END 0x100C7C +#define DSP0INTCONTLVEC_START 0x100C80 +#define DSP0INTCONTLVEC_END 0x100CD8 +#define INTCONTLGLOBALREG_START 0x100D1C +#define INTCONTLGLOBALREG_END 0x100D3C +#define HOSTINTFPORTADDRCONTDSP0 0x100D40 +#define HOSTINTFPORTDATADSP0 0x100D44 +#define TIME0PERENBDSP0 0x100D60 +#define TIME0COUNTERDSP0 0x100D64 +#define TIME1PERENBDSP0 0x100D68 +#define TIME1COUNTERDSP0 0x100D6C +#define TIME2PERENBDSP0 0x100D70 +#define TIME2COUNTERDSP0 0x100D74 +#define TIME3PERENBDSP0 0x100D78 +#define TIME3COUNTERDSP0 0x100D7C +#define XRAMINDOPERREFNOUP_STARTDSP0 0x100D80 +#define XRAMINDOPERREFNOUP_ENDDSP0 0x100D9C +#define XRAMINDOPERREFUP_STARTDSP0 0x100DA0 +#define XRAMINDOPERREFUP_ENDDSP0 0x100DBC +#define YRAMINDOPERREFNOUP_STARTDSP0 0x100DC0 +#define YRAMINDOPERREFNOUP_ENDDSP0 0x100DDC +#define YRAMINDOPERREFUP_STARTDSP0 0x100DE0 +#define YRAMINDOPERREFUP_ENDDSP0 0x100DFC +#define DSP0CONDCODE 0x100E00 +#define DSP0STACKFLAG 0x100E04 +#define DSP0PROGCOUNTSTACKPTREG 0x100E08 +#define DSP0PROGCOUNTSTACKDATAREG 0x100E0C +#define DSP0CURLOOPADDRREG 0x100E10 +#define DSP0CURLOOPCOUNT 0x100E14 +#define DSP0TOPLOOPCOUNTSTACK 0x100E18 +#define DSP0TOPLOOPADDRSTACK 0x100E1C +#define DSP0LOOPSTACKPTR 0x100E20 +#define DSP0STASSTACKDATAREG 0x100E24 +#define DSP0STASSTACKPTR 0x100E28 +#define DSP0PROGCOUNT 0x100E2C +#define GLOBDSPDEBGREG 0x100E30 +#define GLOBDSPBREPTRREG 0x100E30 +#define DSP0XYRAMBASE_START 0x100EA0 +#define DSP0XYRAMBASE_END 0x100EBC +#define DSP0XYRAMLENG_START 0x100EC0 +#define DSP0XYRAMLENG_END 0x100EDC +#define SEMAPHOREREGDSP0 0x100EE0 +#define DSP0INTCONTMASKREG 0x100EE4 +#define DSP0INTCONTPENDREG 0x100EE8 +#define DSP0INTCONTSERVINT 0x100EEC +#define DSPINTCONTEXTINTMODREG 0x100EEC +#define GPIODSP0 0x100EFC +#define DMADSPBASEADDRREG_STARTDSP0 0x100F00 +#define DMADSPBASEADDRREG_ENDDSP0 0x100F1C +#define DMAHOSTBASEADDRREG_STARTDSP0 0x100F20 +#define DMAHOSTBASEADDRREG_ENDDSP0 0x100F3C +#define DMADSPCURADDRREG_STARTDSP0 0x100F40 +#define DMADSPCURADDRREG_ENDDSP0 0x100F5C +#define DMAHOSTCURADDRREG_STARTDSP0 0x100F60 +#define DMAHOSTCURADDRREG_ENDDSP0 0x100F7C +#define DMATANXCOUNTREG_STARTDSP0 0x100F80 +#define DMATANXCOUNTREG_ENDDSP0 0x100F9C +#define DMATIMEBUGREG_STARTDSP0 0x100FA0 +#define DMATIMEBUGREG_ENDDSP0 0x100FAC +#define DMACNTLMODFREG_STARTDSP0 0x100FA0 +#define DMACNTLMODFREG_ENDDSP0 0x100FAC + +#define DMAGLOBSTATSREGDSP0 0x100FEC +#define DSP0XGPRAM_START 0x101000 +#define DSP0XGPRAM_END 0x1017FC +#define DSP0YGPRAM_START 0x101800 +#define DSP0YGPRAM_END 0x101FFC + + + + +#define AUDIORINGIPDSP1_START 0x102000 +#define AUDIORINGIPDSP1_END 0x1023FC +#define AUDIORINGOPDSP1_START 0x102400 +#define AUDIORINGOPDSP1_END 0x1027FC +#define AUDPARARINGIODSP1_START 0x102800 +#define AUDPARARINGIODSP1_END 0x102BFC +#define DSP1LOCALHWREG_START 0x102C00 +#define DSP1LOCALHWREG_END 0x102C3C +#define DSP1XYRAMAGINDEX_START 0x102C40 +#define DSP1XYRAMAGINDEX_END 0x102C5C +#define DSP1XYRAMAGMDFR_START 0x102C60 +#define DSP1XYRAMAGMDFR_END 0x102C7C +#define DSP1INTCONTLVEC_START 0x102C80 +#define DSP1INTCONTLVEC_END 0x102CD8 +#define HOSTINTFPORTADDRCONTDSP1 0x102D40 +#define HOSTINTFPORTDATADSP1 0x102D44 +#define TIME0PERENBDSP1 0x102D60 +#define TIME0COUNTERDSP1 0x102D64 +#define TIME1PERENBDSP1 0x102D68 +#define TIME1COUNTERDSP1 0x102D6C +#define TIME2PERENBDSP1 0x102D70 +#define TIME2COUNTERDSP1 0x102D74 +#define TIME3PERENBDSP1 0x102D78 +#define TIME3COUNTERDSP1 0x102D7C +#define XRAMINDOPERREFNOUP_STARTDSP1 0x102D80 +#define XRAMINDOPERREFNOUP_ENDDSP1 0x102D9C +#define XRAMINDOPERREFUP_STARTDSP1 0x102DA0 +#define XRAMINDOPERREFUP_ENDDSP1 0x102DBC +#define YRAMINDOPERREFNOUP_STARTDSP1 0x102DC0 +#define YRAMINDOPERREFNOUP_ENDDSP1 0x102DDC +#define YRAMINDOPERREFUP_STARTDSP1 0x102DE0 +#define YRAMINDOPERREFUP_ENDDSP1 0x102DFC + +#define DSP1CONDCODE 0x102E00 +#define DSP1STACKFLAG 0x102E04 +#define DSP1PROGCOUNTSTACKPTREG 0x102E08 +#define DSP1PROGCOUNTSTACKDATAREG 0x102E0C +#define DSP1CURLOOPADDRREG 0x102E10 +#define DSP1CURLOOPCOUNT 0x102E14 +#define DSP1TOPLOOPCOUNTSTACK 0x102E18 +#define DSP1TOPLOOPADDRSTACK 0x102E1C +#define DSP1LOOPSTACKPTR 0x102E20 +#define DSP1STASSTACKDATAREG 0x102E24 +#define DSP1STASSTACKPTR 0x102E28 +#define DSP1PROGCOUNT 0x102E2C +#define DSP1XYRAMBASE_START 0x102EA0 +#define DSP1XYRAMBASE_END 0x102EBC +#define DSP1XYRAMLENG_START 0x102EC0 +#define DSP1XYRAMLENG_END 0x102EDC +#define SEMAPHOREREGDSP1 0x102EE0 +#define DSP1INTCONTMASKREG 0x102EE4 +#define DSP1INTCONTPENDREG 0x102EE8 +#define DSP1INTCONTSERVINT 0x102EEC +#define GPIODSP1 0x102EFC +#define DMADSPBASEADDRREG_STARTDSP1 0x102F00 +#define DMADSPBASEADDRREG_ENDDSP1 0x102F1C +#define DMAHOSTBASEADDRREG_STARTDSP1 0x102F20 +#define DMAHOSTBASEADDRREG_ENDDSP1 0x102F3C +#define DMADSPCURADDRREG_STARTDSP1 0x102F40 +#define DMADSPCURADDRREG_ENDDSP1 0x102F5C +#define DMAHOSTCURADDRREG_STARTDSP1 0x102F60 +#define DMAHOSTCURADDRREG_ENDDSP1 0x102F7C +#define DMATANXCOUNTREG_STARTDSP1 0x102F80 +#define DMATANXCOUNTREG_ENDDSP1 0x102F9C +#define DMATIMEBUGREG_STARTDSP1 0x102FA0 +#define DMATIMEBUGREG_ENDDSP1 0x102FAC +#define DMACNTLMODFREG_STARTDSP1 0x102FA0 +#define DMACNTLMODFREG_ENDDSP1 0x102FAC + +#define DMAGLOBSTATSREGDSP1 0x102FEC +#define DSP1XGPRAM_START 0x103000 +#define DSP1XGPRAM_END 0x1033FC +#define DSP1YGPRAM_START 0x103400 +#define DSP1YGPRAM_END 0x1037FC + + + +#define AUDIORINGIPDSP2_START 0x104000 +#define AUDIORINGIPDSP2_END 0x1043FC +#define AUDIORINGOPDSP2_START 0x104400 +#define AUDIORINGOPDSP2_END 0x1047FC +#define AUDPARARINGIODSP2_START 0x104800 +#define AUDPARARINGIODSP2_END 0x104BFC +#define DSP2LOCALHWREG_START 0x104C00 +#define DSP2LOCALHWREG_END 0x104C3C +#define DSP2XYRAMAGINDEX_START 0x104C40 +#define DSP2XYRAMAGINDEX_END 0x104C5C +#define DSP2XYRAMAGMDFR_START 0x104C60 +#define DSP2XYRAMAGMDFR_END 0x104C7C +#define DSP2INTCONTLVEC_START 0x104C80 +#define DSP2INTCONTLVEC_END 0x104CD8 +#define HOSTINTFPORTADDRCONTDSP2 0x104D40 +#define HOSTINTFPORTDATADSP2 0x104D44 +#define TIME0PERENBDSP2 0x104D60 +#define TIME0COUNTERDSP2 0x104D64 +#define TIME1PERENBDSP2 0x104D68 +#define TIME1COUNTERDSP2 0x104D6C +#define TIME2PERENBDSP2 0x104D70 +#define TIME2COUNTERDSP2 0x104D74 +#define TIME3PERENBDSP2 0x104D78 +#define TIME3COUNTERDSP2 0x104D7C +#define XRAMINDOPERREFNOUP_STARTDSP2 0x104D80 +#define XRAMINDOPERREFNOUP_ENDDSP2 0x104D9C +#define XRAMINDOPERREFUP_STARTDSP2 0x104DA0 +#define XRAMINDOPERREFUP_ENDDSP2 0x104DBC +#define YRAMINDOPERREFNOUP_STARTDSP2 0x104DC0 +#define YRAMINDOPERREFNOUP_ENDDSP2 0x104DDC +#define YRAMINDOPERREFUP_STARTDSP2 0x104DE0 +#define YRAMINDOPERREFUP_ENDDSP2 0x104DFC +#define DSP2CONDCODE 0x104E00 +#define DSP2STACKFLAG 0x104E04 +#define DSP2PROGCOUNTSTACKPTREG 0x104E08 +#define DSP2PROGCOUNTSTACKDATAREG 0x104E0C +#define DSP2CURLOOPADDRREG 0x104E10 +#define DSP2CURLOOPCOUNT 0x104E14 +#define DSP2TOPLOOPCOUNTSTACK 0x104E18 +#define DSP2TOPLOOPADDRSTACK 0x104E1C +#define DSP2LOOPSTACKPTR 0x104E20 +#define DSP2STASSTACKDATAREG 0x104E24 +#define DSP2STASSTACKPTR 0x104E28 +#define DSP2PROGCOUNT 0x104E2C +#define DSP2XYRAMBASE_START 0x104EA0 +#define DSP2XYRAMBASE_END 0x104EBC +#define DSP2XYRAMLENG_START 0x104EC0 +#define DSP2XYRAMLENG_END 0x104EDC +#define SEMAPHOREREGDSP2 0x104EE0 +#define DSP2INTCONTMASKREG 0x104EE4 +#define DSP2INTCONTPENDREG 0x104EE8 +#define DSP2INTCONTSERVINT 0x104EEC +#define GPIODSP2 0x104EFC +#define DMADSPBASEADDRREG_STARTDSP2 0x104F00 +#define DMADSPBASEADDRREG_ENDDSP2 0x104F1C +#define DMAHOSTBASEADDRREG_STARTDSP2 0x104F20 +#define DMAHOSTBASEADDRREG_ENDDSP2 0x104F3C +#define DMADSPCURADDRREG_STARTDSP2 0x104F40 +#define DMADSPCURADDRREG_ENDDSP2 0x104F5C +#define DMAHOSTCURADDRREG_STARTDSP2 0x104F60 +#define DMAHOSTCURADDRREG_ENDDSP2 0x104F7C +#define DMATANXCOUNTREG_STARTDSP2 0x104F80 +#define DMATANXCOUNTREG_ENDDSP2 0x104F9C +#define DMATIMEBUGREG_STARTDSP2 0x104FA0 +#define DMATIMEBUGREG_ENDDSP2 0x104FAC +#define DMACNTLMODFREG_STARTDSP2 0x104FA0 +#define DMACNTLMODFREG_ENDDSP2 0x104FAC + +#define DMAGLOBSTATSREGDSP2 0x104FEC +#define DSP2XGPRAM_START 0x105000 +#define DSP2XGPRAM_END 0x1051FC +#define DSP2YGPRAM_START 0x105800 +#define DSP2YGPRAM_END 0x1059FC + + + +#define AUDIORINGIPDSP3_START 0x106000 +#define AUDIORINGIPDSP3_END 0x1063FC +#define AUDIORINGOPDSP3_START 0x106400 +#define AUDIORINGOPDSP3_END 0x1067FC +#define AUDPARARINGIODSP3_START 0x106800 +#define AUDPARARINGIODSP3_END 0x106BFC +#define DSP3LOCALHWREG_START 0x106C00 +#define DSP3LOCALHWREG_END 0x106C3C +#define DSP3XYRAMAGINDEX_START 0x106C40 +#define DSP3XYRAMAGINDEX_END 0x106C5C +#define DSP3XYRAMAGMDFR_START 0x106C60 +#define DSP3XYRAMAGMDFR_END 0x106C7C +#define DSP3INTCONTLVEC_START 0x106C80 +#define DSP3INTCONTLVEC_END 0x106CD8 +#define HOSTINTFPORTADDRCONTDSP3 0x106D40 +#define HOSTINTFPORTDATADSP3 0x106D44 +#define TIME0PERENBDSP3 0x106D60 +#define TIME0COUNTERDSP3 0x106D64 +#define TIME1PERENBDSP3 0x106D68 +#define TIME1COUNTERDSP3 0x106D6C +#define TIME2PERENBDSP3 0x106D70 +#define TIME2COUNTERDSP3 0x106D74 +#define TIME3PERENBDSP3 0x106D78 +#define TIME3COUNTERDSP3 0x106D7C +#define XRAMINDOPERREFNOUP_STARTDSP3 0x106D80 +#define XRAMINDOPERREFNOUP_ENDDSP3 0x106D9C +#define XRAMINDOPERREFUP_STARTDSP3 0x106DA0 +#define XRAMINDOPERREFUP_ENDDSP3 0x106DBC +#define YRAMINDOPERREFNOUP_STARTDSP3 0x106DC0 +#define YRAMINDOPERREFNOUP_ENDDSP3 0x106DDC +#define YRAMINDOPERREFUP_STARTDSP3 0x106DE0 +#define YRAMINDOPERREFUP_ENDDSP3 0x100DFC + +#define DSP3CONDCODE 0x106E00 +#define DSP3STACKFLAG 0x106E04 +#define DSP3PROGCOUNTSTACKPTREG 0x106E08 +#define DSP3PROGCOUNTSTACKDATAREG 0x106E0C +#define DSP3CURLOOPADDRREG 0x106E10 +#define DSP3CURLOOPCOUNT 0x106E14 +#define DSP3TOPLOOPCOUNTSTACK 0x106E18 +#define DSP3TOPLOOPADDRSTACK 0x106E1C +#define DSP3LOOPSTACKPTR 0x106E20 +#define DSP3STASSTACKDATAREG 0x106E24 +#define DSP3STASSTACKPTR 0x106E28 +#define DSP3PROGCOUNT 0x106E2C +#define DSP3XYRAMBASE_START 0x106EA0 +#define DSP3XYRAMBASE_END 0x106EBC +#define DSP3XYRAMLENG_START 0x106EC0 +#define DSP3XYRAMLENG_END 0x106EDC +#define SEMAPHOREREGDSP3 0x106EE0 +#define DSP3INTCONTMASKREG 0x106EE4 +#define DSP3INTCONTPENDREG 0x106EE8 +#define DSP3INTCONTSERVINT 0x106EEC +#define GPIODSP3 0x106EFC +#define DMADSPBASEADDRREG_STARTDSP3 0x106F00 +#define DMADSPBASEADDRREG_ENDDSP3 0x106F1C +#define DMAHOSTBASEADDRREG_STARTDSP3 0x106F20 +#define DMAHOSTBASEADDRREG_ENDDSP3 0x106F3C +#define DMADSPCURADDRREG_STARTDSP3 0x106F40 +#define DMADSPCURADDRREG_ENDDSP3 0x106F5C +#define DMAHOSTCURADDRREG_STARTDSP3 0x106F60 +#define DMAHOSTCURADDRREG_ENDDSP3 0x106F7C +#define DMATANXCOUNTREG_STARTDSP3 0x106F80 +#define DMATANXCOUNTREG_ENDDSP3 0x106F9C +#define DMATIMEBUGREG_STARTDSP3 0x106FA0 +#define DMATIMEBUGREG_ENDDSP3 0x106FAC +#define DMACNTLMODFREG_STARTDSP3 0x106FA0 +#define DMACNTLMODFREG_ENDDSP3 0x106FAC + +#define DMAGLOBSTATSREGDSP3 0x106FEC +#define DSP3XGPRAM_START 0x107000 +#define DSP3XGPRAM_END 0x1071FC +#define DSP3YGPRAM_START 0x107800 +#define DSP3YGPRAM_END 0x1079FC + +//end of DSP reg definitions + +#define DSPAIMAP_START 0x108000 +#define DSPAIMAP_END 0x1083FC +#define DSPPIMAP_START 0x108400 +#define DSPPIMAP_END 0x1087FC +#define DSPPOMAP_START 0x108800 +#define DSPPOMAP_END 0x108BFC +#define DSPPOCTL 0x108C00 +#define TKCTL_START 0x110000 +#define TKCTL_END 0x110FFC +#define TKCC_START 0x111000 +#define TKCC_END 0x111FFC +#define TKIMAP_START 0x112000 +#define TKIMAP_END 0x112FFC +#define TKDCTR16 0x113000 +#define TKPB16 0x113004 +#define TKBS16 0x113008 +#define TKDCTR32 0x11300C +#define TKPB32 0x113010 +#define TKBS32 0x113014 +#define ICDCTR16 0x113018 +#define ITBS16 0x11301C +#define ICDCTR32 0x113020 +#define ITBS32 0x113024 +#define ITSTART 0x113028 +#define TKSQ 0x11302C + +#define TKSCCTL_START 0x114000 +#define TKSCCTL_END 0x11403C +#define TKSCADR_START 0x114100 +#define TKSCADR_END 0x11413C +#define TKSCDATAX_START 0x114800 +#define TKSCDATAX_END 0x1149FC +#define TKPCDATAX_START 0x120000 +#define TKPCDATAX_END 0x12FFFC + +#define MALSA 0x130000 +#define MAPPHA 0x130004 +#define MAPPLA 0x130008 +#define MALSB 0x130010 +#define MAPPHB 0x130014 +#define MAPPLB 0x130018 + +#define TANSPORTMAPABREGS_START 0x130020 +#define TANSPORTMAPABREGS_END 0x13A2FC + +#define PTPAHX 0x13B000 +#define PTPALX 0x13B004 +//#define PTPALX 0x13B004 + +#define TANSPPAGETABLEPHYADDR015_START 0x13B008 +#define TANSPPAGETABLEPHYADDR015_END 0x13B07C +#define TRNQADRX_START 0x13B100 +#define TRNQADRX_END 0x13B13C +#define TRNQTIMX_START 0x13B200 +#define TRNQTIMX_END 0x13B23C +#define TRNQAPARMX_START 0x13B300 +#define TRNQAPARMX_END 0x13B33C + +#define TRNQCNT 0x13B400 +#define TRNCTL 0x13B404 +#define TRNIS 0x13B408 +#define TRNCURTS 0x13B40C + +#define AMOP_START(n) 0x140000+(8*(n)) +#define AMOP_END 0x147FFC +#define PMOP_START 0x148000 +#define PMOP_END 0x14FFFC +#define PCURR_START 0x150000 +#define PCURR_END 0x153FFC +#define PTRAG_START 0x154000 +#define PTRAG_END 0x157FFC +#define PSR_START 0x158000 +#define PSR_END 0x15BFFC + +#define PFSTAT4SEG_START 0x160000 +#define PFSTAT4SEG_END 0x160BFC +#define PFSTAT2SEG_START 0x160C00 +#define PFSTAT2SEG_END 0x1617FC +#define PFTARG4SEG_START 0x164000 +#define PFTARG4SEG_END 0x164BFC +#define PFTARG2SEG_START 0x164C00 +#define PFTARG2SEG_END 0x1657FC +#define PFSR4SEG_START 0x168000 +#define PFSR4SEG_END 0x168BFC +#define PFSR2SEG_START 0x168C00 +#define PFSR2SEG_END 0x1697FC +#define PCURRMS4SEG_START 0x16C000 +#define PCURRMS4SEG_END 0x16CCFC +#define PCURRMS2SEG_START 0x16CC00 +#define PCURRMS2SEG_END 0x16D7FC +#define PTARGMS4SEG_START 0x170000 +#define PTARGMS4SEG_END 0x172FFC +#define PTARGMS2SEG_START 0x173000 +#define PTARGMS2SEG_END 0x1747FC +#define PSRMS4SEG_START 0x170000 +#define PSRMS4SEG_END 0x172FFC +#define PSRMS2SEG_START 0x173000 +#define PSRMS2SEG_END 0x1747FC + +#define PRING_LO_START 0x190000 +#define PRING_LO_END 0x193FFC +#define PRING_HI_START 0x194000 +#define PRING_HI_END 0x197FFC +#define PRING_LO_HI_START(n) 0x198000+(4*(n)) +#define PRING_LO_HI_END 0x19BFFC + +#define PINTFIFO 0x1A0000 +#define SRCCTL(n) 0x1B0000+((n)*0x100) +# define SRCCTL_ILSZ (1<<16) // bits 16-19 +# define SRCCTL_IE (1<<15) +#define SRCCCR(n) 0x1B0004+(0x100*(n)) +#define SRCIMAP(n) 0x1B0008+(0x100*(n)) +#define SRCODDC 0x1B000C +#define SRCCA(n) 0x1B0010+((n)*0x100) +#define SRCCF(n) 0x1B0014+((n)*0x100) +#define SRCSA(n) 0x1B0018+((n)*0x100) +#define SRCLA(n) 0x1B001C+((n)*0x100) +#define SRCCTLSWR 0x1B0020 + +///SRC HERE +#define SRCALBA 0x1B002C +#define SRCMCTL 0x1B012C +#define SRCCERR 0x1B022C +#define SRCITB 0x1B032C +#define SRCIPM 0x1B082C +#define SRCIP(n) 0x1B102C+((n)*0x100) +#define SRCENBSTAT 0x1B202C +#define SRCENBLO 0x1B212C +#define SRCENBHI 0x1B222C +#define SRCENBS 0x1B352C +#define SRCENB07 0x1B282C +#define SRCENBS07 0x1B302C + +#define SRCDN0Z0 0x1B0030 +#define SRCDN0Z1 0x1B0034 +#define SRCDN0Z2 0x1B0038 +#define SRCDN0Z3 0x1B003C +#define SRCDN1Z0 0x1B0040 +#define SRCDN1Z1 0x1B0044 +#define SRCDN1Z2 0x1B0048 +#define SRCDN1Z3 0x1B004C +#define SRCDN1Z4 0x1B0050 +#define SRCDN1Z5 0x1B0054 +#define SRCDN1Z6 0x1B0058 +#define SRCDN1Z7 0x1B005C +#define SRCUPZ0 0x1B0060 +#define SRCUPZ1 0x1B0064 +#define SRCUPZ2 0x1B0068 +#define SRCUPZ3 0x1B006C +#define SRCUPZ4 0x1B0070 +#define SRCUPZ5 0x1B0074 +#define SRCUPZ6 0x1B0078 +#define SRCUPZ7 0x1B007C +#define SRCCD0 0x1B0080 +#define SRCCD1 0x1B0084 +#define SRCCD2 0x1B0088 +#define SRCCD3 0x1B008C +#define SRCCD4 0x1B0090 +#define SRCCD5 0x1B0094 +#define SRCCD6 0x1B0098 +#define SRCCD7 0x1B009C +#define SRCCD8 0x1B00A0 +#define SRCCD9 0x1B00A4 +#define SRCCDA 0x1B00A8 +#define SRCCDB 0x1B00AC +#define SRCCDC 0x1B00B0 +#define SRCCDD 0x1B00B4 +#define SRCCDE 0x1B00B8 +#define SRCCDF 0x1B00BC +#define SRCCD10 0x1B00C0 +#define SRCCD11 0x1B00C4 +#define SRCCD12 0x1B00C8 +#define SRCCD13 0x1B00CC +#define SRCCD14 0x1B00D0 +#define SRCCD15 0x1B00D4 +#define SRCCD16 0x1B00D8 +#define SRCCD17 0x1B00DC +#define SRCCD18 0x1B00E0 +#define SRCCD19 0x1B00E4 +#define SRCCD1A 0x1B00E8 +#define SRCCD1B 0x1B00EC +#define SRCCD1C 0x1B00F0 +#define SRCCD1D 0x1B00F4 +#define SRCCD1E 0x1B00F8 +#define SRCCD1F 0x1B00FC + +#define SRCCONTRBLOCK_START 0x1B0100 +#define SRCCONTRBLOCK_END 0x1BFFFC +#define FILTOP_START 0x1C0000 +#define FILTOP_END 0x1C05FC +#define FILTIMAP_START 0x1C0800 +#define FILTIMAP_END 0x1C0DFC +#define FILTZ1_START 0x1C1000 +#define FILTZ1_END 0x1C15FC +#define FILTZ2_START 0x1C1800 +#define FILTZ2_END 0x1C1DFC +#define DAOIMAP_START(n) 0x1C5000+(4*(n)) +#define DAOIMAP_END 0x1C5124 + +#define AC97D 0x1C5400 +#define AC97A 0x1C5404 +#define AC97CTL 0x1C5408 +#define I2SCTL 0x1C5420 + +#define SPOSA 0x1C5440 +#define SPOSB 0x1C5444 +#define SPOSC 0x1C5448 +#define SPOSD 0x1C544C + +#define SPISA 0x1C5450 +#define SPISB 0x1C5454 +#define SPISC 0x1C5458 +#define SPISD 0x1C545C + +#define SPFSCTL 0x1C5460 + +#define SPFS0 0x1C5468 +#define SPFS1 0x1C546C +#define SPFS2 0x1C5470 +#define SPFS3 0x1C5474 +#define SPFS4 0x1C5478 +#define SPFS5 0x1C547C + +#define SPOCTL 0x1C5480 +#define SPICTL 0x1C5484 +#define SPISTS 0x1C5488 +#define SPINTP 0x1C548C +#define SPINTE 0x1C5490 +#define SPUTCTLAB 0x1C5494 +#define SPUTCTLCD 0x1C5498 + +#define SRTSPA 0x1C54C0 +#define SRTSPB 0x1C54C4 +#define SRTSPC 0x1C54C8 +#define SRTSPD 0x1C54CC + +#define SRTSCTLA 0x1C54D0 +#define SRTSCTLB 0x1C54D4 +#define SRTSCTLC 0x1C54D8 +#define SRTSCTLD 0x1C54DC + +#define SRTI2S 0x1C54E0 +#define SRTICTL 0x1C54F0 + +#define WC 0x1C6000 +#define TIMR 0x1C6004 +# define TIMR_IE (1<<15) +# define TIMR_IP (1<<14) + +#define GIP 0x1C6010 +# define PLL_INT (1<<10) +# define FI_INT (1<<9) +# define IT_INT (1<<8) +# define PCI_INT (1<<7) +# define URT_INT (1<<6) +# define GPI_INT (1<<5) +# define MIX_INT (1<<4) +# define DAI_INT (1<<3) +# define TP_INT (1<<2) +# define DSP_INT (1<<1) +# define SRC_INT (1<<0) +#define GIE 0x1C6014 +#define DIE 0x1C6018 +#define DIC 0x1C601C +#define GPIO 0x1C6020 +#define GPIOCTL 0x1C6024 +#define GPIP 0x1C6028 +#define GPIE 0x1C602C +#define DSPINT0 0x1C6030 +#define DSPEIOC 0x1C6034 +//#define MUADAT 0x00700000L /* Midi Uart A DATa */ +//#define MUACMD 0x00710000L /* Midi Uart A CoMmanD */ +//#define MUASTAT 0x00710000L /* Midi Uart A STATus */ +//#define MUBDAT 0x00720000L /* Midi Uart B DATa */ +//#define MUBCMD 0x00730000L /* Midi Uart B CoMmanD */ +//#define MUBSTAT 0x00730000L /* Midi Uart B STATus */ +#define MUADAT 0x1C6040 +#define MUACMD 0x1C6044 +#define MUASTAT 0x1C6044 +#define MUBDAT 0x1C6048 +#define MUBCMD 0x1C604C +#define MUBSTAT 0x1C604C +#define UARTCMA 0x1C6050 +#define UARTCMB 0x1C6054 +#define UARTIP 0x1C6058 +#define UARTIE 0x1C605C +#define PLLCTL 0x1C6060 +#define PLLDCD 0x1C6064 +#define GCTL 0x1C6070 +#define ID0 0x1C6080 +#define ID1 0x1C6084 +#define ID2 0x1C6088 +#define ID3 0x1C608C +#define SDRCTL 0x1C7000 + + +#define I2SA_L 0x0L +#define I2SA_R 0x1L +#define I2SB_L 0x8L +#define I2SB_R 0x9L +#define I2SC_L 0x10L +#define I2SC_R 0x11L +#define I2SD_L 0x18L +#define I2SD_R 0x19L + + + +typedef enum +{ + //block 0 + FIL_CH_0 = 0, + SRC_CH_0 = 0x1, + MIXER_SUM_CH_0 = 0xc, + + //block 1 + FIL_CH_1 = 0x10, + SRC_CH_1 = 0x11, + MIXER_SUM_CH_1 = 0x1c, + + + DAI_CH_AC97L = 0x5e5, + DAI_CH_AC97R = 0x7e5, + DAI_CH_AC97MIC = 0xde5, + +//daoi i2s out block + DAI_CH_I2SAL = 0x0, + DAI_CH_I2SAR = 0x1, + DAI_CH_I2SA1L = 0x2, + DAI_CH_I2SA1R = 0x3, + DAI_CH_I2SA2L = 0x4, + DAI_CH_I2SA2R = 0x5, + DAI_CH_I2SA3L = 0x6, + DAI_CH_I2SA3R = 0x7, + + DAI_CH_I2SBL = 0x8, + DAI_CH_I2SBR = 0x9, + DAI_CH_I2SB1L = 0xa, + DAI_CH_I2SB1R = 0xb, + DAI_CH_I2SB2L = 0xc, + DAI_CH_I2SB2R = 0xd, + DAI_CH_I2SB3L = 0xe, + DAI_CH_I2SB3R = 0xf, + + DAI_CH_I2SCL = 0x10, + DAI_CH_I2SCR = 0x11, + DAI_CH_I2SC1L = 0x12, + DAI_CH_I2SC1R = 0x13, + DAI_CH_I2SC2L = 0x14, + DAI_CH_I2SC2R = 0x15, + DAI_CH_I2SC3L = 0x16, + DAI_CH_I2SC3R = 0x17, + + DAI_CH_I2SDL = 0x18, + DAI_CH_I2SDR = 0x19, + DAI_CH_I2SD1L = 0x1a, + DAI_CH_I2SD1R = 0x1b, + DAI_CH_I2SD2L = 0x1c, + DAI_CH_I2SD2R = 0x1d, + DAI_CH_I2SD3L = 0x1e, + DAI_CH_I2SD3R = 0x1f, + +//daoi spdif out + DAI_CH_SPDIFAL = 0x20, + DAI_CH_SPDIFAR = 0x21, + DAI_CH_SPDIFA1L = 0x22, + DAI_CH_SPDIFA1R = 0x23, + DAI_CH_SPDIFA2L = 0x24, + DAI_CH_SPDIFA2R = 0x25, + DAI_CH_SPDIFA3L = 0x26, + DAI_CH_SPDIFA3R = 0x27, + + DAI_CH_SPDIFBL = 0x28, + DAI_CH_SPDIFBR = 0x29, + DAI_CH_SPDIFB1L = 0x2a, + DAI_CH_SPDIFB1R = 0x2b, + DAI_CH_SPDIFB2L = 0x2c, + DAI_CH_SPDIFB2R = 0x2d, + DAI_CH_SPDIFB3L = 0x2e, + DAI_CH_SPDIFB3R = 0x2f, + + DAI_CH_SPDIFCL = 0x30, + DAI_CH_SPDIFCR = 0x31, + DAI_CH_SPDIFC1L = 0x32, + DAI_CH_SPDIFC1R = 0x33, + DAI_CH_SPDIFC2L = 0x34, + DAI_CH_SPDIFC2R = 0x35, + DAI_CH_SPDIFC3L = 0x36, + DAI_CH_SPDIFC3R = 0x37, + + DAI_CH_SPDIFDL = 0x38, + DAI_CH_SPDIFDR = 0x39, + DAI_CH_SPDIFD1L = 0x3a, + DAI_CH_SPDIFD1R = 0x3b, + DAI_CH_SPDIFD2L = 0x3c, + DAI_CH_SPDIFD2R = 0x3d, + DAI_CH_SPDIFD3L = 0x3e, + DAI_CH_SPDIFD3R = 0x3f, + +//daio i2s block(in) + DAI_CH_I2SINA1L = 0x035, + DAI_CH_I2SINA1R = 0x03D, + DAI_CH_I2SINB1L = 0x0B5, + DAI_CH_I2SINB1R = 0x0BD, + DAI_CH_I2SINC1L = 0x135, + DAI_CH_I2SINC1R = 0x13D, + DAI_CH_I2SIND1L = 0x1B5, + DAI_CH_I2SIND1R = 0x1BD, + DAI_CH_I2SINA2L = 0x235, + DAI_CH_I2SINA2R = 0x23D, + DAI_CH_I2SINB2L = 0x2B5, + DAI_CH_I2SINB2R = 0x2BD, + DAI_CH_I2SINC2L = 0x335, + DAI_CH_I2SINC2R = 0x33D, + DAI_CH_I2SIND2L = 0x3B5, + DAI_CH_I2SIND2R = 0x3BD, + DAI_CH_I2SINA3L = 0x435, + DAI_CH_I2SINA3R = 0x43D, + DAI_CH_I2SINB3L = 0x4B5, + DAI_CH_I2SINB3R = 0x4BD, + DAI_CH_I2SINC3L = 0x535, + DAI_CH_I2SINC3R = 0x53D, + DAI_CH_I2SIND3L = 0x5B5, + DAI_CH_I2SIND3R = 0x5BD, + DAI_CH_I2SINA4L = 0x635, + DAI_CH_I2SINA4R = 0x63D, + DAI_CH_I2SINB4L = 0x6B5, + DAI_CH_I2SINB4R = 0x6BD, + DAI_CH_I2SINC4L = 0x735, + DAI_CH_I2SINC4R = 0x73D, + DAI_CH_I2SIND4L = 0x7B5, + DAI_CH_I2SIND4R = 0x7BD, + DAI_CH_I2SINA5L = 0x835, + DAI_CH_I2SINA5R = 0x83D, + DAI_CH_I2SINB5L = 0x8B5, + DAI_CH_I2SINB5R = 0x8BD, + DAI_CH_I2SINC5L = 0x935, + DAI_CH_I2SINC5R = 0x93D, + DAI_CH_I2SIND5L = 0x9B5, + DAI_CH_I2SIND5R = 0x9BD, + DAI_CH_I2SINA6L = 0xA35, + DAI_CH_I2SINA6R = 0xA3D, + DAI_CH_I2SINB6L = 0xAB5, + DAI_CH_I2SINB6R = 0xABD, + DAI_CH_I2SINC6L = 0xB35, + DAI_CH_I2SINC6R = 0xB3D, + DAI_CH_I2SIND6L = 0xBB5, + DAI_CH_I2SIND6R = 0xBBD, + DAI_CH_I2SINA7L = 0xC35, + DAI_CH_I2SINA7R = 0xC3D, + DAI_CH_I2SINB7L = 0xCB5, + DAI_CH_I2SINB7R = 0xCBD, + DAI_CH_I2SINC7L = 0xD35, + DAI_CH_I2SINC7R = 0xD3D, + DAI_CH_I2SIND7L = 0xDB5, + DAI_CH_I2SIND7R = 0xDBD, + DAI_CH_I2SINA8L = 0xE35, + DAI_CH_I2SINA8R = 0xE3D, + DAI_CH_I2SINB8L = 0xEB5, + DAI_CH_I2SINB8R = 0xEBD, + DAI_CH_I2SINC8L = 0xF35, + DAI_CH_I2SINC8R = 0xF3D, + DAI_CH_I2SIND8L = 0xFB5, + DAI_CH_I2SIND8R = 0xFBD, + + //daio cd-spidf block + DAI_CH_CDSPDIFINA1L = 0x015, + DAI_CH_CDSPDIFINA1R = 0x01D, + DAI_CH_CDSPDIFINB1L = 0x095, + DAI_CH_CDSPDIFINB1R = 0x09D, + DAI_CH_CDSPDIFINC1L = 0x115, + DAI_CH_CDSPDIFINC1R = 0x11D, + DAI_CH_CDSPDIFIND1L = 0x195, + DAI_CH_CDSPDIFIND1R = 0x19D, + DAI_CH_CDSPDIFINA2L = 0x215, + DAI_CH_CDSPDIFINA2R = 0x21D, + DAI_CH_CDSPDIFINB2L = 0x295, + DAI_CH_CDSPDIFINB2R = 0x29D, + DAI_CH_CDSPDIFINC2L = 0x315, + DAI_CH_CDSPDIFINC2R = 0x31D, + DAI_CH_CDSPDIFIND2L = 0x395, + DAI_CH_CDSPDIFIND2R = 0x39D, + DAI_CH_CDSPDIFINA3L = 0x415, + DAI_CH_CDSPDIFINA3R = 0x41D, + DAI_CH_CDSPDIFINB3L = 0x495, + DAI_CH_CDSPDIFINB3R = 0x49D, + DAI_CH_CDSPDIFINC3L = 0x515, + DAI_CH_CDSPDIFINC3R = 0x51D, + DAI_CH_CDSPDIFIND3L = 0x595, + DAI_CH_CDSPDIFIND3R = 0x59D, + DAI_CH_CDSPDIFINA4L = 0x615, + DAI_CH_CDSPDIFINA4R = 0x61D, + DAI_CH_CDSPDIFINB4L = 0x695, + DAI_CH_CDSPDIFINB4R = 0x69D, + DAI_CH_CDSPDIFINC4L = 0x715, + DAI_CH_CDSPDIFINC4R = 0x71D, + DAI_CH_CDSPDIFIND4L = 0x795, + DAI_CH_CDSPDIFIND4R = 0x79D, + DAI_CH_CDSPDIFINA5L = 0x815, + DAI_CH_CDSPDIFINA5R = 0x81D, + DAI_CH_CDSPDIFINB5L = 0x895, + DAI_CH_CDSPDIFINB5R = 0x89D, + DAI_CH_CDSPDIFINC5L = 0x915, + DAI_CH_CDSPDIFINC5R = 0x91D, + DAI_CH_CDSPDIFIND5L = 0x995, + DAI_CH_CDSPDIFIND5R = 0x99D, + DAI_CH_CDSPDIFINA6L = 0xA15, + DAI_CH_CDSPDIFINA6R = 0xA1D, + DAI_CH_CDSPDIFINB6L = 0xA95, + DAI_CH_CDSPDIFINB6R = 0xA9D, + DAI_CH_CDSPDIFINC6L = 0xB15, + DAI_CH_CDSPDIFINC6R = 0xB1D, + DAI_CH_CDSPDIFIND6L = 0xB95, + DAI_CH_CDSPDIFIND6R = 0xB9D, + DAI_CH_CDSPDIFINA7L = 0xC15, + DAI_CH_CDSPDIFINA7R = 0xC1D, + DAI_CH_CDSPDIFINB7L = 0xC95, + DAI_CH_CDSPDIFINB7R = 0xC9D, + DAI_CH_CDSPDIFINC7L = 0xD15, + DAI_CH_CDSPDIFINC7R = 0xD1D, + DAI_CH_CDSPDIFIND7L = 0xD95, + DAI_CH_CDSPDIFIND7R = 0xD9D, + DAI_CH_CDSPDIFINA8L = 0xE15, + DAI_CH_CDSPDIFINA8R = 0xE1D, + DAI_CH_CDSPDIFINB8L = 0xE95, + DAI_CH_CDSPDIFINB8R = 0xE9D, + DAI_CH_CDSPDIFINC8L = 0xF15, + DAI_CH_CDSPDIFINC8R = 0xF1D, + DAI_CH_CDSPDIFIND8L = 0xF95, + DAI_CH_CDSPDIFIND8R = 0xF9D +} ARCHANNEL; + + +#endif diff --git a/kernel/drv/oss_sbxfi/hwaccess.h b/kernel/drv/oss_sbxfi/hwaccess.h new file mode 100644 index 0000000..872e2e2 --- /dev/null +++ b/kernel/drv/oss_sbxfi/hwaccess.h @@ -0,0 +1,71 @@ +/** +******************************************************************************* +Confidential & Proprietary +Private & Confidential +Creative Confidential +******************************************************************************* +*/ +/** +******************************************************************************* +Copyright (C) Creative Technology, Ltd., 2007. All rights reserved. +******************************************************************************* +**/ + +#ifndef _HWACCESS_H_ +#define _HWACCESS_H_ + +unsigned int GetAudioSrcChan (unsigned int srcchn); +unsigned int GetAudioSumChan (unsigned int chn); +unsigned int GetParamPitchChan (unsigned int i); +void WriteAMOP (sbxfi_devc_t * devc, unsigned int xdata, unsigned int ydata, + unsigned int chn, unsigned int hidata); +void WriteSRC (sbxfi_devc_t * devc, unsigned int srcca, unsigned int srccf, + unsigned int srcsa, unsigned int srcla, unsigned int srcccr, unsigned int srcctl, + unsigned int chn); +unsigned int HwRead20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg); +unsigned int HwRead20K1 (sbxfi_devc_t * devc, unsigned int dwReg); +void HwWrite20K1 (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData); +void HwWrite20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData); +unsigned int ReadCfgDword (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum, + unsigned int dwReg); +unsigned short ReadCfgWord (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum, + unsigned int dwReg); +void WriteConfigDword (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum, + unsigned int dwReg, unsigned int dwData); + +unsigned char DetectAndConfigureHardware (sbxfi_devc_t * devc); +unsigned char IsVistaCompatibleHardware (sbxfi_devc_t * devc); +void SwitchToXFiCore (sbxfi_devc_t * devc); +CTSTATUS InitHardware (sbxfi_devc_t * devc); +CTSTATUS AllocateBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void FreeBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupHardwarePageTable (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void InitADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db); +void ResetDAC (sbxfi_devc_t * devc); +void InitDAC (sbxfi_devc_t * devc, sbxfi_portc_t * portc); + +void SetupPlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void UpdatePlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupPlayFormat (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupAndStartPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void StopPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupPlayInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void StopPlay (sbxfi_devc_t * devc, sbxfi_portc_t * portc); + +void SetupRecordMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupRecordFormat (sbxfi_devc_t * devc); +void SetupAndStartRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void StopRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupRecordInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void SetupInputToOutputMonitoring (sbxfi_devc_t * devc, + sbxfi_portc_t * portc); + +void _dumpRegisters (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void _dumpSRCs (sbxfi_devc_t * devc, sbxfi_portc_t * portc); +void _dumpGlobal (sbxfi_devc_t * devc); + +#define osDelayms(usecs) oss_udelay(usecs) +#define osInportd(devc, ioaddr) INL(devc->osdev, ioaddr) +#define osOutportd(devc, ioaddr, data) OUTL(devc->osdev, data, ioaddr) + +#endif diff --git a/kernel/drv/oss_sbxfi/oss_sbxfi.c b/kernel/drv/oss_sbxfi/oss_sbxfi.c new file mode 100644 index 0000000..837ab33 --- /dev/null +++ b/kernel/drv/oss_sbxfi/oss_sbxfi.c @@ -0,0 +1,1078 @@ +/* + * Purpose: Driver for Sound Blaster X-Fi (emu20k) + * + */ + +/* + * + * 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_sbxfi_cfg.h" +#include <oss_pci.h> +#include "sbxfi.h" +#include "20k1reg.h" +#include "hwaccess.h" + +#define PCI_VENDOR_CREATIVE 0x1102 +#define CREATIVE_SBXFI_K1 0x0005 +#define CREATIVE_SBXFI_K2 0x000b +#define CREATIVE_SBXFI_E 0x0009 + +#define TIMER_INTERVAL 5 /* In milliseconds */ + +#define DEFAULT_PLAY_RATE 96000 /* Default rate of play devices */ +#define DEFAULT_REC_RATE 96000 /* Default rate of rec devices */ +#define HARDWARE_RATE 96000 /* Internal rate used by the hardware */ + +static void +set_interval_timer(sbxfi_devc_t *devc, int msecs) +{ + int tic = (HARDWARE_RATE*msecs)/1000; + + HwWrite20K1 (devc, TIMR, tic | TIMR_IE|TIMR_IP); +} + +static int +sbxfi_intr(oss_device_t *osdev) +{ + unsigned int status; + sbxfi_devc_t *devc = osdev->devc; + + status = HwRead20K1 (devc, GIP); + + if (status==0) /* Not for me */ + return 0; + + devc->interrupt_count++; + +#if 0 + // Not using loop interrupts. + if (status & SRC_INT) /* SRC interrupt(s) pending */ + { + unsigned int srcipm, srcip; + int i; + + srcipm = HwRead20K1 (devc, SRCIPM); /* SRC interrupt pending map register */ + + for (i=0;i<7;i++) + if (srcipm & (1<<i)) + { + int j; + srcip = HwRead20K1 (devc, SRCIP(i)); /* SRC interrupt pending register for block(i) */ + + for (j=0;j<32;j++) + if (srcip & (1<<j)) + { + int chn=i*32+j; + sbxfi_portc_t *portc; + + portc=devc->src_to_portc[chn]; + + if (portc==NULL) + { + cmn_err(CE_NOTE, "portc==NULL\n"); + continue; + } + + oss_audio_outputintr(portc->dev, 0); + } + + HwWrite20K1 (devc, SRCIP(i), srcip); /* Acknowledge SRC interrupts for block(i) */ + } + } +#endif + + if (status & IT_INT) + { + /* + * Interval timer interrupt + */ + sbxfi_portc_t *portc; + int i; + + for (i=0;i<devc->nr_outdevs;i++) + { + portc=&devc->play_portc[i]; + if (portc->running) + oss_audio_outputintr(portc->dev, 0); + } + + for (i=0;i<devc->nr_indevs;i++) + { + portc=&devc->rec_portc[i]; + if (portc->running) + oss_audio_inputintr(portc->dev, 0); + } + + set_interval_timer(devc, TIMER_INTERVAL); /* Rearm interval timer */ + } + + HwWrite20K1 (devc, GIP, status & FI_INT); /* Acknowledge interrupts */ + return 1; +} + + /*ARGSUSED*/ static int +sbxfi_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static mixer_driver_t sbxfi_mixer_driver = { + sbxfi_mixer_ioctl +}; + +static int +sbxfi_set_rate (int dev, int arg) +{ + sbxfi_devc_t *devc = audio_engines[dev]->devc; + sbxfi_portc_t *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); +#if 0 + // TODO: Implement support for other rates + + if (arg == 0) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->rate; + } + +#else + if (portc->direction == PCM_ENABLE_OUTPUT) + arg=DEFAULT_PLAY_RATE; + else + arg=DEFAULT_REC_RATE; +#endif + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return portc->rate = arg; +} + +static short +sbxfi_set_channels (int dev, short arg) +{ + sbxfi_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->channels; + + if (arg<2) + arg=2; + else + if (arg > MAX_PLAY_CHANNELS) + arg = MAX_PLAY_CHANNELS; + arg &= ~1; /* Even number of channels */ + + return portc->channels = arg; +} + +static unsigned int +sbxfi_set_format (int dev, unsigned int arg) +{ + sbxfi_portc_t *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->fmt; + + return portc->fmt = SUPPORTED_FORMAT; +} + +static int +sbxfi_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + //sbxfi_portc_t *portc = audio_engines[dev]->portc; + //sbxfi_devc_t *devc = audio_engines[dev]->devc; + + return OSS_EINVAL; +} + +static void sbxfi_trigger (int dev, int state); + +static void +sbxfi_reset (int dev) +{ + sbxfi_trigger (dev, 0); +} + + /*ARGSUSED*/ static int +sbxfi_open_input (int dev, int mode, int open_flags) +{ + sbxfi_portc_t *portc = audio_engines[dev]->portc; + sbxfi_devc_t *devc = audio_engines[dev]->devc; + adev_p adev = audio_engines[dev]; + oss_native_word flags; + + if (mode & OPEN_WRITE) + { + cmn_err (CE_CONT, "Playback is not possible with %s\n", adev->devnode); + return OSS_ENOTSUP; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + portc->open_mode = mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + + /*ARGSUSED*/ static int +sbxfi_open_output (int dev, int mode, int open_flags) +{ + sbxfi_portc_t *portc = audio_engines[dev]->portc; + sbxfi_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + adev_p adev = audio_engines[dev]; + + if (mode == OPEN_READ) + { + cmn_err (CE_CONT, "Recording is not possible with %s\n", adev->devnode); + return OSS_ENOTSUP; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +sbxfi_close (int dev, int mode) +{ + sbxfi_portc_t *portc = audio_engines[dev]->portc; + sbxfi_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + portc->open_mode = 0; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + /*ARGSUSED*/ static void +sbxfi_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + + /*ARGSUSED*/ static void +sbxfi_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +static void +sbxfi_trigger (int dev, int state) +{ + sbxfi_devc_t *devc = audio_engines[dev]->devc; + sbxfi_portc_t *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->state_bits == state) /* No change */ + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return; + } + portc->state_bits = state; + + if (portc->direction == PCM_ENABLE_OUTPUT) + if (portc->open_mode & OPEN_WRITE) + { + if (state & PCM_ENABLE_OUTPUT) + { + SetupAndStartPlaySRC (devc, portc); + portc->running=1; + } + else + { + StopPlaySRC (devc, portc); + portc->running=0; + } + } + + if (portc->direction == PCM_ENABLE_INPUT) + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + SetupAndStartRecordSRC (devc, portc); + portc->running=1; + } + else + { + StopRecordSRC (devc, portc); + portc->running=0; + } + } + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + + /*ARGSUSED*/ static int +sbxfi_prepare_for_input (int dev, int bsize, int bcount) +{ + sbxfi_devc_t *devc = audio_engines[dev]->devc; + sbxfi_portc_t *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_in; + oss_native_word flags; + int i; + + if (audio_engines[dev]->flags & ADEV_NOINPUT) + return OSS_EACCES; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + // Fill record buffer to the page table entries. + // This need to sync up with setting SRCs start addx + for (i=0;i<(bsize*bcount)/4096;i++) + devc->pdwPageTable[portc->pgtable_index+i] = dmap->dmabuf_phys + (i*4096); + + InitADC (devc, portc->dwDAChan[0], FALSE); + + // Program input mapper + SetupRecordInputMapper (devc, portc); + + // Program I2S + SetupRecordFormat (devc); + SetupRecordMixer (devc, portc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + + /*ARGSUSED*/ static int +sbxfi_prepare_for_output (int dev, int bsize, int bcount) +{ + sbxfi_devc_t *devc = audio_engines[dev]->devc; + sbxfi_portc_t *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + oss_native_word flags; + int i; + + if (audio_engines[dev]->flags & ADEV_NOOUTPUT) + return OSS_EACCES; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + // Fill play buffer to the page table entries. + // This need to sync up with setting SRCs start addx + for (i=0;i<(bsize*bcount)/4096;i++) + devc->pdwPageTable[portc->pgtable_index+i] = dmap->dmabuf_phys + (i*4096); + + InitDAC (devc, portc); + + // Program I2S + SetupPlayFormat (devc, portc); + SetupPlayMixer (devc, portc); + + // Program input mapper + SetupPlayInputMapper (devc, portc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +sbxfi_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + sbxfi_devc_t *devc = audio_engines[dev]->devc; + sbxfi_portc_t *portc = audio_engines[dev]->portc; + int pos; + + pos = HwRead20K1 (devc, SRCCA(portc->SrcChan)) & 0x03ffffff; + + if (pos>=128) + pos -= 128; /* The pointer is always 128 bytes ahead */ + + pos -= portc->pgtable_index*4096; + + return pos; +} + +static audiodrv_t sbxfi_output_driver = { + sbxfi_open_output, + sbxfi_close, + sbxfi_output_block, + sbxfi_start_input, + sbxfi_ioctl, + sbxfi_prepare_for_input, + sbxfi_prepare_for_output, + sbxfi_reset, + NULL, + NULL, + NULL, + NULL, + sbxfi_trigger, + sbxfi_set_rate, + sbxfi_set_format, + sbxfi_set_channels, + NULL, + NULL, + NULL, /* check input */ + NULL, /* sbxfi_check_output */ + NULL, /* sbxfi_alloc_buffer */ + NULL, /* sbxfi_free_buffer */ + NULL, + NULL, + sbxfi_get_buffer_pointer +}; + +static audiodrv_t sbxfi_input_driver = { + sbxfi_open_input, + sbxfi_close, + sbxfi_output_block, + sbxfi_start_input, + sbxfi_ioctl, + sbxfi_prepare_for_input, + sbxfi_prepare_for_output, + sbxfi_reset, + NULL, + NULL, + NULL, + NULL, + sbxfi_trigger, + sbxfi_set_rate, + sbxfi_set_format, + sbxfi_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* sbxfi_alloc_buffer */ + NULL, /* sbxfi_free_buffer */ + NULL, + NULL, + sbxfi_get_buffer_pointer +}; + +static int +init_play_device (sbxfi_devc_t * devc, + char *name, int dev_flags) +{ + int opts, dev, formats; + char tmp[80]; + sbxfi_portc_t *portc = NULL; + adev_p adev; + + sprintf (tmp, "%s %s", devc->name, name); + + if (devc->nr_outdevs > MAX_OUTPUTDEVS) + { + cmn_err (CE_CONT, "Too many audio devices\n"); + return -1; + } + + opts = ADEV_AUTOMODE | ADEV_NOINPUT; + + formats = SUPPORTED_FORMAT; + + if ((dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &sbxfi_output_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1)) < 0) + { + return -1; + } + + if (devc->first_dev == -1) + { + devc->first_dev = dev; + } + adev = audio_engines[dev]; + + portc = &devc->play_portc[devc->nr_outdevs]; + + adev->portc = portc; + adev->devc = devc; + adev->mixer_dev = devc->mixer_dev; + adev->rate_source = devc->first_dev; + adev->min_rate = 48000; + adev->max_rate = 92600; + adev->min_block=4096; + adev->dmabuf_maxaddr = MEMLIMIT_ISA; + + portc->dev = dev; + portc->open_mode = 0; + portc->fmt = SUPPORTED_FORMAT; + portc->dev_flags = dev_flags; + portc->state_bits = 0; + portc->direction = PCM_ENABLE_OUTPUT; + + portc->rate = DEFAULT_PLAY_RATE; + + // use the following SRC channels for Play + portc->SrcChan = devc->next_src; + devc->next_src += MAX_PLAY_CHANNELS; + devc->src_to_portc[portc->SrcChan]=portc; + + portc->dwDAChan[0] = I2SA_L; + portc->dwDAChan[1] = I2SA_R; +#if MAX_PLAY_CHANNELS>2 + portc->dwDAChan[2] = I2SB_L; + portc->dwDAChan[3] = I2SB_R; + portc->dwDAChan[4] = I2SC_L; + portc->dwDAChan[5] = I2SC_R; +#endif + + portc->vol_left=portc->vol_right=MIXER_VOLSTEPS; + + adev->min_channels = 2; + adev->max_channels = MAX_PLAY_CHANNELS; + + portc->pgtable_index = devc->next_pg; + devc->next_pg += 128/4; // Up to 128k for buffer + + devc->nr_outdevs++; + + return dev; +} + +static int +init_rec_device (sbxfi_devc_t * devc, + char *name, int dev_flags) +{ + int opts, dev, formats; + char tmp[80]; + sbxfi_portc_t *portc = NULL; + adev_p adev; + + sprintf (tmp, "%s %s", devc->name, name); + + if (devc->nr_indevs > MAX_INPUTDEVS) + { + cmn_err (CE_CONT, "Too many audio devices\n"); + return -1; + } + + opts = ADEV_AUTOMODE | ADEV_NOOUTPUT; + + formats = SUPPORTED_FORMAT; + + if ((dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp, + &sbxfi_input_driver, + sizeof (audiodrv_t), + opts, formats, devc, -1)) < 0) + { + return -1; + } + + if (devc->first_dev == -1) + { + devc->first_dev = dev; + } + adev = audio_engines[dev]; + + portc = &devc->rec_portc[devc->nr_indevs]; + + adev->portc = portc; + adev->devc = devc; + adev->mixer_dev = devc->mixer_dev; + adev->rate_source = devc->first_dev; + adev->min_rate = 48000; + adev->max_rate = 96000; + adev->min_block=4096; + adev->dmabuf_maxaddr = MEMLIMIT_ISA; + + portc->dev = dev; + portc->open_mode = 0; + portc->fmt = SUPPORTED_FORMAT; + portc->dev_flags = dev_flags; + portc->state_bits = 0; + portc->direction = PCM_ENABLE_INPUT; + + portc->rate = DEFAULT_REC_RATE; + + // use the following SRC channels for record + portc->SrcChan = devc->next_src; + devc->next_src += 2; + devc->src_to_portc[portc->SrcChan]=portc; + + portc->dwDAChan[0] = ADC_SRC_LINEIN; + + portc->vol_left=portc->vol_right=MIXER_VOLSTEPS; + + adev->min_channels = 2; + adev->max_channels = 2; + + portc->pgtable_index = devc->next_pg; + devc->next_pg += 128/4; // Up to 128k for buffer + + devc->nr_indevs++; + + return dev; +} + +static int +sbxfi_set_playvol (int dev, int ctrl, unsigned int cmd, int value) +{ + sbxfi_devc_t *devc = mixer_devs[dev]->devc; + sbxfi_portc_t *portc; + int left, right; + + if (ctrl<0 || ctrl >= devc->nr_outdevs) + return OSS_ENXIO; + portc = &devc->play_portc[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + { + return portc->vol_left | (portc->vol_right << 16); + } + + if (cmd == SNDCTL_MIX_WRITE) + { + left = value & 0xffff; + right = (value>>16) & 0xffff; + + if (left > MIXER_VOLSTEPS) + left=MIXER_VOLSTEPS; + if (right > MIXER_VOLSTEPS) + right=MIXER_VOLSTEPS; + + portc->vol_left=left; + portc->vol_right=right; + if (portc->running) + SetupPlayMixer(devc, portc); + + return portc->vol_left | (portc->vol_right << 16); + } + + return OSS_EINVAL; +} + +static int +sbxfi_set_recvol (int dev, int ctrl, unsigned int cmd, int value) +{ + sbxfi_devc_t *devc = mixer_devs[dev]->devc; + sbxfi_portc_t *portc; + int left, right; + + if (ctrl<0 || ctrl >= devc->nr_indevs) + return OSS_ENXIO; + portc = &devc->rec_portc[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + { + return portc->vol_left | (portc->vol_right << 16); + } + + if (cmd == SNDCTL_MIX_WRITE) + { + left = value & 0xffff; + right = (value>>16) & 0xffff; + + if (left > MIXER_VOLSTEPS) + left=MIXER_VOLSTEPS; + if (right > MIXER_VOLSTEPS) + right=MIXER_VOLSTEPS; + + portc->vol_left=left; + portc->vol_right=right; + if (portc->running) + SetupRecordMixer(devc, portc); + + return portc->vol_left | (portc->vol_right << 16); + } + + return OSS_EINVAL; +} + +static int +sbxfi_set_recsrc (int dev, int ctrl, unsigned int cmd, int value) +{ + sbxfi_devc_t *devc = mixer_devs[dev]->devc; + sbxfi_portc_t *portc; + + if (ctrl<0 || ctrl >= devc->nr_indevs) + return OSS_ENXIO; + portc = &devc->rec_portc[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + { + return portc->dwDAChan[0]; + } + + if (cmd == SNDCTL_MIX_WRITE) + { + if (value<0 || value>ADC_SRC_NONE) + return portc->dwDAChan[0]; + + return portc->dwDAChan[0]=value; + } + + return OSS_EINVAL; +} + +static int +sbxfi_mix_init (int dev) +{ + int root=0, ctl; + + if ((ctl = mixer_ext_create_control (dev, root, + 0, sbxfi_set_playvol, + MIXT_STEREOSLIDER16, + "play", MIXER_VOLSTEPS, + MIXF_PCMVOL | MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL)) < + 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, root, + 0, sbxfi_set_recvol, + MIXT_STEREOSLIDER16, + "rec", MIXER_VOLSTEPS, + MIXF_RECVOL | MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL)) < + 0) + return ctl; + + if ((ctl = mixer_ext_create_control (dev, root, + 0, sbxfi_set_recsrc, + MIXT_ENUM, + "recsrc", 5, + MIXF_READABLE | + MIXF_WRITEABLE | MIXF_CENTIBEL)) < + 0) + return ctl; + + mixer_ext_set_strings (dev, ctl, "mic line video aux none", 0); + + return 0; +} + +int +oss_sbxfi_attach (oss_device_t * osdev) +{ + unsigned short pci_command, vendor, device, revision; + unsigned short subvendor, subdevice; + int pdev, rdev; + extern int sbxfi_type; + + sbxfi_devc_t *devc; + sbxfi_portc_t *portc; + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + + memset (devc, 0, sizeof (*devc)); + + portc = &devc->play_portc[0]; + + devc->osdev = osdev; + osdev->devc = devc; + devc->name = "Sound Blaster X-Fi"; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + DDB (cmn_err + (CE_CONT, "oss_sbxfi_attach(Vendor %x, device %x)\n", vendor, device)); + + if (vendor != PCI_VENDOR_CREATIVE || + (device != CREATIVE_SBXFI_K1 && device != CREATIVE_SBXFI_K2 && + device != CREATIVE_SBXFI_E)) + { + cmn_err (CE_WARN, "Hardware not recognized (vendor=%x, dev=%x)\n", + vendor, device); + return 0; + } + MUTEX_INIT (osdev, devc->mutex, MH_DRV); + MUTEX_INIT (osdev, devc->low_mutex, MH_DRV + 1); + + pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor); + pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &subdevice); + pci_read_config_word (osdev, PCI_REVISION_ID, &revision); + + devc->wVendorID = vendor; + devc->wDeviceID = device; + devc->wSubsystemVendorID = subvendor; + devc->wSubsystemID = subdevice; + devc->wChipRevision = revision; + + switch (sbxfi_type) + { + case 1: + devc->name = "Sound Blaster X-Fi (SB046x/067x/076x)"; + devc->hw_family = HW_ORIG; + break; + + case 2: + devc->name = "Sound Blaster X-Fi (SB073x)"; + devc->hw_family = HW_073x; + break; + + case 3: + devc->name = "Sound Blaster X-Fi (SB055x)"; + devc->hw_family = HW_055x; + break; + + case 4: + devc->name = "Sound Blaster X-Fi (UAA)"; + devc->hw_family = HW_UAA; + break; + + case 5: + devc->name = "Sound Blaster X-Fi (SB076x)"; + devc->hw_family = HW_0760; + break; + + case 6: + devc->name = "Sound Blaster X-Fi (SB0880-1)"; + devc->hw_family = HW_08801; + break; + + case 7: + devc->name = "Sound Blaster X-Fi (SB0880-2)"; + devc->hw_family = HW_08802; + break; + + case 8: + devc->name = "Sound Blaster X-Fi (SB0880-3)"; + devc->hw_family = HW_08803; + break; + + case 0: + default: + devc->hw_family = 0; + break; + } + + if (!devc->hw_family && device == CREATIVE_SBXFI_K1) // EMU20K1 models + switch (subdevice) + { + case 0x0021: /* SB0460 */ + case 0x0023: + case 0x0024: + case 0x0025: + case 0x0026: + case 0x0027: + case 0x0028: + case 0x002a: + case 0x002b: + case 0x002c: + case 0x002d: + case 0x002e: + case 0x0032: + case 0x0033: + case 0x0034: /* This is actually Auzentech Prelude (subvendor 415a) */ + /* + * Original X-Fi hardware revision (SB046x/067x/076x) + */ + devc->name = "Sound Blaster X-Fi (SB046x/067x/076x)"; + devc->hw_family = HW_ORIG; + break; + + case 0x0029: + case 0x0031: + devc->name = "Sound Blaster X-Fi (SB073x)"; + devc->hw_family = HW_073x; + break; + + case 0x0022: + case 0x002f: + devc->name = "Sound Blaster X-Fi (SB055x)"; + devc->hw_family = HW_055x; + break; + + default: + if (subdevice >= 0x6000 && subdevice <= 0x6fff) /* "Vista compatible" HW */ + { + devc->name = "Sound Blaster X-Fi (UAA)"; + devc->hw_family = HW_UAA; + } + } + + if (!devc->hw_family && device == CREATIVE_SBXFI_K2) // EMU 20K2 models + switch (subdevice) + { + case PCI_SUBDEVICE_ID_CREATIVE_SB0760: + devc->name = "Sound Blaster X-Fi (SB076x)"; + devc->hw_family = HW_0760; + break; + + case PCI_SUBDEVICE_ID_CREATIVE_SB08801: + devc->name = "Sound Blaster X-Fi (SB0880-1)"; + devc->hw_family = HW_08801; + break; + + case PCI_SUBDEVICE_ID_CREATIVE_SB08802: + devc->name = "Sound Blaster X-Fi (SB0880-2)"; + devc->hw_family = HW_08802; + break; + + case PCI_SUBDEVICE_ID_CREATIVE_SB08803: + devc->name = "Sound Blaster X-Fi (SB0880-3)"; + devc->hw_family = HW_08803; + break; + + default: + devc->name = "Sound Blaster X-Fi (20K2)"; + devc->hw_family = HW_UAA; // Just a wild guess + } + + if (!devc->hw_family && device == CREATIVE_SBXFI_E) // PCI-e models + { + devc->name = "Sound Blaster X-Fi (PCI-e)"; + devc->hw_family = HW_UAA; // Just a wild guess + } + + +#if 1 +// Temporary hacking until proper 20K2 support is in place + if (devc->hw_family > HW_UAA) devc->hw_family = HW_UAA; +#endif + + oss_register_device (osdev, devc->name); + + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + if ((osdev->hw_info = PMALLOC (osdev, 200)) != NULL) + { + sprintf (osdev->hw_info, "PCI device %04x:%04x, subdevice %04x:%04x\n", + vendor, device, subvendor, subdevice); + } + + devc->interrupt_count=0; + if (oss_register_interrupts (devc->osdev, 0, sbxfi_intr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to install interrupt handler\n"); + return 0; + } + + // Detect and Configure X-Fi PCI config space. + // Obtain the resource configuration from PCI config space. + if (!DetectAndConfigureHardware (devc)) + { + cmn_err (CE_WARN, "Cannot configure X-Fi hardware...\n"); + return 0; + } + + if (IsVistaCompatibleHardware (devc)) + { + // Switch to audio core to X-Fi core. + SwitchToXFiCore (devc); + } + + // Initialize hardware. This include setup the PLL etc. + if (InitHardware (devc) != CTSTATUS_SUCCESS) + { + cmn_err (CE_WARN, "Init Hardware failed...\n"); + return 0; + } + + devc->dwPageTableSize = 1024; /* For up to 4M of memory */ + devc->pdwPageTable = CONTIG_MALLOC (devc->osdev, + devc->dwPageTableSize, + MEMLIMIT_ISA, &devc->dwPTBPhysAddx, devc->pgtable_dma_handle); + + HwWrite20K1 (devc, PTPALX, devc->dwPTBPhysAddx); + HwWrite20K1 (devc, PTPAHX, 0); + + HwWrite20K1 (devc, TRNCTL, 0x13); + HwWrite20K1 (devc, TRNIS, 0x200c01); + + HwWrite20K1 (devc, GIE, FI_INT); /* Enable "forced" interrupts */ + HwWrite20K1 (devc, GIP, FI_INT); /* Trigger forced interrupt */ + + oss_udelay(1000); + if (devc->interrupt_count==0) + cmn_err(CE_WARN, "Interrupts don't seem to be working.\n"); + + set_interval_timer(devc, TIMER_INTERVAL); + +/* + * Disable FI and enable selected global interrupts + * (SRC, Interval Timer). + */ + HwWrite20K1 (devc, GIE, SRC_INT | IT_INT); + + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + devc->name, + &sbxfi_mixer_driver, + sizeof (mixer_driver_t), + devc)) >= 0) + { + mixer_devs[devc->mixer_dev]->hw_devc = devc; + mixer_devs[devc->mixer_dev]->priority = 1; /* Possible default mixer candidate */ + mixer_ext_set_init_fn (devc->mixer_dev, sbxfi_mix_init, 10); + } + + devc->first_dev=-1; /* Not assigned */ + pdev = init_play_device (devc, "output", 0); + rdev = init_rec_device (devc, "input", 0); +#ifdef CONFIG_OSS_VMIX + if (pdev != -1) + { + vmix_attach_audiodev (devc->osdev, pdev, rdev, 0); + } +#endif + +#if 0 + // Initialize ADC + InitADC (devc, ADC_SRC_LINEIN, FALSE); +#endif + + return 1; +} + +int +oss_sbxfi_detach (oss_device_t * osdev) +{ + sbxfi_devc_t *devc = (sbxfi_devc_t *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + HwWrite20K1 (devc, GIE, 0); /* Disable global interrupts */ + oss_unregister_interrupts (devc->osdev); + + HwWrite20K1 (devc, PTPALX, 0); + if (devc->pdwPageTable != NULL) + { + CONTIG_FREE (devc->osdev, devc->pdwPageTable, devc->dwPageTableSize, devc->pgtable_dma_handle); + devc->pdwPageTable = NULL; + } + oss_unregister_device (osdev); + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + return 1; +} diff --git a/kernel/drv/oss_sbxfi/oss_sbxfi.man b/kernel/drv/oss_sbxfi/oss_sbxfi.man new file mode 100644 index 0000000..a1f10bd --- /dev/null +++ b/kernel/drv/oss_sbxfi/oss_sbxfi.man @@ -0,0 +1,20 @@ +NAME +oss_sbxfi - SoundBlaster X-Fi audio driver + +DESCRIPTION +Open Sound System driver for the SoundBlaster X-Fi cards. + +OPTIONS +o sbxfi_type Override X-Fi type autodetection. Values: + 0 - Autodetect type + 1 - Sound Blaster X-Fi (SB046x/067x/076x) + 2 - Sound Blaster X-Fi (SB073x) + 3 - Sound Blaster X-Fi (SB055x) + 4 - Sound Blaster X-Fi (UAA) + Default : 0. + +FILES +CONFIGFILEPATH/oss_sbxfi.conf Device configuration file. + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_sbxfi/sbxfi.h b/kernel/drv/oss_sbxfi/sbxfi.h new file mode 100644 index 0000000..dfb529f --- /dev/null +++ b/kernel/drv/oss_sbxfi/sbxfi.h @@ -0,0 +1,166 @@ +/* + * + * 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 PCI_SUBDEVICE_ID_CREATIVE_SB0760 0x0024 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 +#define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 + +#define MAX_OUTPUTDEVS 1 +#define MAX_INPUTDEVS 1 +#define SUPPORTED_FORMAT (AFMT_S16_LE) + +#define MIXER_VOLSTEPS 144 /* Centibel steps */ + +//#define MAX_PLAY_CHANNELS 6 /* Does not work */ +#define MAX_PLAY_CHANNELS 2 + +#if 0 +typedef unsigned char CTBYTE, *PCTBYTE; +typedef unsigned short unsigned short, *Punsigned short; +typedef signed short CTSHORT, *PCTSHORT; +typedef unsigned int unsigned int, *unsigned int *; +typedef signed long CTLONG, *PCTLONG; +typedef void CTVOID, *PCTVOID; +typedef unsigned int CTBOOL, *PCTBOOL; +typedef unsigned int CTUINT, *PCTUINT; +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +typedef unsigned int CTSTATUS; +typedef oss_native_word IOADDR; + +enum GlobalErrorCode +{ + CTSTATUS_SUCCESS = 0x0000, + CTSTATUS_ERROR, + CTSTATUS_INVALIDPARAM, + CTSTATUS_NOTSUPPORTED, + CTSTATUS_NOMEMORY, + CTSTATUS_INVALIDIO, + CTSTATUS_INVALIDIRQ, + CTSTATUS_INVALIDDMA, + CTSTATUS_INVALIDID, + CTSTATUS_INVALIDVALUE, + CTSTATUS_BADFORMAT_BITS, + CTSTATUS_BADFORMAT_RATE, + CTSTATUS_BADFORMAT_CHANNELS, + CTSTATUS_INUSE, + CTSTATUS_STILLPLAYING, + CTSTATUS_ALLOCATED, + CTSTATUS_INVALID_FORMAT, + CTSTATUS_OUT_OF_RESOURCE, + CTSTATUS_CHIP_INUSE, + CTSTATUS_NOCHIPRESOURCE, + CTSTATUS_PORTS_INUSE, + CTSTATUS_EXIT, + CTSTATUS_FAILURE +}; + + +#define ADC_SRC_MICIN 0x0 +#define ADC_SRC_LINEIN 0x1 +#define ADC_SRC_VIDEO 0x2 +#define ADC_SRC_AUX 0x3 +#define ADC_SRC_NONE 0x4 + +typedef struct +{ + char *name; + int dev; + int open_mode; + int fmt; + int dev_flags; + int direction; + int state_bits; + int pgtable_index; // Pointer to the first page table entry + + int running; + + int channels; + + unsigned int rate; + + // Audio Ring resources + unsigned int SrcChan; + + unsigned int dwDAChan[MAX_PLAY_CHANNELS]; + + // Play volumes + int vol_left, vol_right; +} sbxfi_portc_t; + +typedef struct +{ + oss_device_t *osdev; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + char *name; + int hw_family; + +// 20K1 models +#define HW_ORIG 0x0001 +#define HW_073x 0x0002 +#define HW_055x 0x0004 +#define HW_UAA 0x0008 + +// 20K2 models +#define HW_0760 0x0010 +#define HW_08801 0x0020 +#define HW_08802 0x0040 +#define HW_08803 0x0080 + + + unsigned int interrupt_count; + + // Hardware IDs + unsigned short wVendorID; + unsigned short wDeviceID; + unsigned short wSubsystemVendorID; + unsigned short wSubsystemID; + unsigned short wChipRevision; + + // Hardware Resources + unsigned int dwMemBase; + unsigned short wIOPortBase; + + // Buffers + oss_native_word dwPTBPhysAddx; + unsigned int *pdwPageTable; + unsigned int dwPageTableSize; + oss_dma_handle_t pgtable_dma_handle; + int next_pg; /* Next free index in the page table */ + + sbxfi_portc_t play_portc[MAX_OUTPUTDEVS]; + int nr_outdevs; + + sbxfi_portc_t rec_portc[MAX_INPUTDEVS]; + int nr_indevs; + + // Mixer + int mixer_dev; + + // Audio + int first_dev; + + int next_src; // Next free SRC channel + + sbxfi_portc_t *src_to_portc[256]; +} sbxfi_devc_t; diff --git a/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c b/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c new file mode 100644 index 0000000..4d4dad9 --- /dev/null +++ b/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c @@ -0,0 +1,1391 @@ +/** +******************************************************************************* +Confidential & Proprietary +Private & Confidential +Creative Confidential +******************************************************************************* +*/ +/** +******************************************************************************* +Copyright (C) Creative Technology, Ltd., 2007. All rights reserved. +******************************************************************************* +**/ +#include "oss_sbxfi_cfg.h" +#include <oss_pci.h> +#include "sbxfi.h" +#include "20k1reg.h" +#include "hwaccess.h" + +static const int +volume_table[MIXER_VOLSTEPS+1] = +{ + 0x0000000, 0x000010a, 0x0000110, 0x0000116, 0x000011d, + 0x0000124, 0x000012a, 0x0000131, 0x0000138, 0x0000140, + 0x0000147, 0x000014f, 0x0000157, 0x000015f, 0x0000167, + 0x000016f, 0x0000178, 0x0000180, 0x0000189, 0x0000193, + 0x000019c, 0x00001a6, 0x00001af, 0x00001b9, 0x00001c4, + 0x00001ce, 0x00001d9, 0x00001e4, 0x00001ef, 0x00001fb, + 0x0000207, 0x0000213, 0x000021f, 0x000022c, 0x0000239, + 0x0000246, 0x0000254, 0x0000262, 0x0000270, 0x000027e, + 0x000028d, 0x000029c, 0x00002ac, 0x00002bc, 0x00002cc, + 0x00002dd, 0x00002ee, 0x0000300, 0x0000311, 0x0000324, + 0x0000336, 0x000034a, 0x000035d, 0x0000371, 0x0000386, + 0x000039b, 0x00003b0, 0x00003c6, 0x00003dd, 0x00003f4, + 0x000040c, 0x0000424, 0x000043c, 0x0000456, 0x0000470, + 0x000048a, 0x00004a5, 0x00004c1, 0x00004dd, 0x00004fa, + 0x0000518, 0x0000536, 0x0000555, 0x0000575, 0x0000596, + 0x00005b7, 0x00005d9, 0x00005fc, 0x0000620, 0x0000644, + 0x000066a, 0x0000690, 0x00006b7, 0x00006df, 0x0000708, + 0x0000732, 0x000075d, 0x0000789, 0x00007b6, 0x00007e4, + 0x0000813, 0x0000843, 0x0000874, 0x00008a7, 0x00008da, + 0x000090f, 0x0000945, 0x000097c, 0x00009b5, 0x00009ef, + 0x0000a2a, 0x0000a67, 0x0000aa5, 0x0000ae4, 0x0000b25, + 0x0000b68, 0x0000bac, 0x0000bf1, 0x0000c38, 0x0000c81, + 0x0000ccc, 0x0000d18, 0x0000d66, 0x0000db6, 0x0000e08, + 0x0000e5c, 0x0000eb1, 0x0000f09, 0x0000f63, 0x0000fbe, + 0x000101c, 0x000107c, 0x00010df, 0x0001143, 0x00011aa, + 0x0001214, 0x000127f, 0x00012ee, 0x000135f, 0x00013d2, + 0x0001448, 0x00014c1, 0x000153d, 0x00015bc, 0x000163d, + 0x00016c2, 0x000174a, 0x00017d4, 0x0001863, 0x00018f4, + 0x0001989, 0x0001a21, 0x0001abd, 0x0001b5c, 0x0001c00 +}; + +unsigned char +DetectAndConfigureHardware (sbxfi_devc_t * devc) +{ + unsigned short wData; + + // Default setting for hendrix card is memory access, so must get IO access port from bar5. + // bar0 will be converted to IO access in SwitchToXFiCore() + if (devc->hw_family == HW_UAA) + { + // Base IO address is at register lcoation 0x24 (bar5) + pci_read_config_word (devc->osdev, PCI_BASE_ADDRESS_5, &wData); + devc->wIOPortBase = wData & 0xFFFC; + } + else + { + // Get the IO base address + pci_read_config_word (devc->osdev, PCI_BASE_ADDRESS_0, &wData); + devc->wIOPortBase = wData & 0xFFFC; + } + + return TRUE; +} + +unsigned char +IsVistaCompatibleHardware (sbxfi_devc_t * devc) +{ + // Check the subsystem id + if (devc->hw_family == HW_UAA) + { + return TRUE; + } + + return FALSE; +} + +void +SwitchToXFiCore (sbxfi_devc_t * devc) +{ + unsigned int bar0, bar1, bar2, bar3, bar4, bar5, irq, clSize, lTimer; + + // program the hardware to X-Fi core. + // Check whether its hendrix card + // Save the previous memory/io address + + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_0, &bar0); + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_1, &bar1); + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_2, &bar2); + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_3, &bar3); + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_4, &bar4); + pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_5, &bar5); + + pci_read_config_dword (devc->osdev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_dword (devc->osdev, PCI_CFGHDR_CACHESIZE, &clSize); + pci_read_config_dword (devc->osdev, PCI_CFGHDR_LATENCY, &lTimer); + + cmn_err (CE_CONT, "Switching to xfi core...\n"); + + // Switch to XFi core config space with BAR0 + pci_write_config_dword (devc->osdev, 0xA0, 0x87654321); + + // copy Base I/O address from UAA core to X-Fi core + pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_5, bar5); + + // Switch to XFi core config space without BAR0 + pci_write_config_dword (devc->osdev, 0xA0, 0x12345678); + + // copy all other setting from UAA config space to X-Fi config space + pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_1, bar1); + pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_2, bar2); + pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_3, bar3); + pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_4, bar4); + + pci_write_config_dword (devc->osdev, PCI_INTERRUPT_LINE, irq); + pci_write_config_dword (devc->osdev, PCI_CFGHDR_CACHESIZE, clSize); + pci_write_config_dword (devc->osdev, PCI_CFGHDR_LATENCY, lTimer); + + pci_write_config_dword (devc->osdev, PCI_CFGHDR_CMDREG, 0x07); + + /* + NOTE: + The steps below is needed to switch the control signals to X-Fi core. + + It needs to access the mode change register which reside in the UAA core BAR0 + 0x00003ffc. + Since this demo sample is a real-mode DOS program, it will need other services such as XMS to access + memory above 1MB. + + Here is the pseudo code: + + WriteMemory((bar0 + 0x00003ffc),0x43544c58); // CTLX + WriteMemory((bar0 + 0x00003ffc),0x43544c2d); // CTL- + WriteMemory((bar0 + 0x00003ffc),0x43544c46); // CTLF + WriteMemory((bar0 + 0x00003ffc),0x43544c69); // CTLi + */ +} + + +CTSTATUS +InitHardware (sbxfi_devc_t * devc) +{ + unsigned int gctlorg; + unsigned int dwIterCount, dwData; + + + // kick in auto-init + gctlorg = HwRead20K1 (devc, GCTL); + HwWrite20K1 (devc, GCTL, (~0x2 & gctlorg)); + HwWrite20K1 (devc, GCTL, (0x2 | gctlorg)); + osDelayms (1000); + // poll for AID in GCTL to be set + dwIterCount = 0x400000; + do + { + dwData = HwRead20K1 (devc, GCTL); + } + while (!(dwData & 0x00100000) && --dwIterCount); + + // AID bit is not set when time out, return failure. + if (!(dwData & 0x00100000)) + return CTSTATUS_ERROR; + + gctlorg = HwRead20K1 (devc, GCTL); + HwWrite20K1 (devc, GCTL, (0x100aa3 | gctlorg)); + osDelayms (10000); + + HwWrite20K1 (devc, GIE, 0); + HwWrite20K1 (devc, SRCIP(0), 0); + osDelayms (30000); + + if (((HwRead20K1 (devc, PLLCTL)) != 0x1480a001) + && ((HwRead20K1 (devc, PLLCTL)) != 0x1480a731)) + { + HwWrite20K1 (devc, PLLCTL, 0x1480a001); + } + osDelayms (40000); + dwData = HwRead20K1 (devc, PLLCTL); + + // configure GPIO per the card's family. + switch (devc->hw_family) + { + case HW_055x: + HwWrite20K1 (devc, GPIOCTL, 0x13fe); + break; + case HW_073x: + HwWrite20K1 (devc, GPIOCTL, 0x00e6); + break; + case HW_UAA: + HwWrite20K1 (devc, GPIOCTL, 0x00c2); + break; + case HW_ORIG: + default: + HwWrite20K1 (devc, GPIOCTL, 0x01e6); + break; + } + + return CTSTATUS_SUCCESS; +} + +CTSTATUS +AllocateBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + int ctStatus = CTSTATUS_SUCCESS; + +#if 0 + if (devc->pdwPageTable == NULL) + ctStatus = CTSTATUS_NOMEMORY; + else + { + // alloc playL buffer + portc->pdwPlayLBuffer = CONTIG_MALLOC (devc->osdev, + portc->dwPlayLBufferSize, + MEMLIMIT_32BITS, + &portc->dwPlayLPhysAddx, portc->playl_dma_handle); + + if (portc->pdwPlayLBuffer == NULL) + ctStatus = CTSTATUS_NOMEMORY; + else + { + // alloc playR buffer + portc->pdwPlayRBuffer = CONTIG_MALLOC (devc->osdev, + portc->dwPlayRBufferSize, + MEMLIMIT_32BITS, + &portc->dwPlayLPhysAddx,portc->playr_dma_handle); + + if (portc->pdwPlayRBuffer == NULL) + ctStatus = CTSTATUS_NOMEMORY; + else + { + // alloc recordL buffer + portc->pdwRecordLBuffer = CONTIG_MALLOC (devc->osdev, + portc-> + dwRecordLBufferSize, + MEMLIMIT_32BITS, + &portc-> + dwRecordLPhysAddx, portc->recl_dma_handle); + + if (portc->pdwRecordLBuffer == NULL) + ctStatus = CTSTATUS_NOMEMORY; + else + { + // alloc recordR buffer + portc->pdwRecordRBuffer = CONTIG_MALLOC (devc->osdev, + portc-> + dwRecordRBufferSize, + MEMLIMIT_32BITS, + &portc-> + dwRecordRPhysAddx, portc->recr_dma_handle); + if (portc->pdwRecordRBuffer == NULL) + ctStatus = CTSTATUS_NOMEMORY; + } + } + } + } + + if (ctStatus != CTSTATUS_SUCCESS) + FreeBuffers (devc, portc); +#endif + + return ctStatus; +} + +void +FreeBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ +#if 0 + if (portc->pdwRecordLBuffer != NULL) + { + CONTIG_FREE (devc->osdev, portc->pdwRecordLBuffer, + portc->dwRecordLBufferSize, portc->recl_dma_handle); + portc->pdwRecordLBuffer = NULL; + } + + if (portc->pdwRecordRBuffer != NULL) + { + CONTIG_FREE (devc->osdev, portc->pdwRecordRBuffer, + portc->dwRecordRBufferSize, portc->recr_dma_handle); + portc->pdwRecordRBuffer = NULL; + } + + if (portc->pdwPlayLBuffer != NULL) + { + CONTIG_FREE (devc->osdev, portc->pdwPlayLBuffer, + portc->dwPlayLBufferSize, portc->playl_dma_handle); + portc->pdwPlayLBuffer = NULL; + } + + if (portc->pdwPlayRBuffer != NULL) + { + CONTIG_FREE (devc->osdev, portc->pdwPlayRBuffer, + portc->dwPlayRBufferSize, portc->playr_dma_handle); + portc->pdwPlayRBuffer = NULL; + } +#endif +} + +void +_SetupSB055xADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db) +{ + unsigned short gpioorg; + unsigned short gpioval = 0x28; + + + // check and set the following GPIO bits accordingly + // ADC_Gain = GPIO2 + // Mic_Pwr_on = GPIO7 + // Digital_IO_Sel = GPIO8 + // Mic_Sw = GPIO9 + // Aux/MicLine_Sw = GPIO12 + switch (src) + { + case ADC_SRC_MICIN: + gpioval = 0x28; + if (mic20db) + gpioval |= 4; + break; + + case ADC_SRC_LINEIN: + gpioval = 0; + break; + + case ADC_SRC_VIDEO: + gpioval = 0x100; // not supported, set to digital + break; + + case ADC_SRC_AUX: + gpioval = 0x1000; + break; + + case ADC_SRC_NONE: + gpioval = 0x100; // set to digital + break; + + default: + break; + } + + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg &= 0xec7b; + gpioorg |= gpioval; + HwWrite20K1 (devc, GPIO, gpioorg); + + return; +} + +void +_SetupADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db) +{ + unsigned int i = 0; + unsigned short gpioorg; + unsigned short input_source; + unsigned int adcdata = 0; + + input_source = 0x100; // default to analog + switch (src) + { + case ADC_SRC_MICIN: + adcdata = 0x1; + input_source = 0x180; // set GPIO7 to select Mic + break; + + case ADC_SRC_LINEIN: + adcdata = 0x2; + break; + + case ADC_SRC_VIDEO: + adcdata = 0x4; + break; + + case ADC_SRC_AUX: + adcdata = 0x8; + break; + + case ADC_SRC_NONE: + adcdata = 0x0; + input_source = 0x0; // set to Digital + break; + + default: + break; + } + + + HwWrite20K1PCI (devc, 0xcc, 0x8c); + HwWrite20K1PCI (devc, 0xcc, 0x0e); + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + { + HwWrite20K1PCI (devc, 0xcc, 0xee); + HwWrite20K1PCI (devc, 0xcc, 0xaa); + } + + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + return; + + HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + HwWrite20K1PCI (devc, 0xE4, 0x080e); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + HwWrite20K1PCI (devc, 0xE4, 0x0a18); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + + if (mic20db) + HwWrite20K1PCI (devc, 0xE4, 0xf71c); + else + HwWrite20K1PCI (devc, 0xE4, 0xcf1c); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + + if (mic20db) + HwWrite20K1PCI (devc, 0xE4, 0xf71e); + else + HwWrite20K1PCI (devc, 0xE4, 0xcf1e); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + HwWrite20K1PCI (devc, 0xE4, 0x8628); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + HwWrite20K1PCI (devc, 0xE4, 0x2a | (adcdata << 0x8)); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } //i2c ready poll + + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg &= 0xfe7f; + gpioorg |= input_source; + HwWrite20K1 (devc, GPIO, gpioorg); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + if (!((HwRead20K1 (devc, ID0)) & 0x100)) + { + HwWrite20K1PCI (devc, 0xE0, 0x001a0080); + HwWrite20K1PCI (devc, 0xE4, 0x2616); + } + + return; +} + +void +InitADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db) +{ + unsigned short wSSID; + + wSSID = devc->wSubsystemID; + if ((wSSID == 0x0022) || (wSSID == 0x002F)) + { + // Sb055x card + _SetupSB055xADC (devc, src, mic20db); + } + else + { + _SetupADC (devc, src, mic20db); + } + + return; +} + +void +ResetDAC (sbxfi_devc_t * devc) +{ + unsigned int i = 0; + unsigned short gpioorg; + + + HwWrite20K1PCI (devc, 0xcc, 0x8c); + HwWrite20K1PCI (devc, 0xcc, 0x0e); + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + { + HwWrite20K1PCI (devc, 0xcc, 0xee); + HwWrite20K1PCI (devc, 0xcc, 0xaa); + } + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + return; + + HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + // To be effective, need to reset the DAC twice. + for (i = 0; i < 2; i++) + { + osDelayms (100000); + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg &= 0xfffd; + HwWrite20K1 (devc, GPIO, gpioorg); + osDelayms (1000); + HwWrite20K1 (devc, GPIO, gpioorg | 0x2); + } //set gpio + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, 0x8001); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, 0x1002); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } +} + +void +InitDAC (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int i = 0; + unsigned int wData; + unsigned short gpioorg; + unsigned int dwSamplingRate; + unsigned short wSSID; + + + wSSID = devc->wSubsystemID; + // if SB055x, unmute outputs + if ((wSSID == 0x0022) || (wSSID == 0x002F)) + { + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg &= 0xffbf; // set GPIO6 to low + gpioorg |= 2; // set GPIO1 to high + HwWrite20K1 (devc, GPIO, gpioorg); + + return; + } + + + dwSamplingRate = portc->rate; + + // Mute outputs + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg &= 0xffbf; + HwWrite20K1 (devc, GPIO, gpioorg); + + ResetDAC (devc); + + HwWrite20K1PCI (devc, 0xcc, 0x8c); + HwWrite20K1PCI (devc, 0xcc, 0x0e); + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + { + HwWrite20K1PCI (devc, 0xcc, 0xee); + HwWrite20K1PCI (devc, 0xcc, 0xaa); + } + if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa) + return; + + HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + if (dwSamplingRate == 48000) + wData = 0x2400; + else if (dwSamplingRate == 96000) + wData = 0x2500; + else if (dwSamplingRate == 192000) + wData = 0x2600; + else + wData = 0x2400; + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, (wData | 0x6)); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, (wData | 0x9)); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, (wData | 0xc)); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + HwWrite20K1PCI (devc, 0xE0, 0x00180080); + HwWrite20K1PCI (devc, 0xE4, (wData | 0xf)); + + i = 0; + while (i != 0x800000) + { + i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000); + } + + // unmute outputs + gpioorg = (unsigned short) HwRead20K1 (devc, GPIO); + gpioorg = gpioorg | 0x40; + HwWrite20K1 (devc, GPIO, gpioorg); +} + + +void +SetupPlayInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ +/* + * TODO: This routine supports only stereo + */ + unsigned int i; + unsigned int srcch; + unsigned int dio1, dio2; + unsigned int dwSamplingRate; + + + srcch = portc->SrcChan; + dio1 = portc->dwDAChan[0]; + dio2 = portc->dwDAChan[1]; + dwSamplingRate = portc->rate; + + // initialize input mappers + for (i = 0; i < 0x50; i++) + HwWrite20K1 (devc, DAOIMAP_START(i), 0); + + if (dwSamplingRate == 48000) + { + if (dio1 == 0) + { + HwWrite20K1 (devc, DAOIMAP_START(dio1), 0); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2), + (dio1 << 16) | GetAudioSrcChan (srcch+i)); + HwWrite20K1 (devc, DAOIMAP_START(dio1), + (dio2 << 16) | GetAudioSrcChan (srcch)); + } + else + { + HwWrite20K1 (devc, DAOIMAP_START(0), 0); + HwWrite20K1 (devc, DAOIMAP_START(dio1), + (dio2 << 16) | GetAudioSrcChan (srcch)); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2), + (0 << 16) | GetAudioSrcChan (srcch+i)); + HwWrite20K1 (devc, DAOIMAP_START(0), (dio1 << 16) | 0); + } + } + else if (dwSamplingRate == 96000) + { + // input mapper. Input mapper is a circular linked-list + if (dio1 == 0) + { + HwWrite20K1 (devc, DAOIMAP_START(dio1), 0); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2), + ((dio1 + 2) << 16) | GetAudioSrcChan (srcch+i)); + HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2), + ((dio2 + 2) << 16) | GetAudioSrcChan (srcch + 0x80)); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2), + (dio1 << 16) | GetAudioSrcChan (srcch+i + 0x80)); + HwWrite20K1 (devc, DAOIMAP_START(dio1), + (dio2 << 16) | GetAudioSrcChan (srcch)); + } + else + { + HwWrite20K1 (devc, DAOIMAP_START(0), 0); + HwWrite20K1 (devc, DAOIMAP_START(dio1), + (dio2 << 16) | GetAudioSrcChan (srcch)); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2), + ((dio1 + 2) << 16) | GetAudioSrcChan (srcch+i)); + HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2), + ((dio2 + 2) << 16) | GetAudioSrcChan (srcch + 0x80)); + for (i=1;i<portc->channels;i++) + HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2), + (0 << 16) | GetAudioSrcChan (srcch+i + 0x80)); + HwWrite20K1 (devc, DAOIMAP_START(0), (dio1 << 16) | 0); + } + } +} + +void +SetupPlayFormat (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int i2sorg; + unsigned int dio1; + unsigned int dwSamplingRate; + + + dio1 = portc->dwDAChan[0]; + dwSamplingRate = portc->rate; + + // Read I2S CTL. Keep original value. + i2sorg = HwRead20K1 (devc, I2SCTL); + +#if 1 + i2sorg = i2sorg | 0x04040404; // All I2S outputs enabled +#else + // setup I2S value to program + switch (dio1) + { + case I2SA_L: + i2sorg = i2sorg | 0x4; + break; + case I2SB_L: + i2sorg = i2sorg | 0x400; + break; + case I2SC_L: + i2sorg = i2sorg | 0x40000; + break; + case I2SD_L: + i2sorg = i2sorg | 0x4000000; + break; + default: + i2sorg = i2sorg | 0x4; + break; + } +#endif + + // Program I2S with proper sample rate and enable the correct I2S channel. + i2sorg &= 0xfffffffc; + if (dwSamplingRate == 96000) + { + i2sorg = i2sorg | 2; + HwWrite20K1 (devc, I2SCTL, i2sorg); + } + else + { + i2sorg = i2sorg | 1; + HwWrite20K1 (devc, I2SCTL, i2sorg); + } +} + +void +SetupPlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + int i; + unsigned int fixed_pitch; + unsigned int srcArchn, srcArchnC; + unsigned int srcPrchn, srcPrchnC; + unsigned int srcArchn2, srcArchnC2; + unsigned int srcch; + unsigned int dwSamplingRate; + unsigned int dwYData; + + srcch = portc->SrcChan; + dwSamplingRate = portc->rate; + + // NOTE: Y-Data is a 14-bit immediate floating-point constant multiplier. + // Adjust the Y-Data to control the multiplier. + // This can be used to control the level of the signal. + // dwYData = 0x1c00; // Original level used by Creative's driver. + dwYData = volume_table[portc->vol_left]; + + srcArchn = GetAudioSrcChan (srcch); + srcArchnC = GetAudioSrcChan (srcch + 0x80); // conjugate channel for srcch + srcPrchn = GetParamPitchChan (srcch); + srcPrchnC = GetParamPitchChan (srcch + 0x80); + + // since input is same as output, pitch is 1.0 + // convert to fixed-point 8.24 format, shift left 24 bit. + fixed_pitch = 1; + fixed_pitch = fixed_pitch << 24; + + // write the pitch to param ring of the corresponsing SRC pitch slot + HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchn), fixed_pitch); + HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchnC), fixed_pitch); + + WriteAMOP (devc, srcArchn, dwYData, srcArchn, 0); + if (dwSamplingRate == 96000) + { + WriteAMOP (devc, srcArchnC, dwYData, srcArchnC, 0); + } + + // Handle subsequent channels + + for (i=1;i<portc->channels;i++) + { + dwYData = volume_table[(i&1) ? portc->vol_right : portc->vol_left]; + + // Since we will use 1st SRC ch as pitch master, + // we do not need to program the pitch for SRC ch2 + + srcArchn2 = GetAudioSrcChan (srcch+i); + srcArchnC2 = GetAudioSrcChan (srcch+i + 0x80); // conjugate channel for srcch+i + + WriteAMOP (devc, srcArchn2, dwYData, srcArchn2, 0); + if (dwSamplingRate == 96000) + { + WriteAMOP (devc, srcArchnC2, dwYData, srcArchnC2, 0); + } + } +} + +void +SetupAndStartPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int Sa, Ladr, Ca, Ctl = 0x44c; + unsigned int srcch; + unsigned int dwSamplingRate; + int count; + int i; + + srcch = portc->SrcChan; + dwSamplingRate = portc->rate; + + count = audio_engines[portc->dev]->dmap_out->bytes_in_use; + + // start addx: 1st entry in page table. + // Note: this must match with pagetable entry + Sa = portc->pgtable_index * 4096; + Ladr = Sa + count; + Ca = Sa + 0x100; + if (dwSamplingRate == 48000) + Ctl = 0x44c; // Set the Pitch Master for stereo. + else if ((dwSamplingRate == 96000)) + Ctl = 0x45c; // Set the Pitch Master for stereo. + + Ctl |= (portc->channels-1)*SRCCTL_ILSZ; /* Number of interleaved channels to follow */ + + // Program SRC for channel 1, enable interrupts and interleaved channels + WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch); + + Ladr = Sa + count; + Ca = Sa + 0x100; + + for (i=1;i<portc->channels;i++) + { + if (dwSamplingRate == 48000) + Ctl = 0x4c; // slave + else if ((dwSamplingRate == 96000)) + Ctl = 0x5c; // slave + Ctl |= (portc->channels-i-1)*SRCCTL_ILSZ; + + // Program SRC for channel 2 + WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch+i); + } + + //_dumpRegisters (devc, portc); +} + +void +StopPlay (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int srcch; + unsigned int dwData; + int i; + + srcch = portc->SrcChan; + + //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch); + //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch2); + + dwData = HwRead20K1 (devc, SRCCTL(srcch)); + dwData &= 0xfffffff0; + dwData |= 0; + dwData &= ~SRCCTL_IE; /* Interrupt disable */ + HwWrite20K1 (devc, SRCCTL(srcch), dwData); + + for (i=1;i<portc->channels;i++) + { + dwData = HwRead20K1 (devc, SRCCTL(srcch+i)); + dwData &= 0xfffffff0; + dwData |= 0; + HwWrite20K1 (devc, SRCCTL(srcch+i), dwData); + } +} + + +void +StopPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ +#ifndef INTERNAL_LOOPBACK + StopPlay (devc, portc); +#endif +} + + +//======================== RECORD ========================== + + + +void +SetupRecordInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int srcch, srcch2; + + + srcch = portc->SrcChan; + srcch2 = portc->SrcChan+1; + + // Internal loopback means loop play channels to record +#ifdef INTERNAL_LOOPBACK + { + unsigned int playch1, playch2; + + playch1 = portc->dwPlayLSrcChan; + playch2 = portc->dwPlayRSrcChan; + if (srcch == 0) + { + HwWrite20K1 (devc, SRCIMAP(0), 0); + HwWrite20K1 (devc, SRCIMAP(srcch2), + srcch2 << 24 | (0x80 + + srcch) << 16 | + GetAudioSrcChan (playch2)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch), + (0x80 + srcch) << 24 | (srcch2 + + 0x80) << 16 | + GetAudioSrcChan (playch1 + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0x81 + srcch2), + (0x80 + + srcch2) << 24 | 0 << 16 | GetAudioSrcChan (playch2 + + 0x80)); + HwWrite20K1 (devc, SRCIMAP(srcch), + srcch << 24 | srcch2 << 16 | GetAudioSrcChan (playch1)); + } + else + { + HwWrite20K1 (devc, SRCIMAP(0), 0); + HwWrite20K1 (devc, SRCIMAP(srcch), + srcch << 24 | srcch2 << 16 | GetAudioSrcChan (playch1)); + HwWrite20K1 (devc, SRCIMAP(srcch2), + srcch2 << 24 | (0x80 + + srcch) << 16 | + GetAudioSrcChan (playch2)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch), + (0x80 + srcch) << 24 | (srcch2 + + 0x80) << 16 | + GetAudioSrcChan (playch1 + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch2), + (0x80 + + srcch2) << 24 | 0 << 16 | GetAudioSrcChan (playch2 + + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0), + (0 << 24) | (srcch << 16) | 0x0); + } + } +#else + { + if (srcch == 0) + { + HwWrite20K1 (devc, SRCIMAP(0), 0); + HwWrite20K1 (devc, SRCIMAP(srcch2), + srcch2 << 24 | (0x80 + + srcch) << 16 | + GetAudioSumChan (srcch2)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch), + (0x80 + srcch) << 24 | (srcch2 + + 0x80) << 16 | + GetAudioSumChan (srcch + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0x81 + srcch2), + (0x80 + + srcch2) << 24 | 0 << 16 | GetAudioSumChan (srcch2 + + 0x80)); + HwWrite20K1 (devc, SRCIMAP(srcch), + srcch << 24 | srcch2 << 16 | GetAudioSumChan (srcch)); + } + else + { + HwWrite20K1 (devc, SRCIMAP(0), 0); + HwWrite20K1 (devc, SRCIMAP(srcch), + srcch << 24 | srcch2 << 16 | GetAudioSumChan (srcch)); + HwWrite20K1 (devc, SRCIMAP(srcch2), + srcch2 << 24 | (0x80 + + srcch) << 16 | + GetAudioSumChan (srcch2)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch), + (0x80 + srcch) << 24 | (srcch2 + + 0x80) << 16 | + GetAudioSumChan (srcch + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0x80 + srcch2), + (0x80 + + srcch2) << 24 | 0 << 16 | GetAudioSumChan (srcch2 + + 0x80)); + HwWrite20K1 (devc, SRCIMAP(0), + (0 << 24) | (srcch << 16) | 0x0); + } + } +#endif +} + + +void +_SetupInputToOutputMonitoring (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int i; + unsigned int dio1, dio2; + unsigned int srcch, srcch2; + + + srcch = portc->SrcChan; + srcch2 = portc->SrcChan+1; + + dio1 = portc->dwDAChan[0]; + dio2 = portc->dwDAChan[1]; + + // initialize input mappers + for (i = 0; i < 0x50; i++) + HwWrite20K1 (devc, DAOIMAP_START(i), 0); + + HwWrite20K1 (devc, DAOIMAP_START(dio1), 0); + HwWrite20K1 (devc, DAOIMAP_START(dio2), + ((dio1 + 2) << 16) | GetAudioSumChan (srcch2)); + HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2), + ((dio2 + 2) << 16) | GetAudioSumChan (srcch + 0x80)); + HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2), + (dio1 << 16) | GetAudioSumChan (srcch2 + 0x80)); + HwWrite20K1 (devc, DAOIMAP_START(dio1), + (dio2 << 16) | GetAudioSumChan (srcch)); +} + +void +SetupRecordMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int fixed_pitch; + unsigned int srcPrchn1, srcPrchnC1; + unsigned int srcch, srcch2, srcchnC1, srcchnC2; + unsigned int dwYData; + unsigned short i, inch1, inch2; + + + srcch = portc->SrcChan; + srcch2 = portc->SrcChan+1; + + // NOTE: Y-Data is a 14-bit immediate floating-point constant multiplier. + // Adjust the Y-Data to control the multiplier. + // This can be used to control the level of the signal. + dwYData = 0x1c00; + + srcchnC1 = srcch + 0x80; + srcchnC2 = srcch2 + 0x80; + + srcPrchn1 = GetParamPitchChan (srcch); + srcPrchnC1 = GetParamPitchChan (srcch + 0x80); + + // since input is 2x of output, pitch is 2.0 + // convert to fixed-point 8.24 format, shift left 24 bit. + fixed_pitch = 2; + fixed_pitch = fixed_pitch << 24; + + // write the pitch to param ring of the corresponsing SRC pitch slot + HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchn1), fixed_pitch); + HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchnC1), fixed_pitch); + + inch1 = 0x1b5; // I2S-In3 L + inch2 = 0x1bd; // I2S-In3 R + // program all I2S-In3 slots + for (i = 0; i < 8; i++) + { + if (i <= 3) + { + WriteAMOP (devc, inch1 + (i * 0x200), dwYData, inch1 + (i * 0x200), + (0x80000000 + srcch)); + WriteAMOP (devc, inch2 + (i * 0x200), dwYData, inch2 + (i * 0x200), + (0x80000000 + srcch2)); + } + else + { + WriteAMOP (devc, inch1 + (i * 0x200), dwYData, inch1 + (i * 0x200), + (0x80000000 + srcchnC1)); + WriteAMOP (devc, inch2 + (i * 0x200), dwYData, inch2 + (i * 0x200), + (0x80000000 + srcchnC2)); + } + } + + // enable physical input I2S_in3 to I2S-Out0 monitoring + _SetupInputToOutputMonitoring (devc, portc); +} + +void +SetupRecordFormat (sbxfi_devc_t * devc) +{ + unsigned int i2sorg; + + i2sorg = HwRead20K1 (devc, I2SCTL); + + // enable I2S-D input + i2sorg |= 0x90000000; + HwWrite20K1 (devc, I2SCTL, i2sorg); +} + +void +SetupAndStartRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int Sa, Ladr, Ca, Ctl = 0x64d; + int count; + unsigned int srcch, srcch2; + unsigned int dwSamplingRate; + + + srcch = portc->SrcChan; + srcch2 = portc->SrcChan+1; + dwSamplingRate = portc->rate; + + count = audio_engines[portc->dev]->dmap_in->bytes_in_use; + + // convert the num samples to bytes count + + // hardcoded values: + // start addx: 4th entry in page table. + Sa = portc->pgtable_index * 4096; + Ladr = Sa + count; + Ca = Sa + 0x80; + if (dwSamplingRate == 48000) + Ctl = 0x64d; // record must start with RUN state!. + else if ((dwSamplingRate == 96000)) + Ctl = 0x65d; + + Ctl |= SRCCTL_ILSZ; // Interleaved stereo + + WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch); + + Ladr = Sa + count; + Ca = Sa + 0x80; + if (dwSamplingRate == 48000) + Ctl = 0x24d; + else if ((dwSamplingRate == 96000)) + Ctl = 0x25d; + + WriteSRC (devc, Ca, 0, Sa, Ladr, 0x80, Ctl, srcch2); + + // Enable SRC input from Audio Ring + HwWrite20K1 (devc, SRCMCTL, 0x1); + +// _dumpRegisters(devc); +} + +void +StopRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int srcch, srcch2; + unsigned int dwData; + unsigned int i; + + srcch = portc->SrcChan; + srcch2 = portc->SrcChan+1; + + //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch); + //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch2); + + dwData = HwRead20K1 (devc, SRCCTL(srcch)); + dwData &= 0xfffffff0; + dwData |= 0; + HwWrite20K1 (devc, SRCCTL(srcch), dwData); + + dwData = HwRead20K1 (devc, SRCCTL(srcch2)); + dwData &= 0xfffffff0; + dwData |= 0; + HwWrite20K1 (devc, SRCCTL(srcch2), dwData); + +#ifdef INTERNAL_LOOPBACK + StopPlay (devc, portc); +#endif + + // Disable SRC inputs from Audio Ring + HwWrite20K1 (devc, SRCMCTL, 0x0); + + for (i = 0; i < 0x50; i++) + HwWrite20K1 (devc, DAOIMAP_START(i), 0); +} + +//======================== + +unsigned int +HwRead20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg) +{ + unsigned int dwVal; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x10, dwReg); + dwVal = osInportd (devc, (IOADDR) (devc->wIOPortBase + 0x14)); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dwVal; +} + +unsigned int +HwRead20K1 (sbxfi_devc_t * devc, unsigned int dwReg) +{ + unsigned int dwVal; + + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x0, dwReg); + dwVal = osInportd (devc, (IOADDR) (devc->wIOPortBase + 0x4)); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + + return dwVal; +} + +void +HwWrite20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData) +{ + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x10, dwReg); + osOutportd (devc, (IOADDR) (devc->wIOPortBase + 0x14), dwData); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +void +HwWrite20K1 (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData) +{ + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x0, dwReg); + osOutportd (devc, (IOADDR) (devc->wIOPortBase + 0x4), dwData); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +void +WriteSRC + (sbxfi_devc_t * devc, + unsigned int srcca, + unsigned int srccf, + unsigned int srcsa, unsigned int srcla, unsigned int srcccr, unsigned int srcctl, unsigned int chn) +{ + HwWrite20K1 (devc, SRCCA(chn), srcca); // Current Address + HwWrite20K1 (devc, SRCCF(chn), srccf); // Current Fraction + HwWrite20K1 (devc, SRCSA(chn), srcsa); // START address + HwWrite20K1 (devc, SRCLA(chn), srcla); // LOOP address + HwWrite20K1 (devc, SRCCCR(chn), srcccr); // Cache control + HwWrite20K1 (devc, SRCCTL(chn), srcctl); // SRCCTL +} + +#define CRM_TIMESLOT_ALLOC_BLOCK_SIZE 16 +#define CRM_PTS_PITCH 6 +#define CRM_PARAM_SRC_OFFSET 0x60 + +unsigned int +GetParamPitchChan (unsigned int i) +{ + int interpChanID = + (((int) i * CRM_TIMESLOT_ALLOC_BLOCK_SIZE) + CRM_PTS_PITCH) - + CRM_PARAM_SRC_OFFSET; + if (interpChanID < 0) + { + interpChanID += 4096; + } + return (unsigned int) interpChanID; +} + +unsigned int +GetAudioSrcChan (unsigned int srcchn) +{ + // SRC channel is in Audio Ring slot 1, after every 16 slot. + return (unsigned int) ((srcchn << 4) + 0x1); +} + +unsigned int +GetAudioSumChan (unsigned int chn) +{ + // SUM channel is in Audio Ring slot 0xc, after every 16 slot. + return (unsigned int) ((chn << 4) + 0xc); +} + +void +WriteAMOP + (sbxfi_devc_t * devc, + unsigned int xdata, unsigned int ydata, unsigned int chn, unsigned int hidata) +{ + HwWrite20K1 (devc, AMOP_START(chn), ((((unsigned int) ydata) << 18) | xdata << 4 | 1)); // Audio mixer, y-immediate + HwWrite20K1 (devc, AMOP_START(chn) + 4, hidata); // Audio mixer. +} + +void +_dumpRegisters (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + _dumpGlobal (devc); + _dumpSRCs (devc, portc); +} + +void +_dumpSRCs (sbxfi_devc_t * devc, sbxfi_portc_t * portc) +{ + unsigned int chn; + + chn = portc->SrcChan; + cmn_err (CE_CONT, + "SRC chn=%lx, CA=%lx, CF=%lx, SA=%lx, LA=%lx, CCR=%lx, CTL=%lx\n", + chn, HwRead20K1 (devc, SRCCA(chn)), + HwRead20K1 (devc, SRCCF(chn)), HwRead20K1 (devc, + SRCSA(chn)), + HwRead20K1 (devc, SRCLA(chn)), HwRead20K1 (devc, + SRCCCR(chn)), + HwRead20K1 (devc, SRCCTL(chn))); + + chn = portc->SrcChan+1; + cmn_err (CE_CONT, + "SRC chn=%lx, CA=%lx, CF=%lx, SA=%lx, LA=%lx, CCR=%lx, CTL=%lx\n", + chn, HwRead20K1 (devc, SRCCA(chn)), + HwRead20K1 (devc, SRCCF(chn)), HwRead20K1 (devc, + SRCSA(chn)), + HwRead20K1 (devc, SRCLA(chn)), HwRead20K1 (devc, + SRCCCR(chn)), + HwRead20K1 (devc, SRCCTL(chn))); +} + + +void +_dumpGlobal (sbxfi_devc_t * devc) +{ + unsigned int i; + + cmn_err (CE_CONT, + "GCTL=%lx, PLLCTL=%lx, GPIOCTL=%lx, GPIO=%lx, I2SCTL=%lx\n", + HwRead20K1 (devc, GCTL), HwRead20K1 (devc, PLLCTL), + HwRead20K1 (devc, GPIOCTL), HwRead20K1 (devc, GPIO), + HwRead20K1 (devc, I2SCTL)); +#if 1 + cmn_err (CE_CONT, "DAOIMAP....\n"); + for (i = 0; i < 0x50; i++) + { + cmn_err (CE_CONT, "%02lx: %lx ", i, + HwRead20K1 (devc, DAOIMAP_START(i))); + if (((i + 1) % 8) == 0) + cmn_err (CE_CONT, "\n"); + } +#endif +#if 0 + cmn_err (CE_CONT, "PageTable PhysAddx=%lx\n", HwRead20K1 (devc, PTPALX)); + for (i = 0; i < 10; i++) + { + cmn_err (CE_CONT, "Entry[%lx]=%lx\n", i, devc->pdwPageTable[i]); + } +#endif +} diff --git a/kernel/drv/oss_solo/.config b/kernel/drv/oss_solo/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_solo/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_solo/.devices b/kernel/drv/oss_solo/.devices new file mode 100644 index 0000000..6003e9e --- /dev/null +++ b/kernel/drv/oss_solo/.devices @@ -0,0 +1 @@ +oss_solo pci125d,1969 ESS Solo-1 diff --git a/kernel/drv/oss_solo/.name b/kernel/drv/oss_solo/.name new file mode 100644 index 0000000..4711141 --- /dev/null +++ b/kernel/drv/oss_solo/.name @@ -0,0 +1 @@ +ESS Solo-1 diff --git a/kernel/drv/oss_solo/oss_solo.c b/kernel/drv/oss_solo/oss_solo.c new file mode 100644 index 0000000..03605d9 --- /dev/null +++ b/kernel/drv/oss_solo/oss_solo.c @@ -0,0 +1,1230 @@ +/* + * Purpose: Driver for ESS Solo 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_solo_cfg.h" +#include "oss_pci.h" + +#define ESS_VENDOR_ID 0x125d +#define ESS_SOLO1 0x1969 + +#define DSP_RESET (devc->sb_base + 0x6) +#define DSP_READ (devc->sb_base + 0xA) +#define DSP_WRITE (devc->sb_base + 0xC) +#define DSP_WRSTATUS (devc->sb_base + 0xC) +#define DSP_STATUS (devc->sb_base + 0xE) +#define DSP_STATUS16 (devc->sb_base + 0xF) +#define MIXER_ADDR (devc->sb_base + 0x4) +#define MIXER_DATA (devc->sb_base + 0x5) +#define OPL3_LEFT (devc->sb_base + 0x0) +#define OPL3_RIGHT (devc->sb_base + 0x2) +#define OPL3_BOTH (devc->sb_base + 0x8) + +#define DSP_CMD_SPKON 0xD1 +#define DSP_CMD_SPKOFF 0xD3 + +#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) +#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | \ + SOUND_MASK_LINE | SOUND_MASK_MIC | \ + SOUND_MASK_CD | SOUND_MASK_VOLUME) +#define SOLO_RECORDING_DEVICES (SBPRO_RECORDING_DEVICES) +#define SOLO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER|SOUND_MASK_RECLEV|SOUND_MASK_LINE1) + +#define LEFT_CHN 0 +#define RIGHT_CHN 1 + +#define VOC_VOL 0x04 +#define MIC_VOL 0x0A +#define MIC_MIX 0x0A +#define RECORD_SRC 0x0C +#define IN_FILTER 0x0C +#define OUT_FILTER 0x0E +#define MASTER_VOL 0x22 +#define FM_VOL 0x26 +#define CD_VOL 0x28 +#define LINE_VOL 0x2E +#define IRQ_NR 0x80 +#define DMA_NR 0x81 +#define IRQ_STAT 0x82 +#define OPSW 0x3c + +static int default_levels[32] = { + 0x5a5a, /* Master Volume */ + 0x4b4b, /* Bass */ + 0x4b4b, /* Treble */ + 0x4b4b, /* FM */ + 0x4b4b, /* PCM */ + 0x4b4b, /* PC Speaker */ + 0x4b4b, /* Ext Line */ + 0x2020, /* Mic */ + 0x4b4b, /* CD */ + 0x0000, /* Recording monitor */ + 0x4b4b, /* SB PCM */ + 0x4b4b, /* Recording level */ + 0x4b4b, /* Input gain */ + 0x4b4b, /* Output gain */ + 0x4040, /* Line1 */ + 0x4040, /* Line2 */ + 0x1515 /* Line3 */ +}; + +#define MAX_PORTC 2 + +typedef struct solo_portc +{ + int speed, bits, channels; + int open_mode; + int audiodev; + int trigger_bits; + int audio_enabled; +} +solo_portc; + +typedef struct solo_devc +{ + oss_device_t *osdev; + oss_native_word base, ddma_base, sb_base, mpu_base; + + int mpu_attached, fm_attached; + int irq; + char *chip_name; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + oss_native_word last_capture_addr; + /* Audio parameters */ + solo_portc portc[MAX_PORTC]; + + /* Mixer parameters */ + int *levels; + int recmask; +} +solo_devc; + + +static int +solo_command (solo_devc * devc, unsigned char val) +{ + int i; + + for (i = 0; i < 0x10000; i++) + { + if ((INB (devc->osdev, DSP_WRSTATUS) & 0x80) == 0) + { + OUTB (devc->osdev, val, DSP_WRITE); + return 1; + } + } + + cmn_err (CE_WARN, "Command(%x) Timeout.\n", val); + return 0; +} + +static int +solo_get_byte (solo_devc * devc) +{ + int i; + + for (i=0; i < 0x10000; i++) + if (INB (devc->osdev, DSP_STATUS) & 0x80) + { + return INB (devc->osdev, DSP_READ); + } + + return 0xffff; +} + +static int +ext_read (solo_devc * devc, unsigned char reg) +{ + + if (!solo_command (devc, 0xc0)) /* Read register command */ + return OSS_EIO; + + if (!solo_command (devc, reg)) + return OSS_EIO; + + return solo_get_byte (devc); +} + +static int +ext_write (solo_devc * devc, unsigned char reg, unsigned char data) +{ + if (!solo_command (devc, reg)) + return 0; + return solo_command (devc, data); +} + +static unsigned int +solo_getmixer (solo_devc * devc, unsigned int port) +{ + unsigned int val; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR); + oss_udelay (50); + val = INB (devc->osdev, MIXER_DATA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return val; +} + +static void +solo_setmixer (solo_devc * devc, unsigned int port, unsigned int value) +{ + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR); + oss_udelay (50); + OUTB (devc->osdev, (unsigned char) (value & 0xff), MIXER_DATA); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +static int +solo_reset (solo_devc * devc) +{ + int loopc; + + DDB (cmn_err (CE_WARN, "Entered solo_reset()\n")); + + OUTB (devc->osdev, 3, DSP_RESET); /* Reset FIFO too */ + INB (devc->osdev, DSP_RESET); /* Reset FIFO too */ + OUTB (devc->osdev, 0, DSP_RESET); + oss_udelay (10); + + for (loopc = 0; loopc < 0x10000; loopc++) + if (INB (devc->osdev, DSP_STATUS) & 0x80) + if (INB (devc->osdev, DSP_READ) != 0xAA) + { + DDB (cmn_err (CE_WARN, "No response to RESET\n")); + return 0; /* Sorry */ + } + solo_command (devc, 0xc6); /* Enable extended mode */ + + ext_write (devc, 0xb9, 3); /* Demand mode - set to reserve mode */ + solo_setmixer (devc, 0x71, 0x32); /* 4x sampling + DAC2 asynch */ + + /* enable DMA/IRQ */ + ext_write (devc, 0xb1, (ext_read (devc, 0xb1) & 0x0F) | 0x50); + ext_write (devc, 0xb2, (ext_read (devc, 0xb2) & 0x0F) | 0x50); + + DDB (cmn_err (CE_WARN, "solo_reset() OK\n")); + return 1; +} + +struct mixer_def +{ + unsigned int regno:8; + unsigned int bitoffs:4; + unsigned int nbits:4; +}; + +typedef struct mixer_def mixer_tab[32][2]; +typedef struct mixer_def mixer_ent; + +#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \ + {{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}} + +static mixer_tab solo_mix = { + MIX_ENT (SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4), + MIX_ENT (SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), + MIX_ENT (SOUND_MIXER_PCM, 0x7c, 7, 4, 0x7c, 3, 4), + MIX_ENT (SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), + MIX_ENT (SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), + MIX_ENT (SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), + MIX_ENT (SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_ALTPCM, 0x7c, 7, 4, 0x7c, 3, 4), + MIX_ENT (SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4), + MIX_ENT (SOUND_MIXER_IGAIN, 0x68, 7, 4, 0x68, 3, 4), + MIX_ENT (SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), + MIX_ENT (SOUND_MIXER_LINE1, 0x6d, 7, 4, 0x6d, 3, 4), + MIX_ENT (SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), + MIX_ENT (SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0) +}; + +/*ARGSUSED*/ +static void +change_bits (solo_devc * devc, unsigned char *regval, int dev, int chn, + int newval) +{ + unsigned char mask; + int shift; + + mask = (1 << solo_mix[dev][chn].nbits) - 1; + newval = (int) ((newval * mask) + 50) / 100; /* Scale */ + + shift = solo_mix[dev][chn].bitoffs - solo_mix[dev][LEFT_CHN].nbits + 1; + + *regval &= ~(mask << shift); /* Mask out previous value */ + *regval |= (newval & mask) << shift; /* Set the new value */ +} + +#if 0 +static int +ess_set_reclev (solo_devc * devc, int dev, int left, int right) +{ + unsigned char b; + + b = (((15 * right) / 100) << 4) | (((15 * left) / 100)); + + ext_write (devc, 0xb4, b); /* Change input volume control */ + devc->levels[dev] = left | (right << 8); + return left | (right << 8); +} + +static int +ess_set_altpcm (solo_devc * devc, int dev, int left, int right) +{ + unsigned char b; + + b = (((15 * right) / 100) << 4) | (((15 * left) / 100)); + solo_setmixer (devc, 0x7C, b); /* Change dac2 volume control */ + devc->levels[dev] = left | (right << 8); + return left | (right << 8); +} +#endif + +static int set_recmask (solo_devc * devc, int mask); + +static int +solo_mixer_set (solo_devc * devc, int dev, int value) +{ + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + + int regoffs; + unsigned char val; + + if (left > 100) + left = 100; + if (right > 100) + right = 100; + +#if 0 + if (dev == SOUND_MIXER_RECLEV) + return ess_set_reclev (devc, dev, left, right); + if (dev == SOUND_MIXER_ALTPCM) + return ess_set_altpcm (devc, dev, left, right); +#endif + + if (dev > 31) + return OSS_EINVAL; + + if (!(SOLO_MIXER_DEVICES & (1 << dev))) /* + * Not supported + */ + return OSS_EINVAL; + + regoffs = solo_mix[dev][LEFT_CHN].regno; + + if (regoffs == 0) + return OSS_EINVAL; + + val = solo_getmixer (devc, regoffs); + change_bits (devc, &val, dev, LEFT_CHN, left); + + devc->levels[dev] = left | (left << 8); + + if (solo_mix[dev][RIGHT_CHN].regno != regoffs) /* + * Change register + */ + { + solo_setmixer (devc, regoffs, val); /* + * Save the old one + */ + regoffs = solo_mix[dev][RIGHT_CHN].regno; + + if (regoffs == 0) + return left | (left << 8); /* + * Just left channel present + */ + + val = solo_getmixer (devc, regoffs); /* + * Read the new one + */ + } + + change_bits (devc, &val, dev, RIGHT_CHN, right); + + solo_setmixer (devc, regoffs, val); + + devc->levels[dev] = left | (right << 8); + return left | (right << 8); +} + +/*ARGSUSED*/ +static int +solo_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + solo_devc *devc = mixer_devs[dev]->devc; + int val; + + if (cmd == SOUND_MIXER_PRIVATE1) + { + val = *arg; + if (val != 0 && val != 1) + return (OSS_EINVAL); + + if (val) + { + cmn_err (CE_WARN, "turning on 26db mic boost\n"); + ext_write (devc, 0xa9, ext_read (devc, 0xa9) | 0xC); + } + else + { + cmn_err (CE_WARN, "turning off 26db mic boost\n"); + ext_write (devc, 0xa9, ext_read (devc, 0xa9) & ~0x4); + } + return *arg = val; + } + + + if (((cmd >> 8) & 0xff) == 'M') + { + if (IOC_IS_OUTPUT (cmd)) + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + val = *arg; + return *arg = set_recmask (devc, val); + break; + + default: + + val = *arg; + return *arg = solo_mixer_set (devc, cmd & 0xff, val); + } + else + switch (cmd & 0xff) + { + + case SOUND_MIXER_RECSRC: + return *arg = devc->recmask; + break; + + case SOUND_MIXER_DEVMASK: + return *arg = SOLO_MIXER_DEVICES; + break; + + case SOUND_MIXER_STEREODEVS: + return *arg = SOLO_MIXER_DEVICES & + ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); + break; + + case SOUND_MIXER_RECMASK: + return *arg = SOLO_RECORDING_DEVICES; + break; + + case SOUND_MIXER_CAPS: + return *arg = SOUND_CAP_EXCL_INPUT; + break; + + default: + return *arg = devc->levels[cmd & 0x1f]; + } + } + else + return OSS_EINVAL; +} + +static void +set_recsrc (solo_devc * devc, int src) +{ + solo_setmixer (devc, RECORD_SRC, + (solo_getmixer (devc, RECORD_SRC) & ~7) | (src & 0x7)); +} + +static int +set_recmask (solo_devc * devc, int mask) +{ + int devmask = mask & SOLO_RECORDING_DEVICES; + + if (devmask != SOUND_MASK_MIC && + devmask != SOUND_MASK_LINE && devmask != SOUND_MASK_CD) + { /* + * More than one devices selected. + * Drop the previous selection + */ + devmask &= ~devc->recmask; + } + + if (devmask != SOUND_MASK_MIC && + devmask != SOUND_MASK_LINE && devmask != SOUND_MASK_CD) + { /* + * More than one devices selected. + * Default to mic + */ + devmask = SOUND_MASK_MIC; + } + + + if (devmask ^ devc->recmask) /* + * Input source changed + */ + { + switch (devmask) + { + + case SOUND_MASK_MIC: + set_recsrc (devc, 0); + break; + + case SOUND_MASK_LINE: + set_recsrc (devc, 6); + break; + + case SOUND_MASK_CD: + set_recsrc (devc, 2); + break; + + default: + set_recsrc (devc, 0); + } + } + + devc->recmask = devmask; + return devc->recmask; +} + +static void +solo_mixer_reset (solo_devc * devc) +{ + char name[32]; + int i; + + sprintf (name, "SOLO"); + + devc->levels = load_mixer_volumes (name, default_levels, 1); + devc->recmask = 0; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + solo_mixer_set (devc, i, devc->levels[i]); + + set_recmask (devc, SOUND_MASK_MIC); +} + +static mixer_driver_t solo_mixer_driver = { + solo_mixer_ioctl +}; + +static int +solointr (oss_device_t * osdev) +{ + solo_devc *devc = (solo_devc *) osdev->devc; + int status; + int serviced = 0; + int i; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + status = INB (devc->osdev, devc->base + 7); + + for (i = 0; i < MAX_PORTC; i++) + { + if (status & 0x10) /* ESS Native Mode */ + { + int instat; + solo_portc *portc = &devc->portc[i]; + serviced = 1; + + instat = INB (devc->osdev, DSP_STATUS); /* Ack the interrupt */ + if (portc->trigger_bits & PCM_ENABLE_INPUT) + oss_audio_inputintr (portc->audiodev, 1); + } + + if (status & 0x20) /* ESS DAC2 Mode */ + { + solo_portc *portc = &devc->portc[i]; + serviced = 1; + + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + oss_audio_outputintr (portc->audiodev, 1); + solo_setmixer (devc, 0x7A, solo_getmixer (devc, 0x7A) & 0x47); + } + } + + if (status & 0x80) /* MPU interrupt */ + { + serviced = 1; + /* uart401intr (INT_HANDLER_CALL (devc->irq)); *//* UART401 interrupt */ + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return serviced; +} + +static int +solo_audio_set_rate (int dev, int arg) +{ + solo_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (arg > 48000) + arg = 48000; + if (arg < 8000) + arg = 8000; + portc->speed = arg; + return portc->speed; +} + +static short +solo_audio_set_channels (int dev, short arg) +{ + solo_portc *portc = audio_engines[dev]->portc; + + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +solo_audio_set_format (int dev, unsigned int arg) +{ + solo_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +solo_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void solo_audio_trigger (int dev, int state); + +static void +solo_audio_reset (int dev) +{ + solo_audio_trigger (dev, 0); +} + +static void +solo_audio_reset_input (int dev) +{ + solo_portc *portc = audio_engines[dev]->portc; + solo_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +solo_audio_reset_output (int dev) +{ + solo_portc *portc = audio_engines[dev]->portc; + solo_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +solo_audio_open (int dev, int mode, int open_flags) +{ + oss_native_word flags; + solo_portc *portc = audio_engines[dev]->portc; + solo_devc *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + portc->open_mode = mode; + portc->audio_enabled = ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +solo_audio_close (int dev, int mode) +{ + solo_portc *portc = audio_engines[dev]->portc; + + solo_audio_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +solo_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + solo_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + +} + +/*ARGSUSED*/ +static void +solo_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + solo_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +solo_audio_trigger (int dev, int state) +{ + oss_native_word flags; + solo_portc *portc = audio_engines[dev]->portc; + solo_devc *devc = audio_engines[dev]->devc; + + 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)) + { + solo_setmixer (devc, 0x78, 0x92); /* stablilze fifos */ + oss_udelay(100); + solo_setmixer (devc, 0x78, 0x93); /* Go */ + OUTB (devc->osdev, 0x0A, devc->base + 6); /*unmask dac2 intr */ + 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; + solo_setmixer (devc, 0x78, 0); /* stop the audio dac2 dma */ + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + ext_write (devc, 0xb8, 0x0f); /* Go */ + OUTB (devc->osdev, 0x00, devc->ddma_base + 0x0f); /*start dma*/ + 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; + ext_write (devc, 0xb8, 0x00); /* stop */ + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +ext_speed (int dev, int direction) +{ + solo_devc *devc = audio_engines[dev]->devc; + solo_portc *portc = audio_engines[dev]->portc; + int divider, div, filter; + unsigned int rate; + int speed, s0, s1, use0; + int dif0, dif1; + unsigned char t0, t1; + + /* rate = source / (256 - divisor) */ + /* divisor = 256 - (source / rate) */ + speed = portc->speed; + + t0 = 128 - (793800 / speed); + s0 = 793800 / (128 - t0); + + t1 = 128 - (768000 / speed); + s1 = 768000 / (128 - t1); + t1 |= 0x80; + + dif0 = speed - s0; + if (dif0 < 0) + dif0 *= -1; + dif1 = speed - s1; + if (dif1 < 0) + dif1 *= -1; + + use0 = (dif0 < dif1) ? 1 : 0; + + if (use0) + { + rate = s0; + div = t0; + } + else + { + rate = s1; + div = t1; + } + portc->speed = rate; +/* + * Set filter divider register + */ + filter = (rate * 8 * 82) / 20; /* 80% of the rate */ + divider = 256 - 7160000 / (filter); + if (direction) + { + ext_write (devc, 0xa1, div); + ext_write (devc, 0xa2, divider); + } + else + { + solo_setmixer (devc, 0x70, div); + solo_setmixer (devc, 0x72, divider); + } +} + +/*ARGSUSED*/ +static int +solo_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + solo_devc *devc = audio_engines[dev]->devc; + solo_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + unsigned int left, right, reclev; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int c; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + OUTB (devc->osdev, 2, DSP_RESET); /* Reset FIFO too */ + INB (devc->osdev, DSP_RESET); /* Reset FIFO too */ + OUTB (devc->osdev, 0, DSP_RESET); + oss_udelay (10); + + + ext_speed (dev, 1); + + ext_write (devc, 0xa8, (ext_read (devc, 0xa8) & ~0x3) | (3 - portc->channels)); /* Mono/stereo */ + + solo_command (devc, DSP_CMD_SPKOFF); + + if (portc->channels == 1) + { + if (portc->bits == AFMT_U8) + { /* 8 bit mono */ + ext_write (devc, 0xb7, 0x51); + ext_write (devc, 0xb7, 0xd0); + } + else + { /* 16 bit mono */ + ext_write (devc, 0xb7, 0x71); + ext_write (devc, 0xb7, 0xf4); + } + } + else + { /* Stereo */ + if (portc->bits == AFMT_U8) + { /* 8 bit stereo */ + ext_write (devc, 0xb7, 0x51); + ext_write (devc, 0xb7, 0x98); + } + else + { /* 16 bit stereo */ + ext_write (devc, 0xb7, 0x71); + ext_write (devc, 0xb7, 0xbc); + } + } + + /* + * reset the 0xb4 register to the stored value of RECLEV - for some + * reason it gets reset when you enter ESS Extension mode. + */ + left = devc->levels[SOUND_MIXER_RECLEV] & 0xff; + right = (devc->levels[SOUND_MIXER_RECLEV] >> 8) & 0xff; + reclev = (((15 * right) / 100) << 4) | (((15 * left) / 100)); + ext_write (devc, 0xb4, reclev); + + OUTB (devc->osdev, 0xc4, devc->ddma_base + 0x08); + OUTB (devc->osdev, 0xff, devc->ddma_base + 0x0d); /* clear DMA */ + OUTB (devc->osdev, 0x01, devc->ddma_base + 0x0f); /* stop DMA */ + OUTB (devc->osdev, 0x14, devc->ddma_base + 0x0b); /*Demand/Single Mode */ + + OUTL (devc->osdev, dmap->dmabuf_phys, devc->ddma_base + 0x00); + OUTW (devc->osdev, dmap->bytes_in_use, devc->ddma_base + 0x04); + + c = -(dmap->fragment_size); + /* Reload DMA Count */ + ext_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff)); + ext_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff)); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +solo_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + solo_devc *devc = audio_engines[dev]->devc; + solo_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + dmap_t *dmap = audio_engines[dev]->dmap_out; + int c; + + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + OUTB (devc->osdev, 2, DSP_RESET); /* Reset FIFO too */ + INB (devc->osdev, DSP_RESET); + OUTB (devc->osdev, 0, DSP_RESET); + ext_speed (dev, 0); + if (portc->channels == 1) + { + if (portc->bits == AFMT_U8) + solo_setmixer (devc, 0x7A, 0x40 | 0x00); /*8bit mono unsigned */ + else + solo_setmixer (devc, 0x7A, 0x40 | 0x05); /*16bit mono signed */ + } + else + { + if (portc->bits == AFMT_U8) + solo_setmixer (devc, 0x7A, 0x40 | 0x02); /*8bit stereo unsigned */ + else + solo_setmixer (devc, 0x7A, 0x40 | 0x07); /*16bit stereo signed */ + } + + OUTL (devc->osdev, dmap->dmabuf_phys, devc->base + 0); + OUTW (devc->osdev, dmap->bytes_in_use, devc->base + 4); + + OUTB (devc->osdev, 0x0, devc->base + 6); /* disable the DMA mask */ + + c = -(dmap->fragment_size>>1); + solo_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff)); + solo_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff)); + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +solo_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + solo_devc *devc = audio_engines[dev]->devc; + oss_native_word flags; + oss_native_word ptr=0; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + ptr = dmap->bytes_in_use - INW(devc->osdev, devc->base + 4); + } + + if (direction == PCM_ENABLE_INPUT) + { + int count; + unsigned int diff; + + ptr = INL(devc->osdev, devc->ddma_base + 0x00); + count = INL(devc->osdev, devc->ddma_base + 0x04); + + diff = dmap->dmabuf_phys + dmap->bytes_in_use - ptr - count; + + if (ptr < dmap->dmabuf_phys || + ptr >= dmap->dmabuf_phys + dmap->bytes_in_use) + + ptr = devc->last_capture_addr; /* use prev value */ + else + devc->last_capture_addr = ptr; /* save it */ + + ptr -= dmap->dmabuf_phys; + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + + +static audiodrv_t solo_audio_driver = { + solo_audio_open, + solo_audio_close, + solo_audio_output_block, + solo_audio_start_input, + solo_audio_ioctl, + solo_audio_prepare_for_input, + solo_audio_prepare_for_output, + solo_audio_reset, + NULL, + NULL, + solo_audio_reset_input, + solo_audio_reset_output, + solo_audio_trigger, + solo_audio_set_rate, + solo_audio_set_format, + solo_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* solo_alloc_buffer, */ + NULL, /* solo_free_buffer, */ + NULL, + NULL, + solo_get_buffer_pointer +}; + +static int +init_solo (solo_devc * devc) +{ + int my_mixer; + int i, adev; + int first_dev = 0; + + devc->mpu_attached = devc->fm_attached = 0; + +/* + * Initialize and attach the legacy devices + */ + + if (!solo_reset (devc)) + { + cmn_err (CE_WARN, "Reset command failed\n"); + return 0; + } + +/* setup mixer regs */ + solo_setmixer (devc, 0x7d, 0x0c); + OUTB (devc->osdev, 0xf0, devc->base + 7); + OUTB (devc->osdev, 0x00, devc->ddma_base + 0x0f); + + if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "ESS Solo", + &solo_mixer_driver, + sizeof (mixer_driver_t), devc)) < 0) + { + return 0; + } + solo_mixer_reset (devc); + + for (i = 0; i < MAX_PORTC; i++) + { + char tmp_name[100]; + solo_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE; + strcpy (tmp_name, devc->chip_name); + + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX; + } + else + { + caps |= ADEV_DUPLEX | ADEV_SHADOW; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &solo_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]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->dmabuf_maxaddr = MEMLIMIT_ISA; + audio_engines[adev]->dmabuf_alloc_flags |= DMABUF_SIZE_16BITS; + 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_solo_attach (oss_device_t * osdev) +{ + + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr0, pci_ioaddr1, pci_ioaddr2, pci_ioaddr3; + solo_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered ESS Solo probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != ESS_VENDOR_ID || device != ESS_SOLO1) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr0); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_2, &pci_ioaddr2); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_3, &pci_ioaddr3); + + if (pci_ioaddr0 == 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->irq = pci_irq_line; + devc->chip_name = "ESS Solo-1"; + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr0); + /* Remove I/O space marker in bit 0. */ + devc->base &= ~0x3; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + 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 (oss_register_interrupts (devc->osdev, 0, solointr, NULL) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d\n", pci_irq_line); + return 0; + } + + + /* Read the VCBase register */ + if (pci_ioaddr2 == 0) + { + cmn_err (CE_WARN, "DMA I/O base not set\n"); + /*return 0; */ + } + /* Copy it's contents to the DDMA register */ + pci_write_config_dword (osdev, 0x60, pci_ioaddr2 | 0x1); /* enabled DDMA */ + devc->ddma_base = MAP_PCI_IOADDR (devc->osdev, 2, pci_ioaddr2); + devc->ddma_base &= ~0x3; + + /* Init other SB base registers */ + if (pci_ioaddr1 == 0) + { + cmn_err (CE_WARN, "SB I/O base not set\n"); + return 0; + } + devc->sb_base = MAP_PCI_IOADDR (devc->osdev, 1, pci_ioaddr1); + devc->sb_base &= ~0x3; + + + /* Init MPU base register */ + if (pci_ioaddr3 == 0) + { + cmn_err (CE_WARN, "MPU I/O base not set\n"); + return 0; + } + devc->mpu_base = MAP_PCI_IOADDR (devc->osdev, 3, pci_ioaddr3); + devc->mpu_base &= ~0x3; + + /* Setup Legacy audio register - disable legacy audio */ + pci_write_config_word (osdev, 0x40, 0x805f); + + /* Select DDMA and Disable IRQ emulation */ + pci_write_config_dword (osdev, 0x50, 0); + pci_read_config_dword (osdev, 0x50, &pci_ioaddr0); + pci_ioaddr0 &= (~(0x0700 | 0x6000)); + pci_write_config_dword (osdev, 0x50, pci_ioaddr0); + + return init_solo (devc); /* Detected */ +} + + +int +oss_solo_detach (oss_device_t * osdev) +{ + solo_devc *devc = (solo_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + /* disable all interrupts */ + /*OUTB (devc->osdev, 0, devc->base + 7); */ + +#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); + UNMAP_PCI_IOADDR (devc->osdev, 1); + UNMAP_PCI_IOADDR (devc->osdev, 2); + UNMAP_PCI_IOADDR (devc->osdev, 3); + + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_solo/oss_solo.man b/kernel/drv/oss_solo/oss_solo.man new file mode 100644 index 0000000..a86e810 --- /dev/null +++ b/kernel/drv/oss_solo/oss_solo.man @@ -0,0 +1,19 @@ +NAME +oss_solo - ESS Solo-1 audio driver + +DESCRIPTION +Open Sound System driver for ESS Solo1/1938/1968 audio controllers. +ESS Solo1 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_solo.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_trident/.devices b/kernel/drv/oss_trident/.devices new file mode 100644 index 0000000..4d766ef --- /dev/null +++ b/kernel/drv/oss_trident/.devices @@ -0,0 +1,5 @@ +oss_trident pci1023,2000 Trident 4DWave-DX +oss_trident pci1023,2001 Trident 4DWave-NX +oss_trident pci1023,2002 Trident 4DWave-CX +oss_trident pci1039,7018 SiS 7018 +oss_trident pci10b9,5451 ALI M5451 diff --git a/kernel/drv/oss_trident/.name b/kernel/drv/oss_trident/.name new file mode 100644 index 0000000..f3df66b --- /dev/null +++ b/kernel/drv/oss_trident/.name @@ -0,0 +1 @@ +Trident 4DWave, SiS7018, ALI M5451 diff --git a/kernel/drv/oss_trident/.params b/kernel/drv/oss_trident/.params new file mode 100644 index 0000000..70d8ef5 --- /dev/null +++ b/kernel/drv/oss_trident/.params @@ -0,0 +1,6 @@ +int trident_mpu_ioaddr=0; +/* + * Trident MPU 401 I/O Address + * Values: 0x300, 0x330 Default: 0x330 + */ + diff --git a/kernel/drv/oss_trident/oss_trident.c b/kernel/drv/oss_trident/oss_trident.c new file mode 100644 index 0000000..13d8872 --- /dev/null +++ b/kernel/drv/oss_trident/oss_trident.c @@ -0,0 +1,1580 @@ +/* + * Purpose: Driver for Trident 4DWAVE, ALI 5451 and SiS 7918 audio chips + */ +/* + * + * 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_trident_cfg.h" +#include "oss_pci.h" +#include "ac97.h" + +#if defined(sparc) +#define MEM_MAPPED_REGISTERS +#else +#undef MEM_MAPPED_REGISTERS +#endif + +#define TRIDENT_VENDOR_ID 0x1023 +#define TRIDENT_4DWAVEDX_ID 0x2000 +#define TRIDENT_4DWAVENX_ID 0x2001 +#define TRIDENT_4DWAVECX_ID 0x2002 + +#define ALI_VENDOR_ID 0x10b9 +#define ALI_5451_ID 0x5451 + +#define SIS_VENDOR_ID 0x1039 +#define SIS_7018_ID 0x7018 + +/* DX/NX/CX IO Registers */ +#define SP_CSO 0x24 +#define SP_LBA 0x28 +#define SP_ESO 0x2C +#define ACR0 0x40 +#define SP_STAT 0x64 +#define TLBC 0x6C +#define START_A 0x80 +#define STOP_A 0x84 +#define INT_A 0x98 +#define INTEN_A 0xA4 +#define VOL 0xA8 +#define DELTA 0xAC +#define MISCINT 0xB0 +#define START_B 0xB4 +#define STOP_B 0xB8 +#define INT_B 0xD8 +#define INTEN_B 0xDC +#define CIR 0xA0 +#define CSO 0xE0 +#define LBA 0xE4 +#define ESO 0xE8 +#define FMC 0xEC +#define TCTRL 0xF0 +#define EBUF1 0xF4 +#define EBUF2 0xF8 + +#define DMAR0 0x00 +#define DMAR4 0x04 +#define DMAR6 0x06 +#define DMAR11 0x0b +#define DMAR15 0x0f +#define SBDELTA 0xac +#define SBBL 0xc0 +#define SBCTL 0xc4 + +/* SIS 7018 Define */ +#define SECONDARY_ID 0x00004000 +#define PCMOUT 0x00010000 +#define SURROUT 0x00020000 +#define CENTEROUT 0x00040000 +#define LFEOUT 0x00080000 +#define LINE1OUT 0x00100000 +#define LINE2OUT 0x00200000 +#define GPIOOUT 0x00400000 +#define CHANNEL_PB 0x0000 +#define CHANNEL_SPC_PB 0x4000 +#define CHANNEL_REC 0x8000 +#define CHANNEL_REC_PB 0xc000 +#define MODEM_LINE1 0x0000 +#define MODEM_LINE2 0x0400 +#define PCM_LR 0x0800 +#define HSET 0x0c00 +#define I2S_LR 0x1000 +#define CENTER_LFE 0x1400 +#define SURR_LR 0x1800 +#define SPDIF_LR 0x1c00 +#define MIC 0x1400 +#define MONO_LEFT 0x0000 +#define MONO_RIGHT 0x0100 +#define MONO_MIX 0x0200 +#define SRC_ENABLE 0x0080 + +#define INTR(bank) ((bank==1)?INT_A:INT_B) +#define INTEN(bank) ((bank==1)?INTEN_A:INTEN_B) +#define STOP(bank) ((bank==1)?STOP_A:STOP_B) +#define START(bank) ((bank==1)?START_A:START_B) + +/* ALI5451 definitions */ +#define ALI_5451_V02 0x2 +#define SIS_7018_V02 0x2 + + +extern int trident_mpu_ioaddr; + +#define MAX_PORTC 8 + +typedef struct trident_portc +{ + int speed, bits, channels; + int open_mode; + int audio_enabled; + int trigger_bits; + int audiodev; + int port_type; +#define DF_PCM 0 +#define DF_SPDIF 1 + unsigned char play_chan, play_intr_chan; + unsigned char rec_chan, rec_intr_chan; + int pbank, rbank; +#define BANK_A 1 +#define BANK_B 0 +} trident_portc; + + +typedef struct trident_devc +{ + oss_device_t *osdev; + char *chip_name; + int chip_type; + int revision; + int irq; + +#ifdef MEM_MAPPED_REGISTERS + unsigned int bar1addr; + char *bar1virt; +#else /* */ + oss_native_word base; +#endif /* */ + volatile unsigned char intr_mask; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* Legacy */ + int mpu_base, mpu_irq, mpu_attached; + + /* Mixer parameters */ + ac97_devc ac97devc; + int mixer_dev; + + /* Audio parameters */ + trident_portc portc[MAX_PORTC]; + int audio_opened; + unsigned char sb_dma_flags; +} trident_devc; + +#ifndef MEM_MAPPED_REGISTERS +/* I/O mapped register access */ +#define READL(o,a) INL(o, devc->base+(a)) +#define READW(o,a) INW(o, devc->base+(a)) +#define READB(o,a) INB(o, devc->base+(a)) +#define WRITEL(o,d,a) OUTL(o, d, devc->base+(a)) +#define WRITEW(o,d,a) OUTW(o, d, devc->base+(a)) +#define WRITEB(o,d,a) OUTB(o, d, devc->base+(a)) +#else +/* Mem mapped I/O registers */ +#define READL(o,a) *(volatile unsigned int*)(devc->bar1virt+(a)) +#define READW(o,a) *(volatile unsigned short*)(devc->bar1virt+(a)) +#define READB(o,a) *(volatile unsigned char*)(devc->bar1virt+(a)) +#define WRITEL(o,d,a) *(volatile unsigned int*)(devc->bar1virt+(a))=d +#define WRITEW(o,d,a) *(volatile unsigned short*)(devc->bar1virt+(a))=d +#define WRITEB(o,d,a) *(volatile unsigned char*)(devc->bar1virt+(a))=d +#endif + +static int +ac97_read (void *devc_, int addr) +{ + trident_devc *devc = devc_; + int t, ret; + oss_native_word data, reg = 0; + oss_native_word rmask = 0; + oss_native_word dmask = 0; + oss_native_word wport = 0; + oss_native_word rport = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + t = 20000; + switch (devc->chip_type) + { + case TRIDENT_4DWAVEDX_ID: + case SIS_7018_ID: + wport = 0x40; + rport = 0x44; + if (devc->revision == SIS_7018_V02) + { + rport = 0x40; + } + rmask = 0x00008000; + dmask = 0x00008000; + break; + case TRIDENT_4DWAVENX_ID: + wport = 0x44; + rport = 0x48; + rmask = 0x00000800; + dmask = 0x00000400; + break; + case ALI_5451_ID: + wport = 0x40; + rport = 0x44; + rmask = 0x00008000; + dmask = 0x00008000; + if (devc->revision == ALI_5451_V02) + { + rport = 0x40; + } + break; + default: + { + static int already_done = 0; + if (!already_done) + cmn_err (CE_WARN, "Unknown codec interface\n"); + already_done = 1; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + } + + /* Check to make sure No Writes are pending */ + reg = READL (devc->osdev, wport); + while ((reg & dmask) && --t) + reg = READL (devc->osdev, wport); /* re-read status/data */ + + /* Check to make sure No reads are pending */ + reg = READL (devc->osdev, rport); + while ((reg & dmask) && --t) + reg = READL (devc->osdev, rport); /* re-read status/data */ + data = addr | rmask; + WRITEL (devc->osdev, data, rport); /* select register for reading */ + reg = READL (devc->osdev, rport); /* read status/data */ + + t = 20000; + + while ((reg & dmask) && --t) + { /* busy reading */ + reg = READL (devc->osdev, rport); /* re-read status/data */ + } + if (t) + ret = (reg >> 16); + else + { + DDB (cmn_err (CE_WARN, "AC97 mixer read timed out\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ret; +} + +static int +ac97_write (void *devc_, int addr, int data) +{ + trident_devc *devc = devc_; + int t; + oss_native_word wport = 0; + oss_native_word reg = 0; + unsigned int wmask = 0; + unsigned int dmask = 0; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + t = 2000; + + switch (devc->chip_type) + { + case TRIDENT_4DWAVEDX_ID: + case SIS_7018_ID: + wport = 0x40; + wmask = 0x00008000; + dmask = 0x00008000; + break; + case TRIDENT_4DWAVENX_ID: + wport = 0x44; + wmask = 0x00000800; + dmask = 0x00000800; + break; + case ALI_5451_ID: + wport = 0x40; + wmask = 0x00008000; + dmask = 0x00008000; + if (devc->revision == 2) + dmask = 0x100; + break; + default: + { + static int already_done = 0; + if (!already_done) + cmn_err (CE_WARN, "Unknown codec interface\n"); + already_done = 1; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + } + + /* Check to make sure No Writes are pending */ + reg = READL (devc->osdev, wport); + while ((reg & wmask) && --t) + { + reg = READL (devc->osdev, wport); /* re-read status/data */ + } + if (t) + { + reg = data << 16; + reg |= (addr & 0xff); + reg |= wmask | dmask; + WRITEL (devc->osdev, reg, wport); + } + else + DDB (cmn_err (CE_WARN, "AC97 mixer write timed out\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static int +tridentintr (oss_device_t * osdev) +{ + trident_devc *devc = (trident_devc *) osdev->devc; + int i; + oss_native_word status, intstat; + int serviced = 0; + dmap_t *dmapin; + oss_native_word flag; + + + /* check the interrupt status register MISCINT */ + status = READL (devc->osdev, MISCINT); + serviced = 1; + + /* If it is a not 4DWave Playback or MIDI interrupt then return */ + if (!(status & (0x00000020 | 0x00000008 | 0x4))) + { + WRITEL (devc->osdev, status, MISCINT); + return 1; + } + +#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. + */ + /* Check if this is a MIDI interrupt */ + if (status & 0x00000008) + { + uart401intr (INT_HANDLER_CALL (devc->irq)); + serviced = 1; + } +#endif + MUTEX_ENTER_IRQDISABLE (devc->mutex, flag); + + /* Check to see if this is our channel */ + if (status & 0x20) + for (i = 0; i < MAX_PORTC; i++) + { + trident_portc *portc = &devc->portc[i]; + serviced = 1; + + /* Handle Playback Interrupts */ + intstat = READL (devc->osdev, INTR (portc->pbank)); + + if (intstat & 1L << portc->play_intr_chan) + { + WRITEL (devc->osdev, READL (devc->osdev, INTR (portc->pbank)) + | 1L << portc->play_intr_chan, INTR (portc->pbank)); + oss_audio_outputintr (portc->audiodev, 1); + } + + /* Handle Record Interrupts */ + intstat = READL (devc->osdev, INTR (portc->rbank)); + + if (intstat & 1L << portc->rec_intr_chan) + { + WRITEL (devc->osdev, READL (devc->osdev, INTR (portc->rbank)) + | 1L << portc->rec_intr_chan, INTR (portc->rbank)); + if ((devc->chip_type == ALI_5451_ID) + || (devc->chip_type == SIS_7018_ID)) + { + unsigned int ptr; + int i; + int chan; + dmapin = audio_engines[portc->audiodev]->dmap_in; + + if (portc->rbank == BANK_A) + chan = portc->rec_chan; + + else + chan = portc->rec_chan + 32; + WRITEL (devc->osdev, + (READL (devc->osdev, CIR) & ~0x3F) | chan, CIR); + ptr = READW (devc->osdev, CSO + 2); + ptr++; + ptr *= portc->channels * (portc->bits / 8); + + if (dmapin->bytes_in_use == 0 || dmapin->fragment_size == 0) + { + cmn_err(CE_WARN, "bytes_in_use=%d, fragment_size=%d\n", dmapin->bytes_in_use, dmapin->fragment_size); + continue; + } + ptr %= dmapin->bytes_in_use; + ptr /= dmapin->fragment_size; + i = 0; + while (dmap_get_qtail (dmapin) != ptr && i++ < dmapin->nfrags) + oss_audio_inputintr (portc->audiodev, 0); + } + else + oss_audio_inputintr (portc->audiodev, 0); + } + } + + if (status & 0x4) + { + serviced = 1; + READB (devc->osdev, 0x1E); /*SB ESP ack */ + READB (devc->osdev, 0x1F); /*SB IRQ ack */ + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flag); + return serviced; +} + + +/***************************************************************************/ +static int +trident_audio_set_rate (int dev, int arg) +{ + trident_portc *portc = audio_engines[dev]->portc; + if (arg == 0) + return portc->speed; + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +trident_audio_set_channels (int dev, short arg) +{ + trident_portc *portc = audio_engines[dev]->portc; + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + return portc->channels; +} + +static unsigned int +trident_audio_set_format (int dev, unsigned int arg) +{ + trident_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + return portc->bits; +} + +/*ARGSUSED*/ +static int +trident_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void trident_audio_trigger (int dev, int state); + +static void +trident_audio_reset (int dev) +{ + trident_audio_trigger (dev, 0); +} + +static void +trident_audio_reset_input (int dev) +{ + trident_portc *portc = audio_engines[dev]->portc; + trident_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +trident_audio_reset_output (int dev) +{ + trident_portc *portc = audio_engines[dev]->portc; + trident_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +trident_audio_open (int dev, int mode, int open_flags) +{ + trident_portc *portc = audio_engines[dev]->portc; + trident_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; + } + portc->open_mode = mode; + portc->audio_enabled = ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +trident_audio_close (int dev, int mode) +{ + trident_portc *portc = audio_engines[dev]->portc; + trident_audio_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +trident_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + trident_portc *portc = audio_engines[dev]->portc; + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +trident_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + trident_portc *portc = audio_engines[dev]->portc; + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +trident_audio_trigger (int dev, int state) +{ + trident_devc *devc = audio_engines[dev]->devc; + trident_portc *portc = audio_engines[dev]->portc; + oss_native_word ainten = 0, playstop = 0, recstop = 0; + oss_native_word flags; + + 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)) + { + + /* Enable the channel interrupt */ + WRITEL (devc->osdev, READL (devc->osdev, INTEN (portc->pbank)) + | (1L << portc->play_intr_chan), INTEN (portc->pbank)); + + /* start playback and playback interrupt channels */ + WRITEL (devc->osdev, READL (devc->osdev, START (portc->pbank)) + | (1L << portc->play_chan) + | (1L << portc->play_intr_chan), START (portc->pbank)); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + /* disable playback interrupt channel */ + ainten = READL (devc->osdev, INTEN (portc->pbank)); + ainten = ainten & ~(1L << portc->play_intr_chan); + WRITEL (devc->osdev, ainten, INTEN (portc->pbank)); + + /* stop playback and playback interrupt channels */ + playstop = ((1L << portc->play_chan) | + (1L << portc->play_intr_chan)); + WRITEL (devc->osdev, playstop, STOP (portc->pbank)); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) + && !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Enable the channel interrupts */ + WRITEL (devc->osdev, READL (devc->osdev, INTEN (portc->rbank)) + | (1L << portc->rec_intr_chan), INTEN (portc->rbank)); + + if ((devc->chip_type != ALI_5451_ID) + && (devc->chip_type != SIS_7018_ID)) + { + /* set recording flags */ + WRITEB (devc->osdev, devc->sb_dma_flags, SBCTL); + + /* start record interrupt channel */ + WRITEL (devc->osdev, 1L << portc->rec_intr_chan, + START (portc->rbank)); + } + else + { + WRITEL (devc->osdev, + READL (devc->osdev, + START (portc->rbank)) | (1L << portc-> + rec_chan) | (1L << + portc-> + rec_intr_chan), + START (portc->rbank)); + } + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + if ((devc->chip_type != ALI_5451_ID) + && (devc->chip_type != SIS_7018_ID)) + { + /* disable the record interrrupt enable channel */ + ainten = READL (devc->osdev, INTEN (portc->rbank)); + ainten = ainten & ~(1L << portc->rec_intr_chan); + WRITEL (devc->osdev, ainten, INTEN (portc->rbank)); + + /* stop DMA controller */ + WRITEB (devc->osdev, 0x00, SBCTL); + + /* stop record interrupt channel */ + recstop |= 1L << portc->rec_intr_chan; + WRITEL (devc->osdev, recstop, STOP (portc->rbank)); + } + else + { + /* disable rec interrupt channel */ + ainten = READL (devc->osdev, INTEN (portc->rbank)); + ainten = ainten & ~(1L << portc->rec_intr_chan); + WRITEL (devc->osdev, ainten, INTEN (portc->rbank)); + + /* stop playback and playback interrupt channels */ + recstop = ((1L << portc->rec_chan) | + (1L << portc->rec_intr_chan)); + WRITEL (devc->osdev, recstop, STOP (portc->rbank)); + } + + /* ack any interrupts on INT_A */ + recstop = READL (devc->osdev, INTR (portc->rbank)); + recstop |= 1L << portc->rec_intr_chan; + WRITEL (devc->osdev, recstop, INTR (portc->rbank)); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +trident_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + trident_devc *devc = audio_engines[dev]->devc; + trident_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + oss_native_word bufsize, delta, eso; + oss_native_word temp; + unsigned int attribute = 0; + unsigned char bValue; + unsigned short wValue; + oss_native_word dwValue; + unsigned short wRecCodecSamples; + int chan; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (devc->chip_type == TRIDENT_4DWAVEDX_ID) + { + bValue = READB (devc->osdev, 0x48); /*enable AC97 ADC */ + WRITEB (devc->osdev, bValue | 0x48, 0x48); /*disable rec intr */ + } + + if (devc->chip_type == TRIDENT_4DWAVENX_ID) + { + wValue = READW (devc->osdev, MISCINT); + WRITEW (devc->osdev, wValue | 0x1000, MISCINT); + } + + if ((devc->chip_type != ALI_5451_ID) && (devc->chip_type != SIS_7018_ID)) + { + /* Initialize legacy recording */ + WRITEB (devc->osdev, 0, DMAR15); + bValue = READB (devc->osdev, DMAR11) & 0x03; + WRITEB (devc->osdev, bValue | 0x54, DMAR11); + + /* Set base address in DMAR0-DMAR3 */ + WRITEL (devc->osdev, dmap->dmabuf_phys, DMAR0); + + /* Set count in DMAR4/DMAR5 */ + eso = dmap->bytes_in_use; + WRITEW (devc->osdev, eso - 1, DMAR4); + + /* Set speed in SBDelta */ + dwValue = (48000 << 12) / portc->speed; + WRITEW (devc->osdev, (unsigned short) dwValue, SBDELTA); + + /*Set channel interrupt blk length */ + if ((portc->bits == 16) || (portc->channels == 2)) + wRecCodecSamples = (unsigned short) ((eso >> 1) - 1); + else + wRecCodecSamples = (unsigned short) (eso - 1); + + dwValue = wRecCodecSamples << 16; + dwValue |= wRecCodecSamples & 0x0000ffff; + WRITEL (devc->osdev, dwValue, SBBL); + + /*set format */ + devc->sb_dma_flags |= 0x19; + if (portc->bits == 16) + devc->sb_dma_flags |= 0xA0; + if (portc->channels == 2) + devc->sb_dma_flags |= 0x40; + } + else + { +#if !defined(sparc) + if (devc->chip_type == ALI_5451_ID) + WRITEL (devc->osdev, + READL (devc->osdev, 0xd4) | ((unsigned int) 1 << 31), 0xd4); +#endif + + /* for SiS 7018: Rec with PCM_LR, MONO_MIX, SRC_EN */ + if (devc->chip_type == SIS_7018_ID) + attribute = 0x8880; /* PCM->IN */ + + delta = (48000 << 12) / portc->speed; + bufsize = dmap->bytes_in_use; + + if (portc->bits == 16) + bufsize /= 2; + if (portc->channels == 2) + bufsize /= 2; + bufsize--; + + if (portc->rbank == BANK_A) + chan = portc->rec_chan; + else + chan = portc->rec_chan + 32; + + WRITEL (devc->osdev, (READL (devc->osdev, CIR) & ~0x3F) | chan, CIR); /*select current chan */ + + /* Now set the buffer address pointer */ + WRITEL (devc->osdev, dmap->dmabuf_phys, LBA); + + /* Set the Size and Sampling Rate */ + eso = (bufsize << 16) | (delta & 0x0000FFFF); + WRITEL (devc->osdev, eso, ESO); + temp = 0x80000000; /*enable gvsel */ + if (portc->channels == 2) + temp |= 0x00004000; /*stereo/mono */ + if (portc->bits == 16) + temp |= 0x0000A000; /*unsigned 8/signed 16bit */ + temp |= 0x00001000; /*enable loop */ + temp |= 0x003F0000; /*set pan to off */ + temp |= 0x00000FFF; /*set vol to off */ + WRITEL (devc->osdev, temp, TCTRL); /*set format */ + WRITEL (devc->osdev, attribute << 16, FMC); + WRITEL (devc->osdev, 0, EBUF1); + WRITEL (devc->osdev, 0, EBUF2); + /* WRITEL (devc->osdev, 0xFFFF, VOL); *//*Music/WaveVol set to max */ + WRITEL (devc->osdev, 0, CSO); /*set CSO and Alpha to 0 */ + } + +/* Now prepare the Record Interrupt Channel */ + delta = (48000 << 12) / portc->speed; + bufsize = dmap->fragment_size; + if (portc->bits == 16) + bufsize /= 2; + if (portc->channels == 2) + bufsize /= 2; + bufsize--; + + if (portc->rbank == BANK_A) + chan = portc->rec_intr_chan; + else + chan = portc->rec_intr_chan + 32; + + WRITEL (devc->osdev, (READL (devc->osdev, CIR) & ~0x3F) | chan, CIR); + + /* Now set the buffer address pointer */ + WRITEL (devc->osdev, dmap->dmabuf_phys, LBA); + + /* Set the Size and Sampling Rate */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + eso = (bufsize << 16) | (delta & 0x0000FFFF); + WRITEL (devc->osdev, eso, ESO); + } + else + { + eso = ((delta << 16) & 0xff000000) | (bufsize & 0x00ffffff); + WRITEL (devc->osdev, eso, ESO); + } + + temp = 0x80000000; /*enable gvsel */ + if (portc->channels == 2) + temp |= 0x00004000; /*stereo/mono */ + if (portc->bits == 16) + temp |= 0x0000A000; /*8 unsigned/16bit signed data */ + temp |= 0x00001000; /*enable loop */ + temp |= 0x003F0000; /*set pan to off */ + temp |= 0x00000FFF; /*set vol to off */ + WRITEL (devc->osdev, temp, TCTRL); /*set format */ + + /* for the record interrupt channel note that no attribute should be + * set for SIS7018 + */ + WRITEL (devc->osdev, 0, FMC); + WRITEL (devc->osdev, 0, EBUF1); + WRITEL (devc->osdev, 0, EBUF2); + /* WRITEL (devc->osdev, 0xFFFF, VOL); *//*Music/WaveVol set to min */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + WRITEL (devc->osdev, 0, CSO); /*set CSO and Alpha to 0 */ + } + else + { + WRITEL (devc->osdev, (delta << 24) | (0 & 0x00ffffff), CSO); + } + + /* Now set the mode on portc to record */ + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +trident_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + trident_devc *devc = audio_engines[dev]->devc; + trident_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + oss_native_word bufsize, delta, eso; + oss_native_word temp; + int chan, spdif_rate, spdif_chan; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + /* prepare the main playback channel */ + delta = (portc->speed * 4096) / 48000; + bufsize = dmap->bytes_in_use; + + if (portc->bits == 16) + bufsize /= 2; + if (portc->channels == 2) + bufsize /= 2; + bufsize--; + + if ((devc->chip_type == ALI_5451_ID) && (devc->revision == ALI_5451_V02) + && (portc->port_type == DF_SPDIF)) + + { + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_AUDIO, SNDCTL_MIX_WRITE, + 0); + portc->play_chan = 15; + portc->play_intr_chan = 14; + + if (portc->bits == AFMT_AC3) + + { + ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits); + portc->bits = 16; + portc->channels = 2; + portc->speed = 48000; + /* set non-pcm (AC3) mode on SPDIF control */ + WRITEW (devc->osdev, (READW (devc->osdev, 0x70) & ~0x2) | 0x2, + 0x70); + } + else + /* set pcm mode on SPDIF control */ + WRITEW (devc->osdev, READW (devc->osdev, 0x70) & ~0x2, 0x70); + + /*set up the sampling rate */ + switch (portc->speed) + { + case 44100: + spdif_rate = 0; + break; + case 32000: + spdif_rate = 0x300; + break; + case 48000: + default: + spdif_rate = 0x200; + break; + } + spdif_chan = READB (devc->osdev, 0x74) & 0xbf; /*select spdif_out */ + spdif_chan |= 0x80; /*select right */ + WRITEB (devc->osdev, spdif_chan, 0x74); + WRITEB (devc->osdev, spdif_rate | 0x20, 0x72); + spdif_chan &= (~0x80); /*select left */ + WRITEB (devc->osdev, spdif_chan, 0x74); + WRITEB (devc->osdev, spdif_rate | 0x10, 0x72); + } + + if (portc->pbank == BANK_A) + chan = portc->play_chan; + else + chan = portc->play_chan + 32; + + WRITEL (devc->osdev, (READL (devc->osdev, CIR) & ~0x3F) | chan, CIR); /*select current chan */ + + /* Now set the buffer address pointer */ + WRITEL (devc->osdev, dmap->dmabuf_phys, LBA); + + /* Set the Size and Sampling Rate */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + eso = (bufsize << 16) | (delta & 0x0000FFFF); + WRITEL (devc->osdev, eso, ESO); + } + else + { + eso = ((delta << 16) & 0xff000000) | (bufsize & 0x00ffffff); + WRITEL (devc->osdev, eso, ESO); + } + temp = 0x80000000; /*enable gvsel */ + if (portc->channels == 2) + temp |= 0x00004000; /*stereo/mono */ + if (portc->bits == 16) + temp |= 0x0000A000; /*8 unsigned/16bit signed data */ + temp |= 0x00001000; /*enable loop */ + WRITEL (devc->osdev, temp, TCTRL); /*set format */ + WRITEL (devc->osdev, 0, FMC); + WRITEL (devc->osdev, 0, EBUF1); + WRITEL (devc->osdev, 0, EBUF2); + WRITEL (devc->osdev, 0, VOL); /*Music/WaveVol set to max */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + WRITEL (devc->osdev, 0, CSO); /*set CSO and Alpha to 0 */ + } + else + { + WRITEL (devc->osdev, (delta << 24) | (0 & 0x00ffffff), CSO); + } + + /* Now prepare the playback interrupt channel */ + delta = (portc->speed * 4096) / 48000; + bufsize = dmap->fragment_size; + if (portc->bits == 16) + bufsize /= 2; + if (portc->channels == 2) + bufsize /= 2; + bufsize--; + + if (portc->pbank == BANK_A) + chan = portc->play_intr_chan; + else + chan = portc->play_intr_chan + 32; + + WRITEL (devc->osdev, (READL (devc->osdev, CIR) & ~0x3F) | chan, CIR); /*select current chan */ + + /* Now set the buffer address pointer */ + WRITEL (devc->osdev, dmap->dmabuf_phys, LBA); + + /* Set the Size and Sampling Rate */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + eso = (bufsize << 16) | (delta & 0x0000FFFF); + WRITEL (devc->osdev, eso, ESO); + } + else + { + eso = ((delta << 16) & 0xff000000) | (bufsize & 0x00ffffff); + WRITEL (devc->osdev, eso, ESO); + } + + temp = 0x80000000; /*enable gvsel */ + if (portc->channels == 2) + temp |= 0x00004000; /*stereo/mono */ + if (portc->bits == 16) + temp |= 0x0000A000; /*8 unsigned/16bit signed data */ + temp |= 0x00001000; /*enable loop */ + temp |= 0xFFF; /* no vol */ + temp |= 0x003F0000; /*set volume to off */ + WRITEL (devc->osdev, temp, TCTRL); /*set format */ + WRITEL (devc->osdev, 0, FMC); + WRITEL (devc->osdev, 0, EBUF1); + WRITEL (devc->osdev, 0, EBUF2); + WRITEL (devc->osdev, 0, VOL); /*Music/WaveVol set to max */ + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) || (devc->chip_type == ALI_5451_ID)) + { + WRITEL (devc->osdev, 0, CSO); /*set CSO and Alpha to 0 */ + } + else + { + WRITEL (devc->osdev, (delta << 24) | (0 & 0x00ffffff), CSO); + } + + /* Now set the mode on portc to playback */ + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +#if 0 +static int +trident_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + trident_devc *devc = audio_engines[dev]->devc; + trident_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + int ptr = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (direction == PCM_ENABLE_INPUT) + { + WRITEB (devc->osdev, + (READB (devc->osdev, CIR) & ~0x7F) | portc->rec_chan, CIR); + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) + || (devc->chip_type == ALI_5451_ID)) + ptr = READW (devc->osdev, CSO + 2); + else /* ID_4DWAVE_NX */ + { + ptr = READW (devc->osdev, SBBL) & 0xFFFF; + if (portc->channels > 1) + ptr >>= 1; + if (ptr > 0) + ptr = dmap->bytes_in_use - ptr; + } + } + + if (direction == PCM_ENABLE_OUTPUT) + { + WRITEB (devc->osdev, + (READB (devc->osdev, CIR) & ~0x7F) | portc->play_chan, CIR); + if ((devc->chip_type == TRIDENT_4DWAVEDX_ID) + || (devc->chip_type == SIS_7018_ID) + || (devc->chip_type == ALI_5451_ID)) + { + ptr = READW (devc->osdev, CSO + 2); + } + else + { + ptr = READL (devc->osdev, CSO) & 0x00ffffff; + } + if (ptr > dmap->bytes_in_use) + ptr = 0; + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return ptr; +} +#endif + +#if !defined(sparc) +static int +trident_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + int err; + + if (dmap->dmabuf != NULL) + return 0; + + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + { + cmn_err (CE_WARN, "Failed to allocate a DMA buffer.\n"); + return err; + } + if (dmap->dmabuf_phys & 0x80000000) + + { + cmn_err (CE_WARN, "Got DMA buffer address beyond 2G limit.\n"); + oss_free_dmabuf (dev, dmap); + dmap->dmabuf = NULL; + return OSS_ENOSPC; + } + return 0; +} +#endif + +static audiodrv_t trident_audio_driver = { + trident_audio_open, + trident_audio_close, + trident_audio_output_block, + trident_audio_start_input, + trident_audio_ioctl, + trident_audio_prepare_for_input, + trident_audio_prepare_for_output, + trident_audio_reset, + NULL, + NULL, + trident_audio_reset_input, + trident_audio_reset_output, + trident_audio_trigger, + trident_audio_set_rate, + trident_audio_set_format, + trident_audio_set_channels, + NULL, + NULL, + NULL, /* trident_check_input, */ + NULL, /* trident_check_output, */ +#if !defined(sparc) + trident_alloc_buffer, +#else + NULL, +#endif + NULL, /* trident_free_buffer, */ + NULL, + NULL, + NULL /* trident_get_buffer_pointer */ +}; + + +#ifdef OBSOLETED_STUFF +static void +attach_mpu (trident_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 = devc->chip_name; + 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 (trident_devc * devc) +{ + struct address_info hw_config; + hw_config.io_base = devc->mpu_base; + hw_config.irq = devc->mpu_irq; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = devc->chip_name; + 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_trident (trident_devc * devc) +{ + int my_mixer, i; + oss_device_t *osdev = devc->osdev; + unsigned char legacy; + oss_native_word global_control; + int adev; + unsigned int dwVal; + int first_dev = 0; + +/* + * Legacy I/O setup + */ + devc->mpu_attached = 0; + legacy = 0xA0; /* Enable MPU, GP, FM */ + switch (devc->mpu_base) + { + case 0x330: + legacy |= 0x00; + break; + case 0x300: + legacy |= 0x40; + break; + default: + devc->mpu_base = 0; + } + pci_write_config_byte (osdev, 0x44, legacy); /*setup legacy devs */ + + /* pci_write_config_byte (osdev, 0x45, 0x12); *//*setup DDMA */ + /* pci_write_config_byte (osdev, 0x46, 0x02); *//*setup device r/w */ + + /* Now reset AC97 and unmute the codec channels */ + if (devc->chip_type == TRIDENT_4DWAVEDX_ID) + { + WRITEB (devc->osdev, 0x09, 0x40); /*set ddma */ + WRITEL (devc->osdev, 0x2, 0x48); /*enable the AC97 */ + } + + if (devc->chip_type == SIS_7018_ID) + { + WRITEL (devc->osdev, 0, 0x4c); + WRITEL (devc->osdev, 0xF0000, 0x48); /* enable ac97 link */ + } + + if (devc->chip_type == TRIDENT_4DWAVENX_ID) + { + WRITEL (devc->osdev, 0x2, 0x40); + /* Setup 48KHz S/PDIF output on 4DWave NX */ + WRITEL (devc->osdev, INL (devc->osdev, SP_STAT) | 4, SP_STAT); + WRITEB (devc->osdev, 0x38, SP_CSO + 3); + } + + if (devc->chip_type == ALI_5451_ID) + { +#ifndef sparc + pci_read_config_dword (osdev, 0x7c, &dwVal); + pci_write_config_dword (osdev, 0x7c, dwVal | 0x08000000); + oss_udelay (5000); + pci_read_config_dword (osdev, 0x7c, &dwVal); + pci_write_config_dword (osdev, 0x7c, dwVal & 0xf7ffffff); + oss_udelay (5000); + pci_read_config_dword (osdev, 0x44, &dwVal); + pci_write_config_dword (osdev, 0x44, dwVal | 0x000c0000); + oss_udelay (500); + pci_read_config_dword (osdev, 0x44, &dwVal); + pci_write_config_dword (osdev, 0x44, dwVal & 0xfffbffff); +#endif + /* enable full 32bit and disable DDMA */ + pci_write_config_dword (osdev, 0x40, dwVal & 0x00000008); + oss_udelay (5000); + } + + my_mixer = ac97_install (&devc->ac97devc, devc->chip_name, ac97_read, + ac97_write, devc, devc->osdev); + if (my_mixer >= 0) + { + devc->mixer_dev = my_mixer; + mixer_devs[my_mixer]->priority = 9; + } + else + return 0; + +#ifdef OBSOLETED_STUFF + if (devc->mpu_base > 0) + attach_mpu (devc); +#endif + + for (i = 0; i < 2; i++) + { + char tmp_name[1024]; + trident_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE /* | ADEV_HWMIX */ ; + int porttype = DF_PCM; + + sprintf (tmp_name, "%s (rev %d)", devc->chip_name, devc->revision); + if (i == 0) + { + caps |= ADEV_DUPLEX; + } + else + { + caps |= ADEV_NOINPUT; + if (i > 1) + caps |= ADEV_SHADOW; + } + +#if 0 + /* This will not work any more */ + if ((devc->chip_type == ALI_5451_ID) + && (devc->revision == ALI_5451_V02) && (i == 7)) + { + /* need to set SPDIF output in PCI southbridge chip 0x1533 */ + while ((osdev = (pci_find_class (0x601 << 8, osdev)))) + { + unsigned short vendorid, deviceid; + unsigned char temp; + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendorid); + pci_read_config_word (osdev, PCI_DEVICE_ID, &deviceid); + if (vendorid != 0x10b9 || deviceid != 0x1533) + continue; + pci_read_config_byte (osdev, 0x61, &temp); + temp |= 0x40; + pci_write_config_byte (osdev, 0x61, temp); + pci_read_config_byte (osdev, 0x7d, &temp); + temp |= 0x01; + pci_write_config_byte (osdev, 0x7d, temp); + pci_read_config_byte (osdev, 0x7e, &temp); + temp &= (~0x20); + temp |= 0x10; + pci_write_config_byte (osdev, 0x7e, temp); + + /* SPDIF Magic!!! */ + pci_read_config_byte (osdev, 0x63, &temp); + temp |= 0x3; /* enable SPDIF OUT bit0=out bit1=in */ + pci_write_config_byte (osdev, 0x63, temp); + + /* SPDIF Output in SERIAL Config reg */ + temp = READL (devc->osdev, 0x48); + WRITEB (devc->osdev, temp | 0x20, 0x48); + temp = READL (devc->osdev, 0x74); + WRITEB (devc->osdev, temp & 0xbf, 0x74); + + /* Enable SPDIF on play_channel 15 and setup as SPDIFOUT */ + WRITEW (devc->osdev, READW (devc->osdev, 0xd4) | 0x8000, 0xd4); + WRITEW (devc->osdev, READW (devc->osdev, 0xd4) & ~0x0400, 0xd4); + + porttype = DF_SPDIF; + caps |= ADEV_SPECIAL | ADEV_FIXEDRATE; + sprintf (tmp_name, "%s (S/PDIF Output)", devc->chip_name); + } + } +#endif + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &trident_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_U8 | AFMT_S16_LE | AFMT_AC3, + 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]->min_rate = 8000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + +#if !defined(sparc) + /* + * Only 31 bit memory addresses are supported except under Sparc + * where the on-board audio chip supports the top half of 32 bit PCI + * address space. + */ + audio_engines[adev]->dmabuf_maxaddr = MEMLIMIT_31BITS; +#endif + portc->audiodev = adev; + portc->open_mode = 0; + portc->audio_enabled = 0; + + if (audio_engines[adev]->flags & ADEV_FIXEDRATE) + { + audio_engines[adev]->fixed_rate = 48000; + audio_engines[adev]->min_rate = 48000; + audio_engines[adev]->max_rate = 48000; + } + + portc->port_type = porttype; + portc->play_chan = 3 + (2 * i); + portc->play_intr_chan = 2 + (2 * i); + portc->pbank = BANK_A; + portc->rec_chan = 1; + portc->rec_intr_chan = 0; + portc->rbank = BANK_A; + + if (devc->chip_type == ALI_5451_ID) + { + portc->rec_chan = 31; + portc->rec_intr_chan = 30; + portc->rbank = BANK_A; + } + if (devc->chip_type == SIS_7018_ID) + { + portc->pbank = BANK_B; + portc->rec_chan = 1; + portc->rec_intr_chan = 0; + portc->rbank = BANK_B; + WRITEL (devc->osdev, READL (devc->osdev, CIR) | 0x10000, CIR); + } +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + + devc->audio_opened = 0; + /* set the global control and enable end interrupt condition */ + global_control = READL (devc->osdev, CIR); + global_control |= (1 << 12); /* control end intr */ + WRITEL (devc->osdev, global_control, CIR); + } + return 1; +} + +int +oss_trident_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + trident_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered Trident 4DWAVE probe routine\n")); + + oss_pci_byteswap (osdev, 1); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if ((vendor != TRIDENT_VENDOR_ID && vendor != ALI_VENDOR_ID + && vendor != SIS_VENDOR_ID) || + (device != TRIDENT_4DWAVEDX_ID && device != TRIDENT_4DWAVENX_ID && + device != TRIDENT_4DWAVECX_ID && device != ALI_5451_ID && + device != SIS_7018_ID)) + + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &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->revision = pci_revision; + devc->irq = pci_irq_line; + + switch (device) + { + case TRIDENT_4DWAVEDX_ID: + devc->chip_name = "Trident 4DWAVEDX"; + devc->chip_type = TRIDENT_4DWAVEDX_ID; + break; + case TRIDENT_4DWAVENX_ID: + devc->chip_name = "Trident 4DWAVENX"; + devc->chip_type = TRIDENT_4DWAVENX_ID; + break; + case TRIDENT_4DWAVECX_ID: + devc->chip_name = "Trident 4DWAVECX"; + devc->chip_type = TRIDENT_4DWAVECX_ID; + break; + case ALI_5451_ID: + devc->chip_name = "ALI M5451"; + devc->chip_type = ALI_5451_ID; + break; + case SIS_7018_ID: + devc->chip_name = "SiS 7018"; + devc->chip_type = SIS_7018_ID; + break; + default: + devc->chip_name = "Trident 4DWAVE"; + devc->chip_type = TRIDENT_4DWAVEDX_ID; + } + +#ifdef MEM_MAPPED_REGISTERS + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_1, &devc->bar1addr); + devc->bar1virt = + (char *) MAP_PCI_MEM (devc->osdev, 1, devc->bar1addr, 1024 * 1024); + pci_command |= PCI_COMMAND_MEMORY; +#else + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + + /* Remove I/O space marker in bit 0. */ + devc->base &= ~0x03; + pci_command |= PCI_COMMAND_IO; +#endif + devc->mpu_base = trident_mpu_ioaddr; + devc->mpu_irq = devc->irq; + + /* activate the device */ + pci_command |= PCI_COMMAND_MASTER; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + 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 (oss_register_interrupts (devc->osdev, 0, tridentintr, NULL) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d\n", pci_irq_line); + return 0; + } + + return init_trident (devc); /*Detected */ +} + + + +int +oss_trident_detach (oss_device_t * osdev) +{ + trident_devc *devc = (trident_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + WRITEL (devc->osdev, 0, CIR); + if (devc->chip_type == TRIDENT_4DWAVENX_ID) + WRITEL (devc->osdev, 0x0, SP_CSO); /*disable S/PDIF on NX */ + +#ifdef OBSOLETED_STUFF + if (devc->mpu_attached) + { + unload_mpu (devc); + devc->mpu_attached = 0; + } +#endif + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + +#ifdef MEM_MAPPED_REGISTERS + UNMAP_PCI_MEM(osdev, 1, devc->bar1addr, devc->bar1virt, 1024x1024); +#else + UNMAP_PCI_IOADDR (devc->osdev, 0); +#endif + + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_trident/oss_trident.man b/kernel/drv/oss_trident/oss_trident.man new file mode 100644 index 0000000..d70929d --- /dev/null +++ b/kernel/drv/oss_trident/oss_trident.man @@ -0,0 +1,27 @@ +NAME +oss_trident - SiS7018, 4Dwave, ALIM5451 audio driver. + +DESCRIPTION +Open Sound System driver for Trident 4DWave DX/NX, SiS7018 and ALI5451 audio +controllers. + +Trident device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + o Upto 8 hardware channels to mixing audio streams + +OPTIONS +trident_mpu_ioaddr=<xxx> +Set the MPU I/O address. Refer to the driver.conf file for valid addresses. + +LIMITATIONS +o Due to PCI addressing limitations any add-on cards based on these chips +will not work under Sparc. The only exception is the ALI5451 chip that is +used on the main boards on many Sparc based systems. + +FILES +CONFIGFILEPATH/oss_trident.conf Device configuration file + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_usb/.config b/kernel/drv/oss_usb/.config new file mode 100644 index 0000000..17d7733 --- /dev/null +++ b/kernel/drv/oss_usb/.config @@ -0,0 +1,3 @@ +bus=USB +targetos=SunOS +targetos=Linux diff --git a/kernel/drv/oss_usb/.devices b/kernel/drv/oss_usb/.devices new file mode 100644 index 0000000..456a797 --- /dev/null +++ b/kernel/drv/oss_usb/.devices @@ -0,0 +1,28 @@ +oss_usb usbif,class1 Generic USB audio/MIDI device (BETA) +oss_usb usbif41e,3000 Creative Sound Blaster Extigy (BETA) +oss_usb usbif41e,3010 Creative Sound Blaster MP3+ USB +oss_usb usbif41e,3020 Creative Audigy2 NX USB (BETA) +oss_usb usbif46d,8b2 Logitec Quickcam Pro 4000 (mic) (BETA) +oss_usb usbif46d,a01 Logitec USB Headset +oss_usb usbif471,311 Philips ToUcam Pro (mic) (BETA) +oss_usb usbif672,1041 Labtec LCS1040 Speaker System (BETA) +oss_usb usbifd8c,c C-Media USB audio adapter - model1 +oss_usb usbifd8c,103 C-Media USB audio adapter - model2 +oss_usb usbifd8c,102 C-Media USB 2/4/6/8ch audio adapter +oss_usb usbif6f8,c000 Hercules Gamesurround MUSE Pocket (BETA) +oss_usb usb763,1010 M Audio USB MIDISPORT 1x1 (BETA) +oss_usb usb763,1011 M Audio USB MIDISPORT 1x1 (BETA) +oss_usb usb763,1001 M Audio USB MIDISPORT 2x2 (BETA) +oss_usb usb763,1002 M Audio USB MIDISPORT 2x2 (BETA) +oss_usb usb763,1031 M Audio USB MIDISPORT 8x8 (BETA) +oss_usb usbif763,2001 M Audio USB AudioSport Quatro (BETA) +oss_usb usbif763,2002 M Audio USB AudioSport Duo (BETA) +oss_usb usbif763,classff Generic M Audio USB MIDI interface (BETA) +oss_usb usbif763,2007 M Audio Sonica Theater USB (BETA) +oss_usb usbif763,200d M Audio OmniStudio USB (BETA) +oss_usb usbif763,2805 M Audio Sonica USB (BETA) +oss_usb usb763,1014 M Audio Oygen8 MIDI keyboard +oss_usb usb763,1015 M Audio Oygen8 MIDI keyboard +oss_usb usbifa92,1010 EGO SYStems RoMI/O USB MIDI interface (BETA) +oss_usb usb499,1009 Yamaha UX16 USB MIDI interface (BETA) +oss_usb usb499,101e Yamaha PSR-1K USB MIDI Keyboard (BETA) diff --git a/kernel/drv/oss_usb/.name b/kernel/drv/oss_usb/.name new file mode 100644 index 0000000..42bff9b --- /dev/null +++ b/kernel/drv/oss_usb/.name @@ -0,0 +1 @@ +USB audio device support (BETA) diff --git a/kernel/drv/oss_usb/.params b/kernel/drv/oss_usb/.params new file mode 100644 index 0000000..01df07b --- /dev/null +++ b/kernel/drv/oss_usb/.params @@ -0,0 +1,2 @@ +int usb_trace=0; +int usb_mixerstyle=1; diff --git a/kernel/drv/oss_usb/midisport1x1_fw.h b/kernel/drv/oss_usb/midisport1x1_fw.h new file mode 100755 index 0000000..0a5eb07 --- /dev/null +++ b/kernel/drv/oss_usb/midisport1x1_fw.h @@ -0,0 +1,677 @@ +/* + * Purpose: Firmware download for Midiman MIDISport 1x1 + */ +/* + * + * 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. + * + */ +const struct setup_request midisport1x1_setupRequest[] = { + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x146C, 0x0000, 0x0010, 0x0010, + "\xC2\x00\x90\x7F\xA5\xE0\x54\x18\xFF\x13\x13\x13\x54\x1F\x44\x50"}, + {0x40, 0xA0, 0x147C, 0x0000, 0x0010, 0x0010, + "\xF5\x1C\x13\x92\x01\xD2\xE8\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9"}, + {0x40, 0xA0, 0x148C, 0x0000, 0x0010, 0x0010, + "\xF0\x90\x7F\xAA\xF0\x53\x91\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90"}, + {0x40, 0xA0, 0x149C, 0x0000, 0x0010, 0x0010, + "\x7F\xAF\xE0\x44\x01\xF0\x90\x7F\xAE\xE0\x44\x05\xF0\xD2\xAF\x12"}, + {0x40, 0xA0, 0x14AC, 0x0000, 0x000D, 0x000D, + "\x17\x5F\x30\x00\xFD\x12\x11\x00\xC2\x00\x80\xF6\x22"}, + {0x40, 0xA0, 0x1100, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x24\x5D\x60\x0D\x14\x70\x03\x02\x12\x44\x24\x02"}, + {0x40, 0xA0, 0x1110, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x12\x4A\x90\x7F\xEA\xE0\x75\x08\x00\xF5\x09\xA3\xE0"}, + {0x40, 0xA0, 0x1120, 0x0000, 0x0010, 0x0010, + "\xFE\xE4\x25\x09\xF5\x09\xEE\x35\x08\xF5\x08\x90\x7F\xEE\xE0\x75"}, + {0x40, 0xA0, 0x1130, 0x0000, 0x0010, 0x0010, + "\x0A\x00\xF5\x0B\xA3\xE0\xFE\xE4\x25\x0B\xF5\x0B\xEE\x35\x0A\xF5"}, + {0x40, 0xA0, 0x1140, 0x0000, 0x0010, 0x0010, + "\x0A\x90\x7F\xE8\xE0\x64\xC0\x60\x03\x02\x11\xD4\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x1150, 0x0000, 0x0010, 0x0010, + "\x70\x03\x02\x12\x4A\xC3\xE5\x0B\x94\x40\xE5\x0A\x94\x00\x50\x08"}, + {0x40, 0xA0, 0x1160, 0x0000, 0x0010, 0x0010, + "\x85\x0A\x0C\x85\x0B\x0D\x80\x06\x75\x0C\x00\x75\x0D\x40\x90\x7F"}, + {0x40, 0xA0, 0x1170, 0x0000, 0x0010, 0x0010, + "\xE9\xE0\xB4\xA3\x25\xAE\x0C\xAF\x0D\xAA\x08\xA9\x09\x7B\x01\xC0"}, + {0x40, 0xA0, 0x1180, 0x0000, 0x0010, 0x0010, + "\x03\xC0\x02\xC0\x01\x7A\x7F\x79\x00\x78\x00\x7C\x7F\xAD\x03\xD0"}, + {0x40, 0xA0, 0x1190, 0x0000, 0x0010, 0x0010, + "\x01\xD0\x02\xD0\x03\x12\x13\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D"}, + {0x40, 0xA0, 0x11A0, 0x0000, 0x0010, 0x0010, + "\x7A\x7F\x79\x00\x7B\x00\x12\x15\xA4\x90\x7F\xB5\xE5\x0D\xF0\xE5"}, + {0x40, 0xA0, 0x11B0, 0x0000, 0x0010, 0x0010, + "\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5\x0B\x95\x0D"}, + {0x40, 0xA0, 0x11C0, 0x0000, 0x0010, 0x0010, + "\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x20\xE2\x03\x02"}, + {0x40, 0xA0, 0x11D0, 0x0000, 0x0010, 0x0010, + "\x11\x4C\x80\xF4\x90\x7F\xE8\xE0\x64\x40\x70\x6E\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x11E0, 0x0000, 0x0010, 0x0010, + "\x60\x68\xE4\x90\x7F\xC5\xF0\x90\x7F\xB4\xE0\x20\xE3\xF9\x90\x7F"}, + {0x40, 0xA0, 0x11F0, 0x0000, 0x0010, 0x0010, + "\xC5\xE0\x75\x0C\x00\xF5\x0D\x90\x7F\xE9\xE0\xB4\xA3\x15\xAE\x0C"}, + {0x40, 0xA0, 0x1200, 0x0000, 0x0010, 0x0010, + "\xAF\x0D\xA8\x09\xAC\x08\x7D\x01\x7B\x01\x7A\x7E\x79\xC0\x12\x13"}, + {0x40, 0xA0, 0x1210, 0x0000, 0x0010, 0x0010, + "\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D\x7A\x7F\x79\x00\x7B\x00\x12"}, + {0x40, 0xA0, 0x1220, 0x0000, 0x0010, 0x0010, + "\x14\xB9\xE5\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5"}, + {0x40, 0xA0, 0x1230, 0x0000, 0x0010, 0x0010, + "\x0B\x95\x0D\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x44"}, + {0x40, 0xA0, 0x1240, 0x0000, 0x000A, 0x000A, + "\x02\xF0\x80\x98\x90\x7F\xEA\xE0\xF5\x1C"}, + {0x40, 0xA0, 0x124A, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x1558, 0x0000, 0x0006, 0x0006, "\xAB\x07\xAA\x06\xAC\x05"}, + {0x40, 0xA0, 0x155E, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x11\xEA\xFF\xAE\x05\x0D\xEE\x24\x00\xF5\x82\xE4"}, + {0x40, 0xA0, 0x156E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEF\xF0\xEB\xAE\x05\x0D\x74\x00\x2E\xF5\x82\xE4"}, + {0x40, 0xA0, 0x157E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEB\xF0\xAF\x05\x0D\x74\x00\x2F\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x158E, 0x0000, 0x0010, 0x0010, + "\xE0\xF5\x83\xEC\xF0\xAF\x1C\x7A\xE0\x7B\x00\x12\x17\x20\x7F\x0A"}, + {0x40, 0xA0, 0x159E, 0x0000, 0x0005, 0x0005, "\x7E\x00\x12\x17\x3C"}, + {0x40, 0xA0, 0x15A3, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x14B9, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x14C3, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x13\xE5\x13\xC3\x95\x10\x50\x20\x05\x0F\xE5\x0F\xAE\x0E"}, + {0x40, 0xA0, 0x14D3, 0x0000, 0x0010, 0x0010, + "\x70\x02\x05\x0E\x14\xFF\xE5\x12\x25\x13\xF5\x82\xE4\x35\x11\xF5"}, + {0x40, 0xA0, 0x14E3, 0x0000, 0x000A, 0x000A, + "\x83\xE0\xFD\x12\x15\x58\x05\x13\x80\xD9"}, + {0x40, 0xA0, 0x14ED, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x15A4, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x15AE, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x12\xE5\x0E\xFF\xAE\x05\x0D\xEE\x24\x03\xF5\x82"}, + {0x40, 0xA0, 0x15BE, 0x0000, 0x0010, 0x0010, + "\xE4\x34\xE0\xF5\x83\xEF\xF0\xE5\x0F\xAE\x05\x0D\x74\x03\x2E\xF5"}, + {0x40, 0xA0, 0x15CE, 0x0000, 0x0010, 0x0010, + "\x82\xE4\x34\xE0\xF5\x83\xE5\x0F\xF0\xAF\x1C\x7A\xE0\x7B\x03\x12"}, + {0x40, 0xA0, 0x15DE, 0x0000, 0x000D, 0x000D, + "\x17\x20\xAF\x1C\xAD\x10\xAB\x12\xAA\x11\x12\x17\x04"}, + {0x40, 0xA0, 0x15EB, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x166E, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x167E, 0x0000, 0x0010, 0x0010, + "\x00\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x168E, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1644, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x1654, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x1664, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1695, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16A5, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x02\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16B5, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x16BA, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16CA, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16DA, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x14FF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x16DF, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16EF, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16FF, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1767, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1768, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1769, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176A, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176B, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176C, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176D, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176E, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176F, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1770, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1771, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1772, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1773, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1774, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1775, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1776, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x15\x00"}, + {0x40, 0xA0, 0x1500, 0x0000, 0x0010, 0x0010, + "\x02\x16\x6E\x00\x02\x16\x95\x00\x02\x16\x44\x00\x02\x16\xDF\x00"}, + {0x40, 0xA0, 0x1510, 0x0000, 0x0010, 0x0010, + "\x02\x16\xBA\x00\x02\x14\xFF\x00\x02\x17\x67\x00\x02\x17\x68\x00"}, + {0x40, 0xA0, 0x1520, 0x0000, 0x0010, 0x0010, + "\x02\x17\x69\x00\x02\x17\x6A\x00\x02\x17\x6B\x00\x02\x17\x6C\x00"}, + {0x40, 0xA0, 0x1530, 0x0000, 0x0010, 0x0010, + "\x02\x17\x6D\x00\x02\x17\x6E\x00\x02\x17\x6F\x00\x02\x17\x70\x00"}, + {0x40, 0xA0, 0x1540, 0x0000, 0x0010, 0x0010, + "\x02\x17\x71\x00\x02\x17\x72\x00\x02\x17\x73\x00\x02\x17\x74\x00"}, + {0x40, 0xA0, 0x1550, 0x0000, 0x0008, 0x0008, + "\x02\x17\x75\x00\x02\x17\x76\x00"}, + {0x40, 0xA0, 0x173C, 0x0000, 0x0010, 0x0010, + "\x8E\x14\x8F\x15\xE5\x15\x15\x15\xAE\x14\x70\x02\x15\x14\x4E\x60"}, + {0x40, 0xA0, 0x174C, 0x0000, 0x0007, 0x0007, + "\x05\x12\x14\xEE\x80\xEE\x22"}, + {0x40, 0xA0, 0x175F, 0x0000, 0x0008, 0x0008, + "\xE4\xF5\x1B\xD2\xE9\xD2\xAF\x22"}, + {0x40, 0xA0, 0x1619, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x23\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x1629, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A\x18\x89"}, + {0x40, 0xA0, 0x1639, 0x0000, 0x000B, 0x000B, + "\x19\xE4\xF5\x1A\x75\x1B\x01\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x15EC, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x25\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x15FC, 0x0000, 0x0010, 0x0010, + "\x44\x01\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A"}, + {0x40, 0xA0, 0x160C, 0x0000, 0x000D, 0x000D, + "\x18\x89\x19\xE4\xF5\x1A\x75\x1B\x03\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x004B, 0x0000, 0x0003, 0x0003, "\x02\x13\x7F"}, + {0x40, 0xA0, 0x137F, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x138F, 0x0000, 0x0010, 0x0010, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x01\xC0\x02\xC0\x03\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x139F, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA5\xE0\x30\xE2\x06\x75\x1B\x06\x02\x14\x4E\x90\x7F\xA5"}, + {0x40, 0xA0, 0x13AF, 0x0000, 0x0010, 0x0010, + "\xE0\x20\xE1\x0C\xE5\x1B\x64\x02\x60\x06\x75\x1B\x07\x02\x14\x4E"}, + {0x40, 0xA0, 0x13BF, 0x0000, 0x0010, 0x0010, + "\xAF\x1B\xEF\x24\xFE\x60\x48\x14\x60\x2C\x24\xFE\x60\x77\x24\x04"}, + {0x40, 0xA0, 0x13CF, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x14\x4E\xAB\x17\xAA\x18\xA9\x19\xAF\x1A\x05\x1A\x8F"}, + {0x40, 0xA0, 0x13DF, 0x0000, 0x0010, 0x0010, + "\x82\x75\x83\x00\x12\x12\x4B\x90\x7F\xA6\xF0\xE5\x1A\x65\x16\x70"}, + {0x40, 0xA0, 0x13EF, 0x0000, 0x0010, 0x0010, + "\x5E\x75\x1B\x05\x80\x59\x90\x7F\xA6\xE0\xAB\x17\xAA\x18\xA9\x19"}, + {0x40, 0xA0, 0x13FF, 0x0000, 0x0010, 0x0010, + "\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12\x78\x75\x1B\x02\x80\x40\xE5"}, + {0x40, 0xA0, 0x140F, 0x0000, 0x0010, 0x0010, + "\x16\x24\xFE\xB5\x1A\x07\x90\x7F\xA5\xE0\x44\x20\xF0\xE5\x16\x14"}, + {0x40, 0xA0, 0x141F, 0x0000, 0x0010, 0x0010, + "\xB5\x1A\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x90\x7F\xA6"}, + {0x40, 0xA0, 0x142F, 0x0000, 0x0010, 0x0010, + "\xE0\xAB\x17\xAA\x18\xA9\x19\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12"}, + {0x40, 0xA0, 0x143F, 0x0000, 0x0010, 0x0010, + "\x78\x05\x1A\x80\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x53"}, + {0x40, 0xA0, 0x144F, 0x0000, 0x0010, 0x0010, + "\x91\xDF\xD0\x07\xD0\x06\xD0\x03\xD0\x02\xD0\x01\xD0\x00\xD0\xD0"}, + {0x40, 0xA0, 0x145F, 0x0000, 0x000D, 0x000D, + "\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1704, 0x0000, 0x0010, 0x0010, + "\x12\x15\xEC\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1714, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x1720, 0x0000, 0x0010, 0x0010, + "\x12\x16\x19\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1730, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x14EE, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x14FE, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x17\x53"}, + {0x40, 0xA0, 0x1753, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\x20\x02\x14\x6C"}, + {0x40, 0xA0, 0x124B, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x125B, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x126B, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x1278, 0x0000, 0x0010, 0x0010, + "\xF8\xBB\x01\x0D\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE8\xF0"}, + {0x40, 0xA0, 0x1288, 0x0000, 0x0010, 0x0010, + "\x22\x50\x06\xE9\x25\x82\xC8\xF6\x22\xBB\xFE\x05\xE9\x25\x82\xC8"}, + {0x40, 0xA0, 0x1298, 0x0000, 0x0002, 0x0002, "\xF2\x22"}, + {0x40, 0xA0, 0x129A, 0x0000, 0x0010, 0x0010, + "\xE7\x09\xF6\x08\xDF\xFA\x80\x46\xE7\x09\xF2\x08\xDF\xFA\x80\x3E"}, + {0x40, 0xA0, 0x12AA, 0x0000, 0x0010, 0x0010, + "\x88\x82\x8C\x83\xE7\x09\xF0\xA3\xDF\xFA\x80\x32\xE3\x09\xF6\x08"}, + {0x40, 0xA0, 0x12BA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x6E\xE3\x09\xF2\x08\xDF\xFA\x80\x66\x88\x82\x8C\x83"}, + {0x40, 0xA0, 0x12CA, 0x0000, 0x0010, 0x0010, + "\xE3\x09\xF0\xA3\xDF\xFA\x80\x5A\x89\x82\x8A\x83\xE0\xA3\xF6\x08"}, + {0x40, 0xA0, 0x12DA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x4E\x89\x82\x8A\x83\xE0\xA3\xF2\x08\xDF\xFA\x80\x42"}, + {0x40, 0xA0, 0x12EA, 0x0000, 0x0010, 0x0010, + "\x80\xD2\x80\xFA\x80\xC6\x80\xD4\x80\x55\x80\xF2\x80\x29\x80\x10"}, + {0x40, 0xA0, 0x12FA, 0x0000, 0x0010, 0x0010, + "\x80\xA6\x80\xEA\x80\x9A\x80\xA8\x80\xDA\x80\xE2\x80\xCA\x80\x29"}, + {0x40, 0xA0, 0x130A, 0x0000, 0x0010, 0x0010, + "\x88\x84\x8C\x85\x89\x82\x8A\x83\xE4\x93\xA3\x05\x86\xF0\xA3\x05"}, + {0x40, 0xA0, 0x131A, 0x0000, 0x0010, 0x0010, + "\x86\xDF\xF5\xDE\xF3\x80\x0B\x89\x82\x8A\x83\xE4\x93\xA3\xF6\x08"}, + {0x40, 0xA0, 0x132A, 0x0000, 0x0010, 0x0010, + "\xDF\xF9\xEC\xFA\xA9\xF0\xED\xFB\x22\x88\x84\x8C\x85\x89\x82\x8A"}, + {0x40, 0xA0, 0x133A, 0x0000, 0x0010, 0x0010, + "\x83\xE0\xA3\x05\x86\xF0\xA3\x05\x86\xDF\xF6\xDE\xF4\x80\xE3\x89"}, + {0x40, 0xA0, 0x134A, 0x0000, 0x0010, 0x0010, + "\x82\x8A\x83\xE4\x93\xA3\xF2\x08\xDF\xF9\x80\xD6\x88\xF0\xED\x24"}, + {0x40, 0xA0, 0x135A, 0x0000, 0x0010, 0x0010, + "\x02\xB4\x04\x00\x50\xCC\xF5\x82\xEB\x24\x02\xB4\x04\x00\x50\xC2"}, + {0x40, 0xA0, 0x136A, 0x0000, 0x0010, 0x0010, + "\x23\x23\x45\x82\xF5\x82\xEF\x4E\x60\xB8\xEF\x60\x01\x0E\xE5\x82"}, + {0x40, 0xA0, 0x137A, 0x0000, 0x0005, 0x0005, "\x23\x90\x12\xEA\x73"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x0100, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0110, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0120, 0x0000, 0x0010, 0x0010, + "\x4D\x69\x64\x69\x6D\x61\x6E\x20\x55\x53\x42\x20\x4D\x69\x64\x69"}, + {0x40, 0xA0, 0x0130, 0x0000, 0x0010, 0x0010, + "\x53\x70\x6F\x72\x74\x20\x31\x78\x31\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0140, 0x0000, 0x0010, 0x0010, + "\x46\x69\x72\x6D\x77\x61\x72\x65\x20\x52\x65\x6C\x65\x61\x73\x65"}, + {0x40, 0xA0, 0x0150, 0x0000, 0x0010, 0x0010, + "\x20\x31\x2E\x32\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0160, 0x0000, 0x0010, 0x0010, + "\x28\x63\x29\x20\x32\x30\x30\x30\x2D\x32\x30\x30\x31\x2C\x20\x4D"}, + {0x40, 0xA0, 0x0170, 0x0000, 0x0010, 0x0010, + "\x69\x64\x69\x6D\x61\x6E\x20\x49\x6E\x63\x2E\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0180, 0x0000, 0x0010, 0x0010, + "\x41\x6C\x6C\x20\x72\x69\x67\x68\x74\x73\x20\x72\x65\x73\x65\x72"}, + {0x40, 0xA0, 0x0190, 0x0000, 0x0010, 0x0010, + "\x76\x65\x64\x2E\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01A0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01B0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x08B2, 0x0000, 0x0003, 0x0003, "\x01\x1C\x00"}, + {0x40, 0xA0, 0x040D, 0x0000, 0x0010, 0x0010, + "\xC2\x01\xC2\x00\xC2\x04\xC2\x03\x12\x09\xE1\xD2\xE8\x43\xD8\x20"}, + {0x40, 0xA0, 0x041D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9\xF0\x90\x7F\xAA\xF0\x53\x91"}, + {0x40, 0xA0, 0x042D, 0x0000, 0x0010, 0x0010, + "\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90\x7F\xAF\xE0\x44\x01\xF0\x90"}, + {0x40, 0xA0, 0x043D, 0x0000, 0x0010, 0x0010, + "\x7F\xAE\xE0\x44\x1D\xF0\x90\x7F\x92\xE0\x44\x02\xF0\x90\x7F\x95"}, + {0x40, 0xA0, 0x044D, 0x0000, 0x0010, 0x0010, + "\xE0\x44\x01\xF0\x90\x7F\x9E\xE0\x54\xFE\xF0\x90\x7F\x95\xE0\x44"}, + {0x40, 0xA0, 0x045D, 0x0000, 0x0010, 0x0010, + "\x02\xF0\x90\x7F\x9E\xE0\x44\x02\xF0\x90\x7F\x95\xE0\x54\x83\xF0"}, + {0x40, 0xA0, 0x046D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\x9E\xE0\x44\x7C\xF0\x90\x7F\x94\xE0\x54\xFE\xF0\x90\x7F"}, + {0x40, 0xA0, 0x047D, 0x0000, 0x0010, 0x0010, + "\x9D\xE0\x44\x01\xF0\x90\x7F\x9A\xE0\x44\x01\x90\x7F\x97\xF0\x43"}, + {0x40, 0xA0, 0x048D, 0x0000, 0x0010, 0x0010, + "\x21\x20\x43\x21\x40\x43\x21\x10\x53\x89\xF0\xE4\xF5\x8C\xF5\x8A"}, + {0x40, 0xA0, 0x049D, 0x0000, 0x0010, 0x0010, + "\xD2\x8C\xD2\xA9\x12\x0B\xAE\xD2\xAF\xE5\x89\x54\x0F\x24\x20\xF5"}, + {0x40, 0xA0, 0x04AD, 0x0000, 0x0010, 0x0010, + "\x89\x75\x8D\xFE\x75\x8B\xFE\xD2\x8E\xC2\xAC\x75\x98\x50\xC2\x98"}, + {0x40, 0xA0, 0x04BD, 0x0000, 0x0010, 0x0010, + "\xC2\x99\xD2\xAC\x53\x21\xDF\x53\x21\xBF\x53\x21\xEF\x90\x7F\x9A"}, + {0x40, 0xA0, 0x04CD, 0x0000, 0x0010, 0x0010, + "\xE0\x54\xFE\x90\x7F\x97\xF0\x90\x7F\x98\xE5\x21\xF0\x75\x24\x3D"}, + {0x40, 0xA0, 0x04DD, 0x0000, 0x0010, 0x0010, + "\xE5\x24\x70\xFC\x43\x21\x20\x43\x21\x40\x43\x21\x10\x90\x7F\x98"}, + {0x40, 0xA0, 0x04ED, 0x0000, 0x0010, 0x0010, + "\xE5\x21\xF0\x20\x01\x3C\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9"}, + {0x40, 0xA0, 0x04FD, 0x0000, 0x0010, 0x0010, + "\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9\x75\x24\xF4\xE5\x24\x60"}, + {0x40, 0xA0, 0x050D, 0x0000, 0x0010, 0x0010, + "\x03\x30\x01\xF9\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9\x75\x24"}, + {0x40, 0xA0, 0x051D, 0x0000, 0x0010, 0x0010, + "\xF4\xE5\x24\x60\x03\x30\x01\xF9\x20\x01\xC8\xD2\x06\x12\x0A\xE0"}, + {0x40, 0xA0, 0x052D, 0x0000, 0x0010, 0x0010, + "\x80\xC1\x30\x01\x0C\x12\x01\xFF\xC2\x01\x90\x7F\xAE\xE0\x44\x02"}, + {0x40, 0xA0, 0x053D, 0x0000, 0x0010, 0x0010, + "\xF0\x30\x04\x1A\x12\x0B\x91\x50\x13\x12\x0B\x05\x20\x03\x07\x90"}, + {0x40, 0xA0, 0x054D, 0x0000, 0x0010, 0x0010, + "\x7F\xD6\xE0\x20\xE7\xF3\x12\x0B\x26\x12\x0B\xB2\xC2\x04\x05\x1C"}, + {0x40, 0xA0, 0x055D, 0x0000, 0x0010, 0x0010, + "\xE5\x1C\xC3\x94\x06\x40\x03\xE4\xF5\x1C\xE5\x1C\x75\xF0\x03\xA4"}, + {0x40, 0xA0, 0x056D, 0x0000, 0x000E, 0x000E, + "\x24\x0A\xF8\x08\xE6\xFA\x08\xE6\xF9\x12\x07\x11\x80\xB4"}, + {0x40, 0xA0, 0x057B, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0033, 0x0000, 0x0003, 0x0003, "\x02\x0B\xAA"}, + {0x40, 0xA0, 0x0BAA, 0x0000, 0x0004, 0x0004, "\x53\xD8\xEF\x32"}, + {0x40, 0xA0, 0x0023, 0x0000, 0x0003, 0x0003, "\x02\x07\x17"}, + {0x40, 0xA0, 0x0717, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x0727, 0x0000, 0x000C, 0x000C, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x05\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x0733, 0x0000, 0x0010, 0x0010, + "\x30\x99\x23\xC2\x99\xE5\x68\x60\x1B\xAF\x67\x05\x67\x74\x00\x2F"}, + {0x40, 0xA0, 0x0743, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x0F\xF5\x83\xE0\xF5\x99\x15\x68\x53\x21\xBF\x75"}, + {0x40, 0xA0, 0x0753, 0x0000, 0x0010, 0x0010, + "\x23\x0C\x80\x02\xD2\x02\x30\x98\x1E\xC2\x98\xAF\x99\xE5\x66\x04"}, + {0x40, 0xA0, 0x0763, 0x0000, 0x0010, 0x0010, + "\x54\x3F\xFE\x65\x65\x60\x0A\xAD\x66\x74\x25\x2D\xF8\xA6\x07\x8E"}, + {0x40, 0xA0, 0x0773, 0x0000, 0x0007, 0x0007, + "\x66\x53\x21\xDF\x75\x22\x0C"}, + {0x40, 0xA0, 0x077A, 0x0000, 0x0010, 0x0010, + "\xD0\x07\xD0\x06\xD0\x05\xD0\x00\xD0\xD0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x078A, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0A17, 0x0000, 0x0010, 0x0010, + "\xA2\xAC\x92\x06\xC2\xAC\x30\x02\x0C\xC2\x02\x8F\x99\x53\x21\xBF"}, + {0x40, 0xA0, 0x0A27, 0x0000, 0x0010, 0x0010, + "\x75\x23\x0C\x80\x12\xAE\x69\x05\x69\x74\x00\x2E\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x0A37, 0x0000, 0x000B, 0x000B, + "\x0F\xF5\x83\xEF\xF0\x05\x68\xA2\x06\x92\xAC"}, + {0x40, 0xA0, 0x0A42, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x01C0, 0x0000, 0x0010, 0x0010, + "\x12\x01\x00\x01\x00\x00\x00\x40\x63\x07\x11\x10\x21\x01\x00\x00"}, + {0x40, 0xA0, 0x01D0, 0x0000, 0x0010, 0x0010, + "\x00\x01\x09\x02\x27\x00\x01\x01\x00\xA0\x00\x09\x04\x00\x00\x03"}, + {0x40, 0xA0, 0x01E0, 0x0000, 0x0010, 0x0010, + "\xFF\x00\x00\x00\x07\x05\x81\x03\x20\x00\x01\x07\x05\x82\x02\x20"}, + {0x40, 0xA0, 0x01F0, 0x0000, 0x000F, 0x000F, + "\x00\x00\x07\x05\x02\x02\x20\x00\x00\x04\x03\x09\x04\x00\x00"}, + {0x40, 0xA0, 0x08B5, 0x0000, 0x0010, 0x0010, + "\x01\x24\x00\xC1\x01\x01\x22\x00\x01\x21\xFF\x01\x23\x00\xC1\x82"}, + {0x40, 0xA0, 0x08C5, 0x0000, 0x000F, 0x000F, + "\x01\x65\x00\x01\x66\x00\x01\x67\x00\x01\x69\x00\x01\x68\x00"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x09\x00"}, + {0x40, 0xA0, 0x0900, 0x0000, 0x0010, 0x0010, + "\x02\x0A\x6D\x00\x02\x08\x03\x00\x02\x0A\x43\x00\x02\x0A\x94\x00"}, + {0x40, 0xA0, 0x0910, 0x0000, 0x0010, 0x0010, + "\x02\x0A\xBB\x00\x02\x0B\xBE\x00\x02\x0B\xBF\x00\x02\x0B\xC0\x00"}, + {0x40, 0xA0, 0x0920, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC1\x00\x02\x0B\xC2\x00\x02\x0B\xC3\x00\x02\x0B\xC4\x00"}, + {0x40, 0xA0, 0x0930, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC5\x00\x02\x0B\xC6\x00\x02\x0B\xC7\x00\x02\x0B\xC8\x00"}, + {0x40, 0xA0, 0x0940, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC9\x00\x02\x0B\xCA\x00\x02\x0B\xCB\x00\x02\x0B\xCC\x00"}, + {0x40, 0xA0, 0x0950, 0x0000, 0x0008, 0x0008, + "\x02\x0B\xCD\x00\x02\x0B\xCE\x00"}, + {0x40, 0xA0, 0x08D4, 0x0000, 0x0010, 0x0010, + "\x12\x0A\xFF\x07\x91\xFF\x06\x08\xFF\x09\x58\xFF\x07\x91\xFF\x06"}, + {0x40, 0xA0, 0x08E4, 0x0000, 0x000A, 0x000A, + "\x08\xFF\x0B\x57\x01\x08\xFF\x01\x09\x00"}, + {0x40, 0xA0, 0x0791, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB6\xE0\x20\xE1\x6A\x7A\x7E\x79\x80\x7E\x7E\x7F\x80\x74"}, + {0x40, 0xA0, 0x07A1, 0x0000, 0x0010, 0x0010, + "\x7E\x90\x7F\xE3\xF0\x74\x80\x90\x7F\xE4\xF0\xE4\xFF\xE5\x66\x65"}, + {0x40, 0xA0, 0x07B1, 0x0000, 0x0010, 0x0010, + "\x65\x60\x43\xEF\xC3\x94\x08\x50\x3D\xE4\xFD\xE5\x66\x65\x65\x60"}, + {0x40, 0xA0, 0x07C1, 0x0000, 0x0010, 0x0010, + "\x1B\xED\xC3\x94\x03\x50\x15\x74\x25\x25\x65\xF8\xE6\x90\x7F\xE5"}, + {0x40, 0xA0, 0x07D1, 0x0000, 0x0010, 0x0010, + "\xF0\x05\x65\xE5\x65\x54\x3F\xF5\x65\x0D\x80\xDF\xED\x60\xCE\xFE"}, + {0x40, 0xA0, 0x07E1, 0x0000, 0x0010, 0x0010, + "\xEE\xC3\x94\x03\x50\x08\xE4\x90\x7F\xE5\xF0\x0E\x80\xF2\x90\x7F"}, + {0x40, 0xA0, 0x07F1, 0x0000, 0x0010, 0x0010, + "\xE5\xED\xF0\x0F\x80\xB7\xEF\x60\x08\x25\xE0\x25\xE0\x90\x7F\xB7"}, + {0x40, 0xA0, 0x0801, 0x0000, 0x0001, 0x0001, "\xF0"}, + {0x40, 0xA0, 0x0802, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0958, 0x0000, 0x0010, 0x0010, + "\xE5\x08\x60\x16\x14\x60\x2A\x80\x00\x12\x08\xFD\xEF\x65\x09\x60"}, + {0x40, 0xA0, 0x0968, 0x0000, 0x0010, 0x0010, + "\x36\x12\x08\xFD\x8F\x09\xE4\xF5\x08\x22\xE5\x22\x60\x10\xD5\x22"}, + {0x40, 0xA0, 0x0978, 0x0000, 0x0010, 0x0010, + "\x0D\xA2\xAF\x92\x06\xC2\xAF\x43\x21\x20\xA2\x06\x92\xAF\x05\x08"}, + {0x40, 0xA0, 0x0988, 0x0000, 0x0010, 0x0010, + "\x22\xE5\x23\x60\x10\xD5\x23\x0D\xA2\xAF\x92\x06\xC2\xAF\x43\x21"}, + {0x40, 0xA0, 0x0998, 0x0000, 0x0007, 0x0007, + "\x40\xA2\x06\x92\xAF\x05\x08"}, + {0x40, 0xA0, 0x099F, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0B57, 0x0000, 0x0010, 0x0010, + "\xA2\xAF\x92\x06\xC2\xAF\x90\x7F\x98\xE5\x21\xF0\xA2\x06\x92\xAF"}, + {0x40, 0xA0, 0x0B67, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0608, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xC8\xE0\x30\xE1\x03\x02\x06\x92\x90\x7F\xC9\xE0\xF5\x6A"}, + {0x40, 0xA0, 0x0618, 0x0000, 0x0010, 0x0010, + "\xC3\xE4\x95\x68\xFF\x74\x01\x94\x00\xFE\xC3\xE5\x6A\x9F\xE4\x9E"}, + {0x40, 0xA0, 0x0628, 0x0000, 0x0010, 0x0010, + "\x50\x68\xE4\xF5\x6B\xE5\x6B\xC3\x95\x6A\x50\x59\x74\xC3\x25\x6B"}, + {0x40, 0xA0, 0x0638, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x7D\xF5\x83\xE0\x54\x0F\xFD\x60\x48\x74\xC0\x25"}, + {0x40, 0xA0, 0x0648, 0x0000, 0x0010, 0x0010, + "\x6B\xF5\x82\xE4\x34\x7D\x90\x7F\xE3\xF0\x74\xC0\x25\x6B\xF5\x82"}, + {0x40, 0xA0, 0x0658, 0x0000, 0x0010, 0x0010, + "\xE4\x34\x7D\xE5\x82\x90\x7F\xE4\xF0\xAF\x05\xED\x14\x60\x16\x14"}, + {0x40, 0xA0, 0x0668, 0x0000, 0x0010, 0x0010, + "\x60\x0B\x14\x70\x18\x90\x7F\xE5\xE0\xFF\x12\x0A\x17\x90\x7F\xE5"}, + {0x40, 0xA0, 0x0678, 0x0000, 0x0010, 0x0010, + "\xE0\xFF\x12\x0A\x17\x90\x7F\xE5\xE0\xFF\x12\x0A\x17\x74\x04\x25"}, + {0x40, 0xA0, 0x0688, 0x0000, 0x000A, 0x000A, + "\x6B\xF5\x6B\x80\xA0\xE4\x90\x7F\xC9\xF0"}, + {0x40, 0xA0, 0x0692, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x08EE, 0x0000, 0x0003, 0x0003, "\x01\x1D\x00"}, + {0x40, 0xA0, 0x000B, 0x0000, 0x0003, 0x0003, "\x02\x0B\x84"}, + {0x40, 0xA0, 0x0B84, 0x0000, 0x000D, 0x000D, + "\xC0\xE0\x05\x1D\xE5\x24\x60\x02\x15\x24\xD0\xE0\x32"}, + {0x40, 0xA0, 0x08FD, 0x0000, 0x0003, 0x0003, "\xAF\x1D\x22"}, + {0x40, 0xA0, 0x0BAE, 0x0000, 0x0004, 0x0004, "\xE4\xF5\x1D\x22"}, + {0x40, 0xA0, 0x08F1, 0x0000, 0x000B, 0x000B, + "\x01\x72\x01\x01\x73\x01\xC1\x85\x01\x74\x02"}, + {0x40, 0xA0, 0x01FF, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x70\x03\x02\x02\xD4\x14\x70\x03\x02\x03\x4F\x24"}, + {0x40, 0xA0, 0x020F, 0x0000, 0x0010, 0x0010, + "\xFE\x70\x03\x02\x03\xA8\x24\xFB\x70\x03\x02\x02\xCE\x14\x70\x03"}, + {0x40, 0xA0, 0x021F, 0x0000, 0x0010, 0x0010, + "\x02\x02\xC8\x14\x70\x03\x02\x02\xBC\x14\x70\x03\x02\x02\xC2\x24"}, + {0x40, 0xA0, 0x022F, 0x0000, 0x0010, 0x0010, + "\x05\x60\x03\x02\x03\xFA\x12\x0B\xB4\x40\x03\x02\x04\x05\x90\x7F"}, + {0x40, 0xA0, 0x023F, 0x0000, 0x0010, 0x0010, + "\xEB\xE0\x24\xFE\x60\x16\x14\x60\x3F\x24\x02\x70\x67\x74\x01\x90"}, + {0x40, 0xA0, 0x024F, 0x0000, 0x0010, 0x0010, + "\x7F\xD4\xF0\x74\xC0\x90\x7F\xD5\xF0\x02\x04\x05\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x025F, 0x0000, 0x0010, 0x0010, + "\xFF\x12\x08\x63\x8B\x6A\x8A\x6B\x89\x6C\xEA\x49\x60\x11\xAE\x02"}, + {0x40, 0xA0, 0x026F, 0x0000, 0x0010, 0x0010, + "\xEE\x90\x7F\xD4\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x05\x90"}, + {0x40, 0xA0, 0x027F, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\x74\x01\xF0\x02\x04\x05\x90\x7F\xEA\xE0\xFF\x12\x09\xA0"}, + {0x40, 0xA0, 0x028F, 0x0000, 0x0010, 0x0010, + "\x8B\x6A\x8A\x6B\x89\x6C\xEA\x49\x60\x11\xAE\x02\xEE\x90\x7F\xD4"}, + {0x40, 0xA0, 0x029F, 0x0000, 0x0010, 0x0010, + "\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01"}, + {0x40, 0xA0, 0x02AF, 0x0000, 0x0010, 0x0010, + "\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05\x12\x0B\x76"}, + {0x40, 0xA0, 0x02BF, 0x0000, 0x0010, 0x0010, + "\x02\x04\x05\x12\x0B\xA2\x02\x04\x05\x12\x0B\x9A\x02\x04\x05\x12"}, + {0x40, 0xA0, 0x02CF, 0x0000, 0x0010, 0x0010, + "\x0B\x68\x02\x04\x05\x12\x0B\xB6\x40\x03\x02\x04\x05\x90\x7F\xE8"}, + {0x40, 0xA0, 0x02DF, 0x0000, 0x0010, 0x0010, + "\xE0\x24\x7F\x60\x24\x14\x60\x31\x24\x02\x70\x5B\xA2\x03\xE4\x33"}, + {0x40, 0xA0, 0x02EF, 0x0000, 0x0010, 0x0010, + "\xFF\x25\xE0\xFF\xA2\x00\xE4\x33\x4F\x90\x7F\x00\xF0\xE4\xA3\xF0"}, + {0x40, 0xA0, 0x02FF, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x05\xE4\x90\x7F\x00\xF0\xA3\xF0"}, + {0x40, 0xA0, 0x030F, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x05\x90\x7F\xEC\xE0\xF4\x54\x80"}, + {0x40, 0xA0, 0x031F, 0x0000, 0x0010, 0x0010, + "\xFF\xC4\x54\x0F\xFF\xE0\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4"}, + {0x40, 0xA0, 0x032F, 0x0000, 0x0010, 0x0010, + "\x34\x7F\xF5\x83\xE0\x54\xFD\x90\x7F\x00\xF0\xE4\xA3\xF0\x90\x7F"}, + {0x40, 0xA0, 0x033F, 0x0000, 0x0010, 0x0010, + "\xB5\x74\x02\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05"}, + {0x40, 0xA0, 0x034F, 0x0000, 0x0010, 0x0010, + "\x12\x0B\xB8\x40\x03\x02\x04\x05\x90\x7F\xE8\xE0\x24\xFE\x60\x1C"}, + {0x40, 0xA0, 0x035F, 0x0000, 0x0010, 0x0010, + "\x24\x02\x60\x03\x02\x04\x05\x90\x7F\xEA\xE0\xB4\x01\x05\xC2\x03"}, + {0x40, 0xA0, 0x036F, 0x0000, 0x0010, 0x0010, + "\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x037F, 0x0000, 0x0010, 0x0010, + "\x70\x1F\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0\x54"}, + {0x40, 0xA0, 0x038F, 0x0000, 0x0010, 0x0010, + "\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\xE4\xF0\x80"}, + {0x40, 0xA0, 0x039F, 0x0000, 0x0010, 0x0010, + "\x65\x90\x7F\xC4\x74\x01\xF0\x80\x5D\x12\x0B\xBA\x50\x58\x90\x7F"}, + {0x40, 0xA0, 0x03AF, 0x0000, 0x0010, 0x0010, + "\xE8\xE0\x24\xFE\x60\x17\x24\x02\x70\x4C\x90\x7F\xEA\xE0\xB4\x01"}, + {0x40, 0xA0, 0x03BF, 0x0000, 0x0010, 0x0010, + "\x04\xD2\x03\x80\x41\x90\x7F\xC4\x74\x01\xF0\x80\x39\x90\x7F\xEA"}, + {0x40, 0xA0, 0x03CF, 0x0000, 0x0010, 0x0010, + "\xE0\x70\x20\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0"}, + {0x40, 0xA0, 0x03DF, 0x0000, 0x0010, 0x0010, + "\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\x74\x01"}, + {0x40, 0xA0, 0x03EF, 0x0000, 0x0010, 0x0010, + "\xF0\x80\x13\x90\x7F\xC4\x74\x01\xF0\x80\x0B\x12\x0B\xBC\x50\x06"}, + {0x40, 0xA0, 0x03FF, 0x0000, 0x000D, 0x000D, + "\x90\x7F\xC4\x74\x01\xF0\x90\x7F\xB4\xE0\x44\x02\xF0"}, + {0x40, 0xA0, 0x040C, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x09E1, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xDE\x74\x06\xF0\x90\x7F\xDF\x74\x04\xF0\x90\x7F\xDD\x74"}, + {0x40, 0xA0, 0x09F1, 0x0000, 0x0010, 0x0010, + "\x18\xF0\x90\x7F\xB6\x74\x02\xF0\x90\x7F\xB8\xF0\x90\x7F\xBA\xF0"}, + {0x40, 0xA0, 0x0A01, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xBC\xF0\x90\x7F\xBE\xF0\x90\x7F\xC0\xF0\x90\x7F\xC2\xF0"}, + {0x40, 0xA0, 0x0A11, 0x0000, 0x0006, 0x0006, "\xE4\x90\x7F\xC9\xF0\x22"}, + {0x40, 0xA0, 0x0B91, 0x0000, 0x0009, 0x0009, + "\x90\x7F\xAF\xE0\x44\x08\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BB2, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BB4, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0B9A, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x76\xD3\x22"}, + {0x40, 0xA0, 0x0B68, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x76\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BA2, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x75\xD3\x22"}, + {0x40, 0xA0, 0x0B76, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x75\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BB6, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BB8, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BBA, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BBC, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0A6D, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0A7D, 0x0000, 0x0010, 0x0010, + "\x01\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0A8D, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0A43, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x0A53, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x0A63, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0803, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x0813, 0x0000, 0x0001, 0x0001, "\xD0"}, + {0x40, 0xA0, 0x0814, 0x0000, 0x0010, 0x0010, + "\x53\x91\xEF\x90\x7F\xAB\x74\x02\xF0\x30\x05\x14\x15\x72\xE5\x72"}, + {0x40, 0xA0, 0x0824, 0x0000, 0x0010, 0x0010, + "\x70\x2E\x43\x21\x10\xC2\x05\xC3\x74\x1E\x95\x74\xF5\x72\x80\x20"}, + {0x40, 0xA0, 0x0834, 0x0000, 0x0010, 0x0010, + "\xD5\x72\x1D\x53\x21\xEF\xD2\x05\xE5\x73\x25\x74\xF5\x74\x64\x02"}, + {0x40, 0xA0, 0x0844, 0x0000, 0x0010, 0x0010, + "\x60\x05\xE5\x74\xB4\x1C\x06\xE5\x73\xF4\x04\xF5\x73\x85\x74\x72"}, + {0x40, 0xA0, 0x0854, 0x0000, 0x000F, 0x000F, + "\xD0\xD0\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0ABB, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x0ACB, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x0ADB, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0BBE, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0A94, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0AA4, 0x0000, 0x0010, 0x0010, + "\x04\x53\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0AB4, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0BBF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC0, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC1, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC2, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC3, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC4, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC5, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC6, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC7, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC8, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC9, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCA, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCB, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCC, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCD, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCE, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0B26, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x30\xE7\x12\xE0\x44\x01\xF0\x7F\x14\x7E\x00\x12"}, + {0x40, 0xA0, 0x0B36, 0x0000, 0x000A, 0x000A, + "\x0B\x40\x90\x7F\xD6\xE0\x54\xFE\xF0\x22"}, + {0x40, 0xA0, 0x0B05, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x44\x80\xF0\x43\x87\x01\x00\x00\x00\x00\x00\x22"}, + {0x40, 0xA0, 0x0AE0, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x54\xFB\xF0\xE0\x44\x08\xF0\x30\x06\x04\xE0\x44"}, + {0x40, 0xA0, 0x0AF0, 0x0000, 0x0010, 0x0010, + "\x02\xF0\x7F\xF4\x7E\x01\x12\x0B\x40\x90\x7F\xD6\xE0\x54\xF7\xF0"}, + {0x40, 0xA0, 0x0B00, 0x0000, 0x0005, 0x0005, "\xE0\x44\x04\xF0\x22"}, + {0x40, 0xA0, 0x09A0, 0x0000, 0x0002, 0x0002, "\x8F\x6D"}, + {0x40, 0xA0, 0x09A2, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x6E\x75\x6F\xFF\x75\x70\x01\x75\x71\xF9\xAB\x6F\xAA\x70"}, + {0x40, 0xA0, 0x09B2, 0x0000, 0x0010, 0x0010, + "\xA9\x71\x90\x00\x01\x12\x06\xAC\xB4\x03\x1D\xAF\x6E\x05\x6E\xEF"}, + {0x40, 0xA0, 0x09C2, 0x0000, 0x0010, 0x0010, + "\xB5\x6D\x01\x22\x12\x06\x93\x7E\x00\x29\xFF\xEE\x3A\xA9\x07\x75"}, + {0x40, 0xA0, 0x09D2, 0x0000, 0x000E, 0x000E, + "\x6F\xFF\xF5\x70\x89\x71\x80\xD4\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x09E0, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0863, 0x0000, 0x0010, 0x0010, + "\xE4\xFE\x75\x6F\xFF\x75\x70\x01\x75\x71\xD2\xAB\x6F\xAA\x70\xA9"}, + {0x40, 0xA0, 0x0873, 0x0000, 0x0010, 0x0010, + "\x71\x90\x00\x01\x12\x06\xAC\x64\x02\x70\x2D\xAD\x06\x0E\xED\xB5"}, + {0x40, 0xA0, 0x0883, 0x0000, 0x0010, 0x0010, + "\x07\x01\x22\x90\x00\x02\x12\x06\xD9\x85\xF0\x6D\xF5\x6E\x62\x6D"}, + {0x40, 0xA0, 0x0893, 0x0000, 0x0010, 0x0010, + "\xE5\x6D\x62\x6E\xE5\x6E\x62\x6D\x29\xFD\xE5\x6D\x3A\xA9\x05\x75"}, + {0x40, 0xA0, 0x08A3, 0x0000, 0x000E, 0x000E, + "\x6F\xFF\xF5\x70\x89\x71\x80\xC3\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x08B1, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0B40, 0x0000, 0x0010, 0x0010, + "\x8E\x6A\x8F\x6B\xE5\x6B\x15\x6B\xAE\x6A\x70\x02\x15\x6A\x4E\x60"}, + {0x40, 0xA0, 0x0B50, 0x0000, 0x0007, 0x0007, + "\x05\x12\x0B\x15\x80\xEE\x22"}, + {0x40, 0xA0, 0x0B15, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x0B25, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x05\x7C"}, + {0x40, 0xA0, 0x057C, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\x76\x02\x05\xC3"}, + {0x40, 0xA0, 0x0693, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x06\x89\x82\x8A\x83\xE0\x22\x50\x02\xE7\x22\xBB\xFE\x02"}, + {0x40, 0xA0, 0x06A3, 0x0000, 0x0009, 0x0009, + "\xE3\x22\x89\x82\x8A\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x06AC, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x06BC, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x06CC, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x06D9, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x10\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\xF5\xF0"}, + {0x40, 0xA0, 0x06E9, 0x0000, 0x0010, 0x0010, + "\xA3\xE0\x22\x50\x09\xE9\x25\x82\xF8\x86\xF0\x08\xE6\x22\xBB\xFE"}, + {0x40, 0xA0, 0x06F9, 0x0000, 0x0010, 0x0010, + "\x0A\xE9\x25\x82\xF8\xE2\xF5\xF0\x08\xE2\x22\xE5\x83\x2A\xF5\x83"}, + {0x40, 0xA0, 0x0709, 0x0000, 0x0008, 0x0008, + "\xE9\x93\xF5\xF0\xA3\xE9\x93\x22"}, + {0x40, 0xA0, 0x0711, 0x0000, 0x0006, 0x0006, "\x8A\x83\x89\x82\xE4\x73"}, + {0x40, 0xA0, 0x0588, 0x0000, 0x0010, 0x0010, + "\x02\x04\x0D\xE4\x93\xA3\xF8\xE4\x93\xA3\x40\x03\xF6\x80\x01\xF2"}, + {0x40, 0xA0, 0x0598, 0x0000, 0x0010, 0x0010, + "\x08\xDF\xF4\x80\x29\xE4\x93\xA3\xF8\x54\x07\x24\x0C\xC8\xC3\x33"}, + {0x40, 0xA0, 0x05A8, 0x0000, 0x0010, 0x0010, + "\xC4\x54\x0F\x44\x20\xC8\x83\x40\x04\xF4\x56\x80\x01\x46\xF6\xDF"}, + {0x40, 0xA0, 0x05B8, 0x0000, 0x0010, 0x0010, + "\xE4\x80\x0B\x01\x02\x04\x08\x10\x20\x40\x80\x90\x08\xB2\xE4\x7E"}, + {0x40, 0xA0, 0x05C8, 0x0000, 0x0010, 0x0010, + "\x01\x93\x60\xBC\xA3\xFF\x54\x3F\x30\xE5\x09\x54\x1F\xFE\xE4\x93"}, + {0x40, 0xA0, 0x05D8, 0x0000, 0x0010, 0x0010, + "\xA3\x60\x01\x0E\xCF\x54\xC0\x25\xE0\x60\xA8\x40\xB8\xE4\x93\xA3"}, + {0x40, 0xA0, 0x05E8, 0x0000, 0x0010, 0x0010, + "\xFA\xE4\x93\xA3\xF8\xE4\x93\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA"}, + {0x40, 0xA0, 0x05F8, 0x0000, 0x0010, 0x0010, + "\xF0\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA\xDF\xE9\xDE\xE7\x80\xBE"}, + {0x40, 0xA0, 0x08FC, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x09, 0x0001, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, NULL} +}; diff --git a/kernel/drv/oss_usb/midisport2x2_fw.h b/kernel/drv/oss_usb/midisport2x2_fw.h new file mode 100755 index 0000000..8bfb036 --- /dev/null +++ b/kernel/drv/oss_usb/midisport2x2_fw.h @@ -0,0 +1,756 @@ +/* + * Purpose: Firmware download for Midiman MIDISport 2x2 + */ +/* + * + * 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. + * + */ +struct setup_request +{ + unsigned char bmRequestType; + unsigned char bRequest; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; + unsigned short cbData; + const /*unsigned */ char *pData; +}; + +const struct setup_request midisport2x2_setupRequest[] = { + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x146C, 0x0000, 0x0010, 0x0010, + "\xC2\x00\x90\x7F\xA5\xE0\x54\x18\xFF\x13\x13\x13\x54\x1F\x44\x50"}, + {0x40, 0xA0, 0x147C, 0x0000, 0x0010, 0x0010, + "\xF5\x1C\x13\x92\x01\xD2\xE8\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9"}, + {0x40, 0xA0, 0x148C, 0x0000, 0x0010, 0x0010, + "\xF0\x90\x7F\xAA\xF0\x53\x91\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90"}, + {0x40, 0xA0, 0x149C, 0x0000, 0x0010, 0x0010, + "\x7F\xAF\xE0\x44\x01\xF0\x90\x7F\xAE\xE0\x44\x05\xF0\xD2\xAF\x12"}, + {0x40, 0xA0, 0x14AC, 0x0000, 0x000D, 0x000D, + "\x17\x5F\x30\x00\xFD\x12\x11\x00\xC2\x00\x80\xF6\x22"}, + {0x40, 0xA0, 0x1100, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x24\x5D\x60\x0D\x14\x70\x03\x02\x12\x44\x24\x02"}, + {0x40, 0xA0, 0x1110, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x12\x4A\x90\x7F\xEA\xE0\x75\x08\x00\xF5\x09\xA3\xE0"}, + {0x40, 0xA0, 0x1120, 0x0000, 0x0010, 0x0010, + "\xFE\xE4\x25\x09\xF5\x09\xEE\x35\x08\xF5\x08\x90\x7F\xEE\xE0\x75"}, + {0x40, 0xA0, 0x1130, 0x0000, 0x0010, 0x0010, + "\x0A\x00\xF5\x0B\xA3\xE0\xFE\xE4\x25\x0B\xF5\x0B\xEE\x35\x0A\xF5"}, + {0x40, 0xA0, 0x1140, 0x0000, 0x0010, 0x0010, + "\x0A\x90\x7F\xE8\xE0\x64\xC0\x60\x03\x02\x11\xD4\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x1150, 0x0000, 0x0010, 0x0010, + "\x70\x03\x02\x12\x4A\xC3\xE5\x0B\x94\x40\xE5\x0A\x94\x00\x50\x08"}, + {0x40, 0xA0, 0x1160, 0x0000, 0x0010, 0x0010, + "\x85\x0A\x0C\x85\x0B\x0D\x80\x06\x75\x0C\x00\x75\x0D\x40\x90\x7F"}, + {0x40, 0xA0, 0x1170, 0x0000, 0x0010, 0x0010, + "\xE9\xE0\xB4\xA3\x25\xAE\x0C\xAF\x0D\xAA\x08\xA9\x09\x7B\x01\xC0"}, + {0x40, 0xA0, 0x1180, 0x0000, 0x0010, 0x0010, + "\x03\xC0\x02\xC0\x01\x7A\x7F\x79\x00\x78\x00\x7C\x7F\xAD\x03\xD0"}, + {0x40, 0xA0, 0x1190, 0x0000, 0x0010, 0x0010, + "\x01\xD0\x02\xD0\x03\x12\x13\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D"}, + {0x40, 0xA0, 0x11A0, 0x0000, 0x0010, 0x0010, + "\x7A\x7F\x79\x00\x7B\x00\x12\x15\xA4\x90\x7F\xB5\xE5\x0D\xF0\xE5"}, + {0x40, 0xA0, 0x11B0, 0x0000, 0x0010, 0x0010, + "\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5\x0B\x95\x0D"}, + {0x40, 0xA0, 0x11C0, 0x0000, 0x0010, 0x0010, + "\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x20\xE2\x03\x02"}, + {0x40, 0xA0, 0x11D0, 0x0000, 0x0010, 0x0010, + "\x11\x4C\x80\xF4\x90\x7F\xE8\xE0\x64\x40\x70\x6E\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x11E0, 0x0000, 0x0010, 0x0010, + "\x60\x68\xE4\x90\x7F\xC5\xF0\x90\x7F\xB4\xE0\x20\xE3\xF9\x90\x7F"}, + {0x40, 0xA0, 0x11F0, 0x0000, 0x0010, 0x0010, + "\xC5\xE0\x75\x0C\x00\xF5\x0D\x90\x7F\xE9\xE0\xB4\xA3\x15\xAE\x0C"}, + {0x40, 0xA0, 0x1200, 0x0000, 0x0010, 0x0010, + "\xAF\x0D\xA8\x09\xAC\x08\x7D\x01\x7B\x01\x7A\x7E\x79\xC0\x12\x13"}, + {0x40, 0xA0, 0x1210, 0x0000, 0x0010, 0x0010, + "\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D\x7A\x7F\x79\x00\x7B\x00\x12"}, + {0x40, 0xA0, 0x1220, 0x0000, 0x0010, 0x0010, + "\x14\xB9\xE5\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5"}, + {0x40, 0xA0, 0x1230, 0x0000, 0x0010, 0x0010, + "\x0B\x95\x0D\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x44"}, + {0x40, 0xA0, 0x1240, 0x0000, 0x000A, 0x000A, + "\x02\xF0\x80\x98\x90\x7F\xEA\xE0\xF5\x1C"}, + {0x40, 0xA0, 0x124A, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x1558, 0x0000, 0x0006, 0x0006, "\xAB\x07\xAA\x06\xAC\x05"}, + {0x40, 0xA0, 0x155E, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x11\xEA\xFF\xAE\x05\x0D\xEE\x24\x00\xF5\x82\xE4"}, + {0x40, 0xA0, 0x156E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEF\xF0\xEB\xAE\x05\x0D\x74\x00\x2E\xF5\x82\xE4"}, + {0x40, 0xA0, 0x157E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEB\xF0\xAF\x05\x0D\x74\x00\x2F\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x158E, 0x0000, 0x0010, 0x0010, + "\xE0\xF5\x83\xEC\xF0\xAF\x1C\x7A\xE0\x7B\x00\x12\x17\x20\x7F\x0A"}, + {0x40, 0xA0, 0x159E, 0x0000, 0x0005, 0x0005, "\x7E\x00\x12\x17\x3C"}, + {0x40, 0xA0, 0x15A3, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x14B9, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x14C3, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x13\xE5\x13\xC3\x95\x10\x50\x20\x05\x0F\xE5\x0F\xAE\x0E"}, + {0x40, 0xA0, 0x14D3, 0x0000, 0x0010, 0x0010, + "\x70\x02\x05\x0E\x14\xFF\xE5\x12\x25\x13\xF5\x82\xE4\x35\x11\xF5"}, + {0x40, 0xA0, 0x14E3, 0x0000, 0x000A, 0x000A, + "\x83\xE0\xFD\x12\x15\x58\x05\x13\x80\xD9"}, + {0x40, 0xA0, 0x14ED, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x15A4, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x15AE, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x12\xE5\x0E\xFF\xAE\x05\x0D\xEE\x24\x03\xF5\x82"}, + {0x40, 0xA0, 0x15BE, 0x0000, 0x0010, 0x0010, + "\xE4\x34\xE0\xF5\x83\xEF\xF0\xE5\x0F\xAE\x05\x0D\x74\x03\x2E\xF5"}, + {0x40, 0xA0, 0x15CE, 0x0000, 0x0010, 0x0010, + "\x82\xE4\x34\xE0\xF5\x83\xE5\x0F\xF0\xAF\x1C\x7A\xE0\x7B\x03\x12"}, + {0x40, 0xA0, 0x15DE, 0x0000, 0x000D, 0x000D, + "\x17\x20\xAF\x1C\xAD\x10\xAB\x12\xAA\x11\x12\x17\x04"}, + {0x40, 0xA0, 0x15EB, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x166E, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x167E, 0x0000, 0x0010, 0x0010, + "\x00\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x168E, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1644, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x1654, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x1664, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1695, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16A5, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x02\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16B5, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x16BA, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16CA, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16DA, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x14FF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x16DF, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16EF, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16FF, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1767, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1768, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1769, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176A, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176B, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176C, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176D, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176E, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176F, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1770, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1771, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1772, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1773, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1774, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1775, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1776, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x15\x00"}, + {0x40, 0xA0, 0x1500, 0x0000, 0x0010, 0x0010, + "\x02\x16\x6E\x00\x02\x16\x95\x00\x02\x16\x44\x00\x02\x16\xDF\x00"}, + {0x40, 0xA0, 0x1510, 0x0000, 0x0010, 0x0010, + "\x02\x16\xBA\x00\x02\x14\xFF\x00\x02\x17\x67\x00\x02\x17\x68\x00"}, + {0x40, 0xA0, 0x1520, 0x0000, 0x0010, 0x0010, + "\x02\x17\x69\x00\x02\x17\x6A\x00\x02\x17\x6B\x00\x02\x17\x6C\x00"}, + {0x40, 0xA0, 0x1530, 0x0000, 0x0010, 0x0010, + "\x02\x17\x6D\x00\x02\x17\x6E\x00\x02\x17\x6F\x00\x02\x17\x70\x00"}, + {0x40, 0xA0, 0x1540, 0x0000, 0x0010, 0x0010, + "\x02\x17\x71\x00\x02\x17\x72\x00\x02\x17\x73\x00\x02\x17\x74\x00"}, + {0x40, 0xA0, 0x1550, 0x0000, 0x0008, 0x0008, + "\x02\x17\x75\x00\x02\x17\x76\x00"}, + {0x40, 0xA0, 0x173C, 0x0000, 0x0010, 0x0010, + "\x8E\x14\x8F\x15\xE5\x15\x15\x15\xAE\x14\x70\x02\x15\x14\x4E\x60"}, + {0x40, 0xA0, 0x174C, 0x0000, 0x0007, 0x0007, + "\x05\x12\x14\xEE\x80\xEE\x22"}, + {0x40, 0xA0, 0x175F, 0x0000, 0x0008, 0x0008, + "\xE4\xF5\x1B\xD2\xE9\xD2\xAF\x22"}, + {0x40, 0xA0, 0x1619, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x23\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x1629, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A\x18\x89"}, + {0x40, 0xA0, 0x1639, 0x0000, 0x000B, 0x000B, + "\x19\xE4\xF5\x1A\x75\x1B\x01\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x15EC, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x25\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x15FC, 0x0000, 0x0010, 0x0010, + "\x44\x01\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A"}, + {0x40, 0xA0, 0x160C, 0x0000, 0x000D, 0x000D, + "\x18\x89\x19\xE4\xF5\x1A\x75\x1B\x03\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x004B, 0x0000, 0x0003, 0x0003, "\x02\x13\x7F"}, + {0x40, 0xA0, 0x137F, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x138F, 0x0000, 0x0010, 0x0010, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x01\xC0\x02\xC0\x03\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x139F, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA5\xE0\x30\xE2\x06\x75\x1B\x06\x02\x14\x4E\x90\x7F\xA5"}, + {0x40, 0xA0, 0x13AF, 0x0000, 0x0010, 0x0010, + "\xE0\x20\xE1\x0C\xE5\x1B\x64\x02\x60\x06\x75\x1B\x07\x02\x14\x4E"}, + {0x40, 0xA0, 0x13BF, 0x0000, 0x0010, 0x0010, + "\xAF\x1B\xEF\x24\xFE\x60\x48\x14\x60\x2C\x24\xFE\x60\x77\x24\x04"}, + {0x40, 0xA0, 0x13CF, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x14\x4E\xAB\x17\xAA\x18\xA9\x19\xAF\x1A\x05\x1A\x8F"}, + {0x40, 0xA0, 0x13DF, 0x0000, 0x0010, 0x0010, + "\x82\x75\x83\x00\x12\x12\x4B\x90\x7F\xA6\xF0\xE5\x1A\x65\x16\x70"}, + {0x40, 0xA0, 0x13EF, 0x0000, 0x0010, 0x0010, + "\x5E\x75\x1B\x05\x80\x59\x90\x7F\xA6\xE0\xAB\x17\xAA\x18\xA9\x19"}, + {0x40, 0xA0, 0x13FF, 0x0000, 0x0010, 0x0010, + "\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12\x78\x75\x1B\x02\x80\x40\xE5"}, + {0x40, 0xA0, 0x140F, 0x0000, 0x0010, 0x0010, + "\x16\x24\xFE\xB5\x1A\x07\x90\x7F\xA5\xE0\x44\x20\xF0\xE5\x16\x14"}, + {0x40, 0xA0, 0x141F, 0x0000, 0x0010, 0x0010, + "\xB5\x1A\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x90\x7F\xA6"}, + {0x40, 0xA0, 0x142F, 0x0000, 0x0010, 0x0010, + "\xE0\xAB\x17\xAA\x18\xA9\x19\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12"}, + {0x40, 0xA0, 0x143F, 0x0000, 0x0010, 0x0010, + "\x78\x05\x1A\x80\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x53"}, + {0x40, 0xA0, 0x144F, 0x0000, 0x0010, 0x0010, + "\x91\xDF\xD0\x07\xD0\x06\xD0\x03\xD0\x02\xD0\x01\xD0\x00\xD0\xD0"}, + {0x40, 0xA0, 0x145F, 0x0000, 0x000D, 0x000D, + "\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1704, 0x0000, 0x0010, 0x0010, + "\x12\x15\xEC\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1714, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x1720, 0x0000, 0x0010, 0x0010, + "\x12\x16\x19\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1730, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x14EE, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x14FE, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x17\x53"}, + {0x40, 0xA0, 0x1753, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\x20\x02\x14\x6C"}, + {0x40, 0xA0, 0x124B, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x125B, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x126B, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x1278, 0x0000, 0x0010, 0x0010, + "\xF8\xBB\x01\x0D\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE8\xF0"}, + {0x40, 0xA0, 0x1288, 0x0000, 0x0010, 0x0010, + "\x22\x50\x06\xE9\x25\x82\xC8\xF6\x22\xBB\xFE\x05\xE9\x25\x82\xC8"}, + {0x40, 0xA0, 0x1298, 0x0000, 0x0002, 0x0002, "\xF2\x22"}, + {0x40, 0xA0, 0x129A, 0x0000, 0x0010, 0x0010, + "\xE7\x09\xF6\x08\xDF\xFA\x80\x46\xE7\x09\xF2\x08\xDF\xFA\x80\x3E"}, + {0x40, 0xA0, 0x12AA, 0x0000, 0x0010, 0x0010, + "\x88\x82\x8C\x83\xE7\x09\xF0\xA3\xDF\xFA\x80\x32\xE3\x09\xF6\x08"}, + {0x40, 0xA0, 0x12BA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x6E\xE3\x09\xF2\x08\xDF\xFA\x80\x66\x88\x82\x8C\x83"}, + {0x40, 0xA0, 0x12CA, 0x0000, 0x0010, 0x0010, + "\xE3\x09\xF0\xA3\xDF\xFA\x80\x5A\x89\x82\x8A\x83\xE0\xA3\xF6\x08"}, + {0x40, 0xA0, 0x12DA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x4E\x89\x82\x8A\x83\xE0\xA3\xF2\x08\xDF\xFA\x80\x42"}, + {0x40, 0xA0, 0x12EA, 0x0000, 0x0010, 0x0010, + "\x80\xD2\x80\xFA\x80\xC6\x80\xD4\x80\x55\x80\xF2\x80\x29\x80\x10"}, + {0x40, 0xA0, 0x12FA, 0x0000, 0x0010, 0x0010, + "\x80\xA6\x80\xEA\x80\x9A\x80\xA8\x80\xDA\x80\xE2\x80\xCA\x80\x29"}, + {0x40, 0xA0, 0x130A, 0x0000, 0x0010, 0x0010, + "\x88\x84\x8C\x85\x89\x82\x8A\x83\xE4\x93\xA3\x05\x86\xF0\xA3\x05"}, + {0x40, 0xA0, 0x131A, 0x0000, 0x0010, 0x0010, + "\x86\xDF\xF5\xDE\xF3\x80\x0B\x89\x82\x8A\x83\xE4\x93\xA3\xF6\x08"}, + {0x40, 0xA0, 0x132A, 0x0000, 0x0010, 0x0010, + "\xDF\xF9\xEC\xFA\xA9\xF0\xED\xFB\x22\x88\x84\x8C\x85\x89\x82\x8A"}, + {0x40, 0xA0, 0x133A, 0x0000, 0x0010, 0x0010, + "\x83\xE0\xA3\x05\x86\xF0\xA3\x05\x86\xDF\xF6\xDE\xF4\x80\xE3\x89"}, + {0x40, 0xA0, 0x134A, 0x0000, 0x0010, 0x0010, + "\x82\x8A\x83\xE4\x93\xA3\xF2\x08\xDF\xF9\x80\xD6\x88\xF0\xED\x24"}, + {0x40, 0xA0, 0x135A, 0x0000, 0x0010, 0x0010, + "\x02\xB4\x04\x00\x50\xCC\xF5\x82\xEB\x24\x02\xB4\x04\x00\x50\xC2"}, + {0x40, 0xA0, 0x136A, 0x0000, 0x0010, 0x0010, + "\x23\x23\x45\x82\xF5\x82\xEF\x4E\x60\xB8\xEF\x60\x01\x0E\xE5\x82"}, + {0x40, 0xA0, 0x137A, 0x0000, 0x0005, 0x0005, "\x23\x90\x12\xEA\x73"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x0100, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0110, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0120, 0x0000, 0x0010, 0x0010, + "\x4D\x69\x64\x69\x6D\x61\x6E\x20\x55\x53\x42\x20\x4D\x69\x64\x69"}, + {0x40, 0xA0, 0x0130, 0x0000, 0x0010, 0x0010, + "\x53\x70\x6F\x72\x74\x20\x32\x78\x32\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0140, 0x0000, 0x0010, 0x0010, + "\x46\x69\x72\x6D\x77\x61\x72\x65\x20\x52\x65\x6C\x65\x61\x73\x65"}, + {0x40, 0xA0, 0x0150, 0x0000, 0x0010, 0x0010, + "\x20\x31\x2E\x32\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0160, 0x0000, 0x0010, 0x0010, + "\x28\x63\x29\x20\x31\x39\x39\x39\x2D\x32\x30\x30\x31\x2C\x20\x4D"}, + {0x40, 0xA0, 0x0170, 0x0000, 0x0010, 0x0010, + "\x69\x64\x69\x6D\x61\x6E\x20\x49\x6E\x63\x2E\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0180, 0x0000, 0x0010, 0x0010, + "\x41\x6C\x6C\x20\x72\x69\x67\x68\x74\x73\x20\x72\x65\x73\x65\x72"}, + {0x40, 0xA0, 0x0190, 0x0000, 0x0010, 0x0010, + "\x76\x65\x64\x2E\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01A0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01B0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0962, 0x0000, 0x0003, 0x0003, "\x01\x40\x00"}, + {0x40, 0xA0, 0x041B, 0x0000, 0x0010, 0x0010, + "\xC2\x01\xC2\x00\xC2\x05\xC2\x04\x12\x0A\xBA\xD2\xE8\x43\xD8\x20"}, + {0x40, 0xA0, 0x042B, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9\xF0\x90\x7F\xAA\xF0\x53\x91"}, + {0x40, 0xA0, 0x043B, 0x0000, 0x0010, 0x0010, + "\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90\x7F\xAF\xE0\x44\x01\xF0\x90"}, + {0x40, 0xA0, 0x044B, 0x0000, 0x0010, 0x0010, + "\x7F\xAE\xE0\x44\x1D\xF0\x90\x7F\x92\xE0\x44\x02\xF0\x90\x7F\x94"}, + {0x40, 0xA0, 0x045B, 0x0000, 0x0010, 0x0010, + "\xE0\x44\x04\xF0\x90\x7F\x9D\xE0\x54\xFB\xF0\x90\x7F\x95\xE0\x44"}, + {0x40, 0xA0, 0x046B, 0x0000, 0x0010, 0x0010, + "\x01\xF0\x90\x7F\x9E\xE0\x54\xFE\xF0\x90\x7F\x94\xE0\x44\x08\xF0"}, + {0x40, 0xA0, 0x047B, 0x0000, 0x0010, 0x0010, + "\x90\x7F\x9D\xE0\x44\x08\xF0\x90\x7F\x95\xE0\x44\x02\xF0\x90\x7F"}, + {0x40, 0xA0, 0x048B, 0x0000, 0x0010, 0x0010, + "\x9E\xE0\x44\x02\xF0\x90\x7F\x95\xE0\x54\x83\xF0\x90\x7F\x9E\xE0"}, + {0x40, 0xA0, 0x049B, 0x0000, 0x0010, 0x0010, + "\x44\x7C\xF0\x90\x7F\x94\xE0\x54\xFE\xF0\x90\x7F\x9D\xE0\x44\x01"}, + {0x40, 0xA0, 0x04AB, 0x0000, 0x0010, 0x0010, + "\xF0\x90\x7F\x9A\xE0\x44\x01\x90\x7F\x97\xF0\x43\x08\x20\x43\x08"}, + {0x40, 0xA0, 0x04BB, 0x0000, 0x0010, 0x0010, + "\x08\x43\x08\x10\x43\x08\x04\x43\x08\x40\x53\x89\xF0\xE4\xF5\x8C"}, + {0x40, 0xA0, 0x04CB, 0x0000, 0x0010, 0x0010, + "\xF5\x8A\xD2\x8C\xD2\xA9\x12\x00\x36\xD2\xAF\xE5\x89\x54\x0F\x24"}, + {0x40, 0xA0, 0x04DB, 0x0000, 0x0010, 0x0010, + "\x20\xF5\x89\x75\x8D\xFE\x75\x8B\xFE\xD2\x8E\xC2\xAC\x75\x98\x50"}, + {0x40, 0xA0, 0x04EB, 0x0000, 0x0010, 0x0010, + "\xC2\x98\xC2\x99\xD2\xAC\xC2\xAE\x75\xC0\x50\xC2\xC0\xC2\xC1\xD2"}, + {0x40, 0xA0, 0x04FB, 0x0000, 0x0010, 0x0010, + "\xAE\x53\x08\xDF\x53\x08\xEF\x53\x08\xF7\x53\x08\xFB\x53\x08\xBF"}, + {0x40, 0xA0, 0x050B, 0x0000, 0x0010, 0x0010, + "\x90\x7F\x9A\xE0\x54\xFE\x90\x7F\x97\xF0\x90\x7F\x98\xE5\x08\xF0"}, + {0x40, 0xA0, 0x051B, 0x0000, 0x0010, 0x0010, + "\x75\x0D\x3D\xE5\x0D\x70\xFC\x43\x08\x20\x43\x08\x10\x43\x08\x08"}, + {0x40, 0xA0, 0x052B, 0x0000, 0x0010, 0x0010, + "\x43\x08\x04\x43\x08\x40\x90\x7F\x98\xE5\x08\xF0\x20\x01\x11\x75"}, + {0x40, 0xA0, 0x053B, 0x0000, 0x0010, 0x0010, + "\x0D\xF4\xE5\x0D\x70\xFC\x20\x01\xF3\xD2\x07\x12\x0C\x21\x80\xEC"}, + {0x40, 0xA0, 0x054B, 0x0000, 0x0010, 0x0010, + "\x30\x01\x0C\x12\x02\x0D\xC2\x01\x90\x7F\xAE\xE0\x44\x02\xF0\x30"}, + {0x40, 0xA0, 0x055B, 0x0000, 0x0010, 0x0010, + "\x05\x1A\x12\x0A\xF4\x50\x13\x12\x0C\x46\x20\x04\x07\x90\x7F\xD6"}, + {0x40, 0xA0, 0x056B, 0x0000, 0x0010, 0x0010, + "\xE0\x20\xE7\xF3\x12\x0C\x67\x12\x00\x41\xC2\x05\x05\x40\xE5\x40"}, + {0x40, 0xA0, 0x057B, 0x0000, 0x0010, 0x0010, + "\xC3\x94\x08\x40\x03\xE4\xF5\x40\xE5\x40\x75\xF0\x03\xA4\x24\x23"}, + {0x40, 0xA0, 0x058B, 0x0000, 0x000C, 0x000C, + "\xF8\x08\xE6\xFA\x08\xE6\xF9\x12\x07\xEC\x80\xB4"}, + {0x40, 0xA0, 0x0597, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0033, 0x0000, 0x0003, 0x0003, "\x02\x00\x1F"}, + {0x40, 0xA0, 0x001F, 0x0000, 0x0004, 0x0004, "\x53\xD8\xEF\x32"}, + {0x40, 0xA0, 0x0023, 0x0000, 0x0003, 0x0003, "\x02\x08\x6E"}, + {0x40, 0xA0, 0x086E, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x087E, 0x0000, 0x000C, 0x000C, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x05\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x088A, 0x0000, 0x0010, 0x0010, + "\x30\x99\x23\xC2\x99\xE5\x14\x60\x1B\xAF\x11\x05\x11\x74\x00\x2F"}, + {0x40, 0xA0, 0x089A, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x0E\xF5\x83\xE0\xF5\x99\x15\x14\x53\x08\xEF\x75"}, + {0x40, 0xA0, 0x08AA, 0x0000, 0x0010, 0x0010, + "\x0B\x0C\x80\x02\xD2\x02\x30\x98\x1E\xC2\x98\xAF\x99\xE5\x10\x04"}, + {0x40, 0xA0, 0x08BA, 0x0000, 0x0010, 0x0010, + "\x54\x3F\xFE\x65\x0E\x60\x0A\xAD\x10\x74\x42\x2D\xF8\xA6\x07\x8E"}, + {0x40, 0xA0, 0x08CA, 0x0000, 0x0007, 0x0007, + "\x10\x53\x08\xDF\x75\x09\x0C"}, + {0x40, 0xA0, 0x08D1, 0x0000, 0x0010, 0x0010, + "\xD0\x07\xD0\x06\xD0\x05\xD0\x00\xD0\xD0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x08E1, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x003B, 0x0000, 0x0003, 0x0003, "\x02\x08\xE8"}, + {0x40, 0xA0, 0x08E8, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x08F8, 0x0000, 0x000C, 0x000C, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x05\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x0904, 0x0000, 0x0010, 0x0010, + "\x30\xC1\x23\xC2\xC1\xE5\x15\x60\x1B\xAF\x13\x05\x13\x74\x00\x2F"}, + {0x40, 0xA0, 0x0914, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x0F\xF5\x83\xE0\xF5\xC1\x15\x15\x53\x08\xFB\x75"}, + {0x40, 0xA0, 0x0924, 0x0000, 0x0010, 0x0010, + "\x0C\x0C\x80\x02\xD2\x03\x30\xC0\x1E\xC2\xC0\xAF\xC1\xE5\x12\x04"}, + {0x40, 0xA0, 0x0934, 0x0000, 0x0010, 0x0010, + "\x54\x3F\xFE\x65\x0F\x60\x0A\xAD\x12\x74\x82\x2D\xF8\xA6\x07\x8E"}, + {0x40, 0xA0, 0x0944, 0x0000, 0x0007, 0x0007, + "\x12\x53\x08\xF7\x75\x0A\x0C"}, + {0x40, 0xA0, 0x094B, 0x0000, 0x0010, 0x0010, + "\xD0\x07\xD0\x06\xD0\x05\xD0\x00\xD0\xD0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x095B, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x00D2, 0x0000, 0x0010, 0x0010, + "\xA2\xAC\x92\x07\xC2\xAC\x30\x02\x0C\xC2\x02\x8F\x99\x53\x08\xEF"}, + {0x40, 0xA0, 0x00E2, 0x0000, 0x0010, 0x0010, + "\x75\x0B\x0C\x80\x12\xAE\x16\x05\x16\x74\x00\x2E\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x00F2, 0x0000, 0x000B, 0x000B, + "\x0E\xF5\x83\xEF\xF0\x05\x14\xA2\x07\x92\xAC"}, + {0x40, 0xA0, 0x00FD, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0B58, 0x0000, 0x0010, 0x0010, + "\xA2\xAE\x92\x07\xC2\xAE\x30\x03\x0C\xC2\x03\x8F\xC1\x53\x08\xFB"}, + {0x40, 0xA0, 0x0B68, 0x0000, 0x0010, 0x0010, + "\x75\x0C\x0C\x80\x12\xAE\x17\x05\x17\x74\x00\x2E\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x0B78, 0x0000, 0x000B, 0x000B, + "\x0F\xF5\x83\xEF\xF0\x05\x15\xA2\x07\x92\xAE"}, + {0x40, 0xA0, 0x0B83, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x01C0, 0x0000, 0x0010, 0x0010, + "\x12\x01\x00\x01\x00\x00\x00\x40\x63\x07\x02\x10\x21\x01\x00\x00"}, + {0x40, 0xA0, 0x01D0, 0x0000, 0x0010, 0x0010, + "\x00\x01\x09\x02\x35\x00\x01\x01\x00\xA0\x00\x09\x04\x00\x00\x05"}, + {0x40, 0xA0, 0x01E0, 0x0000, 0x0010, 0x0010, + "\xFF\x00\x00\x00\x07\x05\x81\x03\x20\x00\x01\x07\x05\x82\x02\x20"}, + {0x40, 0xA0, 0x01F0, 0x0000, 0x0010, 0x0010, + "\x00\x00\x07\x05\x02\x02\x20\x00\x00\x07\x05\x84\x02\x20\x00\x00"}, + {0x40, 0xA0, 0x0200, 0x0000, 0x000D, 0x000D, + "\x07\x05\x04\x02\x20\x00\x00\x04\x03\x09\x04\x00\x00"}, + {0x40, 0xA0, 0x0965, 0x0000, 0x0010, 0x0010, + "\x01\x0D\x00\xC1\x01\x01\x09\x00\x01\x0A\x00\x01\x08\xFF\x01\x0B"}, + {0x40, 0xA0, 0x0975, 0x0000, 0x0010, 0x0010, + "\x00\x01\x0C\x00\xC1\x82\xC1\x83\x01\x0E\x00\x01\x10\x00\x01\x0F"}, + {0x40, 0xA0, 0x0985, 0x0000, 0x0010, 0x0010, + "\x00\x01\x12\x00\x01\x11\x00\x01\x16\x00\x01\x14\x00\x01\x13\x00"}, + {0x40, 0xA0, 0x0995, 0x0000, 0x0006, 0x0006, "\x01\x17\x00\x01\x15\x00"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x0B\x00"}, + {0x40, 0xA0, 0x0B00, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xAE\x00\x02\x09\xCA\x00\x02\x0B\x84\x00\x02\x0B\xD5\x00"}, + {0x40, 0xA0, 0x0B10, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xFC\x00\x02\x00\x3A\x00\x02\x0A\xFF\x00\x02\x0C\xC2\x00"}, + {0x40, 0xA0, 0x0B20, 0x0000, 0x0010, 0x0010, + "\x02\x0C\xC3\x00\x02\x0C\xC4\x00\x02\x0C\xC5\x00\x02\x0C\xC6\x00"}, + {0x40, 0xA0, 0x0B30, 0x0000, 0x0010, 0x0010, + "\x02\x0C\xC7\x00\x02\x0C\xC8\x00\x02\x0C\xC9\x00\x02\x0C\xCA\x00"}, + {0x40, 0xA0, 0x0B40, 0x0000, 0x0010, 0x0010, + "\x02\x0C\xCB\x00\x02\x0C\xCC\x00\x02\x0C\xCD\x00\x02\x0C\xCE\x00"}, + {0x40, 0xA0, 0x0B50, 0x0000, 0x0008, 0x0008, + "\x02\x0C\xCF\x00\x02\x0C\xD0\x00"}, + {0x40, 0xA0, 0x099B, 0x0000, 0x0010, 0x0010, + "\x18\x23\xFF\x05\x98\xFF\x06\x58\xFF\x06\xE3\xFF\x07\xF2\xFF\x05"}, + {0x40, 0xA0, 0x09AB, 0x0000, 0x0010, 0x0010, + "\x98\xFF\x06\x58\xFF\x06\xE3\xFF\x00\x0E\x01\x21\xFF\x01\x22\x00"}, + {0x40, 0xA0, 0x0598, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB6\xE0\x30\xE1\x03\x02\x06\x57\x7A\x7E\x79\x80\x7E\x7E"}, + {0x40, 0xA0, 0x05A8, 0x0000, 0x0010, 0x0010, + "\x7F\x80\x74\x7E\x90\x7F\xE3\xF0\x74\x80\x90\x7F\xE4\xF0\xE4\xFF"}, + {0x40, 0xA0, 0x05B8, 0x0000, 0x0010, 0x0010, + "\xE5\x10\x65\x0E\x60\x43\xEF\xC3\x94\x04\x50\x3D\xE4\xFD\xE5\x10"}, + {0x40, 0xA0, 0x05C8, 0x0000, 0x0010, 0x0010, + "\x65\x0E\x60\x1B\xED\xC3\x94\x03\x50\x15\x74\x42\x25\x0E\xF8\xE6"}, + {0x40, 0xA0, 0x05D8, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE5\xF0\x05\x0E\xE5\x0E\x54\x3F\xF5\x0E\x0D\x80\xDF\xED"}, + {0x40, 0xA0, 0x05E8, 0x0000, 0x0010, 0x0010, + "\x60\xCE\xFC\xEC\xC3\x94\x03\x50\x08\xE4\x90\x7F\xE5\xF0\x0C\x80"}, + {0x40, 0xA0, 0x05F8, 0x0000, 0x0010, 0x0010, + "\xF2\x90\x7F\xE5\xED\xF0\x0F\x80\xB7\xE5\x12\x65\x0F\x60\x45\xEF"}, + {0x40, 0xA0, 0x0608, 0x0000, 0x0010, 0x0010, + "\xC3\x94\x08\x50\x3F\xE4\xFD\xE5\x12\x65\x0F\x60\x1B\xED\xC3\x94"}, + {0x40, 0xA0, 0x0618, 0x0000, 0x0010, 0x0010, + "\x03\x50\x15\x74\x82\x25\x0F\xF8\xE6\x90\x7F\xE5\xF0\x05\x0F\xE5"}, + {0x40, 0xA0, 0x0628, 0x0000, 0x0010, 0x0010, + "\x0F\x54\x3F\xF5\x0F\x0D\x80\xDF\xED\x60\xCE\xFC\xEC\xC3\x94\x03"}, + {0x40, 0xA0, 0x0638, 0x0000, 0x0010, 0x0010, + "\x50\x08\xE4\x90\x7F\xE5\xF0\x0C\x80\xF2\xED\x24\x10\x90\x7F\xE5"}, + {0x40, 0xA0, 0x0648, 0x0000, 0x000F, 0x000F, + "\xF0\x0F\x80\xB5\xEF\x60\x08\x25\xE0\x25\xE0\x90\x7F\xB7\xF0"}, + {0x40, 0xA0, 0x0657, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x07F2, 0x0000, 0x0010, 0x0010, + "\xE5\x21\x60\x1C\x14\x60\x30\x14\x60\x44\x14\x60\x58\x80\x00\x12"}, + {0x40, 0xA0, 0x0802, 0x0000, 0x0010, 0x0010, + "\x00\x3E\xEF\x65\x22\x60\x64\x12\x00\x3E\x8F\x22\xE4\xF5\x21\x22"}, + {0x40, 0xA0, 0x0812, 0x0000, 0x0010, 0x0010, + "\xE5\x09\x60\x10\xD5\x09\x0D\xA2\xAF\x92\x07\xC2\xAF\x43\x08\x20"}, + {0x40, 0xA0, 0x0822, 0x0000, 0x0010, 0x0010, + "\xA2\x07\x92\xAF\x05\x21\x22\xE5\x0A\x60\x10\xD5\x0A\x0D\xA2\xAF"}, + {0x40, 0xA0, 0x0832, 0x0000, 0x0010, 0x0010, + "\x92\x07\xC2\xAF\x43\x08\x08\xA2\x07\x92\xAF\x05\x21\x22\xE5\x0B"}, + {0x40, 0xA0, 0x0842, 0x0000, 0x0010, 0x0010, + "\x60\x10\xD5\x0B\x0D\xA2\xAF\x92\x07\xC2\xAF\x43\x08\x10\xA2\x07"}, + {0x40, 0xA0, 0x0852, 0x0000, 0x0010, 0x0010, + "\x92\xAF\x05\x21\x22\xE5\x0C\x60\x10\xD5\x0C\x0D\xA2\xAF\x92\x07"}, + {0x40, 0xA0, 0x0862, 0x0000, 0x000B, 0x000B, + "\xC2\xAF\x43\x08\x04\xA2\x07\x92\xAF\x05\x21"}, + {0x40, 0xA0, 0x086D, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x000E, 0x0000, 0x0010, 0x0010, + "\xA2\xAF\x92\x07\xC2\xAF\x90\x7F\x98\xE5\x08\xF0\xA2\x07\x92\xAF"}, + {0x40, 0xA0, 0x001E, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0658, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xC8\xE0\x30\xE1\x03\x02\x06\xE2\x90\x7F\xC9\xE0\xF5\x18"}, + {0x40, 0xA0, 0x0668, 0x0000, 0x0010, 0x0010, + "\xC3\xE4\x95\x14\xFF\x74\x01\x94\x00\xFE\xC3\xE5\x18\x9F\xE4\x9E"}, + {0x40, 0xA0, 0x0678, 0x0000, 0x0010, 0x0010, + "\x50\x68\xE4\xF5\x19\xE5\x19\xC3\x95\x18\x50\x59\x74\xC3\x25\x19"}, + {0x40, 0xA0, 0x0688, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x7D\xF5\x83\xE0\x54\x0F\xFD\x60\x48\x74\xC0\x25"}, + {0x40, 0xA0, 0x0698, 0x0000, 0x0010, 0x0010, + "\x19\xF5\x82\xE4\x34\x7D\x90\x7F\xE3\xF0\x74\xC0\x25\x19\xF5\x82"}, + {0x40, 0xA0, 0x06A8, 0x0000, 0x0010, 0x0010, + "\xE4\x34\x7D\xE5\x82\x90\x7F\xE4\xF0\xAF\x05\xED\x14\x60\x16\x14"}, + {0x40, 0xA0, 0x06B8, 0x0000, 0x0010, 0x0010, + "\x60\x0B\x14\x70\x18\x90\x7F\xE5\xE0\xFF\x12\x00\xD2\x90\x7F\xE5"}, + {0x40, 0xA0, 0x06C8, 0x0000, 0x0010, 0x0010, + "\xE0\xFF\x12\x00\xD2\x90\x7F\xE5\xE0\xFF\x12\x00\xD2\x74\x04\x25"}, + {0x40, 0xA0, 0x06D8, 0x0000, 0x000A, 0x000A, + "\x19\xF5\x19\x80\xA0\xE4\x90\x7F\xC9\xF0"}, + {0x40, 0xA0, 0x06E2, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x06E3, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xCC\xE0\x30\xE1\x03\x02\x07\x6D\x90\x7F\xCD\xE0\xF5\x18"}, + {0x40, 0xA0, 0x06F3, 0x0000, 0x0010, 0x0010, + "\xC3\xE4\x95\x15\xFF\x74\x01\x94\x00\xFE\xC3\xE5\x18\x9F\xE4\x9E"}, + {0x40, 0xA0, 0x0703, 0x0000, 0x0010, 0x0010, + "\x50\x68\xE4\xF5\x19\xE5\x19\xC3\x95\x18\x50\x59\x74\xC3\x25\x19"}, + {0x40, 0xA0, 0x0713, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x7C\xF5\x83\xE0\x54\x0F\xFD\x60\x48\x74\xC0\x25"}, + {0x40, 0xA0, 0x0723, 0x0000, 0x0010, 0x0010, + "\x19\xF5\x82\xE4\x34\x7C\x90\x7F\xE3\xF0\x74\xC0\x25\x19\xF5\x82"}, + {0x40, 0xA0, 0x0733, 0x0000, 0x0010, 0x0010, + "\xE4\x34\x7C\xE5\x82\x90\x7F\xE4\xF0\xAF\x05\xED\x14\x60\x16\x14"}, + {0x40, 0xA0, 0x0743, 0x0000, 0x0010, 0x0010, + "\x60\x0B\x14\x70\x18\x90\x7F\xE5\xE0\xFF\x12\x0B\x58\x90\x7F\xE5"}, + {0x40, 0xA0, 0x0753, 0x0000, 0x0010, 0x0010, + "\xE0\xFF\x12\x0B\x58\x90\x7F\xE5\xE0\xFF\x12\x0B\x58\x74\x04\x25"}, + {0x40, 0xA0, 0x0763, 0x0000, 0x000A, 0x000A, + "\x19\xF5\x19\x80\xA0\xE4\x90\x7F\xCD\xF0"}, + {0x40, 0xA0, 0x076D, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x09BB, 0x0000, 0x0003, 0x0003, "\x01\x41\x00"}, + {0x40, 0xA0, 0x000B, 0x0000, 0x0003, 0x0003, "\x02\x00\x26"}, + {0x40, 0xA0, 0x0026, 0x0000, 0x000D, 0x000D, + "\xC0\xE0\x05\x41\xE5\x0D\x60\x02\x15\x0D\xD0\xE0\x32"}, + {0x40, 0xA0, 0x003E, 0x0000, 0x0003, 0x0003, "\xAF\x41\x22"}, + {0x40, 0xA0, 0x0036, 0x0000, 0x0004, 0x0004, "\xE4\xF5\x41\x22"}, + {0x40, 0xA0, 0x09BE, 0x0000, 0x000B, 0x000B, + "\x01\x3B\x01\x01\x3C\x01\xC1\x86\x01\x3D\x03"}, + {0x40, 0xA0, 0x020D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x70\x03\x02\x02\xE2\x14\x70\x03\x02\x03\x5D\x24"}, + {0x40, 0xA0, 0x021D, 0x0000, 0x0010, 0x0010, + "\xFE\x70\x03\x02\x03\xB6\x24\xFB\x70\x03\x02\x02\xDC\x14\x70\x03"}, + {0x40, 0xA0, 0x022D, 0x0000, 0x0010, 0x0010, + "\x02\x02\xD6\x14\x70\x03\x02\x02\xCA\x14\x70\x03\x02\x02\xD0\x24"}, + {0x40, 0xA0, 0x023D, 0x0000, 0x0010, 0x0010, + "\x05\x60\x03\x02\x04\x08\x12\x00\xFE\x40\x03\x02\x04\x13\x90\x7F"}, + {0x40, 0xA0, 0x024D, 0x0000, 0x0010, 0x0010, + "\xEB\xE0\x24\xFE\x60\x16\x14\x60\x3F\x24\x02\x70\x67\x74\x01\x90"}, + {0x40, 0xA0, 0x025D, 0x0000, 0x0010, 0x0010, + "\x7F\xD4\xF0\x74\xC0\x90\x7F\xD5\xF0\x02\x04\x13\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x026D, 0x0000, 0x0010, 0x0010, + "\xFF\x12\x0A\x2A\x8B\x18\x8A\x19\x89\x1A\xEA\x49\x60\x11\xAE\x02"}, + {0x40, 0xA0, 0x027D, 0x0000, 0x0010, 0x0010, + "\xEE\x90\x7F\xD4\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x13\x90"}, + {0x40, 0xA0, 0x028D, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\x74\x01\xF0\x02\x04\x13\x90\x7F\xEA\xE0\xFF\x12\x0A\x79"}, + {0x40, 0xA0, 0x029D, 0x0000, 0x0010, 0x0010, + "\x8B\x18\x8A\x19\x89\x1A\xEA\x49\x60\x11\xAE\x02\xEE\x90\x7F\xD4"}, + {0x40, 0xA0, 0x02AD, 0x0000, 0x0010, 0x0010, + "\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x13\x90\x7F\xC4\x74\x01"}, + {0x40, 0xA0, 0x02BD, 0x0000, 0x0010, 0x0010, + "\xF0\x02\x04\x13\x90\x7F\xC4\x74\x01\xF0\x02\x04\x13\x12\x0C\xA6"}, + {0x40, 0xA0, 0x02CD, 0x0000, 0x0010, 0x0010, + "\x02\x04\x13\x12\x0C\xB4\x02\x04\x13\x12\x00\x03\x02\x04\x13\x12"}, + {0x40, 0xA0, 0x02DD, 0x0000, 0x0010, 0x0010, + "\x0C\x98\x02\x04\x13\x12\x0A\xFD\x40\x03\x02\x04\x13\x90\x7F\xE8"}, + {0x40, 0xA0, 0x02ED, 0x0000, 0x0010, 0x0010, + "\xE0\x24\x7F\x60\x24\x14\x60\x31\x24\x02\x70\x5B\xA2\x04\xE4\x33"}, + {0x40, 0xA0, 0x02FD, 0x0000, 0x0010, 0x0010, + "\xFF\x25\xE0\xFF\xA2\x00\xE4\x33\x4F\x90\x7F\x00\xF0\xE4\xA3\xF0"}, + {0x40, 0xA0, 0x030D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x13\xE4\x90\x7F\x00\xF0\xA3\xF0"}, + {0x40, 0xA0, 0x031D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x13\x90\x7F\xEC\xE0\xF4\x54\x80"}, + {0x40, 0xA0, 0x032D, 0x0000, 0x0010, 0x0010, + "\xFF\xC4\x54\x0F\xFF\xE0\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4"}, + {0x40, 0xA0, 0x033D, 0x0000, 0x0010, 0x0010, + "\x34\x7F\xF5\x83\xE0\x54\xFD\x90\x7F\x00\xF0\xE4\xA3\xF0\x90\x7F"}, + {0x40, 0xA0, 0x034D, 0x0000, 0x0010, 0x0010, + "\xB5\x74\x02\xF0\x02\x04\x13\x90\x7F\xC4\x74\x01\xF0\x02\x04\x13"}, + {0x40, 0xA0, 0x035D, 0x0000, 0x0010, 0x0010, + "\x12\x0C\xBC\x40\x03\x02\x04\x13\x90\x7F\xE8\xE0\x24\xFE\x60\x1C"}, + {0x40, 0xA0, 0x036D, 0x0000, 0x0010, 0x0010, + "\x24\x02\x60\x03\x02\x04\x13\x90\x7F\xEA\xE0\xB4\x01\x05\xC2\x04"}, + {0x40, 0xA0, 0x037D, 0x0000, 0x0010, 0x0010, + "\x02\x04\x13\x90\x7F\xC4\x74\x01\xF0\x02\x04\x13\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x038D, 0x0000, 0x0010, 0x0010, + "\x70\x1F\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0\x54"}, + {0x40, 0xA0, 0x039D, 0x0000, 0x0010, 0x0010, + "\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\xE4\xF0\x80"}, + {0x40, 0xA0, 0x03AD, 0x0000, 0x0010, 0x0010, + "\x65\x90\x7F\xC4\x74\x01\xF0\x80\x5D\x12\x0C\xBE\x50\x58\x90\x7F"}, + {0x40, 0xA0, 0x03BD, 0x0000, 0x0010, 0x0010, + "\xE8\xE0\x24\xFE\x60\x17\x24\x02\x70\x4C\x90\x7F\xEA\xE0\xB4\x01"}, + {0x40, 0xA0, 0x03CD, 0x0000, 0x0010, 0x0010, + "\x04\xD2\x04\x80\x41\x90\x7F\xC4\x74\x01\xF0\x80\x39\x90\x7F\xEA"}, + {0x40, 0xA0, 0x03DD, 0x0000, 0x0010, 0x0010, + "\xE0\x70\x20\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0"}, + {0x40, 0xA0, 0x03ED, 0x0000, 0x0010, 0x0010, + "\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\x74\x01"}, + {0x40, 0xA0, 0x03FD, 0x0000, 0x0010, 0x0010, + "\xF0\x80\x13\x90\x7F\xC4\x74\x01\xF0\x80\x0B\x12\x0C\xC0\x50\x06"}, + {0x40, 0xA0, 0x040D, 0x0000, 0x000D, 0x000D, + "\x90\x7F\xC4\x74\x01\xF0\x90\x7F\xB4\xE0\x44\x02\xF0"}, + {0x40, 0xA0, 0x041A, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0ABA, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xDE\x74\x16\xF0\x90\x7F\xDF\x74\x14\xF0\x90\x7F\xDD\x74"}, + {0x40, 0xA0, 0x0ACA, 0x0000, 0x0010, 0x0010, + "\x18\xF0\x90\x7F\xB6\x74\x02\xF0\x90\x7F\xB8\xF0\x90\x7F\xBA\xF0"}, + {0x40, 0xA0, 0x0ADA, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xBC\xF0\x90\x7F\xBE\xF0\x90\x7F\xC0\xF0\x90\x7F\xC2\xF0"}, + {0x40, 0xA0, 0x0AEA, 0x0000, 0x000A, 0x000A, + "\xE4\x90\x7F\xC9\xF0\x90\x7F\xCD\xF0\x22"}, + {0x40, 0xA0, 0x0AF4, 0x0000, 0x0009, 0x0009, + "\x90\x7F\xAF\xE0\x44\x08\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0041, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x00FE, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0003, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x3F\xD3\x22"}, + {0x40, 0xA0, 0x0C98, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x3F\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0CB4, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x3E\xD3\x22"}, + {0x40, 0xA0, 0x0CA6, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x3E\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0AFD, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0CBC, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0CBE, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0CC0, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BAE, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0BBE, 0x0000, 0x0010, 0x0010, + "\x01\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0BCE, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0B84, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x0B94, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x0BA4, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x09CA, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x09DA, 0x0000, 0x0001, 0x0001, "\xD0"}, + {0x40, 0xA0, 0x09DB, 0x0000, 0x0010, 0x0010, + "\x53\x91\xEF\x90\x7F\xAB\x74\x02\xF0\x30\x06\x14\x15\x3B\xE5\x3B"}, + {0x40, 0xA0, 0x09EB, 0x0000, 0x0010, 0x0010, + "\x70\x2E\x43\x08\x40\xC2\x06\xC3\x74\x1E\x95\x3D\xF5\x3B\x80\x20"}, + {0x40, 0xA0, 0x09FB, 0x0000, 0x0010, 0x0010, + "\xD5\x3B\x1D\x53\x08\xBF\xD2\x06\xE5\x3C\x25\x3D\xF5\x3D\x64\x03"}, + {0x40, 0xA0, 0x0A0B, 0x0000, 0x0010, 0x0010, + "\x60\x05\xE5\x3D\xB4\x1C\x06\xE5\x3C\xF4\x04\xF5\x3C\x85\x3D\x3B"}, + {0x40, 0xA0, 0x0A1B, 0x0000, 0x000F, 0x000F, + "\xD0\xD0\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0BFC, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x0C0C, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x0C1C, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x003A, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BD5, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0BE5, 0x0000, 0x0010, 0x0010, + "\x05\x53\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0BF5, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0AFF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC2, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC3, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC4, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC5, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC6, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC7, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC8, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CC9, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCA, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCB, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCC, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCD, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCE, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CCF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0CD0, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0C67, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x30\xE7\x12\xE0\x44\x01\xF0\x7F\x14\x7E\x00\x12"}, + {0x40, 0xA0, 0x0C77, 0x0000, 0x000A, 0x000A, + "\x0C\x81\x90\x7F\xD6\xE0\x54\xFE\xF0\x22"}, + {0x40, 0xA0, 0x0C46, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x44\x80\xF0\x43\x87\x01\x00\x00\x00\x00\x00\x22"}, + {0x40, 0xA0, 0x0C21, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x54\xFB\xF0\xE0\x44\x08\xF0\x30\x07\x04\xE0\x44"}, + {0x40, 0xA0, 0x0C31, 0x0000, 0x0010, 0x0010, + "\x02\xF0\x7F\xF4\x7E\x01\x12\x0C\x81\x90\x7F\xD6\xE0\x54\xF7\xF0"}, + {0x40, 0xA0, 0x0C41, 0x0000, 0x0005, 0x0005, "\xE0\x44\x04\xF0\x22"}, + {0x40, 0xA0, 0x0A79, 0x0000, 0x0002, 0x0002, "\x8F\x1B"}, + {0x40, 0xA0, 0x0A7B, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x1C\x75\x1D\xFF\x75\x1E\x02\x75\x1F\x07\xAB\x1D\xAA\x1E"}, + {0x40, 0xA0, 0x0A8B, 0x0000, 0x0010, 0x0010, + "\xA9\x1F\x90\x00\x01\x12\x07\x87\xB4\x03\x1D\xAF\x1C\x05\x1C\xEF"}, + {0x40, 0xA0, 0x0A9B, 0x0000, 0x0010, 0x0010, + "\xB5\x1B\x01\x22\x12\x07\x6E\x7E\x00\x29\xFF\xEE\x3A\xA9\x07\x75"}, + {0x40, 0xA0, 0x0AAB, 0x0000, 0x000E, 0x000E, + "\x1D\xFF\xF5\x1E\x89\x1F\x80\xD4\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x0AB9, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0A2A, 0x0000, 0x0010, 0x0010, + "\xE4\xFE\x75\x1D\xFF\x75\x1E\x01\x75\x1F\xD2\xAB\x1D\xAA\x1E\xA9"}, + {0x40, 0xA0, 0x0A3A, 0x0000, 0x0010, 0x0010, + "\x1F\x90\x00\x01\x12\x07\x87\x64\x02\x70\x2D\xAD\x06\x0E\xED\xB5"}, + {0x40, 0xA0, 0x0A4A, 0x0000, 0x0010, 0x0010, + "\x07\x01\x22\x90\x00\x02\x12\x07\xB4\x85\xF0\x1B\xF5\x1C\x62\x1B"}, + {0x40, 0xA0, 0x0A5A, 0x0000, 0x0010, 0x0010, + "\xE5\x1B\x62\x1C\xE5\x1C\x62\x1B\x29\xFD\xE5\x1B\x3A\xA9\x05\x75"}, + {0x40, 0xA0, 0x0A6A, 0x0000, 0x000E, 0x000E, + "\x1D\xFF\xF5\x1E\x89\x1F\x80\xC3\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x0A78, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0C81, 0x0000, 0x0010, 0x0010, + "\x8E\x18\x8F\x19\xE5\x19\x15\x19\xAE\x18\x70\x02\x15\x18\x4E\x60"}, + {0x40, 0xA0, 0x0C91, 0x0000, 0x0007, 0x0007, + "\x05\x12\x0C\x56\x80\xEE\x22"}, + {0x40, 0xA0, 0x0C56, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x0C66, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x00\x46"}, + {0x40, 0xA0, 0x0046, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\xC1\x02\x00\x8D"}, + {0x40, 0xA0, 0x076E, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x06\x89\x82\x8A\x83\xE0\x22\x50\x02\xE7\x22\xBB\xFE\x02"}, + {0x40, 0xA0, 0x077E, 0x0000, 0x0009, 0x0009, + "\xE3\x22\x89\x82\x8A\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x0787, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x0797, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x07A7, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x07B4, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x10\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\xF5\xF0"}, + {0x40, 0xA0, 0x07C4, 0x0000, 0x0010, 0x0010, + "\xA3\xE0\x22\x50\x09\xE9\x25\x82\xF8\x86\xF0\x08\xE6\x22\xBB\xFE"}, + {0x40, 0xA0, 0x07D4, 0x0000, 0x0010, 0x0010, + "\x0A\xE9\x25\x82\xF8\xE2\xF5\xF0\x08\xE2\x22\xE5\x83\x2A\xF5\x83"}, + {0x40, 0xA0, 0x07E4, 0x0000, 0x0008, 0x0008, + "\xE9\x93\xF5\xF0\xA3\xE9\x93\x22"}, + {0x40, 0xA0, 0x07EC, 0x0000, 0x0006, 0x0006, "\x8A\x83\x89\x82\xE4\x73"}, + {0x40, 0xA0, 0x0052, 0x0000, 0x0010, 0x0010, + "\x02\x04\x1B\xE4\x93\xA3\xF8\xE4\x93\xA3\x40\x03\xF6\x80\x01\xF2"}, + {0x40, 0xA0, 0x0062, 0x0000, 0x0010, 0x0010, + "\x08\xDF\xF4\x80\x29\xE4\x93\xA3\xF8\x54\x07\x24\x0C\xC8\xC3\x33"}, + {0x40, 0xA0, 0x0072, 0x0000, 0x0010, 0x0010, + "\xC4\x54\x0F\x44\x20\xC8\x83\x40\x04\xF4\x56\x80\x01\x46\xF6\xDF"}, + {0x40, 0xA0, 0x0082, 0x0000, 0x0010, 0x0010, + "\xE4\x80\x0B\x01\x02\x04\x08\x10\x20\x40\x80\x90\x09\x62\xE4\x7E"}, + {0x40, 0xA0, 0x0092, 0x0000, 0x0010, 0x0010, + "\x01\x93\x60\xBC\xA3\xFF\x54\x3F\x30\xE5\x09\x54\x1F\xFE\xE4\x93"}, + {0x40, 0xA0, 0x00A2, 0x0000, 0x0010, 0x0010, + "\xA3\x60\x01\x0E\xCF\x54\xC0\x25\xE0\x60\xA8\x40\xB8\xE4\x93\xA3"}, + {0x40, 0xA0, 0x00B2, 0x0000, 0x0010, 0x0010, + "\xFA\xE4\x93\xA3\xF8\xE4\x93\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA"}, + {0x40, 0xA0, 0x00C2, 0x0000, 0x0010, 0x0010, + "\xF0\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA\xDF\xE9\xDE\xE7\x80\xBE"}, + {0x40, 0xA0, 0x09C9, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x09, 0x0001, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, NULL} +}; diff --git a/kernel/drv/oss_usb/oss_usb.c b/kernel/drv/oss_usb/oss_usb.c new file mode 100644 index 0000000..2b5f119 --- /dev/null +++ b/kernel/drv/oss_usb/oss_usb.c @@ -0,0 +1,2505 @@ +/* + * Purpose: Top level USB audio class initialization and mixer functions + */ + +/* + * + * 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 KBUILD_MODNAME oss_usb +#include "oss_config.h" +#include "ossusb.h" + + +static const udi_usb_devinfo known_devices[] = { + {0x763, 0x2002, "M Audio USB AudioSport Duo", + { + {"OFF 24bit_hispeed 16bit_hispeed 24bit_lowspeed 16bit_lowspeed", 2, + 0x0014}, + {"OFF 24bit_hispeed 16bit_hispeed 24bit_lowspeed 16bit_lowspeed", 2, + 0x0014} + } + }, + {0x763, 0x2001, "M Audio USB AudioSport Quatro"}, + {0x763, 0x2805, "M Audio Sonica"}, + {0x763, 0x2007, "M Audio Sonica Theatre", + { + {"OFF 24bit_hispeed 16bit_hispeed 16bit_hispeed 24bit_lowspeed 24bit24bit 16bit 16bit OFF OFF", 3}, + {"OFF 24bit_hispeed 16bit_hispeed 24bit 16bit_lowspeed", 2} + } + }, + {0x763, 0x200d, "M Audio OmniStudio USB"}, + {0x41e, 0x3000, "Creative Sound Blaster Extigy"}, + {0x41e, 0x3010, "Creative Sound Blaster MP3+"}, + {0x41e, 0x3020, "Creative Audigy2 NX USB", + { + {"OFF 16bit22kHz 16bit44kHz " /* 0-2 */ + "24bit44kHz 16bit48kHz 24bit48kHz " /* 3-5 */ + "16bit96kHz 24bit96kHz 16bit22kHz " /* 6-8 */ + "16bit48kHz 24bit48kHz 16bit5.1ch22kHz " /* 9-11 */ + "16bit5.1ch48kHz 24bit5.1ch48kHz 16bit7.1ch22kHz " /* 12-14 */ + "16bit7.1ch48kHz" /* 15 */ , 4}, + + {"OFF 16bit32kHz 24bit32kHz " /* 0-2 */ + "16bit44kHz 24bit44kHz 16bit48kHz " /* 3-5 */ + "24bit48kHzin 24bit96kHz 24bit96kHz ", /* 6-8 */ + 5} + } + }, + {0x46d, 0x8b2, "Logitec Quickcam Pro 4000 (mic)"}, + {0x46d, 0xa01, "Logitec USB Headset"}, + {0x0471, 0x0311, "Philips ToUcam Pro (mic)"}, + {0x672, 0x1041, "Labtec LCS1040 Speaker System"}, + {0x6f8, 0xc000, "Hercules Gamesurround MUSE Pocket"}, + {0x0d8c, 0x000c, "C-Media USB audio"}, + {0x0d8c, 0x0102, "C-Media 2/4/6/8ch USB audio", + { + {"OFF 7.1 2.0 3.1 5.1 digital", 2}, + {"OFF stereo"} + } + }, + {0x0d8c, 0x0103, "C-Media USB audio"}, + {-1, -1, "USB sound device"} +}; + +typedef struct +{ + unsigned int devid; + special_driver_t driver; +} +special_table_t; + +extern int usb_mixerstyle; + +#define MAX_DEVC 10 +static ossusb_devc *devc_list[MAX_DEVC]; +static int ndevs = 0; +int usb_quiet = 0; + + +void +ossusb_dump_desc (unsigned char *desc, int cfg_len) +{ + int i; + + for (i = 0; i < cfg_len; i++) + { + if (!(i % 16)) + cmn_err (CE_CONT, "\n%04x: ", i); + cmn_err (CE_CONT, "%02x ", desc[i]); + } + cmn_err (CE_CONT, "\n"); +} + +unsigned int +ossusb_get_int (unsigned char *p, int nbytes) +{ + unsigned int v = 0; + int i; + + for (i = 0; i < nbytes; i++) + { + v |= (*p++) << (i * 8); + } + + return v; +} + +/* + * Mixer stuff + */ + +static int +decode_vol (usb_control_t * c, unsigned char *buf, int l) +{ + int value, range; + + if (l == 1) + value = (signed char) buf[0]; + else + value = (signed short) (buf[0] | (buf[1] << 8)); + + range = c->max - c->min; + + value -= c->min; + value = (value * c->scale + range / 2) / range; + + if (value < 0) + value = 0; + if (value > 255) + value = 255; + return value; +} + +static void +encode_vol (usb_control_t * c, unsigned char *buf, int l, int value) +{ + int range; + + range = c->max - c->min; + + value = (value * range + c->scale / 2) / c->scale; + + value += c->min; + + if (l == 1) + buf[0] = value; + else + { + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + } + +} + +static int +read_feature_value (ossusb_devc * devc, usb_control_t * c, int rq, int *v) +{ + int len, value = 0, l; + int nch, ch; + unsigned char buf[2]; + +/* + * Volume controls use two message bytes while the others use just one. + */ + l = (c->index == 1) ? 2 : 1; + + ch = c->min_ch + 1; + if (c->global) + ch = 0; + + if (rq != GET_CUR) + { + buf[0] = buf[1] = 0; + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + rq, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((c->index + 1) << 8) | (ch), // value + (c->unit->num << 8), // index + buf, // buffer + l, // buflen + OSS_HZ * 2); + if (len < 0) + return 0; + + value = + (len == + 1) ? (signed char) buf[0] : (signed short) (buf[0] | (buf[1] << 8)); + *v = value; + return 1; + } + + nch = c->max_ch - c->min_ch + 1; + + buf[0] = buf[1] = 0; + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((c->index + 1) << 8) | (ch), // value + (c->unit->num << 8), // index + buf, // buffer + l, // buflen + OSS_HZ * 2); + if (len < 0) + { + // cmn_err(CE_CONT, "feature (%s/%d) read error %d\n", c->unit->name, c->index, len); + *v = 0; + return 0; + } + + value = decode_vol (c, buf, len); + + if (!c->global) + if (nch == 2) /* Read the right channel */ + { + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((c->index + 1) << 8) | (ch + 1), // value + (c->unit->num << 8), // index + buf, // buffer + l, // buflen + OSS_HZ * 2); + if (len < 0) + value |= (value & 0xff) << 8; + else + value |= (decode_vol (c, buf, len)) << 8; + } + + *v = value; + return 1; +} + +static int +write_feature_value (ossusb_devc * devc, usb_control_t * c, int value) +{ + int len, l; + int left, right; + int ch, nch; + unsigned char buf[2]; + + ch = c->min_ch + 1; + if (c->global) + ch = 0; + + left = value & 0xff; + right = (value >> 8) & 0xff; + + if (left > (c->max - c->min)) + left = c->max - c->min; + if (right > (c->max - c->min)) + right = c->max - c->min; + + l = (c->index == 1) ? 2 : 1; + + nch = c->max_ch - c->min_ch + 1; + buf[0] = buf[1] = 0; + encode_vol (c, buf, l, left); + + len = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint + SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((c->index + 1) << 8) | ch, // value + (c->unit->num << 8), // index + buf, // buffer + l, // buflen + OSS_HZ * 2); + if (len < 0) + { + cmn_err (CE_CONT, "feature write error %d\n", len); + return len; + } + + if (nch == 2) /* Write the right channel */ + { + buf[0] = buf[1] = 0; + encode_vol (c, buf, l, right); + + len = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint + SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((c->index + 1) << 8) | (ch + 1), // value + (c->unit->num << 8), // index + buf, // buffer + l, // buflen + OSS_HZ * 2); + } + else + right = left; + + value = left | (right << 8); + return value; +} + +static int +read_mixer_value (ossusb_devc * devc, usb_control_t * c, int rq, int *v) +{ + int len, value = 0; + unsigned char buf[2]; + + if (rq != GET_CUR) + { + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + rq, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + (c->index << 8) | c->min_ch, // value + (c->unit->num << 8) | 1, // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + if (len < 0) + return 0; + + *v = (signed char) buf[1]; + return 1; + } + + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + rq, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + (c->index << 8) | c->min_ch, // value + (c->unit->num << 8) | 1, // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + if (len < 0) + { + cmn_err (CE_CONT, "mixer read error %d\n", len); + return 0; + } + + value = buf[1] - c->min; + + *v = value; + return 1; +} + +static int +write_mixer_value (ossusb_devc * devc, usb_control_t * c, int value) +{ + int len; + unsigned char buf[2]; + + value &= 0xff; + + buf[0] = 0; + buf[1] = value + c->min; + len = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint + SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + (c->index << 8) | c->min_ch, // value + (c->unit->num << 8) | 1, // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + if (len < 0) + { + cmn_err (CE_CONT, "mixer write error %d\n", len); + return 0; + } + + return value; +} + +static int +read_unit (ossusb_devc * devc, usb_control_t * c, int rq, int *v) +{ + int err, value; + unsigned char buf[2]; + + *v = value = 0; + + switch (c->unit->typ) + { + case TY_FEAT: + return read_feature_value (devc, c, rq, v); + break; + + case TY_MIXER: + return read_mixer_value (devc, c, rq, v); + break; + + case TY_SELECT: + err = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + rq, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + 0, // value + (c->unit->num << 8), // index + buf, // buffer + 1, // buflen + OSS_HZ * 2); + if (err < 0) + { + cmn_err (CE_CONT, "USB mixer unit read error %d\n", err); + return 0; + } + value = buf[0] - 1; + break; + + } /* switch */ + + *v = value; + return 1; +} + +static int +read_current_value (ossusb_devc * devc, usb_control_t * c) +{ + int v; + + if (!read_unit (devc, c, GET_CUR, &v)) + return 0; + + c->value = v; + + return 1; +} + +static int +write_current_value (ossusb_devc * devc, usb_control_t * c, int value) +{ + unsigned char buf[2]; + int err; + + switch (c->unit->typ) + { + case TY_SELECT: + if (value > c->max) + value = c->max; + buf[0] = value + 1; + err = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint + SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + 0, // value + (c->unit->num << 8), // index + buf, // buffer + 1, // buflen + OSS_HZ * 2); + if (err < 0) + { + cmn_err (CE_CONT, "Selector write error %d\n", err); + return 0; + } + break; + + case TY_FEAT: + value = write_feature_value (devc, c, value); + break; + + case TY_MIXER: + value = write_mixer_value (devc, c, value); + break; + + default: + return OSS_EIO; + } + + return value; +} + +static int +new_ctl (ossusb_devc * devc, usb_audio_unit_t * un, int index, int exttype, + int chmask) +{ + int n, min, max; + usb_control_t *c; + int i, min_ch = 0, max_ch = 0; + + if (devc->ncontrols >= MAX_CONTROLS) + { + cmn_err (CE_CONT, "Too many mixer features.\n"); + return OSS_EIO; + } + + n = devc->ncontrols++; + + c = &devc->controls[n]; + + if (chmask) + { + min_ch = -1; + + for (i = 0; i < 32; i++) + if (chmask & (1 << i)) + { + if (min_ch == -1) + min_ch = i; + max_ch = i; + } + } + + c->unit = un; + c->index = index; + c->exttype = exttype; + c->min_ch = min_ch; + c->global = (chmask == 0) ? 1 : 0; + c->max_ch = max_ch; + c->min = 0; + c->max = 255; + c->chmask = chmask; + c->value = 0; + + if (index != 1) /* Not volume control */ + { + c->max = 1; + } + else + { + if (read_unit (devc, c, GET_MAX, &max)) + { + c->max = max; + if (read_unit (devc, c, GET_MIN, &min)) + { + c->min = min; + } + } + } + + if (c->max <= c->min) + { +/* + * The device reported bad limits. Try to fix the situation. + */ + if (c->min < 0) + c->max = 0; + else + c->min = 0; + if (c->max <= c->min) + { + c->min = 0; + c->max = 255; + } + } + + c->scale = 255; + if (c->max - c->min < 255) + c->scale = c->max - c->min; + + + read_current_value (devc, c); + + if (usb_trace) + { + cmn_err (CE_CONT, "Ctl %2d: %d/%s %d ", n, c->unit->num, c->unit->name, + c->index); + cmn_err (CE_CONT, "Min %d, max %d, scale %d\n", c->min, c->max, + c->scale); + cmn_err (CE_CONT, "ch=%x ", c->chmask); + cmn_err (CE_CONT, "Value %04x, (%d - %d, %d)\n", c->value, c->min, + c->max, c->scale); + } + + return n; +} + +static int +mixer_func (int dev, int ctrl, unsigned int cmd, int value) +{ + ossusb_devc *devc = mixer_devs[dev]->devc; + usb_control_t *c; + + if (devc->disabled) + return OSS_EPIPE; + + if (ctrl < 0 || ctrl >= devc->ncontrols) + return OSS_EIO; + + c = &devc->controls[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + { + return c->value; + } + + if (cmd != SNDCTL_MIX_WRITE) + return OSS_EINVAL; + + value = c->value = write_current_value (devc, c, value); + + return value; +} + +static char * +get_feature_name (int n) +{ + switch (n) + { + case 0: + return "mute"; + case 1: + return "vol"; + case 2: + return "bass"; + case 3: + return "mid"; + case 4: + return "treble"; + case 5: + return "eq"; + case 6: + return "agc"; + case 7: + return "delay"; + case 8: + return "boost"; + case 9: + return "loud"; + case 10: + return "igain"; + case 11: + return "igainpad"; + case 12: + return "phaseinv"; + case 13: + return "underflow"; + case 14: + return "overflow"; + default: + return "misc"; + } +} + +static int +get_feature_type (int n) +{ + switch (n) + { + case 0: + return MIXT_ONOFF; + case 1: + return MIXT_SLIDER; + case 2: + return MIXT_SLIDER; + case 3: + return MIXT_SLIDER; + case 4: + return MIXT_SLIDER; + case 5: + return MIXT_SLIDER; + case 6: + return MIXT_ONOFF; + case 7: + return MIXT_SLIDER; + case 8: + return MIXT_ONOFF; + case 9: + return MIXT_ONOFF; + default: + return MIXT_ONOFF; + } +} + +struct chmasks +{ + unsigned int mask; + char *name; + char type; + char channels; +}; + +static const struct chmasks chmasks[] = { + {0x00000003, "front", MIXT_STEREOSLIDER, 2}, + {0x00000001, "L", MIXT_MONOSLIDER, 1}, + {0x00000002, "R", MIXT_MONOSLIDER, 1}, + {0x00000030, "surr", MIXT_STEREOSLIDER, 2}, + {0x00000010, "LS", MIXT_MONOSLIDER, 1}, + {0x00000020, "RS", MIXT_MONOSLIDER, 1}, + {0x0000000c, "C/L", MIXT_STEREOSLIDER, 2}, + {0x00000004, "C", MIXT_MONOSLIDER, 1}, + {0x00000008, "LFE", MIXT_MONOSLIDER, 1}, + {0x000000c0, "center", MIXT_STEREOSLIDER, 2}, + {0x00000040, "LC", MIXT_MONOSLIDER, 1}, + {0x00000080, "RC", MIXT_MONOSLIDER, 1}, + {0x00000100, "surr", MIXT_STEREOSLIDER, 2}, + {0x00000600, "side", MIXT_STEREOSLIDER, 2}, + {0x00000200, "SL", MIXT_MONOSLIDER, 1}, + {0x00000400, "SR", MIXT_MONOSLIDER, 1}, + {0x00000800, "TC", MIXT_MONOSLIDER, 1}, + {0x00001000, "TFL", MIXT_MONOSLIDER, 1}, + {0x00002000, "TFC", MIXT_MONOSLIDER, 1}, + {0x00004000, "TFR", MIXT_MONOSLIDER, 1}, + {0x00008000, "TBL", MIXT_MONOSLIDER, 1}, + {0x00010000, "TBC", MIXT_MONOSLIDER, 1}, + {0x00020000, "TBR", MIXT_MONOSLIDER, 1}, + {0x00040000, "TFLC", MIXT_MONOSLIDER, 1}, + {0x00080000, "TFRC", MIXT_MONOSLIDER, 1}, + {0x00100000, "LLFE", MIXT_MONOSLIDER, 1}, + {0x00200000, "RLFE", MIXT_MONOSLIDER, 1}, + {0x00400000, "TSL", MIXT_MONOSLIDER, 1}, + {0x00800000, "TSR", MIXT_MONOSLIDER, 1}, + {0x01000000, "BC", MIXT_MONOSLIDER, 1}, + {0x02000000, "BLC", MIXT_MONOSLIDER, 1}, + {0x04000000, "BRC", MIXT_MONOSLIDER, 1}, + {0x80000000, "RD", MIXT_MONOSLIDER, 1}, + {0, NULL} +}; + +static int +count_source_controls (ossusb_devc * devc, int unit) +{ + int n = 0, nn, i; + usb_audio_unit_t *un; + unsigned char *d; + + if (unit <= 0 || unit >= devc->nunits) + return 0; + + un = &devc->units[unit]; + d = un->desc; + + if (un == NULL) + return 0; + + switch (un->typ) + { + case TY_MIXER: + case TY_SELECT: + nn = d[4]; + d += 5; + for (i = 0; i < nn; i++) + { + n += count_source_controls (devc, *d); + d++; + } + break; + + case TY_PROC: + case TY_EXT: + nn = d[6]; + d += 7; + for (i = 0; i < nn; i++) + { + n += count_source_controls (devc, *d); + d++; + } + break; + + default: + if (un->source <= 0 && un->source < devc->nunits) + { + n = count_source_controls (devc, un->source); + } + } + + if (!un->ctl_avail) + return n; + + return n + un->control_count; +} + +static int +count_target_controls (ossusb_devc * devc, int unit) +{ + int n = 0; + usb_audio_unit_t *un; + + if (unit <= 0 || unit >= devc->nunits) + return 0; + + un = &devc->units[unit]; + + if (un == NULL) + return 0; + + if (un->typ == TY_SELECT || un->typ == TY_MIXER) + { + n = 0; + } + else if (un->target <= 0 && un->target < devc->nunits) + { + n = count_target_controls (devc, un->target); + } + + if (!un->ctl_avail) + return n; + + return n + un->control_count; +} + +static int +follow_source_links (ossusb_devc * devc, usb_audio_unit_t * un) +{ + while (un->source > 0 && un->source < devc->nunits) + un = &devc->units[un->source]; + + return un->num; +} + +static int +follow_target_links (ossusb_devc * devc, usb_audio_unit_t * un) +{ + while (un->target > 0 && un->target < devc->nunits) + un = &devc->units[un->target]; + + return un->num; +} + +static void +add_controls_for_mixer (ossusb_devc * devc, usb_audio_unit_t * un, int group) +{ + int i, n; + unsigned char *d = un->desc; + + if (!un->ctl_avail) + return; + + n = d[4]; + d += 5; + + for (i = 0; i < n; i++) + if (*d > 0 && *d < devc->nunits) + { + int ref = follow_source_links (devc, &devc->units[*d]); + + { + + int ctl = new_ctl (devc, un, i, MIXT_MONOSLIDER, un->chmask); + UDB (cmn_err + (CE_CONT, "Add mixer control %d/%s\n", un->num, + devc->units[ref].name)); + if (mixer_ext_create_control (devc->mixer_dev, group, ctl, + mixer_func, MIXT_MONOSLIDER, + devc->units[ref].name, 255, + MIXF_READABLE | MIXF_WRITEABLE) < 0) + return; + } + d++; + } + + un->ctl_avail = 0; +} + +/*ARGSUSED*/ +static void +add_controls_for_proc (ossusb_devc * devc, usb_audio_unit_t * un, int group) +{ + int i, n; + unsigned char *d = un->desc; + + if (!un->ctl_avail) + return; + + n = d[6]; + d += 7; + + for (i = 0; i < n; i++) + if (*d > 0 && *d < devc->nunits) + { + d++; + } + + un->ctl_avail = 0; +} + +static void +add_controls_for_selector (ossusb_devc * devc, usb_audio_unit_t * un, + int group) +{ + static oss_mixer_enuminfo ent; + char *s; + int i, n, err; + unsigned char *d = un->desc; + int ctl = new_ctl (devc, un, 0, MIXT_ENUM, 0); + + if (!un->ctl_avail) + return; + + n = d[4]; + d += 5; + UDB (cmn_err (CE_CONT, "Add selector control %d/%s\n", un->num, un->name)); + if ((err = mixer_ext_create_control (devc->mixer_dev, group, + ctl, mixer_func, + MIXT_ENUM, + un->name, n, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return; + + memset (&ent, 0, sizeof (ent)); + + s = ent.strings; + + for (i = 0; i < n; i++) + if (*d > 0 && *d < devc->nunits) + { + int ref = follow_source_links (devc, &devc->units[*d]); + d++; + + if (s > ent.strings) + *s++ = '|'; + strcpy (s, devc->units[ref].name); + s += strlen (s); + } + + s = ent.strings; + for (i = 0; i < strlen (s); i++) + { + if (s[i] == ' ') + s[i] = '_'; + if (s[i] == '|') + s[i] = ' '; + } + + ent.dev = devc->mixer_dev; + ent.ctrl = err; + ent.nvalues = 0; + + mixer_ext_set_enum (&ent); + + un->ctl_avail = 0; +} + +/*ARGSUSED*/ +static void +add_multich_volumes (ossusb_devc * devc, usb_audio_unit_t * un, int group, + int fea, int mask, unsigned int *feature_mask) +{ + int i; + + for (i = 0; mask != 0 && chmasks[i].mask != 0; i++) + { + int m = chmasks[i].mask; + int ctl; + usb_control_t *c; + + if (!(mask & m)) + continue; + + ctl = new_ctl (devc, un, fea, chmasks[i].type, chmasks[i].mask); + c = &devc->controls[ctl]; + + UDB (cmn_err + (CE_CONT, "Add multich feature control %d/%s\n", un->num, + chmasks[i].name)); + if (mixer_ext_create_control (devc->mixer_dev, group, ctl, mixer_func, + chmasks[i].type, chmasks[i].name, + c->scale, + MIXF_READABLE | MIXF_WRITEABLE) < 0) + return; + + mask &= ~m; + } + + if (mask) + cmn_err (CE_CONT, "Warning! Unsupported channels (%02x)\n", mask); +} + +static void +translate_feature_mask_usb2 (ossusb_devc *devc, usb_audio_unit_t * un, unsigned int *feature_mask) +{ + int i, n, c; + unsigned char *d = un->desc; + + n = 4; + d = d + 5 + n; // Skip the global mask + +/* + * USB 2.0 uses 2 bits for each control + * 01b means that the control is read only and 11b means it's RW + */ + for (c = 0; c < un->channels; c++) + { + unsigned int mask; + unsigned char *p = d + c * n; + + mask = p[3] | + (p[2] << 8) | + (p[1] << 16) | + (p[0] << 24); + + for (i = 0; i < n * 4; i++) + if ((mask & (3 << 2*i)) && (un->ctl_avail & (1 << i))) + { + feature_mask[i] |= 1 << c; + } + } +} + +static void +translate_feature_mask (ossusb_devc *devc, usb_audio_unit_t * un, unsigned int *feature_mask) +{ + int i, n, c; + unsigned char *d = un->desc; + + if (devc->usb_version > 1) + { + translate_feature_mask_usb2(devc, un, feature_mask); + return; + } + + n = d[5]; + if (n < 1 || n > 2) + { + cmn_err (CE_CONT, "Bad feature mask size %d\n", n); + return; + } + + d = d + 6 + n; // Skip the global mask + + for (c = 0; c < un->channels; c++) + { + int mask = d[c * n]; + if (n > 1) + mask |= d[c * n + 1]; + + for (i = 0; i < n * 8; i++) + if ((mask & (1 << i)) && (un->ctl_avail & (1 << i))) + { + feature_mask[i] |= 1 << c; + } + } +} + +static void +add_controls_for_feature (ossusb_devc * devc, usb_audio_unit_t * un, + int group) +{ + int i; + unsigned int feature_mask[16], global_mask; + + if (!un->ctl_avail) + return; + +// Handle the global controls first + + global_mask = un->desc[6]; + if (un->desc[5] > 0) + global_mask |= un->desc[7] << 8; + + for (i = 0; i < 11; i++) + if (un->ctl_avail & (1 << i) && (global_mask & (1 << i))) + { + char *name = get_feature_name (i); + int type = get_feature_type (i); + int max; + char tmp[16]; + int ctl; + + ctl = new_ctl (devc, un, i, type, 0); + strcpy (tmp, name); + if (type == MIXT_SLIDER) + max = devc->controls[ctl].max - devc->controls[ctl].min; + else + max = 1; + + if (max > 255) + max = 255; + + UDB (cmn_err + (CE_CONT, "Add (global) feature control %d:%s, max=%d\n", + un->num, name, max)); + if (mixer_ext_create_control (devc->mixer_dev, group, ctl, + mixer_func, type, tmp, max, + MIXF_READABLE | MIXF_WRITEABLE) < 0) + return; + //un->ctl_avail &= ~(1 << i); + } + +// Handle the channelized controls + + if (un->ctl_avail == 0) /* Nothing left */ + return; + + // Translate the channel/feature availability matrix + + memset (feature_mask, 0, sizeof (feature_mask)); + translate_feature_mask (devc, un, feature_mask); + + for (i = 0; i < 16; i++) + if (feature_mask[i]) + { + char *name = get_feature_name (i); + int type = get_feature_type (i); + int max, instances = 0; + + int nc = 0, j; + + for (j = 0; j < 16; j++) + if (feature_mask[i] & (1 << j)) + nc = j + 1; + + if (type == MIXT_SLIDER) + { + if (nc == 1) + { + type = MIXT_MONOSLIDER; + instances = 1; + } + else if (nc == 2) + { + type = MIXT_STEREOSLIDER; + instances = 1; + } + else + { + type = MIXT_MONOSLIDER; + if (i == 1) /* "volume" */ + instances = nc; + else + { + instances = 0; + type = MIXT_MONOSLIDER; + } + } + max = 255; + } + else + max = 2; + + if (instances && (instances > 1 || feature_mask[i] > 0x0003)) + { + int g; + char tmp[16]; + strcpy (tmp, name); + UDB (cmn_err (CE_CONT, "Add feature group %s\n", tmp)); + if ((g = + mixer_ext_create_group (devc->mixer_dev, group, tmp)) < 0) + return; + + add_multich_volumes (devc, un, g, i, feature_mask[i], + feature_mask); + } + else + { + char tmp[16]; + int ctl = new_ctl (devc, un, i, type, un->chmask); + strcpy (tmp, name); + max = devc->controls[ctl].max - devc->controls[ctl].min; + if (max > 255) + max = 255; + + UDB (cmn_err + (CE_CONT, "Add feature control %d:%s\n", un->num, name)); + if (mixer_ext_create_control (devc->mixer_dev, group, ctl, + mixer_func, type, tmp, max, + MIXF_READABLE | MIXF_WRITEABLE) < 0) + return; + } + } + + un->ctl_avail = 0; // All done (hope so) +} + +static void +traverse_source_controls (ossusb_devc * devc, usb_audio_unit_t * un, + int group) +{ + unsigned char *d; + + d = un->desc; + + if (un->typ == TY_MIXER) + { + add_controls_for_mixer (devc, un, group); + return; + } + + if (un->typ == TY_PROC) + { + add_controls_for_proc (devc, un, group); + + if (d[6] > 1) /* More than 1 sources */ + return; + } + + if (un->typ == TY_SELECT) + { + add_controls_for_selector (devc, un, group); + return; + } + + if (un->source > 0 && un->source < devc->nunits) + { + traverse_source_controls (devc, &devc->units[un->source], group); + } + + if (un->typ == TY_FEAT) + { + add_controls_for_feature (devc, un, group); + } +} + +static void +traverse_target_controls (ossusb_devc * devc, usb_audio_unit_t * un, + int group) +{ + unsigned char *d; + + + d = un->desc; + + if (un->typ == TY_SELECT) + { + add_controls_for_selector (devc, un, group); + } + + if (un->typ == TY_PROC || un->typ == TY_EXT) + if (d[6] > 1) // More than 1 input pins + return; + + if (un->typ == TY_MIXER) + { +#if 1 + add_controls_for_mixer (devc, un, group); +#endif + } + + if (un->target > 0 && un->target < devc->nunits) + traverse_target_controls (devc, &devc->units[un->target], group); + + if (un->typ == TY_FEAT) + { + add_controls_for_feature (devc, un, group); + } +} + +void +ossusb_create_altset_control (int dev, int portc_num, int nalt, char *name) +{ + int ctl; + ossusb_devc *devc = mixer_devs[dev]->devc; + char *as = NULL; + int default_altsetting; + unsigned int altsetting_mask; + + if (nalt < 3) /* Only one alternative setting (plus "OFF") available */ + return; + if ((as = + udi_usbdev_get_altsetting_labels (devc->mixer_usbdev, portc_num, + &default_altsetting, + &altsetting_mask)) != NULL) + { + if (altsetting_mask != 0) + { + /* + * Check if more than one of them are enabled. + */ + + int i, n = 0; + + for (i = 1; i < nalt; i++) + if (altsetting_mask & (1 << i)) + n++; + + if (n < 2) /* No */ + return; + } + } + + if ((ctl = mixer_ext_create_control (dev, 0, + portc_num, ossusb_change_altsetting, + MIXT_ENUM, + name, nalt, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return; + + if (as != NULL) /* Use custom labels */ + { + mixer_ext_set_strings (dev, ctl, as, 0); + if (altsetting_mask != 0) + { + oss_mixext *ext; + int i; + + ext = mixer_find_ext (dev, ctl); + + memset (ext->enum_present, 0, sizeof (ext->enum_present)); + for (i = 0; i < nalt; i++) + if (altsetting_mask & (1 << i)) + ext->enum_present[i / 8] |= (1 << (i % 8)); + } + + if (default_altsetting > 0) + ossusb_change_altsetting (dev, portc_num, SNDCTL_MIX_WRITE, + default_altsetting); + } + else + mixer_ext_set_strings (dev, ctl, + "OFF 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19", + 0); + +} + +static int +usb_mix_init (int dev) +{ + ossusb_devc *devc; + int i, group; + + devc = mixer_devs[dev]->devc; + + for (i = 0; i < devc->nunits; i++) + { + usb_audio_unit_t *un = &devc->units[i]; + + if (un->typ == TY_OUTPUT) + { + if (count_source_controls (devc, un->source) == 0) + { + continue; + } + + if ((group = mixer_ext_create_group (dev, 0, un->name)) < 0) + return group; + + traverse_source_controls (devc, un, group); + continue; + } + } + + for (i = 0; i < devc->nunits; i++) + { + usb_audio_unit_t *un = &devc->units[i]; + + if (un->typ == TY_INPUT) + { + if (count_target_controls (devc, un->target) == 0) + { + continue; + } + + if ((group = mixer_ext_create_group (dev, 0, un->name)) < 0) + return group; + + traverse_target_controls (devc, un, group); + un->ctl_avail = 0; + continue; + } + } + + return 0; +} + +static char * +check_feature (usb_audio_unit_t * un, unsigned char *mask, int n) +{ + if (mask[n / 8] & (1 << (n % 8))) + { + un->control_count++; + + return get_feature_name (n); + } + + return NULL; +} + +/*ARGSUSED*/ +static int +usb_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + ossusb_devc *devc = mixer_devs[dev]->hw_devc; + + if (devc->disabled) + return OSS_EPIPE; + + switch (cmd) + { + case SOUND_MIXER_READ_DEVMASK: + return *arg = devc->devmask | devc->recmask; + case SOUND_MIXER_READ_RECMASK: + return *arg = devc->recmask; + case SOUND_MIXER_READ_RECSRC: + return *arg = devc->recsrc; + case SOUND_MIXER_READ_STEREODEVS: + return *arg = devc->stereodevs; + } + + return *arg = 0; +} + +static mixer_driver_t usb_mixer_driver = { + usb_mixer_ioctl +}; + +static int +init_mixer (ossusb_devc * devc) +{ + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + devc->dev_name, + &usb_mixer_driver, + sizeof (mixer_driver_t), + devc)) >= 0) + { + char mxname[20]; + + sprintf (mxname, "USB_%d", ndevs); + + devc->levels = load_mixer_volumes (mxname, NULL, 1); + mixer_devs[devc->mixer_dev]->hw_devc = devc; + mixer_ext_set_init_fn (devc->mixer_dev, usb_mix_init, MAX_CONTROLS); + } + + return 1; +} + +static usb_audio_unit_t * +setup_unit (ossusb_devc * devc, int unit, char *name, unsigned char *desc, + int desclen, int typ) +{ + usb_audio_unit_t *un; + + if (unit < 0 || unit >= MAX_UNIT) + { + cmn_err (CE_WARN, "Bad unit number %d\n", unit); + return NULL; + } + + if (typ >= sizeof (devc->unit_counters)) + { + cmn_err (CE_WARN, "Bad unit type %d\n", typ); + return NULL; + } + + devc->unit_counters[typ]++; + + if (unit >= devc->nunits) + devc->nunits = unit + 1; + + un = &devc->units[unit]; + + un->num = unit; + un->typ = typ; + un->desc = desc; + un->desclen = desclen; + un->mixnum = -1; + un->channels = 2; + un->chmask = 0x03; + strcpy (un->name, name); + + return un; +} + +static char * +get_terminal_id (int type, char *def, int typ, int *mn) +{ + int dummy, *mixnum; + + if (mn != NULL) + mixnum = mn; + else + mixnum = &dummy; + switch (type) + { + case 0x0101: + if (typ == TY_INPUT) + { + *mixnum = SOUND_MIXER_PCM; + return "play"; + } + if (typ == TY_OUTPUT) + { + *mixnum = SOUND_MIXER_RECLEV; + return "rec"; + } + break; + case 0x0301: + *mixnum = SOUND_MIXER_VOLUME; + return "output"; + case 0x0302: + *mixnum = SOUND_MIXER_VOLUME; + return "headph"; + case 0x0307: + return "LFE"; + + case 0x0401: + return "handset"; + case 0x0402: + return "headset"; + + case 0x0403: + case 0x0404: + case 0x0405: + case 0x0500: + case 0x0501: + case 0x0502: + case 0x0504: + return "phone"; + break; + + case 0x0600: + *mixnum = SOUND_MIXER_LINE1; + return "aux"; + case 0x0601: + *mixnum = SOUND_MIXER_LINE2; + return "aux"; + case 0x0602: + return "digital"; + case 0x0603: + *mixnum = SOUND_MIXER_LINE; + return "line"; + case 0x0604: + *mixnum = SOUND_MIXER_SPEAKER; + return "pc_in"; + case 0x0605: + *mixnum = SOUND_MIXER_DIGITAL1; + if (typ == TY_INPUT) + return "spdin"; + else + return "spdout"; + case 0x0606: + return "da_stream"; + case 0x0607: + return "DV_audio"; + + case 0x0701: + return "noise"; + case 0x0702: + return "eq_noise"; + case 0x0703: + *mixnum = SOUND_MIXER_CD; + return "cd"; + case 0x0704: + return "dat"; + case 0x0706: + return "md"; + case 0x0707: + return "tape"; + case 0x0708: + return "phono"; + case 0x0709: + *mixnum = SOUND_MIXER_VIDEO; + return "vcr"; + case 0x070b: + return "dvd"; + case 0x070c: + return "tv"; + case 0x070d: + return "sat"; + case 0x070e: + return "cable"; + case 0x0710: + *mixnum = SOUND_MIXER_RADIO; + return "radio"; + case 0x0711: + *mixnum = SOUND_MIXER_RADIO; + return "xmitter"; + case 0x0712: + return "mtrack"; + case 0x0713: + *mixnum = SOUND_MIXER_SYNTH; + return "synth"; + } + + if (type < 0x201) // Unknown type + return def; + + if (type < 0x300) + { + *mixnum = SOUND_MIXER_MIC; + return "mic"; + } + + return def; +} + +static void +setup_legacy_mixer (ossusb_devc * devc) +{ + int x; + +// Set up the recording selector + + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int i, n; + unsigned char *d = un->desc; + + if (un->typ != TY_SELECT || strcmp (un->name, "rec.src") != 0) + continue; + + if (!un->ctl_avail) + continue; + + devc->rec_unit = x; + un->ctl_avail = 0; + + devc->num_recdevs = n = d[4]; + d += 5; + for (i = 0; i < n; i++) + { + int ref = follow_source_links (devc, &devc->units[*d]); + int mask; + + d++; + + if (ref < 1 || ref >= devc->nunits || devc->units[ref].mixnum == -1) + continue; + + mask = (1 << devc->units[ref].mixnum); + if (devc->recmask & mask) // Duplicate + continue; + UDB (cmn_err + (CE_CONT, "Recsrc %d, num=%d, mask %x\n", i, ref, mask)); + + devc->recdevs[i] = mask; + + devc->recmask |= mask; + if (devc->recsrc == 0) + devc->recsrc = mask; + } + + break; + } + +// Set up the legacy mixer controls + + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int mixnum; + unsigned char *d = un->desc; + + if (!(un->ctl_avail & 0x02)) + continue; + + if (un->typ == TY_FEAT && d[6] & 0x02) // Volume control + { + int t; + mixnum = un->mixnum; + + if (mixnum == -1) + { + t = follow_target_links (devc, un); + if (t && devc->units[t].mixnum != -1) + mixnum = devc->units[t].mixnum; + else + { + t = follow_source_links (devc, un); + if (t && devc->units[t].mixnum != -1) + mixnum = devc->units[t].mixnum; + } + } + + if (mixnum == -1 || un->channels > 2) + continue; + UDB (cmn_err (CE_CONT, "Unit %d is volume %d\n", x, mixnum)); + un->ctl_avail &= ~0x02; // Reserve the volume slider + + devc->devmask |= (1 << mixnum); + if (un->channels == 2) + devc->stereodevs |= (1 << mixnum); + + continue; + } + } + +} + +static char * +get_processor_type (int t) +{ + switch (t) + { + case 0x01: + return "upmix"; + case 0x02: + return "prologic"; + case 0x03: + return "3D"; + case 0x04: + return "reverb"; + case 0x05: + return "chorus"; + case 0x06: + return "compress"; + default: + return "proc"; + } +} + +static void +parse_processing_unit (ossusb_devc * devc, unsigned char *d, int l) +{ + usb_audio_unit_t *un; + char *name; + + name = get_processor_type (d[4]); + + if ((un = setup_unit (devc, d[3], name, d, l, TY_PROC)) == NULL) + return; + un->subtyp = d[4]; + un->ctl_avail = 1; + + if (un->subtyp == 1) // Upmix/downmix unit + { + un->channels = d[8]; + un->chmask = ossusb_get_int (&d[9], 2); + } +} + +static int +get_feature_mask (unsigned char *d, int channels) +{ + int i, n, mask = 0, v; + n = d[5]; + + for (i = 0; i <= channels; i++) + { + v = d[6 + i * n]; + if (n > 1) + v |= d[6 + i * n + 1] << 8; + + mask |= v; + } + + return mask; +} + +#if 1 +static void +mixer_dump (ossusb_devc * devc) +{ + int i, j, c; + usb_audio_unit_t *un; + + for (i = 1; i < devc->nunits; i++) + { + un = &devc->units[i]; + + if (un->typ == TY_FEAT) + { + cmn_err (CE_CONT, "Unit %d\n", un->num); + + for (j = 0; j < 8; j++) + { + for (c = 0; c < 7; c++) + { + unsigned char buf[2]; + int len; + + buf[0] = buf[1] = 0; + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((j) << 8) | (c), // value + (un->num << 8), // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + + if (len < 0) + continue; + cmn_err (CE_CONT, " Feature %d/%d, ch %d: ", un->num, j, + c); + cmn_err (CE_CONT, "%02x%02x ", buf[0], buf[1]); + + if (len == 1) + cmn_err (CE_CONT, "(%d) ", (signed char) buf[0]); + else + cmn_err (CE_CONT, "(%d) ", + (signed short) (buf[0] | (buf[1] << 8))); + + buf[0] = buf[1] = 0; + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((j) << 8) | (c), // value + (un->num << 8), // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + + if (len >= 0) + cmn_err (CE_CONT, "Min=%02x%02x ", buf[0], buf[1]); + if (len == 1) + cmn_err (CE_CONT, "(%d) ", (signed char) buf[0]); + else if (len == 2) + cmn_err (CE_CONT, "(%d) ", + (signed short) (buf[0] | (buf[1] << 8))); + + buf[0] = buf[1] = 0; + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS, // rqtype + ((j) << 8) | (c), // value + (un->num << 8), // index + buf, // buffer + 2, // buflen + OSS_HZ * 2); + + if (len >= 0) + cmn_err (CE_CONT, "max=%02x%02x ", buf[0], buf[1]); + if (len == 1) + cmn_err (CE_CONT, "(%d) ", (signed char) buf[0]); + else if (len == 2) + cmn_err (CE_CONT, "(%d) ", + (signed short) (buf[0] | (buf[1] << 8))); + + cmn_err (CE_CONT, "\n"); + } + } + } + } +} +#endif + +/*ARGSUSED*/ +static ossusb_devc * +ossusb_init_audioctl (ossusb_devc * devc, udi_usb_devc * usbdev, int inum, + int reinit) +{ + int desc_len; + unsigned char *desc, *d; + int i, l, n = 0, p, x, mixnum = -1; + char *name; + usb_audio_unit_t *un; + + /* nsettings = udi_usbdev_get_num_altsettings (usbdev); */ + devc->mixer_usbdev = usbdev; + + if (!init_mixer (devc)) + return NULL; + + desc = udi_usbdev_get_altsetting (usbdev, 0, &desc_len); + + if (desc == NULL) + { + cmn_err (CE_CONT, "Can't read interface descriptors\n"); + return NULL; + } + + p = 0; + while (p < desc_len) + { + d = desc + p; + + l = *d; + if (usb_trace > 1) + { + char str[256], *s = str; + sprintf (s, "Control desc(%d): ", p); + s += strlen (s); + for (i = 0; i < l; i++) + { + sprintf (s, "%02x ", d[i]); + s += strlen (s); + } + cmn_err (CE_CONT, "%s\n", str); + } + +#define CASE(x) case x:cmn_err(CE_CONT, #x "\n"); break; + + if (d[1] == CS_INTERFACE) + switch (d[2]) + { + case AC_HEADER: + if (usb_trace) + { + cmn_err (CE_CONT, " Audio control interface header\n"); + n = d[7]; + cmn_err (CE_CONT, " %d related streaming interfaces: ", + n); + for (i = 0; i < n; i++) + { + cmn_err (CE_CONT, "%d ", d[8 + i]); + } + cmn_err (CE_CONT, "\n"); + } + break; + + case AC_INPUT_TERMINAL: + name = + get_terminal_id (ossusb_get_int (&d[4], 2), "in", TY_INPUT, + &mixnum); + if ((un = setup_unit (devc, d[3], name, d, l, TY_INPUT)) == NULL) + return NULL; + un->mixnum = mixnum; + un->channels = d[7]; + un->chmask = ossusb_get_int (&d[8], 2); + break; + + case AC_OUTPUT_TERMINAL: + name = + get_terminal_id (ossusb_get_int (&d[4], 2), "out", TY_OUTPUT, + &mixnum); + if ((un = setup_unit (devc, d[3], name, d, l, TY_OUTPUT)) == NULL) + return NULL; + un->mixnum = mixnum; + break; + + case AC_MIXER_UNIT: + if ((un = setup_unit (devc, d[3], "mix", d, l, TY_MIXER)) == NULL) + return NULL; + { + // Check if there are any visible controls + + int mask = 0, nn; + + n = d[4]; // # of input pins + d += 5 + n; + nn = *d; // # of channels + d += 4; // Seek to bmControls + + n = (n * nn + 7) / 8; + + for (i = 0; i < n; i++) + mask |= d[i]; + + un->ctl_avail = mask; + } + break; + + case AC_SELECTOR_UNIT: + if ((un = + setup_unit (devc, d[3], "src", d, l, TY_SELECT)) == NULL) + return NULL; + un->ctl_avail = 1; + break; + + case AC_FEATURE_UNIT: + if ((un = setup_unit (devc, d[3], "fea", d, l, TY_FEAT)) == NULL) + return NULL; + un->ctl_avail = get_feature_mask (d, 2); /* For now */ + break; + + case AC_PROCESSING_UNIT: + parse_processing_unit (devc, d, l); + break; + + case AC_EXTENSION_UNIT: + if ((un = setup_unit (devc, d[3], "ext", d, l, TY_EXT)) == NULL) + return NULL; + un->ctl_avail = 1; + + break; + + } + + p += l; + } + +// Make sure the unit names are unique */ + + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int n = 0; + + if (un->typ != TY_SELECT) + for (i = x + 1; i < devc->nunits; i++) + if (strcmp (devc->units[i].name, un->name) == 0) + n++; + + if (n > 0) + { + char tmpname[16]; + strcpy (tmpname, un->name); + n = 1; + + for (i = x; i < devc->nunits; i++) + if (strcmp (devc->units[i].name, tmpname) == 0) + { + if (n > 1) + sprintf (devc->units[i].name, "%s%d", tmpname, n); + n++; + } + } + +// Make sure the mixer control numbers are unique too + + n = 0; + if (un->mixnum != -1) + for (i = x + 1; i < devc->nunits; i++) + if (devc->units[i].mixnum == un->mixnum) + n++; + + if (n > 0) + for (i = x + 1; i < devc->nunits; i++) + if (devc->units[i].mixnum == un->mixnum) + { + usb_audio_unit_t *uu = &devc->units[i]; + + switch (uu->mixnum) + { + case SOUND_MIXER_PCM: + uu->mixnum = SOUND_MIXER_ALTPCM; + break; + case SOUND_MIXER_LINE: + uu->mixnum = SOUND_MIXER_LINE1; + break; + case SOUND_MIXER_LINE1: + uu->mixnum = SOUND_MIXER_LINE2; + break; + case SOUND_MIXER_LINE2: + uu->mixnum = SOUND_MIXER_LINE3; + break; + case SOUND_MIXER_DIGITAL1: + uu->mixnum = SOUND_MIXER_DIGITAL2; + break; + case SOUND_MIXER_DIGITAL2: + uu->mixnum = SOUND_MIXER_DIGITAL3; + break; + default: + uu->mixnum = -1; + } + } + + } + +// Handle output selector names + + + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int n; + + if (un->typ != TY_OUTPUT) + continue; + + n = un->desc[7]; // Source ID + if (n < 0 || n >= devc->nunits) + continue; + + if (devc->units[n].target == 0) + devc->units[n].target = x; + + if (devc->units[n].typ == TY_SELECT && usb_mixerstyle == 0) + sprintf (devc->units[n].name, "%s.src", un->name); + } + +// Find out the sources + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + + d = un->desc; + l = un->desclen; + + switch (un->typ) + { + case TY_INPUT: + break; + + case TY_OUTPUT: + un->source = d[7]; + break; + + case TY_SELECT: + un->source = d[5]; + n = d[4]; + for (i = 0; i < n; i++) + if (d[i + 5] > 0 && d[i + 5] <= devc->nunits) + if (devc->units[d[i + 5]].target == 0) + devc->units[d[i + 5]].target = x; + break; + + case TY_MIXER: + n = d[4]; + un->control_count = n; + un->source = d[5]; + for (i = 0; i < n; i++) + if (d[i + 5] > 0 && d[i + 5] <= devc->nunits) + if (devc->units[d[i + 5]].target == 0) + devc->units[d[i + 5]].target = x; + + d += n + 5; + un->channels = *d++; + un->chmask = ossusb_get_int (d, 2); + break; + + case TY_FEAT: + un->source = d[4]; + if (d[4] > 0 && d[4] <= devc->nunits) + if (devc->units[d[4]].target == 0) + devc->units[d[4]].target = x; + break; + + //case TY_EXT: + case TY_PROC: + n = d[6]; + un->source = d[7]; + for (i = 0; i < n; i++) + if (d[i + 7] > 0 && d[i + 7] <= devc->nunits) + if (devc->units[d[i + 7]].target == 0) + devc->units[d[i + 7]].target = x; + break; + } + } + +// Trace the channel config + + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x], *uu; + int ref; + + if (un->typ == TY_INPUT || un->typ == TY_MIXER) + continue; + + if (un->typ == TY_PROC && un->subtyp == 1) // Upmix/downmix unit + continue; + + ref = follow_source_links (devc, un); + uu = &devc->units[ref]; + + un->channels = uu->channels; + un->chmask = uu->chmask; + } + +// Handle feature channels + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + + if (un->num == 0 || un->typ != TY_FEAT) + continue; + + d = un->desc; + l = un->desclen; + + un->ctl_avail = get_feature_mask (d, un->channels); + } + +// Final checks + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int j; + + if (un->num == 0) + { + //cmn_err(CE_CONT, "Skipped undefined control %d\n", x); + continue; + } + d = un->desc; + l = un->desclen; + + switch (un->typ) + { + case TY_SELECT: + n = d[4]; + un->control_count = n; + d += 5; + break; + + case TY_MIXER: + n = d[4]; + un->control_count = n; + d += 5; + break; + + case TY_FEAT: + n = d[5]; + d += 6; + for (i = 0; i < n * 8; i++) + name = check_feature (un, d, i); + for (j = 1; j <= un->channels; j++) + { + for (i = 0; i < n * 8; i++) + name = check_feature (un, d + j * n, i); + } + break; + + } + } + +#if 0 +// Debugging + if (usb_trace) + for (x = 1; x < devc->nunits; x++) + { + usb_audio_unit_t *un = &devc->units[x]; + int j; + int ref = 0; + + if (un->num == 0) + { + //cmn_err(CE_CONT, "Skipped undefined control %d\n", x); + continue; + } + d = un->desc; + l = un->desclen; + // ossusb_dump_desc (d, l); + cmn_err (CE_CONT, "%2d: %s ", un->num, un->name); + if (un->mixnum != -1) + cmn_err (CE_CONT, "mix=%d ", un->mixnum); + if (un->source) + cmn_err (CE_CONT, "source=%d ", un->source); + if (un->target) + cmn_err (CE_CONT, "target=%d ", un->target); + cmn_err (CE_CONT, "ch=%d/%x ", un->channels, un->chmask); + + switch (un->typ) + { + case TY_INPUT: + cmn_err (CE_CONT, "Input terminal type: %04x ", + ossusb_get_int (&d[4], 2)); + cmn_err (CE_CONT, "Associated output 0x%02x ", d[6]); + cmn_err (CE_CONT, "#chn %d ", d[7]); + cmn_err (CE_CONT, "chconf %04x ", ossusb_get_int (&d[8], 2)); + if (d[10]) + cmn_err (CE_CONT, "chname# %d ", d[10]); + if (d[11]) + cmn_err (CE_CONT, "terminalname# %d (%s) ", d[11], + udi_usbdev_get_string (usbdev, d[11])); + break; + + case TY_OUTPUT: + cmn_err (CE_CONT, "Output terminal type: %04x ", + ossusb_get_int (&d[4], 2)); + cmn_err (CE_CONT, "Associated input 0x%02x ", d[6]); + cmn_err (CE_CONT, "sourceid %d ", d[7]); + if (d[8]) + cmn_err (CE_CONT, "terminalname# %d ", d[8]); + break; + + case TY_SELECT: + n = d[4]; + d += 5; + cmn_err (CE_CONT, "%d input pins (", n); + for (i = 0; i < n; i++) + { + ref = follow_source_links (devc, &devc->units[*d]); + cmn_err (CE_CONT, "%d/%s ", *d, devc->units[ref].name); + d++; + } + cmn_err (CE_CONT, ") "); + break; + + case TY_MIXER: + n = d[4]; + d += 5; + cmn_err (CE_CONT, "%d inputs (", n); + for (i = 0; i < n; i++) + { + ref = follow_source_links (devc, &devc->units[*d]); + cmn_err (CE_CONT, "%d/%s ", *d, devc->units[ref].name); + d++; + } + cmn_err (CE_CONT, ") "); + break; + + case TY_FEAT: + //ossusb_dump_desc(d, l); + cmn_err (CE_CONT, "Source %d:%s ", d[4], devc->units[d[4]].name); + n = d[5]; + d += 6; + cmn_err (CE_CONT, "main (", n); + for (i = 0; i < n * 8; i++) + if ((name = check_feature (un, d, i)) != NULL) + cmn_err (CE_CONT, "%s ", name); + cmn_err (CE_CONT, ") "); + for (j = 1; j <= un->channels; j++) + { + cmn_err (CE_CONT, "ch %d (", j); + for (i = 0; i < n * 8; i++) + if ((name = check_feature (un, d + j * n, i)) != NULL) + cmn_err (CE_CONT, "%s ", name); + cmn_err (CE_CONT, ") "); + } + break; + + case TY_PROC: + cmn_err (CE_CONT, "subtype %x Sources/%d) (", un->subtyp, n); + n = d[6]; + d += 7; + cmn_err (CE_CONT, "%d ", *d); + d++; + cmn_err (CE_CONT, ") "); + break; + + case TY_EXT: + cmn_err (CE_CONT, "Extension unit %02x%02x ", d[5], d[4]); + break; + + } + + cmn_err (CE_CONT, "\n"); + } +#endif + + if (usb_mixerstyle == 0) + setup_legacy_mixer (devc); + touch_mixer (devc->mixer_dev); + + if (usb_trace) + mixer_dump (devc); + + return devc; +} + +static ossusb_devc * +find_devc (char *devpath, int vendor, int product) +{ + int i; + + for (i = 0; i < ndevs; i++) + { + if (devc_list[i]->vendor == vendor && devc_list[i]->product == product) + if (strcmp (devc_list[i]->devpath, devpath) == 0) + { + UDB (cmn_err (CE_CONT, "Another instance of '%s'\n", devpath)); + return devc_list[i]; + } + } + + return NULL; +} + +static void +ossusb_device_disconnect (void *d) +{ + ossusb_devc *devc = d; + int i; + + if (devc == NULL) + { + cmn_err (CE_WARN, "oss_usb_device_disconnect: devc==NULL\n"); + return; + } + + if (devc->unload_func) + { + devc->unload_func (devc); + return; + } + + devc->disabled = 1; + + for (i = 0; i < devc->num_audio_engines; i++) + { + int dev; + + dev = devc->portc[i].audio_dev; + + if (dev < 0 || dev >= num_audio_engines) + continue; + + audio_engines[dev]->enabled = 0; + + if (devc->mixer_dev >= 0) + mixer_devs[devc->mixer_dev]->enabled = 0; + } + +} + +static void * +ossusb_device_attach (udi_usb_devc * usbdev, oss_device_t * osdev) +{ + ossusb_devc *devc; + char *devpath; + int inum; + int old = 1; + int i; + int class, subclass; + int vendor, product, version; + + devpath = udi_usbdev_get_devpath (usbdev); + inum = udi_usbdev_get_inum (usbdev); + class = udi_usbdev_get_class (usbdev); + subclass = udi_usbdev_get_subclass (usbdev); + vendor = udi_usbdev_get_vendor (usbdev); + product = udi_usbdev_get_product (usbdev); + version = udi_usbdev_get_usb_version (usbdev); + + if ((devc = find_devc (devpath, vendor, product)) == NULL) + { + old = 0; + + if (ndevs >= MAX_DEVC) + { + cmn_err (CE_CONT, "Too many USB audio devices\n"); + return NULL; + } + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_CONT, "Out of memory\n"); + return NULL; + } + memset (devc, 0, sizeof (*devc)); + devc->mixer_dev = -1; + + devc->osdev = osdev; + osdev->devc = devc; + + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + + devc->vendor = vendor; + devc->product = product; + devc->usb_version = version; + devc->dev_name = udi_usbdev_get_name (usbdev); + + strcpy (devc->devpath, udi_usbdev_get_devpath (usbdev)); + + devc_list[ndevs++] = devc; + } + else + { + devc->osdev = osdev; + osdev->devc = devc; + } + + if (devc->dev_name == NULL) + devc->dev_name = "Generic USB device"; + oss_register_device (osdev, devc->dev_name); + + devc->disabled = 0; + + if (old) + { + /* Check if this interface number is already seen */ + old = 0; + for (i = 0; !old && i < devc->num_interfaces; i++) + if (devc->inum[i] == inum) + old = 1; + } + + if (!old) + { + if (devc->num_interfaces >= MAX_IFACE) + { + cmn_err (CE_CONT, "The device has too many interfaces\n"); + return NULL; + } + + devc->usbdev[devc->num_interfaces] = usbdev; + devc->last_usbdev = usbdev; + devc->inum[devc->num_interfaces] = inum; + devc->num_interfaces++; + } + else + { + devc->last_usbdev = usbdev; + } + + switch (class) + { + case USBCLASS_AUDIO: + switch (subclass) + { + case 1: /* Audiocontrol subclass */ + devc->main_osdev = osdev; + if (!usb_quiet) + cmn_err (CE_CONT, "%s audioctl device %s/%d - %s\n", + old ? "Reinsert of an" : "New", + devc->devpath, inum, devc->dev_name); + return ossusb_init_audioctl (devc, usbdev, inum, old); + break; + + case 2: /* Audio streaming subclass */ + if (!usb_quiet) + cmn_err (CE_CONT, "%s audio streaming device %s/%d - %s\n", + old ? "Reinsert of an" : "New", + devc->devpath, inum, devc->dev_name); + devc->osdev->first_mixer = devc->main_osdev->first_mixer; + return ossusb_init_audiostream (devc, usbdev, inum, old); + break; + + case 3: /* MIDI streaming subclass */ + return NULL; + break; + + default: + cmn_err (CE_CONT, + "Unknown USB audio device subclass %x:%d, device=%s\n", + class, subclass, devc->dev_name); + return NULL; + } + break; + +#if 0 + case USBCLASS_HID: + cmn_err (CE_CONT, "HID interface class %x:%d, device=%s\n", + class, subclass, devc->dev_name); + return NULL; + break; +#endif + + default: + cmn_err (CE_CONT, "Unknown USB device class %x:%d, device=%s\n", + class, subclass, devc->dev_name); + } + + return devc; +} + +static udi_usb_driver ossusb_driver = { + ossusb_device_attach, + ossusb_device_disconnect +}; + +int +oss_usb_attach (oss_device_t * osdev) +{ + if (usb_trace < 0) + { + udi_usb_trace = 0; + usb_trace = 0; + usb_quiet = 1; + } + else if (usb_trace > 0) + udi_usb_trace = usb_trace; + + return udi_attach_usbdriver (osdev, known_devices, &ossusb_driver); +} + +int +oss_usb_detach (oss_device_t * osdev) +{ + if (oss_disable_device (osdev) < 0) + return 0; + + udi_unload_usbdriver (osdev); + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/oss_usb/oss_usb.man b/kernel/drv/oss_usb/oss_usb.man new file mode 100644 index 0000000..556e4de --- /dev/null +++ b/kernel/drv/oss_usb/oss_usb.man @@ -0,0 +1,56 @@ +NAME + oss_usb - USB Audio/MIDI/Mixer driver + +DESCRIPTION + The Open Sound System driver for USB Audio and MIDI devices. + + AUDIO + The Audio driver supports: + + o 8-96Khz Playback/Recording + o 8 or 16 or 32 bits + o 2, 4, 6 or 8 channel audio. + o SPDIF digital output and Input + o AC3 passthrough + o Volume control and device input mixer + + MIDI +The oss_usb driver supports all MIDI devices that are compatible with the +official USB MIDI specification. In addition the driver supports few devices +that use their own private protocol (including some Yamaha and Midiman models). + + USB MIXER + The USB Audio mixer is a new type of mixer that doesn't have + the normal volume controls found on AC97 or Legacy SB devices. + The USB audio mixer provides control for selecting the Alternate + device setting - this usually allows the device to be switched + into a Professional audio mode (eg 24bit or 96Khz mode) + + ALTERNATIVE SETTINGS + Some USB audio devices use a feature called as alternative settings for + bandwidth management. Typically such devices have multiple high speed + inputs and outputs that may require more bandwidth than provided by the USB + bus. The alternative settings feature is used to select between multiple + low speed devices or just few high speed devices. + + When the device has multiple alternative settings an "altsetting" selector + will be visible in the control panel for the device (use ossmix(1) or + ossxmix(1) to change it). Alternative setting OFF means that all + audio devices are disabled. The other settings provide different combinations + of high/medium speed devices. You can use the ossinfo(1) command + (ossinfo -a -v3) to find out the devices supported by the currently selected + alternative settings and the capabilities of them. + +KNOWN BUGS + Under Linux it is necessary to run the ossdetect -d and ossdevlinks commands + after an USB device has been hot-plugged. Alternatively you can execute + soundoff and soundon to reload OSS. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_usb.conf Device configuration file + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_usb/ossusb.h b/kernel/drv/oss_usb/ossusb.h new file mode 100644 index 0000000..df28418 --- /dev/null +++ b/kernel/drv/oss_usb/ossusb.h @@ -0,0 +1,246 @@ +/* + * Purpose: Definitions for the USB audio driver files + */ +/* + * + * 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. + * + */ + +#ifndef __OSUSB_H_ +#define __OSUSB_H_ + +#include "udi.h" +#include "midi_core.h" + +#define CS_DEVICE 0x21 +#define CS_CONFIG 0x22 +#define CS_STRING 0x23 +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define AC_HEADER 0x01 +#define AC_INPUT_TERMINAL 0x02 +#define AC_OUTPUT_TERMINAL 0x03 +#define AC_MIXER_UNIT 0x04 +#define AC_SELECTOR_UNIT 0x05 +#define AC_FEATURE_UNIT 0x06 +#define AC_PROCESSING_UNIT 0x07 +#define AC_EXTENSION_UNIT 0x08 + +#define AS_GENERAL 0x01 +#define AS_FORMAT_TYPE 0x02 +#define AS_FORMAT_SPECIFIC 0x03 + +#define SET_CUR 0x01 +#define SET_MEM 0x05 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_MEM 0x85 +#define GET_STAT 0xff + +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 +#define USB_VENDOR_REQUEST 0x40 + +#define USB_TYPE_CLASS 0x20 + +/* + * Unit types + * + * Note that TY_OUTPUT is actually PCM input and TY_INPUT is actually + * PCM output. Unit types are defined as seen as the USB control interface. + * Input terminals listen to the output streaming interfases and output + * terminals feed the input streaming interfaces. Confusing it is. + */ +#define TY_INPUT 0 +#define TY_OUTPUT 1 +#define TY_MIXER 2 +#define TY_SELECT 3 +#define TY_FEAT 4 +#define TY_PROC 5 +#define TY_EXT 6 +// Remember to inclease size of devc->unit_counters[] if adding more unit types + +#define USBCLASS_AUDIO 1 +#define USBCLASS_HID 3 + +#define MAX_IFACE 10 + +typedef struct +{ + int num; + int typ; // TY_* + int subtyp; + char name[16]; + unsigned char *desc; + int desclen; + int mixnum; + int target; + int source; + int ctl_avail; + int control_count; + int channels; + int chmask; +} usb_audio_unit_t; + +#define MAX_UNIT 40 +#define MAX_CONTROLS 100 +#define MAX_PORTC 8 /* Max audio streaming interfaces per device */ +#define MAX_MIDIC 16 /* Max MIDI streaming interfaces per device */ + +typedef struct +{ + usb_audio_unit_t *unit; + int index; + int flags; + int min_ch, max_ch; + int global; + int chmask; + int value; + int min, max, scale; + int exttype; +} usb_control_t; + +typedef struct ossusb_devc ossusb_devc; + +typedef struct +{ + ossusb_devc *devc; + int disabled; + int if_number; + void *endpoint_desc, *orig_endpoint_desc; + udi_endpoint_handle_t *endpoint_handle; + int audio_dev; + int open_mode; + int permitted_modes; + int prepared_modes; + int stopping; + + int speed; + int bytes_per_sample; + int terminal_link; + udi_usb_devc *usbdev; + int num_settings; + int act_setting; + +#define NR_DATAPIPES 2 + udi_usb_request_t *datapipe[NR_DATAPIPES]; + int curr_datapipe; + int fragment_size; /* Bytes per (1ms) USB tick */ + int overflow_samples, overflow_size; + int convert_3byte; + int pipeline_delay; + unsigned char *tmp_buf[2]; + int use_tmpbuf; + oss_dma_handle_t tmpbuf_dma_handle[2]; +} ossusb_portc; + +typedef struct +{ + struct ossusb_devc *devc; + oss_device_t *osdev; + udi_usb_devc *usbdev; + + void *in_endpoint_desc, *out_endpoint_desc; + udi_endpoint_handle_t *in_endpoint_handle, *out_endpoint_handle; + int portnum; + int midi_dev; + int open_mode; + // int output_endpoint; + oss_midi_inputbyte_t midi_input_intr; + oss_midi_outputintr_t midi_output_intr; +} ossusb_midic; + +typedef void *(*special_driver_t) (ossusb_devc * devc); +typedef void (*special_unload_t) (void *devc); + +struct ossusb_devc +{ + special_unload_t unload_func; + oss_device_t *osdev; + oss_device_t *main_osdev; + oss_mutex_t mutex; + int num_interfaces; + udi_usb_devc *usbdev[MAX_IFACE], *last_usbdev; + int inum[MAX_IFACE]; + int vendor, product; + char *dev_name, devpath[32]; + int nports; + int disabled; + int usb_version; // 1 or 2 + + /* + * Units + */ + + usb_audio_unit_t units[MAX_UNIT]; + int nunits; + char unit_counters[7]; // For TY_* identifiers + + /* + * Mixer stuff + */ + int mixer_dev; + void *mixer_usbdev; + int devmask, recmask, stereodevs, recsrc; + + int rec_unit; + int num_recdevs; + int recdevs[32]; + + int *levels; + + usb_control_t controls[MAX_CONTROLS]; + int ncontrols; + +/* Audio stuff */ + int num_audio_engines, num_inputs, num_outputs; + ossusb_portc portc[MAX_PORTC]; + +/* MIDI stuff */ + int num_mididevs; + ossusb_midic midic[MAX_MIDIC]; + + unsigned char *playbuf; + oss_dma_handle_t playbuf_dma_handle; + udi_usb_request_t *output_pipe; + int output_busy; +#define Q_MAX 4096 + unsigned char queue[Q_MAX]; + int q_nbytes; + + unsigned char *recbuf; + oss_dma_handle_t recbuf_dma_handle; + udi_usb_request_t *input_pipe; + udi_endpoint_handle_t *input_endpoint_handle; +}; + +extern int usb_trace, usb_quiet; + +#define UDB(x) {if (usb_trace) x;} + +extern ossusb_devc *ossusb_init_audiostream (ossusb_devc * devc, + udi_usb_devc * usbdev, int inum, + int reinit); +extern ossusb_devc *ossusb_init_midistream (ossusb_devc * devc, + udi_usb_devc * usbdev, int inum, + int reinit); +extern void ossusb_disconnect_midistream (ossusb_devc * devc); +extern void ossusb_dump_desc (unsigned char *desc, int cfg_len); +extern unsigned int ossusb_get_int (unsigned char *p, int nbytes); +extern int ossusb_change_altsetting (int dev, int ctrl, unsigned int cmd, + int value); +extern void ossusb_create_altset_control(int dev, int portc_num, int nalt, char *name); +#endif diff --git a/kernel/drv/oss_usb/ossusb_audio.c b/kernel/drv/oss_usb/ossusb_audio.c new file mode 100644 index 0000000..8135d62 --- /dev/null +++ b/kernel/drv/oss_usb/ossusb_audio.c @@ -0,0 +1,1425 @@ +/* + * Purpose: USB audio streaming interface support + */ +/* + * + * 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_config.h" +#include "ossusb.h" + +#define SAMPLING_FREQ_CONTROL 0x01 +#define PITCH_CONTROL 0x02 + +#define FORMAT_II_UNDEFINED 0x1000 +#define FORMAT_II_MPEG 0x1001 +#define FORMAT_II_AC3 0x1002 + +#define TMPBUF_SIZE 4096 + +#if 0 +static int +read_control_value (ossusb_devc * devc, int endpoint, int ctl, int l) +{ + unsigned char buf[4]; + int len, i, v; + + memset (buf, 0, sizeof (buf)); + + len = udi_usb_rcv_control_msg (devc->mixer_usbdev, 0, // endpoint + GET_CUR, USB_RECIP_ENDPOINT | USB_TYPE_CLASS, // rqtype + ctl << 8, // value + endpoint, // index + buf, // buffer + l, // buflen + OSS_HZ); + if (len < 0) + { + cmn_err (CE_WARN, "Endpoint read error %d\n", len); + return 0; + } + + cmn_err (CE_CONT, "Read len %d (%d): ", len, l); + for (i = 0; i < len; i++) + cmn_err (CE_CONT, "%02x ", buf[i]); + + switch (len) + { + case 3: + v = buf[0] | (buf[1] << 8) | (buf[2] << 16); + break; + + default: + cmn_err (CE_CONT, "oss usbaudio: Bad control read (%d)\n", l); + } + + cmn_err (CE_CONT, "= %d\n", v); + + return v; +} +#endif + +static int +write_control_value (ossusb_devc * devc, udi_endpoint_handle_t * endpoint, + int ctl, int l, unsigned int v) +{ + unsigned char buf[4]; + int len; + + memset (buf, 0, sizeof (buf)); + + switch (l) + { + case 3: + buf[0] = (v) & 0xff; + buf[1] = (v >> 8) & 0xff; + buf[2] = (v >> 16) & 0xff; + break; + + default: + cmn_err (CE_CONT, "oss usbaudio: Bad control size %d\n", l); + return OSS_EIO; + } + + len = udi_usb_snd_control_msg (devc->mixer_usbdev, 0, // endpoint + SET_CUR, USB_RECIP_ENDPOINT | USB_TYPE_CLASS, // rqtype + ctl << 8, // value + udi_endpoint_get_num (endpoint), // index + buf, // buffer + l, // buflen + OSS_HZ); + if (len < 0) + { + cmn_err (CE_WARN, "Endpoint control write error %d\n", len); + return OSS_EIO; + } + + return len; +} + +static void +set_fraglimits (adev_t * adev, ossusb_portc * portc) +{ + int l, m; + + if (portc->bytes_per_sample < 1) + portc->bytes_per_sample = 1; + + l = portc->bytes_per_sample * adev->min_channels * portc->speed / 1000; + l = (l / portc->bytes_per_sample) * portc->bytes_per_sample; + + m = 2; + + while (m < l) + m *= 2; + + adev->min_block = m; + adev->max_block = TMPBUF_SIZE / 2; + portc->fragment_size = l; +} + +static int +usbaudio_set_rate (int dev, int arg) +{ + adev_p adev = audio_engines[dev]; + ossusb_portc *portc = adev->portc; + ossusb_devc *devc = adev->devc; + + int i, x, diff, bestdiff; + + if (devc->disabled) + return OSS_EPIPE; + + if (arg == 0) + return portc->speed; + + if (arg < adev->min_rate) + arg = adev->min_rate; + if (arg > adev->max_rate) + arg = adev->max_rate; + + if (!(adev->caps & PCM_CAP_FREERATE)) + { + /* Search for the nearest supported rate */ + bestdiff = 0x7fffffff; + x = -1; + + for (i = 0; i < adev->nrates; i++) + { + diff = arg - adev->rates[i]; + + if (diff < 0) + diff = -diff; /* ABS */ + if (diff < bestdiff) + { + x = i; + bestdiff = diff; + } + } + + if (x > -1) + arg = adev->rates[x]; + } + + portc->speed = arg; + set_fraglimits (adev, portc); + + return portc->speed; +} + +/*ARGSUSED*/ +static short +usbaudio_set_channels (int dev, short arg) +{ + adev_p adev = audio_engines[dev]; + ossusb_devc *devc = adev->devc; + + if (devc->disabled) + return OSS_EPIPE; + + return adev->min_channels; /* max_channels should be the same too */ +} + +/*ARGSUSED*/ +static unsigned int +usbaudio_set_format (int dev, unsigned int arg) +{ + adev_p adev = audio_engines[dev]; + ossusb_devc *devc = adev->devc; + + if (devc->disabled) + return adev->oformat_mask; + + return adev->oformat_mask; /* iformat_mask should be the same too */ +} + +/*ARGSUSED*/ +static int +usbaudio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + if (devc->disabled) + return OSS_EPIPE; + + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static int +setup_format_I (ossusb_devc * devc, ossusb_portc * portc, adev_p adev, + unsigned char *d, int l) +{ + int min_rate = 0, max_rate = 0; + int i, n; + int frame_size, bits, channels; + unsigned int fmt = 0; + + if (usb_trace > 1) + { + cmn_err (CE_CONT, + "AS_FORMAT_TYPE: FORMAT_TYPE_I, #ch %d, framesize %d, bits %d, freq_type %02x, freq=", + d[4], d[5], d[6], d[7]); + if (d[7] == 0) + cmn_err (CE_CONT, "%d-%d ", ossusb_get_int (&d[8], 3), + ossusb_get_int (&d[11], 3)); + { + for (i = 0; i < d[7]; i++) + cmn_err (CE_CONT, "%d ", ossusb_get_int (&d[8 + i * 3], 3)); + cmn_err (CE_CONT, " "); + } + + switch (d[3]) + { + case 0x00: + cmn_err (CE_CONT, "Undefined "); + break; + case 0x01: + cmn_err (CE_CONT, "PCM "); + break; + case 0x02: + cmn_err (CE_CONT, "PCM8 "); + break; + case 0x03: + cmn_err (CE_CONT, "float "); + break; + case 0x04: + cmn_err (CE_CONT, "A-Law "); + break; + case 0x05: + cmn_err (CE_CONT, "u-Law "); + break; + } + cmn_err (CE_CONT, "\n"); + } + + channels = d[4]; + frame_size = d[5]; + bits = d[6]; + UDB (cmn_err (CE_CONT, "Channels %d, bits %d (%d bytes)\n", channels, bits, + frame_size)); + + adev->min_channels = adev->max_channels = channels; + portc->convert_3byte = 0; + + switch (d[3]) + { + case 0x01: + fmt = AFMT_S16_LE; + break; + case 0x02: + fmt = AFMT_U8; + break; + case 0x03: + fmt = AFMT_FLOAT; + break; + case 0x04: + fmt = AFMT_A_LAW; + break; + case 0x05: + fmt = AFMT_MU_LAW; + break; + } + + if (fmt == AFMT_S16_LE) /* Have to check the frame size too */ + { + switch (frame_size) + { + case 1: + fmt = AFMT_S8; + break; + case 2: + fmt = AFMT_S16_LE; + break; + case 3: + fmt = AFMT_S32_LE; + frame_size = 4; + portc->convert_3byte = 1; + break; + case 4: + fmt = AFMT_S32_LE; + break; + } + } + + portc->bytes_per_sample = frame_size; + adev->oformat_mask = adev->iformat_mask = fmt; + UDB (cmn_err (CE_CONT, "Format mask %08x\n", fmt)); + + adev->caps &= ~PCM_CAP_FREERATE; + n = d[7]; + if (n < 1) /* Free rate selection between min (0) and max (1) */ + { + n = 2; + adev->caps |= PCM_CAP_FREERATE; + } + + min_rate = 0x7fffffff; + max_rate = 0; + + if (n > 20) + { + cmn_err (CE_WARN, "The device supports too many sample rates\n"); + n = 20; + } + + adev->nrates = 0; + + for (i = 0; i < n; i++) + { + int rate = ossusb_get_int (&d[8 + i * 3], 3); + +#if 0 + /* Skip rates that are not multiples of 1000 Hz */ + if (rate % 1000) + continue; +#endif + + if (rate < min_rate) + min_rate = rate; + if (rate > max_rate) + max_rate = rate; + adev->rates[adev->nrates++] = rate; + } + + adev->min_rate = min_rate; + adev->max_rate = max_rate; + UDB (cmn_err (CE_CONT, "Min rate %d, max rate %d\n", min_rate, max_rate)); + + adev->caps &= ~DSP_CH_MASK; + + switch (channels) + { + case 1: + adev->caps |= DSP_CH_MONO; + break; + case 2: + adev->caps |= DSP_CH_STEREO; + break; + default: + adev->caps |= DSP_CH_MULTI; + break; + } + return 0; +} + +/*ARGSUSED*/ +static int +setup_format_II (ossusb_devc * devc, ossusb_portc * portc, adev_p adev, + unsigned char *d, int l) +{ + int min_rate = 0, max_rate = 0; + int i; + + if (usb_trace > 1) + { + cmn_err (CE_CONT, "MaxBitRate %d ", d[4]); + cmn_err (CE_CONT, "SamplesPerFrame %d ", d[5]); + + if (d[8] == 0) + cmn_err (CE_CONT, "Sample Rates %d-%d ", ossusb_get_int (&d[9], 3), + ossusb_get_int (&d[12], 3)); + else + { + int n; + int min_rate = 0x7fffffff; + int max_rate = 0; + + n = d[8]; + + if (n > 20) + { + cmn_err (CE_CONT, "oss usbaudio: Too many sample rates (%d)\n", + n); + n = 20; + } + + adev->nrates = 0; + cmn_err (CE_CONT, "Possible sample rates: "); + for (i = 0; i < d[8]; i++) + { + int rate = ossusb_get_int (&d[9 + i * 3], 3); + +#if 0 + /* Skip rates that are not multiples of 1000 Hz */ + if (rate % 1000) + continue; +#endif + + if (rate < min_rate) + min_rate = rate; + if (rate > max_rate) + max_rate = rate; + cmn_err (CE_CONT, "%d ", rate); + adev->rates[adev->nrates++] = rate; + } + adev->min_rate = min_rate; + adev->max_rate = max_rate; + } + + cmn_err (CE_CONT, "\n"); + } + + adev->caps &= ~PCM_CAP_FREERATE; + if (d[8] == 0) + { + min_rate = ossusb_get_int (&d[9], 3); + max_rate = ossusb_get_int (&d[12], 3); + adev->caps |= PCM_CAP_FREERATE; + } + else + { + min_rate = 1 << 30; + max_rate = 0; + + for (i = 0; i < d[8]; i++) + { + int r = ossusb_get_int (&d[9 + i * 3], 3); + + if (r < min_rate) + min_rate = r; + if (r > max_rate) + max_rate = r; + } + } + + adev->min_channels = adev->max_channels = 2; + adev->oformat_mask = adev->iformat_mask = AFMT_AC3; + adev->min_rate = min_rate; + adev->max_rate = max_rate; + + return 0; +} + +/*ARGSUSED*/ +static int +setup_format_specific (ossusb_devc * devc, ossusb_portc * portc, adev_p adev, + unsigned char *d, int l) +{ + int fmt; + + fmt = ossusb_get_int (&d[3], 2); + + if (usb_trace > 1) + cmn_err (CE_CONT, "Format specific: fmt=%04x\n", fmt); + + switch (fmt) + { + case FORMAT_II_MPEG: + if (usb_trace > 1) + cmn_err (CE_CONT, "MPEG format\n"); + adev->oformat_mask = adev->iformat_mask = AFMT_MPEG; + break; + + case FORMAT_II_AC3: + if (usb_trace > 1) + cmn_err (CE_CONT, "AC3 format\n"); + adev->oformat_mask = adev->iformat_mask = AFMT_AC3; +#if 0 + cmn_err (CE_CONT, "BSID=%08x\n", ossusb_get_int (&d[5], 4)); + cmn_err (CE_CONT, "AC3Features %02x\n", d[9]); +#endif + break; + + default: + cmn_err (CE_CONT, "oss usbaudio: Unsupported FORMAT II tag %04x\n", + fmt); + adev->enabled = 0; + return OSS_ENXIO; + } + return 0; +} + +static int +prepare_altsetting (ossusb_devc * devc, ossusb_portc * portc, int new_setting) +{ + int desc_len; + unsigned char *desc, *d; + int l, p; + int err; + adev_p adev; + + adev = audio_engines[portc->audio_dev]; + adev->enabled = 1; + portc->disabled = 0; + + if (portc->act_setting == new_setting) /* No need to change */ + return 0; + + if (new_setting < portc->num_settings) + desc = udi_usbdev_get_altsetting (portc->usbdev, new_setting, &desc_len); + else + desc = NULL; + + if (desc == NULL || desc_len < 3) + { + cmn_err (CE_CONT, + "Audio device %d not available when altsetting=%d\n", + audio_engines[portc->audio_dev]->real_dev, new_setting); + portc->disabled = 1; + adev->enabled = 0; + portc->act_setting = new_setting; + return OSS_ENXIO; + } + + UDB (cmn_err + (CE_CONT, "Select active setting %d on interface %d (dsp%d)\n", + new_setting, portc->if_number, adev->engine_num)); + portc->act_setting = new_setting; + + p = 0; + while (p < desc_len) + { + int i; + + d = desc + p; + l = *d; + + if (usb_trace > 1) + { + cmn_err (CE_CONT, "Streaming desc: "); + for (i = 0; i < l; i++) + cmn_err (CE_CONT, "%02x ", d[i]); + cmn_err (CE_CONT, "\n"); + + } + + if (d[1] != CS_INTERFACE) + { + UDB (cmn_err (CE_CONT, "Unknown descriptor type %02x\n", d[1]))} + else + switch (d[2]) + { + case AS_GENERAL: + portc->terminal_link = d[3]; + portc->pipeline_delay = d[4]; + + if (usb_trace > 1) + { + cmn_err (CE_CONT, "AS_GENERAL "); + cmn_err (CE_CONT, "Terminal link %d/%s ", d[3], + devc->units[d[3]].name); + cmn_err (CE_CONT, "Delay %d ", d[4]); + cmn_err (CE_CONT, "Format tag %02x%02x ", d[5], d[6]); + cmn_err (CE_CONT, "\n"); + } + break; + + case AS_FORMAT_TYPE: + if (usb_trace > 1) + { + cmn_err (CE_CONT, "AS_FORMAT_TYPE: FORMAT_TYPE_%d: ", d[3]); + } + + switch (d[3]) + { + case 1: /* FORMAT_TYPE_I */ + if ((err = setup_format_I (devc, portc, adev, d, l)) < 0) + return err; + break; + + case 2: /* FORMAT_TYPE_II */ + if ((err = setup_format_II (devc, portc, adev, d, l)) < 0) + return err; + break; + + default: + cmn_err (CE_CONT, + "\noss usbaudio: Unsupported format type %d\n", + d[3]); + adev->enabled = 0; + return OSS_ENXIO; + } + break; + + case AS_FORMAT_SPECIFIC: + if ((err = setup_format_specific (devc, portc, adev, d, l)) < 0) + return err; + break; + + default: + UDB (cmn_err + (CE_CONT, "Unknown descriptor subtype %02x\n", d[2])); + } + + p += l; + } + + desc = udi_usbdev_get_endpoint (portc->usbdev, portc->act_setting, 0, &l); + if (desc == NULL) + { + cmn_err (CE_CONT, "oss usbaudio: Bad endpoint\n"); + return OSS_EIO; + } + + portc->endpoint_desc = desc; + + desc = udi_usbdev_get_endpoint (portc->usbdev, portc->act_setting, 1, &l); +#if 0 + if (desc != NULL) + { + /* TODO: Handle sync endpoints */ + cmn_err (CE_CONT, "Sync Endpoint: "); + ossusb_dump_desc (desc, l); + } +#endif + + return 0; +} + +static void usbaudio_close (int dev, int mode); + +/*ARGSUSED*/ +static int +usbaudio_open (int dev, int mode, int open_flags) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + ossusb_portc *portc = audio_engines[dev]->portc; + oss_native_word flags, phaddr; + int err; + int i; + + if (devc->disabled) + return OSS_EPIPE; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (portc->open_mode != 0) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + portc->open_mode = mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if ((err = prepare_altsetting (devc, portc, portc->act_setting)) < 0) + { + portc->open_mode = 0; + return err; + } + + { + int i; + + for (i = 0; i < 2; i++) + portc->tmp_buf[i] = + CONTIG_MALLOC (devc->osdev, TMPBUF_SIZE, MEMLIMIT_32BITS, &phaddr, portc->tmpbuf_dma_handle[i]); + } + + if ((err = + udi_usbdev_set_interface (portc->usbdev, portc->if_number, + portc->act_setting)) < 0) + { + cmn_err (CE_NOTE, + "oss usbaudio: Failed to set interface mode, error %d - ignored\n", + err); + // portc->open_mode = 0; + //return err; + } + + portc->curr_datapipe = 0; + + if ((portc->endpoint_handle = + udi_open_endpoint (portc->usbdev, portc->endpoint_desc)) == NULL) + { + usbaudio_close (dev, mode); + cmn_err (CE_WARN, "Cannot open audio pipe\n"); + return OSS_ENOMEM; + } + + for (i = 0; i < 2; i++) + { + if ((portc->datapipe[i] = + udi_usb_alloc_request (portc->usbdev, portc->endpoint_handle, 1, + UDI_USBXFER_ISO_WRITE)) == NULL) + { + usbaudio_close (dev, mode); + cmn_err (CE_WARN, "Cannot alloc isoc request\n"); + return OSS_ENOMEM; + } + } + + set_fraglimits (audio_engines[dev], portc); + return 0; +} + +static void usbaudio_reset (int dev); + +/*ARGSUSED*/ +static void +usbaudio_close (int dev, int mode) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + ossusb_portc *portc = audio_engines[dev]->portc; + int i; + + usbaudio_reset (dev); + + for (i = 0; i < 2; i++) + { + if (portc->datapipe[i] != NULL) + { + udi_usb_free_request (portc->datapipe[i]); + portc->datapipe[i] = NULL; + } + + if (portc->tmp_buf[i] != NULL) + { + CONTIG_FREE (devc->osdev, portc->tmp_buf[i], TMPBUF_SIZE, portc->tmpbuf_dma_handle[i]); + portc->tmp_buf[i] = NULL; + } + } + + if (portc->endpoint_handle != NULL) + udi_close_endpoint (portc->endpoint_handle); + + udi_usbdev_set_interface (portc->usbdev, portc->if_number, 0); + portc->open_mode = 0; +} + +/*ARGSUSED*/ +static void +usbaudio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + if (devc->disabled) + return; +} + +/*ARGSUSED*/ +static void +usbaudio_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + if (devc->disabled) + return; +} + +static int feed_output (int dev, ossusb_devc * devc, ossusb_portc * portc); +static void start_input (int dev, ossusb_devc * devc, ossusb_portc * portc); + +static int +copy_input (ossusb_portc * portc, dmap_t * dmap, unsigned char *buf, int len) +{ + int outlen = 0; + int offs; + + offs = (int) (dmap->byte_counter % dmap->bytes_in_use); + + while (len > 0) + { + int l; + l = len; + + if (portc->convert_3byte) + { + int i, n; + int *dmabuf; + + l = (l * 4) / 3; + /* Check for buffer wraparound */ + if (offs + l > dmap->bytes_in_use) + l = dmap->bytes_in_use - offs; + + n = (l / 4); + + if (dmap == NULL || dmap->dmabuf == NULL) + return outlen; + + dmabuf = (int *) (dmap->dmabuf + offs); + + for (i = 0; i < n; i++) + { + int v; + + v = buf[2] | (buf[1] << 8) | (buf[0] << 16); + *dmabuf++ = v; + buf += 3; + } + + outlen += l; + } + else + { + unsigned char *dmabuf; + dmabuf = dmap->dmabuf; + + if (dmap == NULL || dmap->dmabuf == NULL) + return outlen; + + /* Check for buffer wraparound */ + if (offs + l > dmap->bytes_in_use) + l = dmap->bytes_in_use - offs; + + memcpy (dmabuf + offs, buf, l); + outlen += l; + buf += l; + } + + len -= l; + offs = 0; + } + + return outlen; +} + +/*ARGSUSED*/ +static void +play_callback (udi_usb_request_t * request, void *arg) +{ + ossusb_portc *portc = arg; + + feed_output (portc->audio_dev, portc->devc, portc); + oss_audio_outputintr (portc->audio_dev, + AINTR_NO_POINTER_UPDATES | AINTR_LOCALQUEUE); +} + +static void +rec_callback (udi_usb_request_t * request, void *arg) +{ + ossusb_portc *portc = arg; + dmap_t *dmap; + int len; + + if (portc == NULL || (unsigned long) arg < 4096) + { + cmn_err (CE_WARN, "Bad portc\n"); + return; + } + + dmap = audio_engines[portc->audio_dev]->dmap_in; + len = udi_usb_request_actlen (request); + + if (len == 0) + return; /* No data so it looks like we are closing down */ + + if ((len = + copy_input (portc, dmap, udi_usb_request_actdata (request), len)) < 1) + { + cmn_err (CE_WARN, "Saving recorded data failed (%d)\n", len); + return; + } + + oss_audio_inc_byte_counter (dmap, len); + oss_audio_inputintr (portc->audio_dev, AINTR_NO_POINTER_UPDATES); +#ifdef linux + start_input (portc->audio_dev, portc->devc, portc); +#endif +} + +#if 0 +/* + * Testing stuff only + */ +static int +sin_gen (void) +{ + + static int phase = 0, v; + + static short sinebuf[48] = { + 0, 4276, 8480, 12539, 16383, 19947, 23169, 25995, + 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272, + 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, + 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995, + -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272, + -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276 + }; + v = sinebuf[phase] * 256; + phase = (phase + 1) % 48; + + return v; +} +#endif + +/*ARGSUSED*/ +static int +output_convert (ossusb_devc * devc, ossusb_portc * portc, dmap_p dmap, + unsigned char *dmabuf, int pos, int pn, int total_len) +{ + unsigned char *tmpbuf = portc->tmp_buf[pn], *b; + int i, n, len, out_size = 0; + int err; + + while (total_len > 0) + { + int l = total_len; + + /* Check for buffer wraparound */ + if (pos + l > dmap->bytes_in_use) + l = dmap->bytes_in_use - pos; + + total_len -= l; + + b = dmabuf + pos; + + if (portc->convert_3byte) + { + int *buf; + + n = l / sizeof (*buf); + buf = (int *) b; + + len = n * 3; + + for (i = 0; i < n; i++) + { + int val = (*buf++); + + val /= 256; + // val=sin_gen(); + *tmpbuf++ = (val) & 0xff; + *tmpbuf++ = (val >> 8) & 0xff; + *tmpbuf++ = (val >> 16) & 0xff; + } + } + else + { + len = l; + memcpy (tmpbuf, b, l); + tmpbuf += l; + } + + pos = 0; + out_size += len; + } + + if ((err = + udi_usb_submit_request (portc->datapipe[pn], play_callback, portc, + portc->endpoint_handle, UDI_USBXFER_ISO_WRITE, + portc->tmp_buf[pn], out_size)) < 0) + { + //cmn_err(CE_CONT, "oss usbaudio: Write transfer eror %d\n", err); + return err; + } + + return 0; +} + +static int +feed_output (int dev, ossusb_devc * devc, ossusb_portc * portc) +{ + int pn, pos, len; + oss_native_word flags; + adev_p adev = audio_engines[dev]; + dmap_p dmap = adev->dmap_out; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->stopping) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + pn = portc->curr_datapipe; + portc->curr_datapipe = (portc->curr_datapipe + 1) % NR_DATAPIPES; + + pos = (int) (dmap->byte_counter % dmap->bytes_in_use); + len = portc->fragment_size; + + portc->overflow_samples += portc->overflow_size; + if (portc->overflow_samples > 1000) + { + len += dmap->frame_size * (portc->overflow_samples / 1000); + portc->overflow_samples = portc->overflow_samples % 1000; + } + + output_convert (devc, portc, dmap, dmap->dmabuf, pos, pn, len); + oss_audio_inc_byte_counter (dmap, len); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +start_input (int dev, ossusb_devc * devc, ossusb_portc * portc) +{ + int frag, err; + oss_native_word flags; + adev_p adev = audio_engines[dev]; + dmap_p dmap = adev->dmap_in; + + if (portc->stopping) + return; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + frag = 0; + + if ((err = + udi_usb_submit_request (portc->datapipe[0], rec_callback, portc, + portc->endpoint_handle, UDI_USBXFER_ISO_READ, + dmap->dmabuf + frag * portc->fragment_size, + portc->fragment_size)) < 0) + { + cmn_err (CE_WARN, "oss usbaudio: Read transfer error %d\n", err); + cmn_err (CE_CONT, "Endpoint %02x\n", + udi_endpoint_get_num (portc->endpoint_handle)); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +usbaudio_trigger (int dev, int state) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + ossusb_portc *portc = audio_engines[dev]->portc; + + if (devc->disabled) + return; + + if (portc->open_mode & PCM_ENABLE_OUTPUT) + { + if ((portc->prepared_modes & PCM_ENABLE_OUTPUT) + && (state & PCM_ENABLE_OUTPUT)) + { + portc->prepared_modes &= ~PCM_ENABLE_OUTPUT; + portc->curr_datapipe = 0; + portc->stopping = 0; + + feed_output (dev, devc, portc); + feed_output (dev, devc, portc); + } + else if (!(state & PCM_ENABLE_OUTPUT)) + { + portc->stopping = 1; +#if 1 + udi_usb_cancel_request (portc->datapipe[0]); + udi_usb_cancel_request (portc->datapipe[1]); +#endif + portc->curr_datapipe = 0; + } + } + + if (portc->open_mode & PCM_ENABLE_INPUT) + { + if ((portc->prepared_modes & PCM_ENABLE_INPUT) + && (state & PCM_ENABLE_INPUT)) + { + portc->prepared_modes &= ~PCM_ENABLE_INPUT; + portc->stopping = 0; + start_input (dev, devc, portc); + } + else if (!(state & PCM_ENABLE_INPUT)) + { + portc->stopping = 1; +#if 0 + udi_usb_cancel_request (portc->datapipe[0]); + udi_usb_cancel_request (portc->datapipe[1]); +#endif + portc->curr_datapipe = 0; + } + } +} + +static void +usbaudio_reset (int dev) +{ + usbaudio_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +usbaudio_prepare_for_input (int dev, int bsize, int bcount) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + ossusb_portc *portc = audio_engines[dev]->portc; + adev_p adev = audio_engines[dev]; + + if (devc->disabled) + return OSS_EPIPE; + + + if (adev->flags & ADEV_NOINPUT) + return OSS_ENOTSUP; + + portc->stopping = 0; + + if (write_control_value + (devc, portc->endpoint_handle, SAMPLING_FREQ_CONTROL, 3, + portc->speed) < 0) + { + cmn_err (CE_CONT, "Failed to set %d Hz sampling rate\n", portc->speed); + return OSS_EIO; + } + + /* + * Handle fractional samples that don't fit in the 1ms period. + */ + portc->overflow_size = portc->speed % 1000; + portc->overflow_samples = 0; + + portc->prepared_modes |= PCM_ENABLE_INPUT; + return 0; +} + +/*ARGSUSED*/ +static int +usbaudio_prepare_for_output (int dev, int bsize, int bcount) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + ossusb_portc *portc = audio_engines[dev]->portc; + adev_p adev = audio_engines[dev]; + + if (devc->disabled) + return OSS_EPIPE; + + if (adev->flags & ADEV_NOOUTPUT) + return OSS_ENOTSUP; + + portc->stopping = 0; + + if (write_control_value + (devc, portc->endpoint_handle, SAMPLING_FREQ_CONTROL, 3, + portc->speed) < 0) + { + cmn_err (CE_CONT, "Failed to set %d Hz sampling rate\n", portc->speed); + return OSS_EIO; + } + + /* + * Handle fractional samples that don't fit in the 1ms period. + */ + portc->overflow_size = portc->speed % 1000; + portc->overflow_samples = 0; + + portc->prepared_modes |= PCM_ENABLE_OUTPUT; + return 0; +} + +static int +usbaudio_check_input (int dev) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + if (devc->disabled) + { + cmn_err (CE_CONT, + "oss usbaudio: Audio device %d removed from the system.\n", + dev); + return OSS_EPIPE; + } + + cmn_err (CE_CONT, "oss usbaudio: Audio input timed out on device %d.\n", + dev); + return OSS_EIO; +} + +static int +usbaudio_check_output (int dev) +{ + ossusb_devc *devc = audio_engines[dev]->devc; + if (devc->disabled) + { + cmn_err (CE_CONT, + "oss usbaudio: Audio device %d removed from the system.\n", + dev); + return OSS_EPIPE; + } + + cmn_err (CE_CONT, "oss usbaudio: Audio output timed out on device %d.\n", + dev); + return OSS_EIO; +} + +static int +usbaudio_local_qlen (int dev) +{ + ossusb_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + int delay = portc->pipeline_delay + 1; /* Pipeline delay in 1 msec ticks */ + + delay = delay * dmap->data_rate / 1000; /* Bytes/msec */ + + return delay; +} + +static audiodrv_t usbaudio_driver = { + usbaudio_open, + usbaudio_close, + usbaudio_output_block, + usbaudio_start_input, + usbaudio_ioctl, + usbaudio_prepare_for_input, + usbaudio_prepare_for_output, + usbaudio_reset, + usbaudio_local_qlen, + NULL, + NULL, + NULL, + usbaudio_trigger, + usbaudio_set_rate, + usbaudio_set_format, + usbaudio_set_channels, + NULL, + NULL, + usbaudio_check_input, + usbaudio_check_output, + NULL, /* usbaudio_alloc_buffer */ + NULL, /* usbaudio_free_buffer */ + NULL, + NULL, + NULL /* usbaudio_get_buffer_pointer */ +}; + +ossusb_devc * +ossusb_init_audiostream (ossusb_devc * devc, udi_usb_devc * usbdev, int inum, + int reinit) +{ + int nsettings, actsetting = 0, desc_len; + unsigned char *desc, *d; + adev_p adev; + int i, p, l; + int portc_num; + void *endpoint_desc; + + char dev_name[128]; + + int opts = ADEV_AUTOMODE; + + ossusb_portc *portc; + + if (devc->num_audio_engines >= MAX_PORTC) + { + cmn_err (CE_CONT, "usbaudio: Too many audio streaming interfaces\n"); + return devc; + } + + if (usbdev == NULL) + { + cmn_err (CE_CONT, "usbaudio: usbdev==NULL\n"); + return devc; + } + + nsettings = udi_usbdev_get_num_altsettings (usbdev); + desc = udi_usbdev_get_endpoint (usbdev, 1, 0, &l); + if (desc != NULL) + { + /* cmn_err(CE_CONT, "Endpoint: ");ossusb_dump_desc(desc, l); */ + endpoint_desc = desc; + } + else + endpoint_desc = NULL; + + if (reinit) + for (i = 0; i < devc->num_audio_engines; i++) + if (devc->portc[i].orig_endpoint_desc == endpoint_desc) /* Already registered this */ + { + prepare_altsetting (devc, &devc->portc[i], + devc->portc[i].act_setting); + return devc; + } + + portc = &devc->portc[devc->num_audio_engines]; + portc_num = devc->num_audio_engines; + portc->if_number = inum; + portc->endpoint_desc = portc->orig_endpoint_desc = endpoint_desc; + portc->usbdev = usbdev; + portc->act_setting = -1; /* Set to an impossible value */ + devc->num_audio_engines++; + + memset (dev_name, 0, sizeof (dev_name)); + strncpy (dev_name, devc->dev_name, sizeof (dev_name) - 1); + portc->num_settings = nsettings; + +#if 1 + if (usb_trace > 2) + for (i = 0; i < nsettings; i++) + { + desc = udi_usbdev_get_altsetting (usbdev, i, &desc_len); + cmn_err (CE_CONT, "\nDumping altsetting %d (l=%d)\n", i, desc_len); + if (usb_trace) + ossusb_dump_desc (desc, desc_len); + } +#endif + + desc = udi_usbdev_get_altsetting (usbdev, actsetting, &desc_len); + + if (desc == NULL || desc_len < 1) + for (i = 0; i < nsettings && (desc == NULL || desc_len < 1); i++) + { + UDB (cmn_err (CE_CONT, "Trying to read altsetting %d\n", i)); + desc = udi_usbdev_get_altsetting (usbdev, i, &desc_len); + if (desc != NULL) + actsetting = i; + } + + UDB (cmn_err (CE_CONT, "Altsetting %d, len %d\n", actsetting, desc_len)); + + if (desc == NULL) + { + cmn_err (CE_WARN, "Can't read interface descriptors\n"); + return NULL; + } + + if (usb_trace > 2) + ossusb_dump_desc (desc, desc_len); + + p = 0; + while (p < desc_len) + { + d = desc + p; + l = *d; + + if (d[1] != CS_INTERFACE) + { + UDB (cmn_err (CE_CONT, "Unknown descriptor type %02x\n", d[1]))} + else + switch (d[2]) + { + case AS_GENERAL: + portc->terminal_link = d[3]; + break; + } + + p += l; + } + + if (portc->terminal_link > 0 && portc->terminal_link <= devc->nunits) + { + char *s = dev_name + strlen (dev_name); + + sprintf (s, " %s", devc->units[portc->terminal_link].name); + s += strlen (s); + + if (devc->units[portc->terminal_link].typ == TY_OUTPUT) /* USB terminal type */ + { + opts |= ADEV_NOOUTPUT; + } + else + { + opts |= ADEV_NOINPUT; + } + } + + if ((portc->audio_dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + dev_name, + &usbaudio_driver, + sizeof (audiodrv_t), + opts, + AFMT_S16_NE, devc, -1)) < 0) + { + return devc; + } + + portc->devc = devc; + adev = audio_engines[portc->audio_dev]; + adev->portc = portc; + adev->mixer_dev = devc->mixer_dev; + adev->rate_source = devc->portc[0].audio_dev; + adev->max_block = 256; + adev->min_fragments = 4; /* vmix needs this */ + + prepare_altsetting (devc, portc, 1); + + if (portc->num_settings > 2) + { + char name[128]; + + sprintf (name, "%s-altset", devc->units[portc->terminal_link].name); + ossusb_create_altset_control (devc->mixer_dev, portc_num, + portc->num_settings, name); + } + +#if 0 + // TODO: This needs to be checked before vmix is enabled +#ifdef CONFIG_OSS_VMIX + if (devc->units[portc->terminal_link].typ != TY_OUTPUT) + vmix_attach_audiodev(devc->osdev, portc->audio_dev, -1, 0); +#endif +#endif + return devc; +} + +/*ARGSUSED*/ +int +ossusb_change_altsetting (int dev, int ctrl, unsigned int cmd, int value) +{ + ossusb_devc *devc = mixer_devs[dev]->devc; + ossusb_portc *portc; + + if (ctrl < 0 || ctrl >= devc->num_audio_engines) + return OSS_ENXIO; + + portc = &devc->portc[ctrl]; + + if (cmd == SNDCTL_MIX_READ) + return portc->act_setting; + + if (value >= portc->num_settings) + value = portc->num_settings - 1; + + if (portc->act_setting != value) + { + prepare_altsetting (devc, portc, value); + } + return value; +} diff --git a/kernel/drv/oss_usb/ossusb_midi.c b/kernel/drv/oss_usb/ossusb_midi.c new file mode 100644 index 0000000..f843594 --- /dev/null +++ b/kernel/drv/oss_usb/ossusb_midi.c @@ -0,0 +1,442 @@ +/* + * Purpose: USB MIDI streaming interface support + */ +/* + * + * 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_config.h" +#include "ossusb.h" + +#define RECBUF_SIZE 32 +#define PLAYBUF_SIZE 32 + +/* + * MS Class-Specific Interface Descriptor Subtypes + */ +#define MS_HEADER 0x01 +#define MIDI_IN_JACK 0x02 +#define MIDI_OUT_JACK 0x03 +#define ELEMENT 0x04 + +/* Jack types */ +#define JT_EMBEDDED 0x01 +#define JT_EXTERNAL 0x02 + +static int usb_midi_start_input (ossusb_devc * devc, ossusb_midic * midic); + +static void +record_callback (udi_usb_request_t * request, void *arg) +{ + ossusb_midic *midic = arg; + ossusb_devc *devc = midic->devc; + int i, l; + + l = udi_usb_request_actlen (request); + if (l == 0) + goto restart; + + for (i = 0; i < l; i++) + cmn_err (CE_CONT, "%02x ", devc->recbuf[i]); + cmn_err (CE_CONT, "\n"); + +restart: + usb_midi_start_input (devc, midic); +} + +static int +usb_midi_start_input (ossusb_devc * devc, ossusb_midic * midic) +{ + oss_native_word flags; + int err = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if ((err = + udi_usb_submit_request (devc->input_pipe, record_callback, midic, + midic->in_endpoint_handle, + UDI_USBXFER_BULK_READ, devc->recbuf, + RECBUF_SIZE)) < 0) + { + cmn_err (CE_WARN, "usbmidi: udi_usb_submit_request failed, err=%d\n", + err); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return err; +} + +static int usb_midi_start_output (ossusb_devc * devc, ossusb_midic * midic); + + /*ARGSUSED*/ static void +play_callback (udi_usb_request_t * request, void *arg) +{ + ossusb_midic *midic = arg; + ossusb_devc *devc = midic->devc; + + devc->output_busy = 0; + usb_midi_start_output (devc, midic); +} + +static int +usb_midi_start_output (ossusb_devc * devc, ossusb_midic * midic) +{ + oss_native_word flags; + int err = 0, l = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + l = devc->q_nbytes; + if (l > PLAYBUF_SIZE) + l = PLAYBUF_SIZE; + + if (l == 0 || devc->output_busy) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + memcpy (devc->playbuf, devc->queue, l); + + if ((err = + udi_usb_submit_request (devc->output_pipe, play_callback, midic, + midic->out_endpoint_handle, + UDI_USBXFER_BULK_WRITE, devc->playbuf, l)) < 0) + { + cmn_err (CE_WARN, "usbmidi: udi_usb_submit_request() failed, err=%d\n", + err); + } + else + devc->output_busy = 1; + + /* Remove the vbytes from the queue */ + if (l >= devc->q_nbytes) + devc->q_nbytes = 0; + else + { + int n = devc->q_nbytes - l; + memcpy (devc->queue, devc->queue + l, n); + devc->q_nbytes -= l; + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return err; +} + +static void +usb_midi_close (int dev, int mode) +{ + oss_native_word flags; + ossusb_midic *midic; + ossusb_devc *devc; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + midic->open_mode = 0; + midic->midi_input_intr = NULL; + midic->midi_output_intr = NULL; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (mode & OPEN_READ) + { + if (devc->input_pipe != NULL) + udi_usb_cancel_request (devc->input_pipe); + devc->input_pipe = NULL; + + if (devc->recbuf != NULL) + CONTIG_FREE (devc->osdev, devc->recbuf, RECBUF_SIZE, devc->recbuf_dma_handle); + devc->recbuf = NULL; + if (devc->playbuf != NULL) + CONTIG_FREE (devc->osdev, devc->playbuf, PLAYBUF_SIZE, devc->playbuf_dma_handle); + devc->playbuf = NULL; + udi_close_endpoint (midic->in_endpoint_handle); + } + + if (mode & OPEN_WRITE) + { + udi_usb_cancel_request (devc->output_pipe); + udi_close_endpoint (midic->out_endpoint_handle); + } +} + + /*ARGSUSED*/ static int +usb_midi_open (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, oss_midi_outputintr_t outputintr) +{ + oss_native_word flags, phaddr; + ossusb_midic *midic; + ossusb_devc *devc; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if (midic->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + midic->open_mode = mode; + midic->midi_input_intr = inputbyte; + midic->midi_output_intr = outputintr; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (mode & OPEN_WRITE) + { + if ((midic->out_endpoint_handle = + udi_open_endpoint (midic->usbdev, + midic->out_endpoint_desc)) == NULL) + { + usb_midi_close (dev, mode); + cmn_err (CE_WARN, "Cannot open midi output pipe\n"); + return OSS_ENOMEM; + } + + if ((devc->output_pipe = + udi_usb_alloc_request (midic->usbdev, midic->out_endpoint_handle, + 1, UDI_USBXFER_BULK_WRITE)) == NULL) + { + cmn_err (CE_WARN, "usbmidi: Failed to allocate output pipe\n"); + } + + devc->playbuf = + CONTIG_MALLOC (devc->osdev, PLAYBUF_SIZE, MEMLIMIT_32BITS, &phaddr, devc->playbuf_dma_handle); + + devc->output_busy = 0; + devc->q_nbytes = 0; + } + + if (mode & OPEN_READ) + { + int err; + + if ((midic->in_endpoint_handle = + udi_open_endpoint (midic->usbdev, + midic->in_endpoint_desc)) == NULL) + { + usb_midi_close (dev, mode); + cmn_err (CE_WARN, "Cannot open midi input pipe\n"); + return OSS_ENOMEM; + } + if ((devc->input_pipe = + udi_usb_alloc_request (midic->usbdev, midic->in_endpoint_handle, 1, + UDI_USBXFER_BULK_READ)) == NULL) + { + cmn_err (CE_WARN, "usbmidi: Failed to allocate input pipe\n"); + } + devc->recbuf = + CONTIG_MALLOC (devc->osdev, RECBUF_SIZE, MEMLIMIT_32BITS, &phaddr, devc->recbuf_dma_handle); + + if ((err = usb_midi_start_input (devc, midic)) < 0) + { + cmn_err (CE_WARN, "usbmidi: Input error %d\n", err); + usb_midi_close (dev, mode); + return OSS_EIO; + } + } + + return 0; +} + +static int +usb_midi_out (int dev, unsigned char data) +{ + ossusb_midic *midic = midi_devs[dev]->devc; + ossusb_devc *devc; + oss_native_word flags; + unsigned char *buf; + + devc = midic->devc; + + cmn_err (CE_CONT, "Send %02x\n", data); + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if ((devc->q_nbytes + 4) >= Q_MAX) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; + } + + buf = devc->queue + devc->q_nbytes; + + memset (buf, 0, 4); + buf[0] = 0x0f; + buf[1] = data; + + devc->q_nbytes += 4; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + usb_midi_start_output (devc, midic); + return 1; +} + + /*ARGSUSED*/ static int +usb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t usb_midi_driver = { + usb_midi_open, + usb_midi_close, + usb_midi_ioctl, + usb_midi_out, +}; + + /*ARGSUSED*/ + ossusb_devc * +ossusb_init_midistream (ossusb_devc * devc, udi_usb_devc * usbdev, int inum, + int reinit) +{ + int i, n; + int p, l; + char tmp[64]; + unsigned char *in_endpoints[16], *out_endpoints[16]; + void *in_endpoint_desc = NULL, *out_endpoint_desc = NULL; + int num_in_endpoints = 0, num_out_endpoints = 0; + int cin = 0, cout = 0; + ossusb_midic *midic; + unsigned char *desc, *d; + int desc_len; + + for (i = 0; i < 32; i++) + if ((desc = udi_usbdev_get_endpoint (usbdev, 0, i, &desc_len)) != NULL) + { + unsigned char *ep; + + if (desc_len > 100) + desc_len = 100; + + cmn_err (CE_CONT, "Endpoint %d (%d)", i, desc_len); + ossusb_dump_desc (desc, desc_len); + ep = desc; + + if (desc[2] & 0x80) + { + in_endpoints[num_in_endpoints++] = ep; + } + else + { + out_endpoints[num_out_endpoints++] = ep; + } + } + + cmn_err (CE_CONT, "%d input endpoints: ", num_in_endpoints); + for (i = 0; i < num_in_endpoints; i++) + cmn_err (CE_CONT, "%02x ", in_endpoints[i][2]); + cmn_err (CE_CONT, "\n"); + cmn_err (CE_CONT, "%d input endpoints: ", num_out_endpoints); + for (i = 0; i < num_out_endpoints; i++) + cmn_err (CE_CONT, "%02x ", out_endpoints[i][2]); + cmn_err (CE_CONT, "\n"); + + cmn_err (CE_CONT, "USB MIDI stream\n"); + desc = udi_usbdev_get_altsetting (usbdev, 0, &desc_len); + if (desc == NULL || desc_len < 3) + { + cmn_err (CE_WARN, "usbmidi: bad altsetting\n"); + return NULL; + } + // ossusb_dump_desc (desc, desc_len); + p = 0; + while (p < desc_len) + { + d = desc + p; + + l = *d; + //if (usb_trace > 1) + { + cmn_err (CE_CONT, "MIDI streaming desc: "); + for (i = 0; i < l; i++) + cmn_err (CE_CONT, "%02x ", d[i]); + cmn_err (CE_CONT, "\n"); + } + + if (d[1] != CS_INTERFACE) + { + cmn_err (CE_WARN, "usbmidi: Unrecognized descriptor: \n"); + ossusb_dump_desc (d, l); + p += l; + continue; + } + + switch (d[2]) + { + case MS_HEADER: + cmn_err (CE_CONT, "MS_HEADER: "); + cmn_err (CE_CONT, "v%x.%02x ", d[3], d[4]); + break; + + case MIDI_IN_JACK: + cmn_err (CE_CONT, "MIDI_IN_JACK: "); + cmn_err (CE_CONT, "Type %d, ID %02x, iJack %d\n", d[3], d[4], d[5]); + in_endpoint_desc = in_endpoints[cin]; + if (cin < num_in_endpoints - 1) + cin++; + break; + + case MIDI_OUT_JACK: + cmn_err (CE_CONT, "MIDI_OUT_JACK: "); + cmn_err (CE_CONT, "Type %d, ID %02x, iJack %d\n", d[3], d[4], d[5]); + n = d[5]; + cmn_err (CE_CONT, "\t%d inputs: ", n); + for (i = 0; i < n; i++) + cmn_err (CE_CONT, "%02x/%02x ", d[6 + i * 2], d[6 + i * 2 + 1]); + cmn_err (CE_CONT, "\n"); + out_endpoint_desc = out_endpoints[cout]; + if (cout < num_out_endpoints - 1) + cout++; + break; + + case ELEMENT: + cmn_err (CE_CONT, "ELEMENT\n"); + break; + } + + p += l; + } + + +#if 1 + if (reinit) + for (i = 0; i < devc->num_mididevs; i++) + if (devc->midic[i].in_endpoint_desc == in_endpoint_desc) /* Already registered this */ + if (devc->midic[i].out_endpoint_desc == out_endpoint_desc) /* Already registered this */ + { + return devc; + } +#endif + + midic = &devc->midic[devc->num_mididevs]; + + devc->osdev = devc->osdev; + midic->devc = devc; + midic->usbdev = usbdev; + midic->in_endpoint_desc = in_endpoint_desc; + midic->out_endpoint_desc = out_endpoint_desc; + + strcpy (tmp, devc->dev_name); + + midic->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "USBMIDI", tmp, + &usb_midi_driver, sizeof (midi_driver_t), + 0, midic, devc->osdev); + devc->num_mididevs++; + + return devc; +} + + /*ARGSUSED*/ void +ossusb_disconnect_midistream (ossusb_devc * devc) +{ +} diff --git a/kernel/drv/oss_usb/ossusb_midisport.c b/kernel/drv/oss_usb/ossusb_midisport.c new file mode 100644 index 0000000..bbeee14 --- /dev/null +++ b/kernel/drv/oss_usb/ossusb_midisport.c @@ -0,0 +1,957 @@ +/* + * Purpose: Dedicated driver for M-Audio/Midiman MIDISPORT USB MIDI family + */ + +/* + * + * 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_config.h" +#include "midi_core.h" +#include "ossusb.h" +#include "midisport2x2_fw.h" +#include "midisport1x1_fw.h" +#include "oxygen8_fw.h" + +/* + * Audiosport Quattro also use the same packet protocol (no FW load). + * Out EP 2 is the output and in EP 1 is the input (check this). + */ +#define RECBUF_SIZE (10*4) +#define DLBUF_SIZE 63 +#define MAX_PACK 32 +#define PLAYBUF_SIZE (MAX_PACK*4) +#define QUEUE_ENTRIES 17 +#define QUEUE_SIZE (QUEUE_ENTRIES*PLAYBUF_SIZE) +#define MAX_PORTS 9 + +static int instance_num = 0; + +typedef struct midisport_devc midisport_devc; + +typedef unsigned char playbuf_t[PLAYBUF_SIZE]; + +typedef struct +{ + oss_mutex_t mutex; + midisport_devc *devc; + int open_count; + int busy; + int max_out_blocks; /* Num of 4(3) byte blocks allowed in single message */ + + playbuf_t *playbuf; /* QUEUE_SIZE */ + oss_dma_handle_t playbuf_dma_handle; + int playbuf_h, playbuf_t; + + unsigned char *out_ep_desc; + udi_usb_request_t *output_pipe; + udi_endpoint_handle_t *output_endpoint_handle; +} midisport_outqueue_t; + +typedef struct +{ + midisport_devc *devc; + oss_device_t *osdev; + oss_mutex_t mutex; + + int portnum; + int midi_dev; + int open_mode; + oss_midi_inputbyte_t midi_input_intr; + playbuf_t output_buf; + int outbuf_p; + + int outqueue_ix; /* Output queue 0 or 1 */ + oss_midi_outputintr_t outputintr; +} midisport_midic; + +static int alphabethic_numbering = 1; + +struct midisport_devc +{ + special_unload_t unload_func; + int is_dummy; + oss_device_t *osdev; + oss_mutex_t mutex; + ossusb_devc *usb_devc; + udi_usb_devc *usbdev; + + int instance_num; + + unsigned char *in_ep_desc; + + int num_inputs, num_outputs; + int open_inputs; + midisport_midic in_midic[MAX_PORTS]; + midisport_midic out_midic[MAX_PORTS]; + + unsigned char *recbuf; + oss_dma_handle_t recbuf_dma_handle; + udi_usb_request_t *input_pipe; + udi_endpoint_handle_t *input_endpoint_handle; + + int num_queues; + midisport_outqueue_t out_queues[2]; +}; + +static void +load_firmware (midisport_devc * devc, const struct setup_request *setup, + char *name) +{ + int err; + + if (setup == NULL) + { + cmn_err (CE_WARN, "midisport: No firmware available\n"); + return; + } + + while (setup->pData != NULL) + { +#if 0 + cmn_err (CE_CONT, "Load(%x, Rq=%x, Rqt=%x, Val=%x, Ix=%x, data=%x, len=%d\n", devc->usbdev, setup->bRequest, /* Request */ + setup->bmRequestType, /* Rqtype */ + setup->wValue, /* Value */ + setup->wIndex, /* Index */ + setup->pData, /* Data */ + setup->wLength); /* Len */ +#endif + + err = udi_usb_snd_control_msg (devc->usbdev, 0, /* Endpoint */ + setup->bRequest, /* Request */ + setup->bmRequestType, /* Rqtype */ + setup->wValue, /* Value */ + setup->wIndex, /* Index */ + (void *) setup->pData, /* Data */ + setup->wLength, /* Len */ + OSS_HZ); + if (err < 0) + { + cmn_err (CE_WARN, "%s: Firmware download failed (%d)\n", name, err); + return; + } + + setup++; + } +} + +static void +midisport_unload (void *d) +{ + midisport_devc *devc = d; + + if (devc->is_dummy) + { + return; + } + + MUTEX_CLEANUP (devc->mutex); +} + +void * +midisport_init (ossusb_devc * usb_devc) +{ + midisport_devc *devc; + unsigned int devid; + char *name = "Unknown device"; + const struct setup_request *setup = NULL; + + devid = (usb_devc->vendor << 16) | usb_devc->product; + + switch (devid) + { + case 0x07631001: + name = "MIDISPORT 2x2"; + setup = midisport2x2_setupRequest; + break; + case 0x07631014: + name = "Oxygen8"; + setup = oxygen8_setupRequest; + break; + case 0x07631010: + name = "MIDISPORT 1x1"; + setup = midisport1x1_setupRequest; + break; + } + + cmn_err (CE_CONT, "%s firmware load started\n", name); + + if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "midisport: Out of memory\n"); + return NULL; + } + + memset (devc, 0, sizeof (*devc)); + + devc->unload_func = midisport_unload; + devc->is_dummy = 1; + devc->osdev = usb_devc->osdev; + devc->usb_devc = usb_devc; + devc->usbdev = usb_devc->last_usbdev; + + load_firmware (devc, setup, name); + + cmn_err (CE_CONT, "%s firmware load completed\n", name); + return devc; +} + +static int midisport_start_input (midisport_devc * devc); + +static void +record_callback (udi_usb_request_t * request, void *arg) +{ + midisport_devc *devc = arg; + int i, l, p; + unsigned char *data; + data = udi_usb_request_actdata (request); + + l = udi_usb_request_actlen (request); + if (l == 0) + goto restart; + + for (p = 0; p < l - 3; p += 4) + { + unsigned char *buf, cmd; + int nbytes, src; + midisport_midic *midic; + + buf = data + p; + cmd = buf[3]; + nbytes = cmd & 0x0f; + src = (cmd >> 4) & 0x0f; + + if (nbytes == 0) /* End of data */ + break; + + if (nbytes > 3 || src >= devc->num_inputs) + continue; /* No data or error */ + + midic = &devc->in_midic[src]; + + if (!(midic->open_mode & OPEN_READ) || midic->midi_input_intr == NULL) + continue; /* This device is not recording */ + + for (i = 0; i < nbytes; i++) + { + midic->midi_input_intr (midic->midi_dev, buf[i]); + } + } + +restart: + midisport_start_input (devc); +} + +static int +midisport_start_input (midisport_devc * devc) +{ + oss_native_word flags; + int err = 0; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if ((err = + udi_usb_submit_request (devc->input_pipe, record_callback, devc, + devc->input_endpoint_handle, + UDI_USBXFER_INTR_READ, devc->recbuf, + RECBUF_SIZE)) < 0) + { + cmn_err (CE_WARN, "udi_usb_submit_request failed, err=%d\n", err); + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return err; +} + +static void submit_output (midisport_devc * devc, midisport_outqueue_t * q); + + /*ARGSUSED*/ static void +play_callback (udi_usb_request_t * request, void *arg) +{ + midisport_outqueue_t *q = arg; + midisport_devc *devc = q->devc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (q->mutex, flags); + q->busy = 0; + submit_output (devc, q); + MUTEX_EXIT_IRQRESTORE (q->mutex, flags); +} + + /*ARGSUSED*/ static void +submit_output (midisport_devc * devc, midisport_outqueue_t * q) +{ + int err; + int max_bytes; + unsigned char *qbuf; + + if (q->busy) + return; + + if (q->playbuf_h == q->playbuf_t) /* Queue empty */ + return; + + qbuf = q->playbuf[q->playbuf_h]; + max_bytes = q->max_out_blocks * 4; + + q->playbuf_h = (q->playbuf_h + 1) % QUEUE_ENTRIES; + q->busy = 1; + + if ((err = + udi_usb_submit_request (q->output_pipe, play_callback, q, + q->output_endpoint_handle, + UDI_USBXFER_BULK_WRITE, qbuf, max_bytes)) < 0) + { + cmn_err (CE_WARN, "udi_usb_submit_request (play) failed, err=%d\n", + err); + } +} + + /*ARGSUSED*/ static void +midisport_close_input (int dev, int mode) +{ + oss_native_word flags; + midisport_midic *midic; + midisport_devc *devc; + int do_stop = 0; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_inputs--; + if (devc->open_inputs == 0) + do_stop = 1; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (do_stop) + { + udi_usb_free_request (devc->input_pipe); + udi_close_endpoint (devc->input_endpoint_handle); + if (devc->recbuf != NULL) + CONTIG_FREE (midic->osdev, devc->recbuf, RECBUF_SIZE, devc->recbuf_dma_handle); + } + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + midic->open_mode = 0; + midic->midi_input_intr = NULL; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} + + /*ARGSUSED*/ static int +midisport_open_input (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags; + midisport_midic *midic; + midisport_devc *devc; + oss_native_word phaddr; + int do_start = 0; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + if (midic->open_mode) + { + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + return OSS_EBUSY; + } + + midic->open_mode = mode; + midic->midi_input_intr = inputbyte; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + devc->open_inputs++; + if (devc->open_inputs == 1) + do_start = 1; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + if (do_start) + { + int err; + + devc->recbuf = + CONTIG_MALLOC (devc->osdev, RECBUF_SIZE, MEMLIMIT_32BITS, &phaddr, devc->recbuf_dma_handle); + if (devc->recbuf == NULL) + { + cmn_err (CE_CONT, "Failed to allocate the recording buffer\n"); + return OSS_ENOMEM; + } + + if ((devc->input_endpoint_handle = + udi_open_endpoint (devc->usbdev, devc->in_ep_desc)) == NULL) + { + midic->open_mode = 0; + midic->midi_input_intr = NULL; + cmn_err (CE_WARN, "Cannot open audio pipe\n"); + return OSS_ENOMEM; + } + if ((devc->input_pipe = + udi_usb_alloc_request (devc->usbdev, devc->input_endpoint_handle, + 1, UDI_USBXFER_INTR_READ)) == NULL) + { + return OSS_EIO; + } + + if ((err = midisport_start_input (devc)) < 0) + { + cmn_err (CE_WARN, "midisport: Input error %d\n", err); + midisport_close_input (dev, mode); + return OSS_EIO; + } + } + + return 0; +} + +static int +open_output_queue (midisport_devc * devc, int queue_ix) +{ + oss_native_word flags; + midisport_outqueue_t *q; + int open_count; + oss_native_word phaddr; + + if (queue_ix < 0 || queue_ix >= devc->num_queues) + { + cmn_err (CE_WARN, "Bad output queue index %d\n", queue_ix); + return OSS_EIO; + } + + q = &devc->out_queues[queue_ix]; + + MUTEX_ENTER_IRQDISABLE (q->mutex, flags); + open_count = q->open_count++; + + if (open_count == 0) /* First open */ + { + q->playbuf_h = q->playbuf_t = 0; + q->busy = 0; + } + MUTEX_EXIT_IRQRESTORE (q->mutex, flags); + + if (open_count == 0) /* First open */ + { + if ((q->playbuf = + CONTIG_MALLOC (devc->osdev, QUEUE_SIZE, MEMLIMIT_32BITS, + &phaddr, q->playbuf_dma_handle)) == NULL) + { + cmn_err (CE_WARN, "Failed to allocate output buffer (%d bytes)\n", + QUEUE_SIZE); + q->open_count--; + return OSS_ENOMEM; + } + + if ((q->output_endpoint_handle = + udi_open_endpoint (devc->usbdev, q->out_ep_desc)) == NULL) + { + cmn_err (CE_WARN, "Failed to open output endpoint\n"); + q->open_count--; + return OSS_EIO; + } + + if ((q->output_pipe = + udi_usb_alloc_request (devc->usbdev, q->output_endpoint_handle, 1, + UDI_USBXFER_BULK_WRITE)) == NULL) + { + cmn_err (CE_WARN, "Failed to allocate output request\n"); + q->open_count--; + return OSS_EIO; + } + + } + return 0; +} + +static void +close_output_queue (midisport_devc * devc, int queue_ix) +{ + oss_native_word flags; + midisport_outqueue_t *q; + int open_count; + + if (queue_ix < 0 || queue_ix >= devc->num_queues) + { + cmn_err (CE_WARN, "Bad output queue index %d\n", queue_ix); + return; + } + + q = &devc->out_queues[queue_ix]; + + if (q->open_count <= 0) /* Was not opened at all */ + return; + + MUTEX_ENTER_IRQDISABLE (q->mutex, flags); + open_count = q->open_count--; + MUTEX_EXIT_IRQRESTORE (q->mutex, flags); + + if (open_count <= 1) /* Queue not needed any more */ + { + udi_usb_free_request (q->output_pipe); + udi_close_endpoint (q->output_endpoint_handle); + if (q->playbuf != NULL) + CONTIG_FREE (devc->osdev, q->playbuf, QUEUE_SIZE, q->playbuf_dma_handle); + } +} + + /*ARGSUSED*/ static void +midisport_close_output (int dev, int mode) +{ + oss_native_word flags; + midisport_midic *midic; + midisport_devc *devc; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + close_output_queue (devc, midic->outqueue_ix); + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + midic->open_mode = 0; + midic->outputintr = NULL; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} + + /*ARGSUSED*/ static int +midisport_open_output (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags; + midisport_midic *midic; + midisport_devc *devc; + int err; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + if (midic->open_mode) + { + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + return OSS_EBUSY; + } + + midic->open_mode = mode; + midic->midi_input_intr = NULL, midic->outputintr = outputintr; + midic->outbuf_p = 0; + memset (midic->output_buf, 0, sizeof (midic->output_buf)); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + if ((err = open_output_queue (devc, midic->outqueue_ix)) < 0) + { + cmn_err (CE_WARN, "Failed to open the output queue (%d)\n", err); + midisport_close_output (dev, mode); + return err; + } + + return 0; +} + +static int +do_flush (midisport_devc * devc, midisport_midic * midic, + midisport_outqueue_t * q) +{ + int next; + unsigned char *qbuf; + int max_bytes; + + /* + * Move stuff from the intermediate buffer to the EP queue + */ + max_bytes = q->max_out_blocks * 4; + next = (q->playbuf_t + 1) % QUEUE_ENTRIES; + if (next == q->playbuf_h) /* No more space in any of the buffers */ + { + return 0; + } + + qbuf = q->playbuf[q->playbuf_t]; + memcpy (qbuf, midic->output_buf, max_bytes); + memset (midic->output_buf, 0, max_bytes); + midic->outbuf_p = 0; + q->playbuf_t = next; + + submit_output (devc, q); + + return 1; +} + +#if 0 +static void +midisport_flush_output (int dev) +{ + midisport_midic *midic = midi_devs[dev]->devc; + midisport_devc *devc = midic->devc; + midisport_outqueue_t *q; + oss_native_word flags; + oss_native_word qflags; + + q = &devc->out_queues[midic->outqueue_ix]; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + MUTEX_ENTER_IRQDISABLE (q->mutex, qflags); + do_flush (devc, midic, q); + MUTEX_EXIT_IRQRESTORE (q->mutex, qflags); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} +#endif + +static int +midisport_bulk_write (int dev, unsigned char *buf, int len) +{ + midisport_midic *midic = midi_devs[dev]->devc; + midisport_devc *devc = midic->devc; + oss_native_word flags; + oss_native_word qflags; + int i, l = 0, n = 0, p; + //int max_bytes; + midisport_outqueue_t *q; + unsigned char *outbuf; + + if (midic->outqueue_ix < 0 || midic->outqueue_ix >= devc->num_queues) + { + cmn_err (CE_WARN, "Bad output queue index %d\n", midic->outqueue_ix); + return OSS_EIO; + } + + q = &devc->out_queues[midic->outqueue_ix]; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + + //max_bytes = q->max_out_blocks * 4; + + for (i = 0; i < len; i += 3) + { + l = len - i; + if (l > 3) + l = 3; + p = midic->outbuf_p; + + if ((p + 4) >= q->max_out_blocks) + { + int next; + MUTEX_ENTER_IRQDISABLE (q->mutex, qflags); + + next = (q->playbuf_t + 1) % QUEUE_ENTRIES; + if (next == q->playbuf_h) /* No more space in any of the buffers */ + { + MUTEX_EXIT_IRQRESTORE (q->mutex, qflags); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + return n; + } + + if (!do_flush (devc, midic, q)) /* Output FIFO full */ + { + MUTEX_EXIT_IRQRESTORE (q->mutex, qflags); + return n; + } + p = midic->outbuf_p; + MUTEX_EXIT_IRQRESTORE (q->mutex, qflags); + } + + outbuf = midic->output_buf + p; + memcpy (outbuf, buf, l); + outbuf[3] = (midic->portnum << 4) | l; + midic->outbuf_p += 4; + if (midic->outbuf_p >= q->max_out_blocks) + do_flush (devc, midic, q); + n += l; + } + + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + return n; +} + + /*ARGSUSED*/ static int +midisport_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t midisport_midi_input_driver = { + midisport_open_input, + midisport_close_input, + midisport_ioctl +}; + +static midi_driver_t midisport_midi_output_driver = { + midisport_open_output, + midisport_close_output, + midisport_ioctl, + NULL, + midisport_bulk_write, + 8 * 3 /* 8 packets of 3 bytes */ +}; + +static void +create_inputs (midisport_devc * devc, char *name, int ep, int ninputs) +{ + int desc_len; + int i, ix = ep; + char portid = 'A'; + unsigned char *desc; + int flags = MFLAG_INPUT; + + for (i = 0; i < 32; i++) + if ((desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL) + { + if (desc[2] == (ep | 0x80)) + ix = i; + } + + if (!alphabethic_numbering) + portid = '1'; + + if (ninputs > MAX_PORTS) + { + cmn_err (CE_WARN, "Too many input ports %d\n", ninputs); + return; + } + + if ((devc->in_ep_desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, ix, &desc_len)) == NULL) + { + cmn_err (CE_WARN, "Bad endpoint %d\n", ep); + return; + } + + if (!(devc->in_ep_desc[2] & 0x80)) + { + cmn_err (CE_WARN, "Bad endpoint %d - not input\n", ep); + } + + for (i = 0; i < ninputs; i++) + { + midisport_midic *midic = midic = &devc->in_midic[i]; + char tmp[128]; + + midic->devc = devc; + midic->osdev = devc->osdev; + MUTEX_INIT (devc->osdev, midic->mutex, MH_DRV + 1); + midic->portnum = i; + devc->num_inputs++; + + if (i == 8) + { + sprintf (tmp, "%s SMPTE status", name); + flags = MFLAG_MTC; + } + else + sprintf (tmp, "%s input %c", name, portid + i); + + midic->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "MIDISPORT", tmp, + &midisport_midi_input_driver, + sizeof (midi_driver_t), + flags, midic, midic->osdev); + } +} + +static void +create_output (midisport_devc * devc, char *name, int queue_ix) +{ + int n; + midisport_midic *midic = NULL; + char tmp[128]; + char portid = 'A'; + int flags = MFLAG_OUTPUT; + + if (!alphabethic_numbering) + portid = '1'; + + n = devc->num_outputs++; + midic = &devc->out_midic[n]; + midic->devc = devc; + MUTEX_INIT (devc->osdev, midic->mutex, MH_DRV + 1); + midic->osdev = devc->osdev; + midic->portnum = n; + midic->outqueue_ix = queue_ix; + + if (n == 8) + { + sprintf (tmp, "%s SMPTE control", name); + flags = MFLAG_MTC; + } + else + sprintf (tmp, "%s output %c", name, portid + n); + + midic->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "MIDISPORT", tmp, + &midisport_midi_output_driver, + sizeof (midi_driver_t), + flags, midic, midic->osdev); +} + +static void +init_outqueue (midisport_devc * devc, int ix, int ep, int max_blocks) +{ + int desc_len; + midisport_outqueue_t *q; + int i, epix = ep; + + unsigned char *desc; + + for (i = 0; i < 32; i++) + if ((desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL) + { + if (desc[2] == ep) + epix = i; + } + + if (ix < 0 || ix > devc->num_queues) + { + cmn_err (CE_WARN, "Endpoint index outside bounds\n"); + return; + } + + q = &devc->out_queues[ix]; + MUTEX_INIT (devc->osdev, q->mutex, MH_DRV + 2); + q->max_out_blocks = max_blocks; + q->devc = devc; + + if ((q->out_ep_desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, epix, &desc_len)) == NULL) + { + cmn_err (CE_WARN, "Bad endpoint %d\n", ep); + return; + } + + if (q->out_ep_desc[2] & 0x80) + { + cmn_err (CE_WARN, "Bad endpoint %d - not output\n", ep); + } + cmn_err (CE_CONT, "Attaching output endpoint %d=%02x\n", ep, + q->out_ep_desc[2]); +} + +void * +midisport_driver (ossusb_devc * usb_devc) +{ + midisport_devc *devc; + char *name; + unsigned int devid; + int i; + unsigned char *desc; + int desc_len; + + devid = (usb_devc->vendor << 16) | usb_devc->product; + + if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "midisport: Out of memory\n"); + return NULL; + } + + memset (devc, 0, sizeof (*devc)); + + devc->unload_func = midisport_unload; + devc->osdev = usb_devc->osdev; + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + + devc->usb_devc = usb_devc; + devc->usbdev = usb_devc->last_usbdev; + devc->instance_num = instance_num++; + + for (i = 0; i < 32; i++) + if ((desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL) + { + if (desc[2] & 0x80) + { + cmn_err (CE_CONT, "Input endpoint %02x\n", desc[2]); + } + else + { + cmn_err (CE_CONT, "Output endpoint %02x\n", desc[2]); + } + } + + alphabethic_numbering = 1; + + devc->num_queues = 2; + + switch (devid) + { + case 0x07631002: + name = "Midisport 2x2"; + create_inputs (devc, name, 1, 2); + init_outqueue (devc, 0, 2, 8); + init_outqueue (devc, 1, 4, 8); + create_output (devc, name, 0); + create_output (devc, name, 1); + break; + + case 0x07631011: + name = "Midisport 1x1"; + devc->num_queues = 1; + init_outqueue (devc, 0, 2, 8); + create_inputs (devc, name, 1, 1); + create_output (devc, name, 0); + break; + + case 0x07631015: + name = "Oxygen8"; + devc->num_queues = 1; + create_inputs (devc, name, 1, 1); + init_outqueue (devc, 0, 2, 8); + create_output (devc, name, 0); + break; + + case 0x07632001: + name = "Quattro"; + devc->num_queues = 1; + create_inputs (devc, name, 1, 1); + init_outqueue (devc, 0, 2, 8); + create_output (devc, name, 0); + break; + + case 0x07631031: + name = "Midisport 8x8"; + alphabethic_numbering = 0; + create_inputs (devc, name, 2, 9); + init_outqueue (devc, 0, 2, 10); + init_outqueue (devc, 1, 4, 8); + create_output (devc, name, 0); + create_output (devc, name, 1); + create_output (devc, name, 0); + create_output (devc, name, 1); + create_output (devc, name, 0); + create_output (devc, name, 1); + create_output (devc, name, 0); + create_output (devc, name, 1); + create_output (devc, name, 0); /* SMPTE control */ + break; + + case 0x07631021: + name = "Midisport 4x4"; + create_inputs (devc, name, 2, 4); + init_outqueue (devc, 0, 2, 16); + init_outqueue (devc, 1, 4, 16); + create_output (devc, name, 0); + create_output (devc, name, 1); + create_output (devc, name, 0); + create_output (devc, name, 1); + break; + + default: + cmn_err (CE_WARN, "Unrecognized MIDI device %08x\n", devid); + } + + return devc; +} diff --git a/kernel/drv/oss_usb/ossusb_ymhmidi.c b/kernel/drv/oss_usb/ossusb_ymhmidi.c new file mode 100644 index 0000000..89f749b --- /dev/null +++ b/kernel/drv/oss_usb/ossusb_ymhmidi.c @@ -0,0 +1,653 @@ +/* + * Purpose: Dedicated driver for Yamaha USB MIDI devices + */ +/* + * + * 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_config.h" +#include "midi_core.h" +#include "ossusb.h" +#include "midiparser.h" + +typedef struct ymhusb_devc ymhusb_devc; + +#define MAX_INDEVS 1 +#define MAX_OUTDEVS 1 +#define TMPBUF_SIZE 64 +#define TMPBUF_NSLOTS 24 + +typedef unsigned char tmpbuf_slot_t[TMPBUF_SIZE]; +#define OUTBUF_SIZE (TMPBUF_NSLOTS*TMPBUF_SIZE) + +typedef struct +{ + ymhusb_devc *devc; + oss_device_t *osdev; + udi_usb_devc *usbdev; + oss_mutex_t mutex; + + int portnum; + int midi_dev; + int open_mode; + + void *endpoint_desc; + udi_endpoint_handle_t *endpoint_handle; + udi_usb_request_t *datapipe; + + oss_midi_inputbyte_t midi_input_intr; + unsigned char *tmpbuf; + oss_dma_handle_t tmpbuf_dma_handle; + int tmp_len; + midiparser_common_p parser; + + volatile int output_busy; + + /* Output buffer */ + tmpbuf_slot_t *outbuf; + oss_dma_handle_t outbuf_dma_handle; + int buf_t, buf_h; +} ymhusb_midic; + +struct ymhusb_devc +{ + special_unload_t unload_func; + + oss_device_t *osdev; + udi_usb_devc *usbdev; + + oss_mutex_t mutex; + + int n_inputs, n_outputs; + ymhusb_midic indevs[MAX_INDEVS], outdevs[MAX_OUTDEVS]; +}; + +static void +ymhusb_unload (void *d) +{ + ymhusb_devc *devc = (ymhusb_devc *) d; + int i; + + for (i = 0; i < devc->n_inputs; i++) + { + MUTEX_CLEANUP (devc->indevs[i].mutex); + } + for (i = 0; i < devc->n_outputs; i++) + { + MUTEX_CLEANUP (devc->outdevs[i].mutex); + } + MUTEX_CLEANUP (devc->mutex); +} + +static int ymhmidi_start_input (ymhusb_devc * devc, ymhusb_midic * midic); + +void +ymhmidi_record_callback (udi_usb_request_t * request, void *arg) +{ + ymhusb_midic *midic = arg; + ymhusb_devc *devc = midic->devc; + unsigned char *data; + int l; + + l = udi_usb_request_actlen (request); + data = udi_usb_request_actdata (request); + + if (l == 0) + goto restart; + + if (midi_devs[midic->midi_dev]->event_input != NULL) + midi_devs[midic->midi_dev]->event_input (midic->midi_dev, data, l); + +restart: + if (midic->open_mode & OPEN_READ) + ymhmidi_start_input (devc, midic); +} + +static int ymhmidi_submit_output (ymhusb_devc * devc, ymhusb_midic * midic); + + /*ARGSUSED*/ void +ymhmidi_play_callback (udi_usb_request_t * request, void *arg) +{ + ymhusb_midic *midic = arg; + ymhusb_devc *devc = midic->devc; + + midic->output_busy = 0; + ymhmidi_submit_output (devc, midic); +} + + /*ARGSUSED*/ static int +ymhmidi_start_input (ymhusb_devc * devc, ymhusb_midic * midic) +{ + int err; + + if ((err = + udi_usb_submit_request (midic->datapipe, ymhmidi_record_callback, + midic, midic->endpoint_handle, + UDI_USBXFER_BULK_READ, midic->tmpbuf, + TMPBUF_SIZE)) < 0) + { + return err; + } + + return 0; +} + + /*ARGSUSED*/ static int +ymhmidi_submit_output (ymhusb_devc * devc, ymhusb_midic * midic) +{ + int err; + int n = midic->buf_t; + + if (midic->buf_h == midic->buf_t) + return 0; + + if ((err = + udi_usb_submit_request (midic->datapipe, ymhmidi_play_callback, midic, + midic->endpoint_handle, UDI_USBXFER_BULK_WRITE, + midic->outbuf[n], TMPBUF_SIZE)) < 0) + { + cmn_err (CE_WARN, "Submit USB MIDI request failed\n"); + return err; + } + + midic->buf_t = (n + 1) % TMPBUF_NSLOTS;; + midic->output_busy = 1; + + return 0; +} + +static int +ymhmidi_put_output (ymhusb_devc * devc, ymhusb_midic * midic) +{ + int n = midic->buf_h; + + midic->buf_h = (n + 1) % TMPBUF_NSLOTS; + + memcpy (midic->outbuf[n], midic->tmpbuf, TMPBUF_SIZE); + midic->tmp_len = 0; + memset (midic->tmpbuf, 0, TMPBUF_SIZE); + + if (midic->output_busy) + return 0; + + ymhmidi_submit_output (devc, midic); + + return 0; +} + + /*ARGSUSED*/ static void +ymhusb_close_input (int dev, int mode) +{ + oss_native_word flags; + ymhusb_midic *midic; + + midic = midi_devs[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + midic->open_mode = 0; + midic->midi_input_intr = NULL; + udi_usb_free_request (midic->datapipe); + udi_close_endpoint (midic->endpoint_handle); + if (midic->tmpbuf != NULL) + CONTIG_FREE (midic->osdev, midic->tmpbuf, TMPBUF_SIZE, midic->tmpbuf_dma_handle); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} + + /*ARGSUSED*/ static int +ymhusb_open_input (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags, phaddr; + ymhusb_midic *midic; + ymhusb_devc *devc; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + if (midic->open_mode) + { + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + return OSS_EBUSY; + } + + midic->open_mode = mode; + midic->midi_input_intr = inputbyte; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + midic->tmpbuf = + CONTIG_MALLOC (midic->osdev, TMPBUF_SIZE, MEMLIMIT_32BITS, &phaddr, midic->tmpbuf_dma_handle); + memset (midic->tmpbuf, 0, TMPBUF_SIZE); + + if ((midic->endpoint_handle = + udi_open_endpoint (midic->usbdev, midic->endpoint_desc)) == NULL) + { + midic->open_mode = 0; + midic->midi_input_intr = NULL; + cmn_err (CE_WARN, "Cannot open audio pipe\n"); + return OSS_ENOMEM; + } + if ((midic->datapipe = + udi_usb_alloc_request (midic->usbdev, midic->endpoint_handle, 1, + UDI_USBXFER_BULK_READ)) == NULL) + { + return OSS_EIO; + } + + return ymhmidi_start_input (devc, midic); +} + +static void +ymhusb_flush_output (int dev) +{ + oss_native_word flags; + ymhusb_midic *midic; + ymhusb_devc *devc; + int next; + + midic = midi_devs[dev]->devc; + devc = midic->devc; + + if (midic->tmp_len == 0) + return; + next = (midic->buf_t + 1) % TMPBUF_NSLOTS; + if (next == midic->buf_h) /* Buffer full */ + return; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + ymhmidi_put_output (devc, midic); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} + +static int +ymhusb_wait_output (int dev) +{ + ymhusb_midic *midic; + + ymhusb_flush_output (dev); + + midic = midi_devs[dev]->devc; + + if (midic->output_busy) + return 1; + + if (midic->buf_t == midic->buf_h) + return 0; /* Not busy */ + + return 1; +} + + /*ARGSUSED*/ static void +ymhusb_close_output (int dev, int mode) +{ + oss_native_word flags; + ymhusb_midic *midic; + + midic = midi_devs[dev]->devc; + + ymhusb_flush_output (dev); + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + midic->open_mode = 0; + midic->midi_input_intr = NULL; + udi_usb_free_request (midic->datapipe); + udi_close_endpoint (midic->endpoint_handle); + if (midic->outbuf != NULL) + CONTIG_FREE (midic->osdev, midic->outbuf, OUTBUF_SIZE, midic->outbuf_dma_handle); + if (midic->tmpbuf != NULL) + KERNEL_FREE (midic->tmpbuf); + midiparser_unalloc (midic->parser); + midic->parser = NULL; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); +} + +static void +out_event (ymhusb_midic * midic, unsigned char a, unsigned char b, + unsigned char c, unsigned char d) +{ + unsigned char *e; + ymhusb_devc *devc = midic->devc; + + if (midic->tmp_len > TMPBUF_SIZE - 4) + ymhmidi_put_output (devc, midic); + + e = midic->tmpbuf + midic->tmp_len; + *e++ = a; + *e++ = b; + *e++ = c; + *e++ = d; + + midic->tmp_len += 4; + + if (midic->tmp_len >= TMPBUF_SIZE) + ymhmidi_put_output (devc, midic); +} + +void +parser_cb (void *context, int category, unsigned char msg, unsigned char ch, + unsigned char *parms, int len) +{ + ymhusb_midic *midic = context; + + if (category == CAT_VOICE) + { + switch (msg) + { + case MIDI_NOTEON: + out_event (midic, 0x9, msg | ch, parms[0], parms[1]); + break; + + case MIDI_NOTEOFF: + out_event (midic, 0x8, msg | ch, parms[0], parms[1]); + break; + + case MIDI_KEY_PRESSURE: + out_event (midic, 0xa, msg | ch, parms[0], parms[1]); + break; + } + + return; + } + + if (category == CAT_CHN) + { + switch (msg) + { + case MIDI_CTL_CHANGE: + out_event (midic, 0xb, msg | ch, parms[0], parms[1]); + break; + + case MIDI_PGM_CHANGE: + out_event (midic, 0xc, msg | ch, parms[0], 0); + break; + + case MIDI_CHN_PRESSURE: + out_event (midic, 0xd, msg | ch, parms[0], 0); + break; + + case MIDI_PITCH_BEND: + out_event (midic, 0xe, msg | ch, parms[0], parms[1]); + break; + } + return; + } + + if (category == CAT_REALTIME) + { + out_event (midic, 0xf, msg | ch, 0, 0); + return; + } + + if (category == CAT_MTC) + { + out_event (midic, 0x2, 0xf1, parms[0], 0); + return; + } + + if (category == CAT_SYSEX) + { + int l = len, n; + unsigned char *d = parms; + + while (l > 0) + { + n = l; + if (n > 3) + n = 3; + + switch (n) + { + case 3: + out_event (midic, 0x4, d[0], d[1], d[2]); + break; + case 2: + out_event (midic, 0x6, d[0], d[1], 0); + break; + case 1: + out_event (midic, 0x5, d[0], 0, 0); + break; + } + + l -= n; + d += n; + } + return; + } +} + + /*ARGSUSED*/ static int +ymhusb_open_output (int dev, int mode, oss_midi_inputbyte_t inputbyte, + oss_midi_inputbuf_t inputbuf, + oss_midi_outputintr_t outputintr) +{ + oss_native_word flags, phaddr; + ymhusb_midic *midic; + + midic = midi_devs[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + if (midic->open_mode) + { + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + return OSS_EBUSY; + } + + midic->open_mode = mode; + midic->output_busy = 0; + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + midic->tmpbuf = KERNEL_MALLOC (TMPBUF_SIZE); + memset (midic->tmpbuf, 0, TMPBUF_SIZE); + midic->outbuf = + CONTIG_MALLOC (midic->osdev, OUTBUF_SIZE, MEMLIMIT_32BITS, &phaddr, midic->outbuf_dma_handle); + midic->tmp_len = 0; + midic->buf_h = midic->buf_t = 0; /* Empty buffer */ + memset (midic->outbuf, 0, OUTBUF_SIZE); + + if ((midic->parser = midiparser_create (parser_cb, midic)) == NULL) + { + midic->open_mode = 0; + midic->midi_input_intr = NULL; + cmn_err (CE_WARN, "Cannot create MIDI parser\n"); + return OSS_ENOMEM; + } + + if ((midic->endpoint_handle = + udi_open_endpoint (midic->usbdev, midic->endpoint_desc)) == NULL) + { + midic->open_mode = 0; + midic->midi_input_intr = NULL; + cmn_err (CE_WARN, "Cannot open audio pipe\n"); + return OSS_ENOMEM; + } + if ((midic->datapipe = + udi_usb_alloc_request (midic->usbdev, midic->endpoint_handle, 1, + UDI_USBXFER_BULK_WRITE)) == NULL) + { + return OSS_EIO; + } + + return 0; +} + +static int +ymhusb_out (int dev, unsigned char midi_byte) +{ + ymhusb_midic *midic = midi_devs[dev]->devc; + oss_native_word flags; + int next; + + next = (midic->buf_t + 1) % TMPBUF_NSLOTS; + if (next == midic->buf_h) /* Buffer full */ + return 0; /* Try again later */ + + MUTEX_ENTER_IRQDISABLE (midic->mutex, flags); + midiparser_input (midic->parser, midi_byte); + MUTEX_EXIT_IRQRESTORE (midic->mutex, flags); + + return 1; +} + + /*ARGSUSED*/ static int +ymhusb_ioctl (int dev, unsigned cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static midi_driver_t ymhusb_input_driver = { + ymhusb_open_input, + ymhusb_close_input, + ymhusb_ioctl, + ymhusb_out, +}; + +static void +add_input_device (ymhusb_devc * devc, char *name, void *desc, int caps) +{ + int n; + ymhusb_midic *midic; + char tmp[128]; + + if (devc->n_inputs >= MAX_INDEVS) + { + cmn_err (CE_WARN, "Yamaha MIDI: Too many inputs\n"); + return; + } + + n = devc->n_inputs++; + + midic = &devc->indevs[n]; + + midic->devc = devc; + midic->osdev = devc->osdev; + MUTEX_INIT (midic->osdev, midic->mutex, MH_DRV + 1); + midic->endpoint_desc = desc; + midic->portnum = n; + midic->usbdev = devc->usbdev; + + sprintf (tmp, "%s input %d", name, n); + if ((midic->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "YMHMIDI", tmp, + &ymhusb_input_driver, + sizeof (ymhusb_input_driver), + MFLAG_INPUT, midic, midic->osdev)) < 0) + { + cmn_err (CE_CONT, "Failed to install MIDI device\n"); + return; + } + midi_devs[midic->midi_dev]->caps |= caps; +} + +static midi_driver_t ymhusb_output_driver = { + ymhusb_open_output, + ymhusb_close_output, + ymhusb_ioctl, + ymhusb_out, + NULL, + 0, + ymhusb_flush_output, + ymhusb_wait_output +}; + +static void +add_output_device (ymhusb_devc * devc, char *name, void *desc, int caps) +{ + int n; + ymhusb_midic *midic; + char tmp[128]; + + if (devc->n_outputs >= MAX_OUTDEVS) + { + cmn_err (CE_WARN, "Yamaha MIDI: Too many outputs\n"); + return; + } + + n = devc->n_outputs++; + + midic = &devc->outdevs[n]; + + midic->devc = devc; + midic->osdev = devc->osdev; + MUTEX_INIT (midic->osdev, midic->mutex, MH_DRV + 1); + midic->endpoint_desc = desc; + midic->portnum = n; + midic->usbdev = devc->usbdev; + + sprintf (tmp, "%s output %d", name, n); + if ((midic->midi_dev = + oss_install_mididev (OSS_MIDI_DRIVER_VERSION, "YMHMIDI", tmp, + &ymhusb_output_driver, + sizeof (ymhusb_output_driver), + MFLAG_OUTPUT, midic, midic->osdev)) < 0) + { + cmn_err (CE_CONT, "Failed to install MIDI device\n"); + return; + } + + midi_devs[midic->midi_dev]->caps |= caps; +} + +void * +yamaha_usb_midi_driver (ossusb_devc * usb_devc) +{ + ymhusb_devc *devc; + int i; + unsigned char *desc; + int desc_len; + int caps = MIDI_CAP_EXTERNAL; + unsigned int devid; + + char *name = "Yamaha USB MIDI"; + + if (usb_devc->dev_name != NULL) + name = usb_devc->dev_name; + + if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Yamaha MIDI: Out of memory\n"); + return NULL; + } + + memset (devc, 0, sizeof (*devc)); + + devc->unload_func = ymhusb_unload; + devc->osdev = usb_devc->osdev; + devc->usbdev = usb_devc->last_usbdev; + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + devid = (usb_devc->vendor << 16) | usb_devc->product; + + DDB (cmn_err + (CE_CONT, "Attaching Yamaha MIDI device %08x (%s)\n", devid, name)); + + switch (devid) + { + case 0x0499101e: /* PSR-K1 keyboard */ + caps |= MIDI_CAP_PTOP; + break; + } + + for (i = 0; i < 32; i++) + if ((desc = + udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL) + { + if (desc[2] & 0x80) + { + add_input_device (devc, name, desc, caps); + } + else + { + add_output_device (devc, name, desc, caps); + } + } + + return devc; +} diff --git a/kernel/drv/oss_usb/oxygen8_fw.h b/kernel/drv/oss_usb/oxygen8_fw.h new file mode 100755 index 0000000..a5fe5e6 --- /dev/null +++ b/kernel/drv/oss_usb/oxygen8_fw.h @@ -0,0 +1,678 @@ +/* + * Purpose: Firmware download for M-Audio Oxygen8 MIDI keyboard + */ +/* + * + * 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. + * + */ + +const struct setup_request oxygen8_setupRequest[] = { + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x146C, 0x0000, 0x0010, 0x0010, + "\xC2\x00\x90\x7F\xA5\xE0\x54\x18\xFF\x13\x13\x13\x54\x1F\x44\x50"}, + {0x40, 0xA0, 0x147C, 0x0000, 0x0010, 0x0010, + "\xF5\x1C\x13\x92\x01\xD2\xE8\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9"}, + {0x40, 0xA0, 0x148C, 0x0000, 0x0010, 0x0010, + "\xF0\x90\x7F\xAA\xF0\x53\x91\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90"}, + {0x40, 0xA0, 0x149C, 0x0000, 0x0010, 0x0010, + "\x7F\xAF\xE0\x44\x01\xF0\x90\x7F\xAE\xE0\x44\x05\xF0\xD2\xAF\x12"}, + {0x40, 0xA0, 0x14AC, 0x0000, 0x000D, 0x000D, + "\x17\x5F\x30\x00\xFD\x12\x11\x00\xC2\x00\x80\xF6\x22"}, + {0x40, 0xA0, 0x1100, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x24\x5D\x60\x0D\x14\x70\x03\x02\x12\x44\x24\x02"}, + {0x40, 0xA0, 0x1110, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x12\x4A\x90\x7F\xEA\xE0\x75\x08\x00\xF5\x09\xA3\xE0"}, + {0x40, 0xA0, 0x1120, 0x0000, 0x0010, 0x0010, + "\xFE\xE4\x25\x09\xF5\x09\xEE\x35\x08\xF5\x08\x90\x7F\xEE\xE0\x75"}, + {0x40, 0xA0, 0x1130, 0x0000, 0x0010, 0x0010, + "\x0A\x00\xF5\x0B\xA3\xE0\xFE\xE4\x25\x0B\xF5\x0B\xEE\x35\x0A\xF5"}, + {0x40, 0xA0, 0x1140, 0x0000, 0x0010, 0x0010, + "\x0A\x90\x7F\xE8\xE0\x64\xC0\x60\x03\x02\x11\xD4\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x1150, 0x0000, 0x0010, 0x0010, + "\x70\x03\x02\x12\x4A\xC3\xE5\x0B\x94\x40\xE5\x0A\x94\x00\x50\x08"}, + {0x40, 0xA0, 0x1160, 0x0000, 0x0010, 0x0010, + "\x85\x0A\x0C\x85\x0B\x0D\x80\x06\x75\x0C\x00\x75\x0D\x40\x90\x7F"}, + {0x40, 0xA0, 0x1170, 0x0000, 0x0010, 0x0010, + "\xE9\xE0\xB4\xA3\x25\xAE\x0C\xAF\x0D\xAA\x08\xA9\x09\x7B\x01\xC0"}, + {0x40, 0xA0, 0x1180, 0x0000, 0x0010, 0x0010, + "\x03\xC0\x02\xC0\x01\x7A\x7F\x79\x00\x78\x00\x7C\x7F\xAD\x03\xD0"}, + {0x40, 0xA0, 0x1190, 0x0000, 0x0010, 0x0010, + "\x01\xD0\x02\xD0\x03\x12\x13\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D"}, + {0x40, 0xA0, 0x11A0, 0x0000, 0x0010, 0x0010, + "\x7A\x7F\x79\x00\x7B\x00\x12\x15\xA4\x90\x7F\xB5\xE5\x0D\xF0\xE5"}, + {0x40, 0xA0, 0x11B0, 0x0000, 0x0010, 0x0010, + "\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5\x0B\x95\x0D"}, + {0x40, 0xA0, 0x11C0, 0x0000, 0x0010, 0x0010, + "\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x20\xE2\x03\x02"}, + {0x40, 0xA0, 0x11D0, 0x0000, 0x0010, 0x0010, + "\x11\x4C\x80\xF4\x90\x7F\xE8\xE0\x64\x40\x70\x6E\xE5\x0B\x45\x0A"}, + {0x40, 0xA0, 0x11E0, 0x0000, 0x0010, 0x0010, + "\x60\x68\xE4\x90\x7F\xC5\xF0\x90\x7F\xB4\xE0\x20\xE3\xF9\x90\x7F"}, + {0x40, 0xA0, 0x11F0, 0x0000, 0x0010, 0x0010, + "\xC5\xE0\x75\x0C\x00\xF5\x0D\x90\x7F\xE9\xE0\xB4\xA3\x15\xAE\x0C"}, + {0x40, 0xA0, 0x1200, 0x0000, 0x0010, 0x0010, + "\xAF\x0D\xA8\x09\xAC\x08\x7D\x01\x7B\x01\x7A\x7E\x79\xC0\x12\x13"}, + {0x40, 0xA0, 0x1210, 0x0000, 0x0010, 0x0010, + "\x56\x80\x0F\xAF\x09\xAE\x08\xAD\x0D\x7A\x7F\x79\x00\x7B\x00\x12"}, + {0x40, 0xA0, 0x1220, 0x0000, 0x0010, 0x0010, + "\x14\xB9\xE5\x0D\x25\x09\xF5\x09\xE5\x0C\x35\x08\xF5\x08\xC3\xE5"}, + {0x40, 0xA0, 0x1230, 0x0000, 0x0010, 0x0010, + "\x0B\x95\x0D\xF5\x0B\xE5\x0A\x95\x0C\xF5\x0A\x90\x7F\xB4\xE0\x44"}, + {0x40, 0xA0, 0x1240, 0x0000, 0x000A, 0x000A, + "\x02\xF0\x80\x98\x90\x7F\xEA\xE0\xF5\x1C"}, + {0x40, 0xA0, 0x124A, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x1558, 0x0000, 0x0006, 0x0006, "\xAB\x07\xAA\x06\xAC\x05"}, + {0x40, 0xA0, 0x155E, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x11\xEA\xFF\xAE\x05\x0D\xEE\x24\x00\xF5\x82\xE4"}, + {0x40, 0xA0, 0x156E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEF\xF0\xEB\xAE\x05\x0D\x74\x00\x2E\xF5\x82\xE4"}, + {0x40, 0xA0, 0x157E, 0x0000, 0x0010, 0x0010, + "\x34\xE0\xF5\x83\xEB\xF0\xAF\x05\x0D\x74\x00\x2F\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x158E, 0x0000, 0x0010, 0x0010, + "\xE0\xF5\x83\xEC\xF0\xAF\x1C\x7A\xE0\x7B\x00\x12\x17\x20\x7F\x0A"}, + {0x40, 0xA0, 0x159E, 0x0000, 0x0005, 0x0005, "\x7E\x00\x12\x17\x3C"}, + {0x40, 0xA0, 0x15A3, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x14B9, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x14C3, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x13\xE5\x13\xC3\x95\x10\x50\x20\x05\x0F\xE5\x0F\xAE\x0E"}, + {0x40, 0xA0, 0x14D3, 0x0000, 0x0010, 0x0010, + "\x70\x02\x05\x0E\x14\xFF\xE5\x12\x25\x13\xF5\x82\xE4\x35\x11\xF5"}, + {0x40, 0xA0, 0x14E3, 0x0000, 0x000A, 0x000A, + "\x83\xE0\xFD\x12\x15\x58\x05\x13\x80\xD9"}, + {0x40, 0xA0, 0x14ED, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x15A4, 0x0000, 0x000A, 0x000A, + "\x8E\x0E\x8F\x0F\x8D\x10\x8A\x11\x8B\x12"}, + {0x40, 0xA0, 0x15AE, 0x0000, 0x0010, 0x0010, + "\xE4\xFD\x30\x01\x12\xE5\x0E\xFF\xAE\x05\x0D\xEE\x24\x03\xF5\x82"}, + {0x40, 0xA0, 0x15BE, 0x0000, 0x0010, 0x0010, + "\xE4\x34\xE0\xF5\x83\xEF\xF0\xE5\x0F\xAE\x05\x0D\x74\x03\x2E\xF5"}, + {0x40, 0xA0, 0x15CE, 0x0000, 0x0010, 0x0010, + "\x82\xE4\x34\xE0\xF5\x83\xE5\x0F\xF0\xAF\x1C\x7A\xE0\x7B\x03\x12"}, + {0x40, 0xA0, 0x15DE, 0x0000, 0x000D, 0x000D, + "\x17\x20\xAF\x1C\xAD\x10\xAB\x12\xAA\x11\x12\x17\x04"}, + {0x40, 0xA0, 0x15EB, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x166E, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x167E, 0x0000, 0x0010, 0x0010, + "\x00\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x168E, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1644, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x1654, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x1664, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1695, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16A5, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x02\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16B5, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x16BA, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16CA, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16DA, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x14FF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x16DF, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x16EF, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x16FF, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1767, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1768, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1769, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176A, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176B, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176C, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176D, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176E, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x176F, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1770, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1771, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1772, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1773, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1774, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1775, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x1776, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x15\x00"}, + {0x40, 0xA0, 0x1500, 0x0000, 0x0010, 0x0010, + "\x02\x16\x6E\x00\x02\x16\x95\x00\x02\x16\x44\x00\x02\x16\xDF\x00"}, + {0x40, 0xA0, 0x1510, 0x0000, 0x0010, 0x0010, + "\x02\x16\xBA\x00\x02\x14\xFF\x00\x02\x17\x67\x00\x02\x17\x68\x00"}, + {0x40, 0xA0, 0x1520, 0x0000, 0x0010, 0x0010, + "\x02\x17\x69\x00\x02\x17\x6A\x00\x02\x17\x6B\x00\x02\x17\x6C\x00"}, + {0x40, 0xA0, 0x1530, 0x0000, 0x0010, 0x0010, + "\x02\x17\x6D\x00\x02\x17\x6E\x00\x02\x17\x6F\x00\x02\x17\x70\x00"}, + {0x40, 0xA0, 0x1540, 0x0000, 0x0010, 0x0010, + "\x02\x17\x71\x00\x02\x17\x72\x00\x02\x17\x73\x00\x02\x17\x74\x00"}, + {0x40, 0xA0, 0x1550, 0x0000, 0x0008, 0x0008, + "\x02\x17\x75\x00\x02\x17\x76\x00"}, + {0x40, 0xA0, 0x173C, 0x0000, 0x0010, 0x0010, + "\x8E\x14\x8F\x15\xE5\x15\x15\x15\xAE\x14\x70\x02\x15\x14\x4E\x60"}, + {0x40, 0xA0, 0x174C, 0x0000, 0x0007, 0x0007, + "\x05\x12\x14\xEE\x80\xEE\x22"}, + {0x40, 0xA0, 0x175F, 0x0000, 0x0008, 0x0008, + "\xE4\xF5\x1B\xD2\xE9\xD2\xAF\x22"}, + {0x40, 0xA0, 0x1619, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x23\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x1629, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A\x18\x89"}, + {0x40, 0xA0, 0x1639, 0x0000, 0x000B, 0x000B, + "\x19\xE4\xF5\x1A\x75\x1B\x01\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x15EC, 0x0000, 0x0010, 0x0010, + "\xA9\x07\xE5\x1B\x70\x25\x90\x7F\xA5\xE0\x44\x80\xF0\xE9\x25\xE0"}, + {0x40, 0xA0, 0x15FC, 0x0000, 0x0010, 0x0010, + "\x44\x01\x90\x7F\xA6\xF0\x8D\x16\xAF\x03\xA9\x07\x75\x17\x01\x8A"}, + {0x40, 0xA0, 0x160C, 0x0000, 0x000D, 0x000D, + "\x18\x89\x19\xE4\xF5\x1A\x75\x1B\x03\xD3\x22\xC3\x22"}, + {0x40, 0xA0, 0x004B, 0x0000, 0x0003, 0x0003, "\x02\x13\x7F"}, + {0x40, 0xA0, 0x137F, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x138F, 0x0000, 0x0010, 0x0010, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x01\xC0\x02\xC0\x03\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x139F, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xA5\xE0\x30\xE2\x06\x75\x1B\x06\x02\x14\x4E\x90\x7F\xA5"}, + {0x40, 0xA0, 0x13AF, 0x0000, 0x0010, 0x0010, + "\xE0\x20\xE1\x0C\xE5\x1B\x64\x02\x60\x06\x75\x1B\x07\x02\x14\x4E"}, + {0x40, 0xA0, 0x13BF, 0x0000, 0x0010, 0x0010, + "\xAF\x1B\xEF\x24\xFE\x60\x48\x14\x60\x2C\x24\xFE\x60\x77\x24\x04"}, + {0x40, 0xA0, 0x13CF, 0x0000, 0x0010, 0x0010, + "\x60\x03\x02\x14\x4E\xAB\x17\xAA\x18\xA9\x19\xAF\x1A\x05\x1A\x8F"}, + {0x40, 0xA0, 0x13DF, 0x0000, 0x0010, 0x0010, + "\x82\x75\x83\x00\x12\x12\x4B\x90\x7F\xA6\xF0\xE5\x1A\x65\x16\x70"}, + {0x40, 0xA0, 0x13EF, 0x0000, 0x0010, 0x0010, + "\x5E\x75\x1B\x05\x80\x59\x90\x7F\xA6\xE0\xAB\x17\xAA\x18\xA9\x19"}, + {0x40, 0xA0, 0x13FF, 0x0000, 0x0010, 0x0010, + "\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12\x78\x75\x1B\x02\x80\x40\xE5"}, + {0x40, 0xA0, 0x140F, 0x0000, 0x0010, 0x0010, + "\x16\x24\xFE\xB5\x1A\x07\x90\x7F\xA5\xE0\x44\x20\xF0\xE5\x16\x14"}, + {0x40, 0xA0, 0x141F, 0x0000, 0x0010, 0x0010, + "\xB5\x1A\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x90\x7F\xA6"}, + {0x40, 0xA0, 0x142F, 0x0000, 0x0010, 0x0010, + "\xE0\xAB\x17\xAA\x18\xA9\x19\xAE\x1A\x8E\x82\x75\x83\x00\x12\x12"}, + {0x40, 0xA0, 0x143F, 0x0000, 0x0010, 0x0010, + "\x78\x05\x1A\x80\x0A\x90\x7F\xA5\xE0\x44\x40\xF0\x75\x1B\x00\x53"}, + {0x40, 0xA0, 0x144F, 0x0000, 0x0010, 0x0010, + "\x91\xDF\xD0\x07\xD0\x06\xD0\x03\xD0\x02\xD0\x01\xD0\x00\xD0\xD0"}, + {0x40, 0xA0, 0x145F, 0x0000, 0x000D, 0x000D, + "\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x1704, 0x0000, 0x0010, 0x0010, + "\x12\x15\xEC\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1714, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x1720, 0x0000, 0x0010, 0x0010, + "\x12\x16\x19\xE5\x1B\x24\xFA\x60\x0E\x14\x60\x06\x24\x07\x70\xF3"}, + {0x40, 0xA0, 0x1730, 0x0000, 0x000C, 0x000C, + "\xD3\x22\xE4\xF5\x1B\xD3\x22\xE4\xF5\x1B\xD3\x22"}, + {0x40, 0xA0, 0x14EE, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x14FE, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x17\x53"}, + {0x40, 0xA0, 0x1753, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\x20\x02\x14\x6C"}, + {0x40, 0xA0, 0x124B, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x125B, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x126B, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x1278, 0x0000, 0x0010, 0x0010, + "\xF8\xBB\x01\x0D\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE8\xF0"}, + {0x40, 0xA0, 0x1288, 0x0000, 0x0010, 0x0010, + "\x22\x50\x06\xE9\x25\x82\xC8\xF6\x22\xBB\xFE\x05\xE9\x25\x82\xC8"}, + {0x40, 0xA0, 0x1298, 0x0000, 0x0002, 0x0002, "\xF2\x22"}, + {0x40, 0xA0, 0x129A, 0x0000, 0x0010, 0x0010, + "\xE7\x09\xF6\x08\xDF\xFA\x80\x46\xE7\x09\xF2\x08\xDF\xFA\x80\x3E"}, + {0x40, 0xA0, 0x12AA, 0x0000, 0x0010, 0x0010, + "\x88\x82\x8C\x83\xE7\x09\xF0\xA3\xDF\xFA\x80\x32\xE3\x09\xF6\x08"}, + {0x40, 0xA0, 0x12BA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x6E\xE3\x09\xF2\x08\xDF\xFA\x80\x66\x88\x82\x8C\x83"}, + {0x40, 0xA0, 0x12CA, 0x0000, 0x0010, 0x0010, + "\xE3\x09\xF0\xA3\xDF\xFA\x80\x5A\x89\x82\x8A\x83\xE0\xA3\xF6\x08"}, + {0x40, 0xA0, 0x12DA, 0x0000, 0x0010, 0x0010, + "\xDF\xFA\x80\x4E\x89\x82\x8A\x83\xE0\xA3\xF2\x08\xDF\xFA\x80\x42"}, + {0x40, 0xA0, 0x12EA, 0x0000, 0x0010, 0x0010, + "\x80\xD2\x80\xFA\x80\xC6\x80\xD4\x80\x55\x80\xF2\x80\x29\x80\x10"}, + {0x40, 0xA0, 0x12FA, 0x0000, 0x0010, 0x0010, + "\x80\xA6\x80\xEA\x80\x9A\x80\xA8\x80\xDA\x80\xE2\x80\xCA\x80\x29"}, + {0x40, 0xA0, 0x130A, 0x0000, 0x0010, 0x0010, + "\x88\x84\x8C\x85\x89\x82\x8A\x83\xE4\x93\xA3\x05\x86\xF0\xA3\x05"}, + {0x40, 0xA0, 0x131A, 0x0000, 0x0010, 0x0010, + "\x86\xDF\xF5\xDE\xF3\x80\x0B\x89\x82\x8A\x83\xE4\x93\xA3\xF6\x08"}, + {0x40, 0xA0, 0x132A, 0x0000, 0x0010, 0x0010, + "\xDF\xF9\xEC\xFA\xA9\xF0\xED\xFB\x22\x88\x84\x8C\x85\x89\x82\x8A"}, + {0x40, 0xA0, 0x133A, 0x0000, 0x0010, 0x0010, + "\x83\xE0\xA3\x05\x86\xF0\xA3\x05\x86\xDF\xF6\xDE\xF4\x80\xE3\x89"}, + {0x40, 0xA0, 0x134A, 0x0000, 0x0010, 0x0010, + "\x82\x8A\x83\xE4\x93\xA3\xF2\x08\xDF\xF9\x80\xD6\x88\xF0\xED\x24"}, + {0x40, 0xA0, 0x135A, 0x0000, 0x0010, 0x0010, + "\x02\xB4\x04\x00\x50\xCC\xF5\x82\xEB\x24\x02\xB4\x04\x00\x50\xC2"}, + {0x40, 0xA0, 0x136A, 0x0000, 0x0010, 0x0010, + "\x23\x23\x45\x82\xF5\x82\xEF\x4E\x60\xB8\xEF\x60\x01\x0E\xE5\x82"}, + {0x40, 0xA0, 0x137A, 0x0000, 0x0005, 0x0005, "\x23\x90\x12\xEA\x73"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x0100, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0110, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0120, 0x0000, 0x0010, 0x0010, + "\x4D\x69\x64\x69\x6D\x61\x6E\x20\x55\x53\x42\x20\x4D\x69\x64\x69"}, + {0x40, 0xA0, 0x0130, 0x0000, 0x0010, 0x0010, + "\x53\x70\x6F\x72\x74\x20\x31\x78\x31\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0140, 0x0000, 0x0010, 0x0010, + "\x46\x69\x72\x6D\x77\x61\x72\x65\x20\x52\x65\x6C\x65\x61\x73\x65"}, + {0x40, 0xA0, 0x0150, 0x0000, 0x0010, 0x0010, + "\x20\x31\x2E\x32\x31\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0160, 0x0000, 0x0010, 0x0010, + "\x28\x63\x29\x20\x32\x30\x30\x30\x2D\x32\x30\x30\x31\x2C\x20\x4D"}, + {0x40, 0xA0, 0x0170, 0x0000, 0x0010, 0x0010, + "\x69\x64\x69\x6D\x61\x6E\x20\x49\x6E\x63\x2E\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x0180, 0x0000, 0x0010, 0x0010, + "\x41\x6C\x6C\x20\x72\x69\x67\x68\x74\x73\x20\x72\x65\x73\x65\x72"}, + {0x40, 0xA0, 0x0190, 0x0000, 0x0010, 0x0010, + "\x76\x65\x64\x2E\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01A0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x01B0, 0x0000, 0x0010, 0x0010, + "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"}, + {0x40, 0xA0, 0x08B2, 0x0000, 0x0003, 0x0003, "\x01\x1C\x00"}, + {0x40, 0xA0, 0x040D, 0x0000, 0x0010, 0x0010, + "\xC2\x01\xC2\x00\xC2\x04\xC2\x03\x12\x09\xE1\xD2\xE8\x43\xD8\x20"}, + {0x40, 0xA0, 0x041D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xAB\x74\xFF\xF0\x90\x7F\xA9\xF0\x90\x7F\xAA\xF0\x53\x91"}, + {0x40, 0xA0, 0x042D, 0x0000, 0x0010, 0x0010, + "\xEF\x90\x7F\x95\xE0\x44\xC0\xF0\x90\x7F\xAF\xE0\x44\x01\xF0\x90"}, + {0x40, 0xA0, 0x043D, 0x0000, 0x0010, 0x0010, + "\x7F\xAE\xE0\x44\x1D\xF0\x90\x7F\x92\xE0\x44\x02\xF0\x90\x7F\x95"}, + {0x40, 0xA0, 0x044D, 0x0000, 0x0010, 0x0010, + "\xE0\x44\x01\xF0\x90\x7F\x9E\xE0\x54\xFE\xF0\x90\x7F\x95\xE0\x44"}, + {0x40, 0xA0, 0x045D, 0x0000, 0x0010, 0x0010, + "\x02\xF0\x90\x7F\x9E\xE0\x44\x02\xF0\x90\x7F\x95\xE0\x54\x83\xF0"}, + {0x40, 0xA0, 0x046D, 0x0000, 0x0010, 0x0010, + "\x90\x7F\x9E\xE0\x44\x7C\xF0\x90\x7F\x94\xE0\x54\xFE\xF0\x90\x7F"}, + {0x40, 0xA0, 0x047D, 0x0000, 0x0010, 0x0010, + "\x9D\xE0\x44\x01\xF0\x90\x7F\x9A\xE0\x44\x01\x90\x7F\x97\xF0\x43"}, + {0x40, 0xA0, 0x048D, 0x0000, 0x0010, 0x0010, + "\x21\x20\x43\x21\x40\x43\x21\x10\x53\x89\xF0\xE4\xF5\x8C\xF5\x8A"}, + {0x40, 0xA0, 0x049D, 0x0000, 0x0010, 0x0010, + "\xD2\x8C\xD2\xA9\x12\x0B\xAE\xD2\xAF\xE5\x89\x54\x0F\x24\x20\xF5"}, + {0x40, 0xA0, 0x04AD, 0x0000, 0x0010, 0x0010, + "\x89\x75\x8D\xFE\x75\x8B\xFE\xD2\x8E\xC2\xAC\x75\x98\x50\xC2\x98"}, + {0x40, 0xA0, 0x04BD, 0x0000, 0x0010, 0x0010, + "\xC2\x99\xD2\xAC\x53\x21\xDF\x53\x21\xBF\x53\x21\xEF\x90\x7F\x9A"}, + {0x40, 0xA0, 0x04CD, 0x0000, 0x0010, 0x0010, + "\xE0\x54\xFE\x90\x7F\x97\xF0\x90\x7F\x98\xE5\x21\xF0\x75\x24\x3D"}, + {0x40, 0xA0, 0x04DD, 0x0000, 0x0010, 0x0010, + "\xE5\x24\x70\xFC\x43\x21\x20\x43\x21\x40\x43\x21\x10\x90\x7F\x98"}, + {0x40, 0xA0, 0x04ED, 0x0000, 0x0010, 0x0010, + "\xE5\x21\xF0\x20\x01\x3C\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9"}, + {0x40, 0xA0, 0x04FD, 0x0000, 0x0010, 0x0010, + "\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9\x75\x24\xF4\xE5\x24\x60"}, + {0x40, 0xA0, 0x050D, 0x0000, 0x0010, 0x0010, + "\x03\x30\x01\xF9\x75\x24\xF4\xE5\x24\x60\x03\x30\x01\xF9\x75\x24"}, + {0x40, 0xA0, 0x051D, 0x0000, 0x0010, 0x0010, + "\xF4\xE5\x24\x60\x03\x30\x01\xF9\x20\x01\xC8\xD2\x06\x12\x0A\xE0"}, + {0x40, 0xA0, 0x052D, 0x0000, 0x0010, 0x0010, + "\x80\xC1\x30\x01\x0C\x12\x01\xFF\xC2\x01\x90\x7F\xAE\xE0\x44\x02"}, + {0x40, 0xA0, 0x053D, 0x0000, 0x0010, 0x0010, + "\xF0\x30\x04\x1A\x12\x0B\x91\x50\x13\x12\x0B\x05\x20\x03\x07\x90"}, + {0x40, 0xA0, 0x054D, 0x0000, 0x0010, 0x0010, + "\x7F\xD6\xE0\x20\xE7\xF3\x12\x0B\x26\x12\x0B\xB2\xC2\x04\x05\x1C"}, + {0x40, 0xA0, 0x055D, 0x0000, 0x0010, 0x0010, + "\xE5\x1C\xC3\x94\x06\x40\x03\xE4\xF5\x1C\xE5\x1C\x75\xF0\x03\xA4"}, + {0x40, 0xA0, 0x056D, 0x0000, 0x000E, 0x000E, + "\x24\x0A\xF8\x08\xE6\xFA\x08\xE6\xF9\x12\x07\x11\x80\xB4"}, + {0x40, 0xA0, 0x057B, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0033, 0x0000, 0x0003, 0x0003, "\x02\x0B\xAA"}, + {0x40, 0xA0, 0x0BAA, 0x0000, 0x0004, 0x0004, "\x53\xD8\xEF\x32"}, + {0x40, 0xA0, 0x0023, 0x0000, 0x0003, 0x0003, "\x02\x07\x17"}, + {0x40, 0xA0, 0x0717, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x0727, 0x0000, 0x000C, 0x000C, + "\xD0\x75\xD0\x00\xC0\x00\xC0\x05\xC0\x06\xC0\x07"}, + {0x40, 0xA0, 0x0733, 0x0000, 0x0010, 0x0010, + "\x30\x99\x23\xC2\x99\xE5\x68\x60\x1B\xAF\x67\x05\x67\x74\x00\x2F"}, + {0x40, 0xA0, 0x0743, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x0F\xF5\x83\xE0\xF5\x99\x15\x68\x53\x21\xBF\x75"}, + {0x40, 0xA0, 0x0753, 0x0000, 0x0010, 0x0010, + "\x23\x0C\x80\x02\xD2\x02\x30\x98\x1E\xC2\x98\xAF\x99\xE5\x66\x04"}, + {0x40, 0xA0, 0x0763, 0x0000, 0x0010, 0x0010, + "\x54\x3F\xFE\x65\x65\x60\x0A\xAD\x66\x74\x25\x2D\xF8\xA6\x07\x8E"}, + {0x40, 0xA0, 0x0773, 0x0000, 0x0007, 0x0007, + "\x66\x53\x21\xDF\x75\x22\x0C"}, + {0x40, 0xA0, 0x077A, 0x0000, 0x0010, 0x0010, + "\xD0\x07\xD0\x06\xD0\x05\xD0\x00\xD0\xD0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x078A, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0A17, 0x0000, 0x0010, 0x0010, + "\xA2\xAC\x92\x06\xC2\xAC\x30\x02\x0C\xC2\x02\x8F\x99\x53\x21\xBF"}, + {0x40, 0xA0, 0x0A27, 0x0000, 0x0010, 0x0010, + "\x75\x23\x0C\x80\x12\xAE\x69\x05\x69\x74\x00\x2E\xF5\x82\xE4\x34"}, + {0x40, 0xA0, 0x0A37, 0x0000, 0x000B, 0x000B, + "\x0F\xF5\x83\xEF\xF0\x05\x68\xA2\x06\x92\xAC"}, + {0x40, 0xA0, 0x0A42, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x01C0, 0x0000, 0x0010, 0x0010, + "\x12\x01\x00\x01\x00\x00\x00\x40\x63\x07\x15\x10\x21\x01\x00\x00"}, + {0x40, 0xA0, 0x01D0, 0x0000, 0x0010, 0x0010, + "\x00\x01\x09\x02\x27\x00\x01\x01\x00\xA0\x00\x09\x04\x00\x00\x03"}, + {0x40, 0xA0, 0x01E0, 0x0000, 0x0010, 0x0010, + "\xFF\x00\x00\x00\x07\x05\x81\x03\x20\x00\x01\x07\x05\x82\x02\x20"}, + {0x40, 0xA0, 0x01F0, 0x0000, 0x000F, 0x000F, + "\x00\x00\x07\x05\x02\x02\x20\x00\x00\x04\x03\x09\x04\x00\x00"}, + {0x40, 0xA0, 0x08B5, 0x0000, 0x0010, 0x0010, + "\x01\x24\x00\xC1\x01\x01\x22\x00\x01\x21\xFF\x01\x23\x00\xC1\x82"}, + {0x40, 0xA0, 0x08C5, 0x0000, 0x000F, 0x000F, + "\x01\x65\x00\x01\x66\x00\x01\x67\x00\x01\x69\x00\x01\x68\x00"}, + {0x40, 0xA0, 0x0043, 0x0000, 0x0003, 0x0003, "\x02\x09\x00"}, + {0x40, 0xA0, 0x0900, 0x0000, 0x0010, 0x0010, + "\x02\x0A\x6D\x00\x02\x08\x03\x00\x02\x0A\x43\x00\x02\x0A\x94\x00"}, + {0x40, 0xA0, 0x0910, 0x0000, 0x0010, 0x0010, + "\x02\x0A\xBB\x00\x02\x0B\xBE\x00\x02\x0B\xBF\x00\x02\x0B\xC0\x00"}, + {0x40, 0xA0, 0x0920, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC1\x00\x02\x0B\xC2\x00\x02\x0B\xC3\x00\x02\x0B\xC4\x00"}, + {0x40, 0xA0, 0x0930, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC5\x00\x02\x0B\xC6\x00\x02\x0B\xC7\x00\x02\x0B\xC8\x00"}, + {0x40, 0xA0, 0x0940, 0x0000, 0x0010, 0x0010, + "\x02\x0B\xC9\x00\x02\x0B\xCA\x00\x02\x0B\xCB\x00\x02\x0B\xCC\x00"}, + {0x40, 0xA0, 0x0950, 0x0000, 0x0008, 0x0008, + "\x02\x0B\xCD\x00\x02\x0B\xCE\x00"}, + {0x40, 0xA0, 0x08D4, 0x0000, 0x0010, 0x0010, + "\x12\x0A\xFF\x07\x91\xFF\x06\x08\xFF\x09\x58\xFF\x07\x91\xFF\x06"}, + {0x40, 0xA0, 0x08E4, 0x0000, 0x000A, 0x000A, + "\x08\xFF\x0B\x57\x01\x08\xFF\x01\x09\x00"}, + {0x40, 0xA0, 0x0791, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB6\xE0\x20\xE1\x6A\x7A\x7E\x79\x80\x7E\x7E\x7F\x80\x74"}, + {0x40, 0xA0, 0x07A1, 0x0000, 0x0010, 0x0010, + "\x7E\x90\x7F\xE3\xF0\x74\x80\x90\x7F\xE4\xF0\xE4\xFF\xE5\x66\x65"}, + {0x40, 0xA0, 0x07B1, 0x0000, 0x0010, 0x0010, + "\x65\x60\x43\xEF\xC3\x94\x08\x50\x3D\xE4\xFD\xE5\x66\x65\x65\x60"}, + {0x40, 0xA0, 0x07C1, 0x0000, 0x0010, 0x0010, + "\x1B\xED\xC3\x94\x03\x50\x15\x74\x25\x25\x65\xF8\xE6\x90\x7F\xE5"}, + {0x40, 0xA0, 0x07D1, 0x0000, 0x0010, 0x0010, + "\xF0\x05\x65\xE5\x65\x54\x3F\xF5\x65\x0D\x80\xDF\xED\x60\xCE\xFE"}, + {0x40, 0xA0, 0x07E1, 0x0000, 0x0010, 0x0010, + "\xEE\xC3\x94\x03\x50\x08\xE4\x90\x7F\xE5\xF0\x0E\x80\xF2\x90\x7F"}, + {0x40, 0xA0, 0x07F1, 0x0000, 0x0010, 0x0010, + "\xE5\xED\xF0\x0F\x80\xB7\xEF\x60\x08\x25\xE0\x25\xE0\x90\x7F\xB7"}, + {0x40, 0xA0, 0x0801, 0x0000, 0x0001, 0x0001, "\xF0"}, + {0x40, 0xA0, 0x0802, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0958, 0x0000, 0x0010, 0x0010, + "\xE5\x08\x60\x16\x14\x60\x2A\x80\x00\x12\x08\xFD\xEF\x65\x09\x60"}, + {0x40, 0xA0, 0x0968, 0x0000, 0x0010, 0x0010, + "\x36\x12\x08\xFD\x8F\x09\xE4\xF5\x08\x22\xE5\x22\x60\x10\xD5\x22"}, + {0x40, 0xA0, 0x0978, 0x0000, 0x0010, 0x0010, + "\x0D\xA2\xAF\x92\x06\xC2\xAF\x43\x21\x20\xA2\x06\x92\xAF\x05\x08"}, + {0x40, 0xA0, 0x0988, 0x0000, 0x0010, 0x0010, + "\x22\xE5\x23\x60\x10\xD5\x23\x0D\xA2\xAF\x92\x06\xC2\xAF\x43\x21"}, + {0x40, 0xA0, 0x0998, 0x0000, 0x0007, 0x0007, + "\x40\xA2\x06\x92\xAF\x05\x08"}, + {0x40, 0xA0, 0x099F, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0B57, 0x0000, 0x0010, 0x0010, + "\xA2\xAF\x92\x06\xC2\xAF\x90\x7F\x98\xE5\x21\xF0\xA2\x06\x92\xAF"}, + {0x40, 0xA0, 0x0B67, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0608, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xC8\xE0\x30\xE1\x03\x02\x06\x92\x90\x7F\xC9\xE0\xF5\x6A"}, + {0x40, 0xA0, 0x0618, 0x0000, 0x0010, 0x0010, + "\xC3\xE4\x95\x68\xFF\x74\x01\x94\x00\xFE\xC3\xE5\x6A\x9F\xE4\x9E"}, + {0x40, 0xA0, 0x0628, 0x0000, 0x0010, 0x0010, + "\x50\x68\xE4\xF5\x6B\xE5\x6B\xC3\x95\x6A\x50\x59\x74\xC3\x25\x6B"}, + {0x40, 0xA0, 0x0638, 0x0000, 0x0010, 0x0010, + "\xF5\x82\xE4\x34\x7D\xF5\x83\xE0\x54\x0F\xFD\x60\x48\x74\xC0\x25"}, + {0x40, 0xA0, 0x0648, 0x0000, 0x0010, 0x0010, + "\x6B\xF5\x82\xE4\x34\x7D\x90\x7F\xE3\xF0\x74\xC0\x25\x6B\xF5\x82"}, + {0x40, 0xA0, 0x0658, 0x0000, 0x0010, 0x0010, + "\xE4\x34\x7D\xE5\x82\x90\x7F\xE4\xF0\xAF\x05\xED\x14\x60\x16\x14"}, + {0x40, 0xA0, 0x0668, 0x0000, 0x0010, 0x0010, + "\x60\x0B\x14\x70\x18\x90\x7F\xE5\xE0\xFF\x12\x0A\x17\x90\x7F\xE5"}, + {0x40, 0xA0, 0x0678, 0x0000, 0x0010, 0x0010, + "\xE0\xFF\x12\x0A\x17\x90\x7F\xE5\xE0\xFF\x12\x0A\x17\x74\x04\x25"}, + {0x40, 0xA0, 0x0688, 0x0000, 0x000A, 0x000A, + "\x6B\xF5\x6B\x80\xA0\xE4\x90\x7F\xC9\xF0"}, + {0x40, 0xA0, 0x0692, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x08EE, 0x0000, 0x0003, 0x0003, "\x01\x1D\x00"}, + {0x40, 0xA0, 0x000B, 0x0000, 0x0003, 0x0003, "\x02\x0B\x84"}, + {0x40, 0xA0, 0x0B84, 0x0000, 0x000D, 0x000D, + "\xC0\xE0\x05\x1D\xE5\x24\x60\x02\x15\x24\xD0\xE0\x32"}, + {0x40, 0xA0, 0x08FD, 0x0000, 0x0003, 0x0003, "\xAF\x1D\x22"}, + {0x40, 0xA0, 0x0BAE, 0x0000, 0x0004, 0x0004, "\xE4\xF5\x1D\x22"}, + {0x40, 0xA0, 0x08F1, 0x0000, 0x000B, 0x000B, + "\x01\x72\x01\x01\x73\x01\xC1\x85\x01\x74\x02"}, + {0x40, 0xA0, 0x01FF, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xE9\xE0\x70\x03\x02\x02\xD4\x14\x70\x03\x02\x03\x4F\x24"}, + {0x40, 0xA0, 0x020F, 0x0000, 0x0010, 0x0010, + "\xFE\x70\x03\x02\x03\xA8\x24\xFB\x70\x03\x02\x02\xCE\x14\x70\x03"}, + {0x40, 0xA0, 0x021F, 0x0000, 0x0010, 0x0010, + "\x02\x02\xC8\x14\x70\x03\x02\x02\xBC\x14\x70\x03\x02\x02\xC2\x24"}, + {0x40, 0xA0, 0x022F, 0x0000, 0x0010, 0x0010, + "\x05\x60\x03\x02\x03\xFA\x12\x0B\xB4\x40\x03\x02\x04\x05\x90\x7F"}, + {0x40, 0xA0, 0x023F, 0x0000, 0x0010, 0x0010, + "\xEB\xE0\x24\xFE\x60\x16\x14\x60\x3F\x24\x02\x70\x67\x74\x01\x90"}, + {0x40, 0xA0, 0x024F, 0x0000, 0x0010, 0x0010, + "\x7F\xD4\xF0\x74\xC0\x90\x7F\xD5\xF0\x02\x04\x05\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x025F, 0x0000, 0x0010, 0x0010, + "\xFF\x12\x08\x63\x8B\x6A\x8A\x6B\x89\x6C\xEA\x49\x60\x11\xAE\x02"}, + {0x40, 0xA0, 0x026F, 0x0000, 0x0010, 0x0010, + "\xEE\x90\x7F\xD4\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x05\x90"}, + {0x40, 0xA0, 0x027F, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\x74\x01\xF0\x02\x04\x05\x90\x7F\xEA\xE0\xFF\x12\x09\xA0"}, + {0x40, 0xA0, 0x028F, 0x0000, 0x0010, 0x0010, + "\x8B\x6A\x8A\x6B\x89\x6C\xEA\x49\x60\x11\xAE\x02\xEE\x90\x7F\xD4"}, + {0x40, 0xA0, 0x029F, 0x0000, 0x0010, 0x0010, + "\xF0\xAF\x01\xEF\x90\x7F\xD5\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01"}, + {0x40, 0xA0, 0x02AF, 0x0000, 0x0010, 0x0010, + "\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05\x12\x0B\x76"}, + {0x40, 0xA0, 0x02BF, 0x0000, 0x0010, 0x0010, + "\x02\x04\x05\x12\x0B\xA2\x02\x04\x05\x12\x0B\x9A\x02\x04\x05\x12"}, + {0x40, 0xA0, 0x02CF, 0x0000, 0x0010, 0x0010, + "\x0B\x68\x02\x04\x05\x12\x0B\xB6\x40\x03\x02\x04\x05\x90\x7F\xE8"}, + {0x40, 0xA0, 0x02DF, 0x0000, 0x0010, 0x0010, + "\xE0\x24\x7F\x60\x24\x14\x60\x31\x24\x02\x70\x5B\xA2\x03\xE4\x33"}, + {0x40, 0xA0, 0x02EF, 0x0000, 0x0010, 0x0010, + "\xFF\x25\xE0\xFF\xA2\x00\xE4\x33\x4F\x90\x7F\x00\xF0\xE4\xA3\xF0"}, + {0x40, 0xA0, 0x02FF, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x05\xE4\x90\x7F\x00\xF0\xA3\xF0"}, + {0x40, 0xA0, 0x030F, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xB5\x74\x02\xF0\x02\x04\x05\x90\x7F\xEC\xE0\xF4\x54\x80"}, + {0x40, 0xA0, 0x031F, 0x0000, 0x0010, 0x0010, + "\xFF\xC4\x54\x0F\xFF\xE0\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4"}, + {0x40, 0xA0, 0x032F, 0x0000, 0x0010, 0x0010, + "\x34\x7F\xF5\x83\xE0\x54\xFD\x90\x7F\x00\xF0\xE4\xA3\xF0\x90\x7F"}, + {0x40, 0xA0, 0x033F, 0x0000, 0x0010, 0x0010, + "\xB5\x74\x02\xF0\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05"}, + {0x40, 0xA0, 0x034F, 0x0000, 0x0010, 0x0010, + "\x12\x0B\xB8\x40\x03\x02\x04\x05\x90\x7F\xE8\xE0\x24\xFE\x60\x1C"}, + {0x40, 0xA0, 0x035F, 0x0000, 0x0010, 0x0010, + "\x24\x02\x60\x03\x02\x04\x05\x90\x7F\xEA\xE0\xB4\x01\x05\xC2\x03"}, + {0x40, 0xA0, 0x036F, 0x0000, 0x0010, 0x0010, + "\x02\x04\x05\x90\x7F\xC4\x74\x01\xF0\x02\x04\x05\x90\x7F\xEA\xE0"}, + {0x40, 0xA0, 0x037F, 0x0000, 0x0010, 0x0010, + "\x70\x1F\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0\x54"}, + {0x40, 0xA0, 0x038F, 0x0000, 0x0010, 0x0010, + "\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\xE4\xF0\x80"}, + {0x40, 0xA0, 0x039F, 0x0000, 0x0010, 0x0010, + "\x65\x90\x7F\xC4\x74\x01\xF0\x80\x5D\x12\x0B\xBA\x50\x58\x90\x7F"}, + {0x40, 0xA0, 0x03AF, 0x0000, 0x0010, 0x0010, + "\xE8\xE0\x24\xFE\x60\x17\x24\x02\x70\x4C\x90\x7F\xEA\xE0\xB4\x01"}, + {0x40, 0xA0, 0x03BF, 0x0000, 0x0010, 0x0010, + "\x04\xD2\x03\x80\x41\x90\x7F\xC4\x74\x01\xF0\x80\x39\x90\x7F\xEA"}, + {0x40, 0xA0, 0x03CF, 0x0000, 0x0010, 0x0010, + "\xE0\x70\x20\x90\x7F\xEC\xE0\xF4\x54\x80\xFF\xC4\x54\x0F\xFF\xE0"}, + {0x40, 0xA0, 0x03DF, 0x0000, 0x0010, 0x0010, + "\x54\x07\x2F\x25\xE0\x24\xB4\xF5\x82\xE4\x34\x7F\xF5\x83\x74\x01"}, + {0x40, 0xA0, 0x03EF, 0x0000, 0x0010, 0x0010, + "\xF0\x80\x13\x90\x7F\xC4\x74\x01\xF0\x80\x0B\x12\x0B\xBC\x50\x06"}, + {0x40, 0xA0, 0x03FF, 0x0000, 0x000D, 0x000D, + "\x90\x7F\xC4\x74\x01\xF0\x90\x7F\xB4\xE0\x44\x02\xF0"}, + {0x40, 0xA0, 0x040C, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x09E1, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xDE\x74\x06\xF0\x90\x7F\xDF\x74\x04\xF0\x90\x7F\xDD\x74"}, + {0x40, 0xA0, 0x09F1, 0x0000, 0x0010, 0x0010, + "\x18\xF0\x90\x7F\xB6\x74\x02\xF0\x90\x7F\xB8\xF0\x90\x7F\xBA\xF0"}, + {0x40, 0xA0, 0x0A01, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xBC\xF0\x90\x7F\xBE\xF0\x90\x7F\xC0\xF0\x90\x7F\xC2\xF0"}, + {0x40, 0xA0, 0x0A11, 0x0000, 0x0006, 0x0006, "\xE4\x90\x7F\xC9\xF0\x22"}, + {0x40, 0xA0, 0x0B91, 0x0000, 0x0009, 0x0009, + "\x90\x7F\xAF\xE0\x44\x08\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BB2, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BB4, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0B9A, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x76\xD3\x22"}, + {0x40, 0xA0, 0x0B68, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x76\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BA2, 0x0000, 0x0008, 0x0008, + "\x90\x7F\xEA\xE0\xF5\x75\xD3\x22"}, + {0x40, 0xA0, 0x0B76, 0x0000, 0x000E, 0x000E, + "\x90\x7F\x00\xE5\x75\xF0\x90\x7F\xB5\x74\x01\xF0\xD3\x22"}, + {0x40, 0xA0, 0x0BB6, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BB8, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BBA, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0BBC, 0x0000, 0x0002, 0x0002, "\xD3\x22"}, + {0x40, 0xA0, 0x0A6D, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0A7D, 0x0000, 0x0010, 0x0010, + "\x01\x53\x91\xEF\x90\x7F\xAB\x74\x01\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0A8D, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0A43, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x90"}, + {0x40, 0xA0, 0x0A53, 0x0000, 0x0010, 0x0010, + "\x7F\xC4\xE4\xF0\x53\x91\xEF\x90\x7F\xAB\x74\x04\xF0\xD0\x86\xD0"}, + {0x40, 0xA0, 0x0A63, 0x0000, 0x000A, 0x000A, + "\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0803, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xC0"}, + {0x40, 0xA0, 0x0813, 0x0000, 0x0001, 0x0001, "\xD0"}, + {0x40, 0xA0, 0x0814, 0x0000, 0x0010, 0x0010, + "\x53\x91\xEF\x90\x7F\xAB\x74\x02\xF0\x30\x05\x14\x15\x72\xE5\x72"}, + {0x40, 0xA0, 0x0824, 0x0000, 0x0010, 0x0010, + "\x70\x2E\x43\x21\x10\xC2\x05\xC3\x74\x1E\x95\x74\xF5\x72\x80\x20"}, + {0x40, 0xA0, 0x0834, 0x0000, 0x0010, 0x0010, + "\xD5\x72\x1D\x53\x21\xEF\xD2\x05\xE5\x73\x25\x74\xF5\x74\x64\x02"}, + {0x40, 0xA0, 0x0844, 0x0000, 0x0010, 0x0010, + "\x60\x05\xE5\x74\xB4\x1C\x06\xE5\x73\xF4\x04\xF5\x73\x85\x74\x72"}, + {0x40, 0xA0, 0x0854, 0x0000, 0x000F, 0x000F, + "\xD0\xD0\xD0\x86\xD0\x84\xD0\x85\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0ABB, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\x53"}, + {0x40, 0xA0, 0x0ACB, 0x0000, 0x0010, 0x0010, + "\x91\xEF\x90\x7F\xAB\x74\x10\xF0\xD0\x86\xD0\x84\xD0\x85\xD0\x82"}, + {0x40, 0xA0, 0x0ADB, 0x0000, 0x0005, 0x0005, "\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0BBE, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0A94, 0x0000, 0x0010, 0x0010, + "\xC0\xE0\xC0\x83\xC0\x82\xC0\x85\xC0\x84\xC0\x86\x75\x86\x00\xD2"}, + {0x40, 0xA0, 0x0AA4, 0x0000, 0x0010, 0x0010, + "\x04\x53\x91\xEF\x90\x7F\xAB\x74\x08\xF0\xD0\x86\xD0\x84\xD0\x85"}, + {0x40, 0xA0, 0x0AB4, 0x0000, 0x0007, 0x0007, + "\xD0\x82\xD0\x83\xD0\xE0\x32"}, + {0x40, 0xA0, 0x0BBF, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC0, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC1, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC2, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC3, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC4, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC5, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC6, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC7, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC8, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BC9, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCA, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCB, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCC, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCD, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0BCE, 0x0000, 0x0001, 0x0001, "\x32"}, + {0x40, 0xA0, 0x0B26, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x30\xE7\x12\xE0\x44\x01\xF0\x7F\x14\x7E\x00\x12"}, + {0x40, 0xA0, 0x0B36, 0x0000, 0x000A, 0x000A, + "\x0B\x40\x90\x7F\xD6\xE0\x54\xFE\xF0\x22"}, + {0x40, 0xA0, 0x0B05, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x44\x80\xF0\x43\x87\x01\x00\x00\x00\x00\x00\x22"}, + {0x40, 0xA0, 0x0AE0, 0x0000, 0x0010, 0x0010, + "\x90\x7F\xD6\xE0\x54\xFB\xF0\xE0\x44\x08\xF0\x30\x06\x04\xE0\x44"}, + {0x40, 0xA0, 0x0AF0, 0x0000, 0x0010, 0x0010, + "\x02\xF0\x7F\xF4\x7E\x01\x12\x0B\x40\x90\x7F\xD6\xE0\x54\xF7\xF0"}, + {0x40, 0xA0, 0x0B00, 0x0000, 0x0005, 0x0005, "\xE0\x44\x04\xF0\x22"}, + {0x40, 0xA0, 0x09A0, 0x0000, 0x0002, 0x0002, "\x8F\x6D"}, + {0x40, 0xA0, 0x09A2, 0x0000, 0x0010, 0x0010, + "\xE4\xF5\x6E\x75\x6F\xFF\x75\x70\x01\x75\x71\xF9\xAB\x6F\xAA\x70"}, + {0x40, 0xA0, 0x09B2, 0x0000, 0x0010, 0x0010, + "\xA9\x71\x90\x00\x01\x12\x06\xAC\xB4\x03\x1D\xAF\x6E\x05\x6E\xEF"}, + {0x40, 0xA0, 0x09C2, 0x0000, 0x0010, 0x0010, + "\xB5\x6D\x01\x22\x12\x06\x93\x7E\x00\x29\xFF\xEE\x3A\xA9\x07\x75"}, + {0x40, 0xA0, 0x09D2, 0x0000, 0x000E, 0x000E, + "\x6F\xFF\xF5\x70\x89\x71\x80\xD4\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x09E0, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0863, 0x0000, 0x0010, 0x0010, + "\xE4\xFE\x75\x6F\xFF\x75\x70\x01\x75\x71\xD2\xAB\x6F\xAA\x70\xA9"}, + {0x40, 0xA0, 0x0873, 0x0000, 0x0010, 0x0010, + "\x71\x90\x00\x01\x12\x06\xAC\x64\x02\x70\x2D\xAD\x06\x0E\xED\xB5"}, + {0x40, 0xA0, 0x0883, 0x0000, 0x0010, 0x0010, + "\x07\x01\x22\x90\x00\x02\x12\x06\xD9\x85\xF0\x6D\xF5\x6E\x62\x6D"}, + {0x40, 0xA0, 0x0893, 0x0000, 0x0010, 0x0010, + "\xE5\x6D\x62\x6E\xE5\x6E\x62\x6D\x29\xFD\xE5\x6D\x3A\xA9\x05\x75"}, + {0x40, 0xA0, 0x08A3, 0x0000, 0x000E, 0x000E, + "\x6F\xFF\xF5\x70\x89\x71\x80\xC3\x7B\x00\x7A\x00\x79\x00"}, + {0x40, 0xA0, 0x08B1, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0B40, 0x0000, 0x0010, 0x0010, + "\x8E\x6A\x8F\x6B\xE5\x6B\x15\x6B\xAE\x6A\x70\x02\x15\x6A\x4E\x60"}, + {0x40, 0xA0, 0x0B50, 0x0000, 0x0007, 0x0007, + "\x05\x12\x0B\x15\x80\xEE\x22"}, + {0x40, 0xA0, 0x0B15, 0x0000, 0x0010, 0x0010, + "\x74\x00\xF5\x86\x90\xFD\xA5\x7C\x05\xA3\xE5\x82\x45\x83\x70\xF9"}, + {0x40, 0xA0, 0x0B25, 0x0000, 0x0001, 0x0001, "\x22"}, + {0x40, 0xA0, 0x0000, 0x0000, 0x0003, 0x0003, "\x02\x05\x7C"}, + {0x40, 0xA0, 0x057C, 0x0000, 0x000C, 0x000C, + "\x78\x7F\xE4\xF6\xD8\xFD\x75\x81\x76\x02\x05\xC3"}, + {0x40, 0xA0, 0x0693, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x06\x89\x82\x8A\x83\xE0\x22\x50\x02\xE7\x22\xBB\xFE\x02"}, + {0x40, 0xA0, 0x06A3, 0x0000, 0x0009, 0x0009, + "\xE3\x22\x89\x82\x8A\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x06AC, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x0C\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\x22\x50"}, + {0x40, 0xA0, 0x06BC, 0x0000, 0x0010, 0x0010, + "\x06\xE9\x25\x82\xF8\xE6\x22\xBB\xFE\x06\xE9\x25\x82\xF8\xE2\x22"}, + {0x40, 0xA0, 0x06CC, 0x0000, 0x000D, 0x000D, + "\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE4\x93\x22"}, + {0x40, 0xA0, 0x06D9, 0x0000, 0x0010, 0x0010, + "\xBB\x01\x10\xE5\x82\x29\xF5\x82\xE5\x83\x3A\xF5\x83\xE0\xF5\xF0"}, + {0x40, 0xA0, 0x06E9, 0x0000, 0x0010, 0x0010, + "\xA3\xE0\x22\x50\x09\xE9\x25\x82\xF8\x86\xF0\x08\xE6\x22\xBB\xFE"}, + {0x40, 0xA0, 0x06F9, 0x0000, 0x0010, 0x0010, + "\x0A\xE9\x25\x82\xF8\xE2\xF5\xF0\x08\xE2\x22\xE5\x83\x2A\xF5\x83"}, + {0x40, 0xA0, 0x0709, 0x0000, 0x0008, 0x0008, + "\xE9\x93\xF5\xF0\xA3\xE9\x93\x22"}, + {0x40, 0xA0, 0x0711, 0x0000, 0x0006, 0x0006, "\x8A\x83\x89\x82\xE4\x73"}, + {0x40, 0xA0, 0x0588, 0x0000, 0x0010, 0x0010, + "\x02\x04\x0D\xE4\x93\xA3\xF8\xE4\x93\xA3\x40\x03\xF6\x80\x01\xF2"}, + {0x40, 0xA0, 0x0598, 0x0000, 0x0010, 0x0010, + "\x08\xDF\xF4\x80\x29\xE4\x93\xA3\xF8\x54\x07\x24\x0C\xC8\xC3\x33"}, + {0x40, 0xA0, 0x05A8, 0x0000, 0x0010, 0x0010, + "\xC4\x54\x0F\x44\x20\xC8\x83\x40\x04\xF4\x56\x80\x01\x46\xF6\xDF"}, + {0x40, 0xA0, 0x05B8, 0x0000, 0x0010, 0x0010, + "\xE4\x80\x0B\x01\x02\x04\x08\x10\x20\x40\x80\x90\x08\xB2\xE4\x7E"}, + {0x40, 0xA0, 0x05C8, 0x0000, 0x0010, 0x0010, + "\x01\x93\x60\xBC\xA3\xFF\x54\x3F\x30\xE5\x09\x54\x1F\xFE\xE4\x93"}, + {0x40, 0xA0, 0x05D8, 0x0000, 0x0010, 0x0010, + "\xA3\x60\x01\x0E\xCF\x54\xC0\x25\xE0\x60\xA8\x40\xB8\xE4\x93\xA3"}, + {0x40, 0xA0, 0x05E8, 0x0000, 0x0010, 0x0010, + "\xFA\xE4\x93\xA3\xF8\xE4\x93\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA"}, + {0x40, 0xA0, 0x05F8, 0x0000, 0x0010, 0x0010, + "\xF0\xA3\xC8\xC5\x82\xC8\xCA\xC5\x83\xCA\xDF\xE9\xDE\xE7\x80\xBE"}, + {0x40, 0xA0, 0x08FC, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x01"}, + {0x40, 0xA0, 0x7F92, 0x0000, 0x0001, 0x0001, "\x00"}, + {0x00, 0x05, 0x0002, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x09, 0x0001, 0x0000, 0x0000, 0x0000, ""}, + {0x00, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, NULL} +}; diff --git a/kernel/drv/oss_userdev/.config b/kernel/drv/oss_userdev/.config new file mode 100644 index 0000000..828bd4f --- /dev/null +++ b/kernel/drv/oss_userdev/.config @@ -0,0 +1,2 @@ +bus=VIRTUAL +targetcpu=any diff --git a/kernel/drv/oss_userdev/.devices b/kernel/drv/oss_userdev/.devices new file mode 100644 index 0000000..41dd8b4 --- /dev/null +++ b/kernel/drv/oss_userdev/.devices @@ -0,0 +1 @@ +oss_userdev oss_userdev OSS user space audio driver I/O module diff --git a/kernel/drv/oss_userdev/.name b/kernel/drv/oss_userdev/.name new file mode 100644 index 0000000..4d501dc --- /dev/null +++ b/kernel/drv/oss_userdev/.name @@ -0,0 +1 @@ +OSS loopback audio driver diff --git a/kernel/drv/oss_userdev/.params b/kernel/drv/oss_userdev/.params new file mode 100644 index 0000000..45f9032 --- /dev/null +++ b/kernel/drv/oss_userdev/.params @@ -0,0 +1,11 @@ +int userdev_visible_clientnodes=0; +/* + * By default the oss_userdev driver will not create private device nodes + * for the client side devices. Instead all client devices will share + * the same device node (/dev/oss/oss_userdev/client). + * + * If userdev_visible_clientnodes is set to 1 then each oss_userdev instance + * will have private device node (/dev/oss/oss_userdev0/pcmN) that can be + * opened directly. This mode can be used when the oss_userdev driver is used + * for multiple purposes in the same system. + */ diff --git a/kernel/drv/oss_userdev/oss_userdev.c b/kernel/drv/oss_userdev/oss_userdev.c new file mode 100644 index 0000000..c026ff3 --- /dev/null +++ b/kernel/drv/oss_userdev/oss_userdev.c @@ -0,0 +1,352 @@ +/* + * Purpose: Kernel space support module for user land audio/mixer drivers + * + */ +/* + * + * 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_userdev_cfg.h" +#include <oss_userdev_exports.h> +#include "userdev.h" + +oss_device_t *userdev_osdev = NULL; +static int client_dev = -1, server_dev = -1; /* Control devces */ + +char *userdev_client_devnode = "/dev/oss/oss_userdev0/client"; +char *userdev_server_devnode = "/dev/oss/oss_userdev0/server"; + +/* + * Global device lists and the mutex that protects them. + */ +oss_mutex_t userdev_global_mutex; + +/* + * The oss_userdev driver creates new device pairs on-demand. All device + * pairs that are not in use will be kept in the userdev_free_device_list + * (linked) list. If this list contains any entries then they will be + * reused whenever a new device pair is required. + */ +userdev_devc_t *userdev_free_device_list = NULL; + +/* + * Linked list for device pairs that have a server attached. These device + * pairs are available for the clients. + */ +userdev_devc_t *userdev_active_device_list = NULL; + +/*ARGSUSED*/ +static int +userdev_server_redirect (int dev, int mode, int open_flags) +{ +/* + * Purpose: This entry point is used to create new userdev instances and to redirect clients to them. + */ + int server_engine; + + + if ((server_engine=usrdev_find_free_device_pair()) >= 0) + { + userdev_devc_t *devc = audio_engines[server_engine]->devc; + + userdev_reinit_instance(devc); + return server_engine; + } + + return userdev_create_device_pair(); +} + +/*ARGSUSED*/ +static int +userdev_client_redirect (int dev, int mode, int open_flags) +{ +/* + * Purpose: This entry point is used to create new userdev instances and to redirect clients to them. + */ + + userdev_devc_t *devc; + oss_native_word flags; + + uid_t uid; + + uid = oss_get_procinfo(OSS_GET_PROCINFO_UID); + + MUTEX_ENTER_IRQDISABLE(userdev_global_mutex, flags); + devc=userdev_active_device_list; + + while (devc != NULL) + { + int ok=1; + + switch (devc->match_method) + { + case UD_MATCH_UID: + if (devc->match_key != uid) /* Wrong UID */ + ok=0; + break; + } + + if (ok) + { + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); + return devc->client_portc.audio_dev; + } + + devc = devc->next_instance; + } + + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); + return OSS_EIO; +} + +/* + * Dummy audio driver entrypoint functions. + * + * Functionality of the control device is handled by userdev_[client|server]_redirect(). + * The other entry points are not used for any purpose but the audio core + * framework expects to see them. + */ +/*ARGSUSED*/ +static int +userdev_control_set_rate (int dev, int arg) +{ + /* Dumy routine - Not actually used */ + return 48000; +} + +/*ARGSUSED*/ +static short +userdev_control_set_channels (int dev, short arg) +{ + /* Dumy routine - Not actually used */ + return 2; +} + +/*ARGSUSED*/ +static unsigned int +userdev_control_set_format (int dev, unsigned int arg) +{ + /* Dumy routine - Not actually used */ + return AFMT_S16_NE; +} + +static void +userdev_control_reset (int dev) +{ + /* Dumy routine - Not actually used */ +} + +/*ARGSUSED*/ +static int +userdev_control_open (int dev, int mode, int open_flags) +{ + /* Dumy routine - Not actually used */ + return OSS_EIO; +} + +/*ARGSUSED*/ +static void +userdev_control_close (int dev, int mode) +{ + /* Dumy routine - Not actually used */ +} + +/*ARGSUSED*/ +static int +userdev_control_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + /* Dumy routine - Not actually used */ + return OSS_EINVAL; +} + +/*ARGSUSED*/ +static void +userdev_control_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + /* Dumy routine - Not actually used */ +} + +/*ARGSUSED*/ +static void +userdev_control_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ + /* Dumy routine - Not actually used */ +} + +/*ARGSUSED*/ +static int +userdev_control_prepare_for_input (int dev, int bsize, int bcount) +{ + /* Dumy routine - Not actually used */ + return OSS_EIO; +} + +/*ARGSUSED*/ +static int +userdev_control_prepare_for_output (int dev, int bsize, int bcount) +{ + /* Dumy routine - Not actually used */ + return OSS_EIO; +} + +static audiodrv_t userdev_server_control_driver = { + userdev_control_open, + userdev_control_close, + userdev_control_output_block, + userdev_control_start_input, + userdev_control_ioctl, + userdev_control_prepare_for_input, + userdev_control_prepare_for_output, + userdev_control_reset, + NULL, + NULL, + NULL, + NULL, + NULL, /* trigger */ + userdev_control_set_rate, + userdev_control_set_format, + userdev_control_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + userdev_server_redirect +}; + +static audiodrv_t userdev_client_control_driver = { + userdev_control_open, + userdev_control_close, + userdev_control_output_block, + userdev_control_start_input, + userdev_control_ioctl, + userdev_control_prepare_for_input, + userdev_control_prepare_for_output, + userdev_control_reset, + NULL, + NULL, + NULL, + NULL, + NULL, /* trigger */ + userdev_control_set_rate, + userdev_control_set_format, + userdev_control_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + userdev_client_redirect +}; + +static void +attach_control_device(void) +{ +/* + * Create the control device files that are used to create client/server + * device pairs and to redirect access to them. + */ + userdev_devc_t *devc = (userdev_devc_t*)0xdeadcafe; /* This should never get referenced */ + + if ((client_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + userdev_osdev, + userdev_osdev, + "User space audio device client side", + &userdev_client_control_driver, + sizeof (audiodrv_t), + ADEV_AUTOMODE, AFMT_S16_NE, devc, -1, + "client")) < 0) + { + return; + } + userdev_server_devnode = audio_engines[server_dev]->devnode; + audio_engines[client_dev]->vmix_mixer=NULL; + + if ((server_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, + userdev_osdev, + userdev_osdev, + "User space audio device server side", + &userdev_server_control_driver, + sizeof (audiodrv_t), + ADEV_AUTOMODE, AFMT_S16_NE, devc, -1, + "server")) < 0) + { + return; + } + audio_engines[server_dev]->caps |= PCM_CAP_HIDDEN; + audio_engines[server_dev]->vmix_mixer=NULL; + userdev_client_devnode = audio_engines[client_dev]->devnode; +} + +int +oss_userdev_attach (oss_device_t * osdev) +{ + userdev_osdev = osdev; + + osdev->devc = NULL; + MUTEX_INIT (osdev, userdev_global_mutex, MH_DRV); + + oss_register_device (osdev, "User space audio driver subsystem"); + + attach_control_device(); + + return 1; +} + +int +oss_userdev_detach (oss_device_t * osdev) +{ + userdev_devc_t *devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + devc = userdev_free_device_list; + + while (devc != NULL) + { + userdev_devc_t *next = devc->next_instance; + + userdev_delete_device_pair(devc); + + devc = next; + } + + oss_unregister_device (osdev); + + MUTEX_CLEANUP(userdev_global_mutex); + + return 1; +} diff --git a/kernel/drv/oss_userdev/oss_userdev.man b/kernel/drv/oss_userdev/oss_userdev.man new file mode 100644 index 0000000..cdb0d12 --- /dev/null +++ b/kernel/drv/oss_userdev/oss_userdev.man @@ -0,0 +1,37 @@ +NAME +oss_userdev - OSS client/server audio pseudo device. + +NOTICE +This audio device is not designed to be used as-is by the users. It requires +a specially designed server application that implements the actual service +(please see the OSS programming documentation for more info). The server +application will then create the audio devices that can be used to record +and/or play audio. + +DESCRIPTION +The oss_userdev driver is a special purpose loop back audio device that can be +used when implementing OSS audio devices based on a server running in the +background. + +OPTIONS + +o userdev_visible_clientnodes=0|1 +By default (0) common client device node (/dev/oss/oss_userdev0/client) will +be created for all server instances. The clients will then get directed to the +right instance based on some search criteria (for example UID). This +alternative is best when using single server application that can serve large +number of different sesions. + +If this option +is set to 1 then OSS will create separate client device nodes for each +instance. Applications will have to open the right device nodes. This +alternative is best when oss_userdev is used to create different kind of +services in one system. In this way for example a VoIP link can be accessed +by opening a different device node than when opening some other service. + +FILES +CONFIGFILEPATH/oss_userdev.conf Device configuration file. + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_userdev/oss_userdev_devicepair.c b/kernel/drv/oss_userdev/oss_userdev_devicepair.c new file mode 100644 index 0000000..8119cb9 --- /dev/null +++ b/kernel/drv/oss_userdev/oss_userdev_devicepair.c @@ -0,0 +1,1255 @@ +/* + * Purpose: Client/server audio device pair for oss_userdev + * + * This file implements the actual client/server device pair. There will be + * separate oss_userdev instance for each process that has opened the + * client side. + */ +/* + * + * 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_userdev_cfg.h" +#include <oss_userdev_exports.h> +#include "userdev.h" +static void userdev_free_device_pair (userdev_devc_t *devc); + +extern int userdev_visible_clientnodes; + +static void +transfer_audio (userdev_portc_t * server_portc, dmap_t * dmap_from, + dmap_t * dmap_to) +{ + int l = dmap_from->fragment_size; + unsigned char *fromp, *top; + + if (dmap_to->fragment_size != l) + { + cmn_err (CE_WARN, "Fragment size mismatch (%d != %d)\n", + dmap_to->fragment_size, l); + + /* Perform emergency stop */ + server_portc->input_triggered = 0; + server_portc->output_triggered = 0; + server_portc->peer->input_triggered = 0; + server_portc->peer->output_triggered = 0; + return; + } + + fromp = + dmap_from->dmabuf + (dmap_from->byte_counter % dmap_from->bytes_in_use); + top = dmap_to->dmabuf + (dmap_to->byte_counter % dmap_to->bytes_in_use); + + memcpy (top, fromp, l); + +} + +static void +handle_input (userdev_portc_t * server_portc) +{ + userdev_portc_t *client_portc = server_portc->peer; + + if (client_portc->output_triggered) + { + transfer_audio (server_portc, + audio_engines[client_portc->audio_dev]->dmap_out, + audio_engines[server_portc->audio_dev]->dmap_in); + oss_audio_outputintr (client_portc->audio_dev, 0); + } + + oss_audio_inputintr (server_portc->audio_dev, 0); +} + +static void +handle_output (userdev_portc_t * server_portc) +{ + userdev_portc_t *client_portc = server_portc->peer; + + if (client_portc->input_triggered) + { + transfer_audio (server_portc, + audio_engines[server_portc->audio_dev]->dmap_out, + audio_engines[client_portc->audio_dev]->dmap_in); + oss_audio_inputintr (client_portc->audio_dev, 0); + } + + oss_audio_outputintr (server_portc->audio_dev, 0); +} + +static void +userdev_cb (void *pc) +{ +/* + * This timer callback routine will get called 100 times/second. It handles + * movement of audio data between the client and server sides. + */ + userdev_portc_t *server_portc = pc; + userdev_devc_t *devc = server_portc->devc; + int tmout = devc->poll_ticks; + + if (tmout < 1) + tmout = 1; + + devc->timeout_id = 0; /* No longer valid */ + + if (server_portc->input_triggered) + handle_input (server_portc); + + if (server_portc->output_triggered) + handle_output (server_portc); + + /* Retrigger timer callback */ + if (server_portc->input_triggered || server_portc->output_triggered) + devc->timeout_id = timeout (userdev_cb, server_portc, tmout); +} + +static int +userdev_check_input (int dev) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + if (!portc->peer->output_triggered) + { + return OSS_ECONNRESET; + } + return 0; +} + +static int +userdev_check_output (int dev) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + + if (!portc->peer->input_triggered) + { + return OSS_ECONNRESET; + } + + if (portc->peer->open_mode == 0) + return OSS_EIO; + return 0; +} + +static void +setup_sample_format (userdev_portc_t * portc) +{ + adev_t *adev; + userdev_devc_t *devc = portc->devc; + int fragsize, frame_size; + + frame_size = devc->channels * devc->fmt_bytes; + if (frame_size == 0) + frame_size = 4; + + fragsize = (devc->rate * frame_size * devc->poll_ticks) / OSS_HZ; /* Number of bytes/fragment */ + devc->rate = fragsize * 100 / frame_size; + +/* Setup the server side */ + adev = audio_engines[portc->audio_dev]; + adev->min_block = adev->max_block = fragsize; + +/* Setup the client side */ + adev = audio_engines[portc->peer->audio_dev]; + adev->min_block = adev->max_block = fragsize; + + adev->max_rate = adev->min_rate = devc->rate; + adev->iformat_mask = devc->fmt; + adev->oformat_mask = devc->fmt; + adev->xformat_mask = devc->fmt; + adev->min_channels = adev->max_channels = devc->channels; +} + +static int +userdev_server_set_rate (int dev, int arg) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + adev_t *client_adev = audio_engines[portc->peer->audio_dev]; + + if (arg == 0) + return devc->rate; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return devc->rate; + + if (arg < 5000) + arg = 5000; + if (arg > MAX_RATE) + arg = MAX_RATE; + + /* Force the sample rate to be multiple of 100 */ + arg = (arg / 100) * 100; + + devc->rate = arg; + + client_adev->min_rate = arg; + client_adev->max_rate = arg; + + setup_sample_format (portc); + + return devc->rate = arg; +} + +/*ARGSUSED*/ +static int +userdev_client_set_rate (int dev, int arg) +{ + userdev_devc_t *devc = audio_engines[dev]->devc; + + return devc->rate; +} + +static short +userdev_server_set_channels (int dev, short arg) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + adev_t *client_adev = audio_engines[portc->peer->audio_dev]; + + if (arg == 0) + return devc->channels; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return devc->channels; + + if (arg < 1) + arg = 1; + if (arg > MAX_CHANNELS) + arg = MAX_CHANNELS; + + devc->channels = arg; + client_adev->min_channels=client_adev->max_channels=arg; + + setup_sample_format (portc); + + return devc->channels; +} + +/*ARGSUSED*/ +static short +userdev_client_set_channels (int dev, short arg) +{ + userdev_devc_t *devc = audio_engines[dev]->devc; + + return devc->channels; /* Server side channels */ +} + +static unsigned int +userdev_server_set_format (int dev, unsigned int arg) +{ + userdev_devc_t *devc = audio_engines[dev]->devc; + userdev_portc_t *portc = audio_engines[dev]->portc; + adev_t *client_adev = audio_engines[portc->peer->audio_dev]; + + if (arg == 0) + return devc->fmt; + + if (portc->peer->input_triggered || portc->peer->output_triggered) + return devc->fmt; + + switch (arg) + { + case AFMT_S16_NE: + devc->fmt_bytes = 2; + break; + + case AFMT_S32_NE: + devc->fmt_bytes = 4; + break; + + default: /* Unsupported format */ + arg = AFMT_S16_NE; + devc->fmt_bytes = 2; + + } + + devc->fmt = arg; + + client_adev->oformat_mask = arg; + client_adev->iformat_mask = arg; + + setup_sample_format (portc); + + return devc->fmt; +} + +/*ARGSUSED*/ +static unsigned int +userdev_client_set_format (int dev, unsigned int arg) +{ + userdev_devc_t *devc = audio_engines[dev]->devc; + + return devc->fmt; /* Server side sample format */ +} + +static void userdev_trigger (int dev, int state); + +static void +userdev_reset (int dev) +{ + userdev_trigger (dev, 0); +} + +/*ARGSUSED*/ +static int +userdev_server_open (int dev, int mode, int open_flags) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + if (portc == NULL || portc->peer == NULL) + return OSS_ENXIO; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + devc->open_count++; + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_client_open (int dev, int mode, int open_flags) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + + if (portc == NULL || portc->peer == NULL) + return OSS_ENXIO; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->open_mode) + { + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return OSS_EBUSY; + } + + portc->open_mode = mode; + devc->open_count++; + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static void +wipe_audio_buffers(userdev_devc_t *devc) +{ +/* + * Write silence to the audio buffers when only one of the sides + * is open. This prevents the device from looping the last fragments + * written to the device. + */ + dmap_t *dmap; + + dmap = audio_engines[devc->client_portc.audio_dev]->dmap_out; + if (dmap != NULL && dmap->dmabuf != NULL) + memset(dmap->dmabuf, 0, dmap->buffsize); + + dmap = audio_engines[devc->client_portc.audio_dev]->dmap_in; + if (dmap != NULL && dmap->dmabuf != NULL) + memset(dmap->dmabuf, 0, dmap->buffsize); + + dmap = audio_engines[devc->server_portc.audio_dev]->dmap_out; + if (dmap != NULL && dmap->dmabuf != NULL) + memset(dmap->dmabuf, 0, dmap->buffsize); + + dmap = audio_engines[devc->server_portc.audio_dev]->dmap_in; + if (dmap != NULL && dmap->dmabuf != NULL) + memset(dmap->dmabuf, 0, dmap->buffsize); +} + +/*ARGSUSED*/ +static void +userdev_server_close (int dev, int mode) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + int open_count; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + + /* Stop the client side because there is no server */ + portc->peer->input_triggered = 0; + portc->peer->output_triggered = 0; + open_count = --devc->open_count; + + if (open_count == 0) + userdev_free_device_pair (devc); + else + wipe_audio_buffers(devc); + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static void +userdev_client_close (int dev, int mode) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + oss_native_word flags; + int open_count; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->open_mode = 0; + + open_count = --devc->open_count; + + if (open_count == 0) + userdev_free_device_pair (devc); + else + wipe_audio_buffers(devc); + + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +userdev_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + switch (cmd) + { + case SNDCTL_GETLABEL: + { + /* + * Return an empty string so that this feature can be tested. + * Complete functionality is to be implemented later. + */ + oss_label_t *s = (oss_label_t *) arg; + memset (s, 0, sizeof (oss_label_t)); + return 0; + } + break; + + case SNDCTL_GETSONG: + { + /* + * Return an empty string so that this feature can be tested. + * Complete functionality is to be implemented later. + */ + oss_longname_t *s = (oss_longname_t *) arg; + memset (s, 0, sizeof (oss_longname_t)); + return 0; + } + break; + } + + return OSS_EINVAL; +} + +static void +set_adev_name(int dev, const char *name) +{ + adev_t *adev = audio_engines[dev]; + + strcpy(adev->name, name); + +#ifdef CONFIG_OSS_VMIX + if (adev->vmix_mixer != NULL) + vmix_change_devnames(adev->vmix_mixer, name); +#endif + +} + +static int +create_instance(int dev, userdev_create_t *crea) +{ + userdev_devc_t *devc = audio_engines[dev]->devc; + char tmp_name[64]; + + devc->match_method = crea->match_method; + devc->match_key = crea->match_key; + devc->create_flags = crea->flags; + + devc->poll_ticks = (crea->poll_interval * OSS_HZ) / 1000; + + if (devc->poll_ticks < 1) + devc->poll_ticks = 1; + + crea->poll_interval = (1000*devc->poll_ticks) / OSS_HZ; + + if (crea->poll_interval<1) + crea->poll_interval = 1; + + crea->name[sizeof(crea->name)-1]=0; /* Overflow protectgion */ + + sprintf(tmp_name, "%s (server)", crea->name); + tmp_name[49]=0; + set_adev_name (devc->client_portc.audio_dev, crea->name); + set_adev_name (devc->server_portc.audio_dev, tmp_name); + + strcpy(crea->devnode, audio_engines[devc->client_portc.audio_dev]->devnode); + + return 0; +} + +static int +userdev_set_control (int dev, int ctl, unsigned int cmd, int value) +{ + userdev_devc_t *devc = mixer_devs[dev]->devc; + + if (ctl < 0 || ctl >= USERDEV_MAX_MIXERS) + return OSS_EINVAL; + + if (cmd == SNDCTL_MIX_READ) + { + return devc->mixer_values[ctl]; + } + + devc->mixer_values[ctl] = value; + devc->modify_counter++; + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_server_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + switch (cmd) + { + case USERDEV_CREATE_INSTANCE: + { + userdev_create_t *crea = (userdev_create_t *)arg; + + return create_instance(dev, crea); + } + break; + + case USERDEV_GET_CLIENTCOUNT: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + + return *arg = (devc->client_portc.open_mode != 0); + } + break; + + /* + * Mixer related ioctl calls + */ + + case USERDEV_CREATE_MIXGROUP: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + userdev_mixgroup_t *grp=(userdev_mixgroup_t*)arg; + int group; + + grp->name[sizeof(grp->name)-1]=0; /* Buffer overflow protection */ + if ((group=mixer_ext_create_group(devc->mixer_dev, grp->parent, grp->name))<0) + return group; + grp->num = group; + return 0; + } + break; + + case USERDEV_CREATE_MIXCTL: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + userdev_mixctl_t *c=(userdev_mixctl_t*)arg; + oss_mixext *ext; + int ctl; + + c->name[sizeof(c->name)-1]=0; /* Buffer overflow protection */ + + if (c->index < 0 || c->index >= USERDEV_MAX_MIXERS) + return OSS_EINVAL; + + if ((ctl = mixer_ext_create_control (devc->mixer_dev, + c->parent, + c->index, + userdev_set_control, + c->type, + c->name, + c->maxvalue, + c->flags)) < 0) + return ctl; + + c->num = ctl; + ext = mixer_find_ext (devc->mixer_dev, ctl); + + ext->minvalue = c->offset; + ext->control_no= c->control_no; + ext->rgbcolor = c->rgbcolor; + + if (c->type == MIXT_ENUM) + { + memcpy(ext->enum_present, c->enum_present, sizeof(ext->enum_present)); + mixer_ext_set_strings (devc->mixer_dev, ctl, c->enum_choises, 0); + } + + return 0; + } + break; + + case USERDEV_GET_MIX_CHANGECOUNT: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + + return *arg = devc->modify_counter; + } + break; + + case USERDEV_SET_MIXERS: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + + memcpy(devc->mixer_values, arg, sizeof(devc->mixer_values)); + mixer_devs[devc->mixer_dev]->modify_counter++; +//cmn_err(CE_CONT, "Set %08x %08x\n", devc->mixer_values[0], devc->mixer_values[1]); + return 0; + } + break; + + case USERDEV_GET_MIXERS: + { + userdev_devc_t *devc = audio_engines[dev]->devc; + + memcpy(arg, devc->mixer_values, sizeof(devc->mixer_values)); + return 0; + } + break; + + } + + return userdev_ioctl(dev, cmd, arg); +} + +/*ARGSUSED*/ +static void +userdev_output_block (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +/*ARGSUSED*/ +static void +userdev_start_input (int dev, oss_native_word buf, int count, int fragsize, + int intrflag) +{ +} + +static void +userdev_trigger (int dev, int state) +{ + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + + if (portc->open_mode & OPEN_READ) /* Handle input */ + { + portc->input_triggered = !!(state & OPEN_READ); + } + + if (portc->open_mode & OPEN_WRITE) /* Handle output */ + { + portc->output_triggered = !!(state & OPEN_WRITE); + } + + if (portc->output_triggered || portc->input_triggered) /* Something is going on */ + { + int tmout = devc->poll_ticks; + + if (tmout < 1) + tmout = 1; + + if (portc->port_type != PT_SERVER) + portc = portc->peer; /* Switch to the server side */ + + if (portc->output_triggered || portc->input_triggered) /* Something is going on */ + if (devc->timeout_id == 0) + { + devc->timeout_id = timeout (userdev_cb, portc, tmout); + } + } + else + { + if (portc->port_type == PT_SERVER) + if (devc->timeout_id != 0) + { + untimeout (devc->timeout_id); + devc->timeout_id = 0; + } + } +} + +/*ARGSUSED*/ +static int +userdev_server_prepare_for_input (int dev, int bsize, int bcount) +{ + oss_native_word flags; + + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->input_triggered = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_server_prepare_for_output (int dev, int bsize, int bcount) +{ + oss_native_word flags; + + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->output_triggered = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_client_prepare_for_input (int dev, int bsize, int bcount) +{ + oss_native_word flags; + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->input_triggered = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_client_prepare_for_output (int dev, int bsize, int bcount) +{ + oss_native_word flags; + userdev_portc_t *portc = audio_engines[dev]->portc; + userdev_devc_t *devc = audio_engines[dev]->devc; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + portc->output_triggered = 0; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ +#define MY_BUFFSIZE (64*1024) + if (dmap->dmabuf != NULL) + return 0; + dmap->dmabuf_phys = 0; /* Not mmap() capable */ + dmap->dmabuf = KERNEL_MALLOC (MY_BUFFSIZE); + if (dmap->dmabuf == NULL) + return OSS_ENOSPC; + dmap->buffsize = MY_BUFFSIZE; + + return 0; +} + +/*ARGSUSED*/ +static int +userdev_free_buffer (int dev, dmap_t * dmap, int direction) +{ + if (dmap->dmabuf == NULL) + return 0; + KERNEL_FREE (dmap->dmabuf); + + dmap->dmabuf = NULL; + return 0; +} + +#if 0 +static int +userdev_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ +} +#endif + +/*ARGSUSED*/ +static int +userdev_ioctl_override (int dev, unsigned int cmd, ioctl_arg arg) +{ +/* + * Purpose of this ioctl override function is to intercept mixer + * ioctl calls made on the client side and to hide everything + * outside the userdev instance from the application. + * + * Note that this ioctl is related with the client side audio device. However + * if /dev/mixer points to this (audio) device then all mixer acess will + * be redirected too. Also the vmix driver will redirect mixer/system ioctl + * calls to this function. + */ + int err; + userdev_devc_t *devc = audio_engines[dev]->devc; + adev_t *adev = audio_engines[devc->client_portc.audio_dev]; + + switch (cmd) + { + case SNDCTL_MIX_NRMIX: + return *arg=1; + break; + + case SNDCTL_MIX_NREXT: + *arg = devc->mixer_dev; + return OSS_EAGAIN; /* Continue with the default handler */ + break; + + case SNDCTL_SYSINFO: + { + /* + * Fake SNDCTL_SYSINFO to report just one mixer device which is + * the one associated with the client. + */ + oss_sysinfo *info = (oss_sysinfo *) arg; + int i; + + if ((err=oss_mixer_ext(dev, OSS_DEV_DSP_ENGINE, cmd, arg))<0) + return err; + + /* + * Hide all non-oss_userdev devices + */ + strcpy (info->product, "OSS (userdev)"); + info->nummixers = 1; + info->numcards = 1; + info->numaudios = 1; + for (i = 0; i < 8; i++) + info->openedaudio[i] = 0; + + return 0; + } + break; + + case SNDCTL_MIXERINFO: + { + oss_mixerinfo *info = (oss_mixerinfo *) arg; + + info->dev = devc->mixer_dev; /* Redirect to oss_userdev mixer */ + + if ((err=oss_mixer_ext(dev, OSS_DEV_DSP_ENGINE, cmd, arg))<0) + return err; + + strcpy(info->name, adev->name); + info->card_number = 0; + return 0; + } + + case SNDCTL_AUDIOINFO: + case SNDCTL_AUDIOINFO_EX: + { + oss_audioinfo *info = (oss_audioinfo *) arg; + + info->dev = devc->client_portc.audio_dev; + + cmd = SNDCTL_ENGINEINFO; + + if ((err=oss_mixer_ext(dev, OSS_DEV_DSP_ENGINE, cmd, arg))<0) + return err; + + info->card_number = 0; + return 0; + } + + case SNDCTL_CARDINFO: + { + oss_card_info *info = (oss_card_info *) arg; + + info->card = adev->card_number; /* Redirect to oss_userdev0 */ + + if ((err=oss_mixer_ext(dev, OSS_DEV_DSP_ENGINE, cmd, arg))<0) + return err; + + info->card = 0; + return 0; + } + + case SNDCTL_MIX_EXTINFO: + { + oss_mixext *ext = (oss_mixext*)arg; + + ext->dev = devc->mixer_dev; + + if ((err=oss_mixer_ext(dev, OSS_DEV_DSP_ENGINE, cmd, arg))<0) + return err; + + if (ext->type == MIXT_DEVROOT) + { + oss_mixext_root *root = (oss_mixext_root *) ext->data; + strncpy(root->name, adev->name, 48); + root->name[47]=0; + } + + return 0; + } + break; + + case SNDCTL_MIX_READ: + case SNDCTL_MIX_WRITE: + { + oss_mixer_value *ent = (oss_mixer_value*)arg; + + ent->dev = devc->mixer_dev; + + return OSS_EAGAIN; /* Redirect */ + } + break; + + default: + return OSS_EAGAIN; + } +} + +static audiodrv_t userdev_server_driver = { + userdev_server_open, + userdev_server_close, + userdev_output_block, + userdev_start_input, + userdev_server_ioctl, + userdev_server_prepare_for_input, + userdev_server_prepare_for_output, + userdev_reset, + NULL, + NULL, + NULL, + NULL, + userdev_trigger, + userdev_server_set_rate, + userdev_server_set_format, + userdev_server_set_channels, + NULL, + NULL, + userdev_check_input, + userdev_check_output, + userdev_alloc_buffer, + userdev_free_buffer, + NULL, + NULL, + NULL /* userdev_get_buffer_pointer */ +}; + +static audiodrv_t userdev_client_driver = { + userdev_client_open, + userdev_client_close, + userdev_output_block, + userdev_start_input, + userdev_ioctl, + userdev_client_prepare_for_input, + userdev_client_prepare_for_output, + userdev_reset, + NULL, + NULL, + NULL, + NULL, + userdev_trigger, + userdev_client_set_rate, + userdev_client_set_format, + userdev_client_set_channels, + NULL, + NULL, + userdev_check_input, + userdev_check_output, + userdev_alloc_buffer, + userdev_free_buffer, + NULL, + NULL, + NULL, // userdev_get_buffer_pointer + NULL, // userdev_calibrate_speed + NULL, // userdev_sync_control + NULL, // userdev_prepare_to_stop + NULL, // userdev_get_input_pointer + NULL, // userdev_get_output_pointer + NULL, // userdev_bind + NULL, // userdev_setup_fragments + NULL, // userdev_redirect + userdev_ioctl_override +}; + +static int +userdev_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg) +{ + + if (cmd == SOUND_MIXER_READ_CAPS) + return *arg = SOUND_CAP_NOLEGACY; + +#if 0 + if (cmd == SOUND_MIXER_READ_DEVMASK || + cmd == SOUND_MIXER_READ_RECMASK || cmd == SOUND_MIXER_READ_RECSRC) + return *arg = 0; + + if (cmd == SOUND_MIXER_READ_VOLUME || cmd == SOUND_MIXER_READ_PCM) + return *arg = 100 | (100 << 8); + if (cmd == SOUND_MIXER_WRITE_VOLUME || cmd == SOUND_MIXER_WRITE_PCM) + return *arg = 100 | (100 << 8); +#endif + return OSS_EINVAL; +} + +static mixer_driver_t userdev_mixer_driver = { + userdev_mixer_ioctl +}; + +static int +install_server (userdev_devc_t * devc) +{ + userdev_portc_t *portc = &devc->server_portc; + int adev; + + int opts = + ADEV_STEREOONLY | ADEV_16BITONLY | ADEV_VIRTUAL | + ADEV_FIXEDRATE | ADEV_SPECIAL | ADEV_HIDDEN | ADEV_DUPLEX; + + memset (portc, 0, sizeof (*portc)); + + portc->devc = devc; + portc->port_type = PT_SERVER; + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "User space audio device server side", + &userdev_server_driver, + sizeof (audiodrv_t), + opts, SUPPORTED_FORMATS, devc, -1)) < 0) + { + return adev; + } + + audio_engines[adev]->portc = portc; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = MAX_RATE; + audio_engines[adev]->min_channels = 1; + audio_engines[adev]->max_channels = MAX_CHANNELS; + audio_engines[adev]->vmix_mixer=NULL; + strcpy(audio_engines[adev]->devnode, userdev_server_devnode); + + portc->audio_dev = adev; + + return adev; +} + +static int +null_mixer_init(int de) +{ + return 0; +} + +static void +userdev_create_mixer(userdev_devc_t * devc) +{ + if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "OSS userdev mixer", + &userdev_mixer_driver, + sizeof (mixer_driver_t), devc)) < 0) + { + devc->mixer_dev = -1; + return; + } + mixer_ext_set_init_fn (devc->mixer_dev, null_mixer_init, USERDEV_MAX_MIXERS*2); +} + +static int +install_client (userdev_devc_t * devc) +{ + userdev_portc_t *portc = &devc->client_portc; + int adev; + + int opts = + ADEV_STEREOONLY | ADEV_16BITONLY | ADEV_VIRTUAL | ADEV_DUPLEX | + ADEV_FIXEDRATE | ADEV_SPECIAL | ADEV_LOOP; + + memset (portc, 0, sizeof (*portc)); + + userdev_create_mixer(devc); + + portc->devc = devc; + portc->port_type = PT_CLIENT; + + if (!userdev_visible_clientnodes && !(devc->create_flags & USERDEV_F_VMIX_PRIVATENODE)) + { + opts |= ADEV_HIDDEN; + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + "User space audio device", + &userdev_client_driver, + sizeof (audiodrv_t), + opts, SUPPORTED_FORMATS, devc, -1)) < 0) + { + return adev; + } + + if (!userdev_visible_clientnodes) /* Invisible client device nodes */ + strcpy(audio_engines[adev]->devnode, userdev_client_devnode); + + audio_engines[adev]->portc = portc; + audio_engines[adev]->mixer_dev = devc->mixer_dev; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = MAX_RATE; + audio_engines[adev]->min_channels = 1; + audio_engines[adev]->max_channels = MAX_CHANNELS; + + portc->audio_dev = adev; +#ifdef CONFIG_OSS_VMIX + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + + return adev; +} + +int +userdev_create_device_pair(void) +{ + int client_engine, server_engine; + userdev_devc_t *devc; + oss_native_word flags; + + if ((devc=PMALLOC(userdev_osdev, sizeof (*devc))) == NULL) + return OSS_ENOMEM; + memset(devc, 0, sizeof(*devc)); + + devc->osdev = userdev_osdev; + MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV); + devc->active=1; + + devc->rate = 48000; + devc->fmt = AFMT_S16_NE; + devc->fmt_bytes = 2; + devc->channels = 2; + devc->poll_ticks = 10; + + if ((server_engine=install_server (devc)) < 0) + return server_engine; + + if ((client_engine=install_client (devc)) < 0) + return client_engine; + + devc->client_portc.peer = &devc->server_portc; + devc->server_portc.peer = &devc->client_portc; + + /* + * Insert the device to the list of available devices + */ + MUTEX_ENTER_IRQDISABLE(userdev_global_mutex, flags); + devc->next_instance = userdev_active_device_list; + userdev_active_device_list = devc; + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); + + return server_engine; +} + +static void +userdev_free_device_pair (userdev_devc_t *devc) +{ + oss_native_word flags; + + set_adev_name(devc->client_portc.audio_dev, "User space audio device"); + set_adev_name(devc->server_portc.audio_dev, "User space audio device server side"); + + MUTEX_ENTER_IRQDISABLE(userdev_global_mutex, flags); + + devc->match_method = 0; + devc->match_key = 0; + + /* + * Add to the free device pair list. + */ + devc->next_instance = userdev_free_device_list; + userdev_free_device_list = devc; + + /* + * Remove the device pair from the active device list. + */ + + if (userdev_active_device_list == devc) /* First device in the list */ + { + userdev_active_device_list = userdev_active_device_list->next_instance; + } + else + { + userdev_devc_t *this = userdev_active_device_list, *prev = NULL; + + while (this != NULL) + { + if (this == devc) + { + prev->next_instance = this->next_instance; /* Remove */ + break; + } + + prev = this; + this = this->next_instance; + } + } + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); +} + +void +userdev_reinit_instance(userdev_devc_t *devc) +{ + if (devc->mixer_dev < 0) + return; + + mixer_ext_rebuild_all (devc->mixer_dev, null_mixer_init, USERDEV_MAX_MIXERS*2); +} + +void +userdev_delete_device_pair(userdev_devc_t *devc) +{ + if (!devc->active) + return; + + devc->active = 0; + MUTEX_CLEANUP(devc->mutex); +} + +int +usrdev_find_free_device_pair(void) +{ + oss_native_word flags; + userdev_devc_t *devc; + + MUTEX_ENTER_IRQDISABLE(userdev_global_mutex, flags); + + if (userdev_free_device_list != NULL) + { + devc = userdev_free_device_list; + userdev_free_device_list = userdev_free_device_list->next_instance; + + devc->next_instance = userdev_active_device_list; + userdev_active_device_list = devc; + + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); + return devc->server_portc.audio_dev; + } + MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); + + return OSS_ENXIO; +} diff --git a/kernel/drv/oss_userdev/userdev.h b/kernel/drv/oss_userdev/userdev.h new file mode 100644 index 0000000..1ed1040 --- /dev/null +++ b/kernel/drv/oss_userdev/userdev.h @@ -0,0 +1,81 @@ +/* + * Purpose: Definition file for the oss_userdev 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 MAX_RATE 192000 +#define MAX_CHANNELS 64 +#define SUPPORTED_FORMATS (AFMT_S16_NE|AFMT_S32_NE) + +typedef struct _userdev_devc_t userdev_devc_t; +typedef struct _userdev_portc_t userdev_portc_t; + +struct _userdev_portc_t +{ + userdev_devc_t *devc; + userdev_portc_t *peer; + int audio_dev; + int open_mode; + int port_type; +#define PT_CLIENT 1 +#define PT_SERVER 2 + + /* State variables */ + int input_triggered, output_triggered; +}; + +struct _userdev_devc_t +{ + oss_device_t *osdev; + int active; + oss_mutex_t mutex; + + int open_count; /* 0=not in use, 2=both client and server in use */ + + int create_flags; /* Flags from ioctl(USERDEV_CREATE_INSTANCE) */ + + unsigned int poll_ticks; /* Number of clock tickes (OSS_HZ) between polls. */ + + unsigned int match_method; + unsigned int match_key; + int mixer_dev; + + userdev_devc_t *next_instance; + + int rate; + int channels; + unsigned int fmt, fmt_bytes; + timeout_id_t timeout_id; + + userdev_portc_t client_portc; + userdev_portc_t server_portc; + + /* + * Mixer related fields + */ + int modify_counter; + int mixer_values[USERDEV_MAX_MIXERS]; +}; + +extern oss_device_t *userdev_osdev; +extern oss_mutex_t userdev_global_mutex; +extern userdev_devc_t *userdev_active_device_list; +extern userdev_devc_t *userdev_free_device_list; + +extern int userdev_create_device_pair(void); +extern void userdev_delete_device_pair(userdev_devc_t *devc); +extern int usrdev_find_free_device_pair(void); +extern void userdev_reinit_instance(userdev_devc_t *devc); + +extern char *userdev_client_devnode; +extern char *userdev_server_devnode; diff --git a/kernel/drv/oss_via823x/.config b/kernel/drv/oss_via823x/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_via823x/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_via823x/.devices b/kernel/drv/oss_via823x/.devices new file mode 100644 index 0000000..dfb8b74 --- /dev/null +++ b/kernel/drv/oss_via823x/.devices @@ -0,0 +1,5 @@ +oss_via823x pci1106,3059 VIA VT8233/8235/8237 +oss_via823x pci1106,4551 VIA VT5432B +oss_via823x pci1106,7059 VIA VT8233A +oss_via823x pcs1462,3800 MSI K7T266 +oss_via823x pcs1462,4720 MSI KT3 Ultra diff --git a/kernel/drv/oss_via823x/.name b/kernel/drv/oss_via823x/.name new file mode 100644 index 0000000..e947b9d --- /dev/null +++ b/kernel/drv/oss_via823x/.name @@ -0,0 +1 @@ +VIA VT8233/8235/8237 motherboard audio diff --git a/kernel/drv/oss_via823x/oss_via823x.c b/kernel/drv/oss_via823x/oss_via823x.c new file mode 100644 index 0000000..096a72a --- /dev/null +++ b/kernel/drv/oss_via823x/oss_via823x.c @@ -0,0 +1,1013 @@ +/* + * Purpose: Driver for the VIA8233/8235 AC97 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_via823x_cfg.h" +#include <oss_pci.h> +#include <ac97.h> +#include "via8233.h" + + +static void feed_sgd (via8233_devc * devc, dmap_t * dmap, engine_desc * eng); + +static int +ac97_read (void *devc_, int wIndex) +{ + oss_native_word flags; + unsigned int dwWriteValue = 0, dwTmpValue, i = 0; + via8233_devc *devc = devc_; + + + /* Index has only 7 bit */ + if (wIndex > 0x7F) + return 0; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + dwWriteValue = ((unsigned int) wIndex << 16) + CODEC_RD; + OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC); + oss_udelay (100); + /* Check AC CODEC access time out */ + for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) + { + /* if send command over, break */ + if (INL (devc->osdev, devc->base + AC97CODEC) & STA_VALID) + break; + oss_udelay (50); + } + if (i == CODEC_TIMEOUT_COUNT) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + } + + /* Check if Index still ours? If yes, return data, else return FAIL */ + dwTmpValue = INL (devc->osdev, devc->base + AC97CODEC); + OUTB (devc->osdev, 0x02, devc->base + AC97CODEC + 3); + if (((dwTmpValue & CODEC_INDEX) >> 16) == wIndex) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ((int) dwTmpValue & CODEC_DATA); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; + +} + +static int +ac97_write (void *devc_, int wIndex, int wData) +{ + oss_native_word flags; + unsigned int dwWriteValue = 0, i = 0; + via8233_devc *devc = devc_; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + dwWriteValue = ((unsigned int) wIndex << 16) + wData; + OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC); + oss_udelay (100); + + /* Check AC CODEC access time out */ + for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) + { + /* if send command over, break */ + if (!(INL (devc->osdev, devc->base + AC97CODEC) & IN_CMD)) + break; + oss_udelay (50); + } + if (i == CODEC_TIMEOUT_COUNT) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +via8233intr (oss_device_t * osdev) +{ + int serviced = 0, i; + via8233_devc *devc = osdev->devc; + via8233_portc *portc; + engine_desc *eng; + unsigned int engine_stat; + unsigned int status = 0; + oss_native_word flags; + + MUTEX_ENTER (devc->mutex, flags); + status = INL (devc->osdev, devc->base + 0x84); +#if 0 + // This is reported to cause hang because some status register bits + // may be turned on even ehen the device is not interrupting. + if (status == 0) + { + /* + * No interrupts are pending so we can stop without + * polling all the individual status registers. + */ + MUTEX_EXIT (devc->mutex, flags); + return 0; + } +#endif + + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + eng = portc->play_engine; + + if (eng != NULL) + if ((eng->mode & OPEN_WRITE) + && (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + engine_stat = INB (devc->osdev, eng->base + 0x00); + if (engine_stat & 0x01) + { + oss_audio_outputintr (portc->audiodev, 1); + feed_sgd (devc, audio_engines[portc->audiodev]->dmap_out, + eng); + serviced = 1; + } + OUTB (devc->osdev, engine_stat, eng->base + 0x00); + } + + eng = portc->rec_engine; + if (eng != NULL) + if ((eng->mode & OPEN_READ) + && (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + engine_stat = INB (devc->osdev, eng->base + 0x00); + if (engine_stat & 0x01) + { + oss_audio_inputintr (portc->audiodev, 0); + feed_sgd (devc, audio_engines[portc->audiodev]->dmap_in, eng); + serviced = 1; + } + OUTB (devc->osdev, engine_stat, eng->base + 0x00); + } + } + MUTEX_EXIT (devc->mutex, flags); + + return serviced; +} + +/* + * Audio routines + */ + +static int +via8233_audio_set_rate (int dev, int arg) +{ + via8233_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 +via8233_audio_set_channels (int dev, short arg) +{ + via8233_portc *portc = audio_engines[dev]->portc; + + if (arg > 6) + arg=6; + + if ((arg != 1) && (arg != 2) && (arg != 4) && (arg != 6)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +via8233_audio_set_format (int dev, unsigned int arg) +{ + via8233_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +via8233_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void via8233_audio_trigger (int dev, int state); + +static void +via8233_audio_reset (int dev) +{ + via8233_audio_trigger (dev, 0); +} + +static void +via8233_audio_reset_input (int dev) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +via8233_audio_reset_output (int dev) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +via8233_audio_open (int dev, int mode, int open_flags) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +via8233_audio_close (int dev, int mode) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_devc *devc = audio_engines[dev]->devc; + + via8233_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +via8233_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + via8233_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + +} + +/*ARGSUSED*/ +static void +via8233_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + via8233_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + +} + +static void +via8233_audio_trigger (int dev, int state) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_devc *devc = audio_engines[dev]->devc; + engine_desc *eng; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + if ((portc->open_mode & OPEN_WRITE) && portc->play_engine != NULL) + { + eng = portc->play_engine; + + if (state & PCM_ENABLE_OUTPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + !(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + /* Start with autoinit and SGD flag interrupts enabled */ + OUTB (devc->osdev, 0xa1, eng->base + 0x01); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */ + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + } + } + } + + if ((portc->open_mode & OPEN_READ) && portc->rec_engine != NULL) + { + eng = portc->rec_engine; + + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* Start with autoinit and SGD flag interrupts enabled */ + OUTB (devc->osdev, 0xa1, eng->base + 0x01); + 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; + OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */ + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static void +feed_sgd (via8233_devc * devc, dmap_t * dmap, engine_desc * eng) +{ + unsigned int addr, p, tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + addr = dmap->dmabuf_phys + eng->cfrag * dmap->fragment_size; + p = eng->sgd_ptr; + + eng->sgd[p].phaddr = addr; + eng->sgd[p].flags = dmap->fragment_size | SGD_FLAG; + if (p == (SGD_SIZE - 1)) + eng->sgd[p].flags |= SGD_EOL; + + /* Update the last entry ptr */ + tmp = INL (devc->osdev, eng->base + 0x08); + tmp &= 0x00ffffff; + tmp |= (p << 24); + OUTL (devc->osdev, tmp, eng->base + 0x08); + + eng->prev_sgd = p; + eng->frags[p] = eng->cfrag; + eng->cfrag = (eng->cfrag + 1) % dmap->nfrags; + eng->sgd_ptr = (eng->sgd_ptr + 1) % SGD_SIZE; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); +} + +/*ARGSUSED*/ +static int +via8233_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + via8233_devc *devc = audio_engines[dev]->devc; + via8233_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + engine_desc *eng; + int i; + unsigned int fmt; + oss_native_word flags; + + if (portc->rec_engine == NULL) + { + cmn_err (CE_WARN, "No rec engine (dev=%d)\n", dev); + return OSS_EIO; + } + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + eng = portc->rec_engine; + + OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */ + + eng->cfrag = 0; + eng->sgd_ptr = 0; + eng->prevpos = 0xffffffff; + + for (i = 0; i < 2; i++) + feed_sgd (devc, dmap, eng); + + OUTL (devc->osdev, eng->sgd_phys, eng->base + 0x04); + + fmt = 0; + if (portc->bits == AFMT_S16_LE) + fmt |= (1 << 21); + if (portc->channels == 2) + fmt |= (1 << 20); + + if (devc->chip_type != CHIP_8233A) + { + if (portc->speed == 48000) + fmt |= (1 << 20) - 1; + else + fmt |= ((1024 * portc->speed + 24000) / 48000) * 1024; + } + + fmt |= (eng->prev_sgd << 24); + OUTL (devc->osdev, fmt, eng->base + 0x08); + ac97_recrate (&devc->ac97devc, portc->speed); + + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +via8233_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + via8233_devc *devc = audio_engines[dev]->devc; + via8233_portc *portc = audio_engines[dev]->portc; + dmap_p dmap = audio_engines[dev]->dmap_out; + + engine_desc *eng; + int i, tmp; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + eng = portc->play_engine; + + OUTB (devc->osdev, 0x40, eng->base + 0x01); /* Stop */ + + eng->cfrag = 0; + eng->sgd_ptr = 0; + eng->prevpos = 0xffffffff; + + for (i = 0; i < 2; i++) + feed_sgd (devc, dmap, eng); + + OUTL (devc->osdev, eng->sgd_phys, eng->base + 0x4); + + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_AUDIO, SNDCTL_MIX_WRITE, 0); + + if (portc->bits == AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + } + ac97_spdif_setup (devc->mixer_dev, portc->speed, portc->bits); + + tmp = (portc->bits == AFMT_U8) ? 0 : 0x80; + tmp |= portc->channels << 4; + OUTB (devc->osdev, tmp, eng->base + 0x02); + + /* Select channel assignment - not valid for 8233A */ + tmp = 0; + if (devc->chip_type != CHIP_8233A) + { + switch (portc->channels) + { + case 1: + tmp = (1 << 0) | (1 << 4); + break; + case 2: + tmp = (1 << 0) | (2 << 4); + break; + case 4: + tmp = (1 << 0) | (2 << 4) | (3 << 8) | (4 << 12); + break; + case 6: + tmp = + (1 << 0) | (2 << 4) | (5 << 8) | (6 << 12) | (3 << 16) | (4 << + 20); + break; + default: + tmp = 0; + break; + } + } + tmp |= 0xFF000000; + OUTL (devc->osdev, tmp, eng->base + 0x08); + /* need to set the speed twice - for some odd reason */ + ac97_playrate (&devc->ac97devc, portc->speed); + ac97_playrate (&devc->ac97devc, portc->speed); + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +/*ARGSUSED*/ +static int +via8233_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + int err; + via8233_devc *devc = audio_engines[dev]->devc; + via8233_portc *portc = audio_engines[dev]->portc; + engine_desc *eng; + + if (dmap->dmabuf != NULL) + return 0; + + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + return err; + + + if (direction == PCM_ENABLE_INPUT) + { + eng = &devc->engines[REC_SGD_NUM]; + eng->mode = OPEN_READ; + portc->rec_engine = eng; + } + else + { + eng = &devc->engines[PLAY_SGD_NUM]; + eng->mode = OPEN_WRITE; + portc->play_engine = eng; + } + + return 0; +} + + +/*ARGSUSED*/ +static int +via8233_free_buffer (int dev, dmap_t * dmap, int direction) +{ + via8233_portc *portc = audio_engines[dev]->portc; + + if (dmap->dmabuf == NULL) + return 0; + oss_free_dmabuf (dev, dmap); + + dmap->dmabuf = NULL; + dmap->dmabuf_phys = 0; + + if (direction == PCM_ENABLE_OUTPUT) + portc->play_engine = NULL; + + if (direction == PCM_ENABLE_INPUT) + portc->rec_engine = NULL; + + return 0; +} + +static int +via8233_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + via8233_portc *portc = audio_engines[dev]->portc; + via8233_devc *devc = audio_engines[dev]->devc; + unsigned int ptr, pos, tmp; + engine_desc *eng; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + if (direction == PCM_ENABLE_OUTPUT) + { + int status; + /* int this_sgd, prev_sgd */ ; + + if (portc->play_engine == NULL + || !(portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + eng = portc->play_engine; + + ptr = INL (devc->osdev, eng->base + 0x0c); + status = INB (devc->osdev, eng->base + 0x00); + if (!(status & 0x80)) /* SGD not triggered */ + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + +#ifdef DO_TIMINGS + oss_timing_printf ("rawpos=%d", ptr); +#endif +#if 0 + this_sgd = ptr >> 24; + prev_sgd = eng->prevpos >> 24; + prev_sgd = (prev_sgd + 1) % SGD_SIZE; /* Increment */ + /* Chip bug catcher */ + if (((ptr & 0xffffff) == 0) && + ((eng->prevpos & 0xffffff) == 0) && (this_sgd == prev_sgd)) + ptr = eng->prevpos; + else + eng->prevpos = ptr; +#endif + + tmp = ptr & 0xffffff; + ptr >>= 24; + + pos = eng->frags[ptr] * dmap->fragment_size; + pos += (dmap->fragment_size - tmp) & ~3; + +#ifdef DO_TIMINGS + oss_timing_printf ("Playpos=%d", pos); +#endif + pos = pos % dmap->bytes_in_use; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return pos; + } + + if (direction == PCM_ENABLE_INPUT) + { + int status; + /* int this_sgd, prev_sgd; */ + + if (portc->rec_engine == NULL + || !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + eng = portc->rec_engine; + + ptr = INL (devc->osdev, eng->base + 0x0c); + status = INB (devc->osdev, eng->base + 0x00); + if (!(status & 0x80)) /* SGD not triggered */ + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + +#if 0 + this_sgd = ptr >> 24; + prev_sgd = eng->prevpos >> 24; + prev_sgd = (prev_sgd + 1) % SGD_SIZE; /* Increment */ + + /* Chip bug catcher */ + if (((ptr & 0xffffff) == 0) && + ((eng->prevpos & 0xffffff) == 0) && (this_sgd == prev_sgd)) + ptr = eng->prevpos; + else + eng->prevpos = ptr; +#endif + + tmp = ptr & 0xffffff; + ptr >>= 24; + + pos = eng->frags[ptr] * dmap->fragment_size; + pos += (dmap->fragment_size - tmp) & ~3; + +#ifdef DO_TIMINGS + oss_timing_printf ("Recpos=%d", pos); +#endif + pos = pos % dmap->bytes_in_use; + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return pos; + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static const audiodrv_t via8233_audio_driver = { + via8233_audio_open, + via8233_audio_close, + via8233_audio_output_block, + via8233_audio_start_input, + via8233_audio_ioctl, + via8233_audio_prepare_for_input, + via8233_audio_prepare_for_output, + via8233_audio_reset, + NULL, + NULL, + via8233_audio_reset_input, + via8233_audio_reset_output, + via8233_audio_trigger, + via8233_audio_set_rate, + via8233_audio_set_format, + via8233_audio_set_channels, + NULL, + NULL, + NULL, /* via8233_check_input, */ + NULL, /* via8233_check_output, */ + via8233_alloc_buffer, + via8233_free_buffer, + NULL, + NULL, + via8233_get_buffer_pointer +}; + +static int +via8233_alloc_engines (via8233_devc * devc) +{ + engine_desc *eng; + oss_native_word phaddr; + int i; + + for (i = 0; i < MAX_ENGINES; i++) + { + if (i) + { + eng = &devc->engines[REC_SGD_NUM]; + eng->base = devc->base + 0x60; + } + else + { + eng = &devc->engines[PLAY_SGD_NUM]; + eng->base = devc->base + 0x40; + } + + if (eng->sgd == NULL) + { + eng->sgd = + CONTIG_MALLOC (devc->osdev, SGD_ALLOC, MEMLIMIT_32BITS, &phaddr, eng->sgd_dma_handle); + + if (eng->sgd == NULL) + { + cmn_err (CE_WARN, "can't allocate SGD table\n"); + return OSS_ENOSPC; + } + eng->sgd_phys = phaddr; + } + } + return 0; +} + +static int +via8233_init (via8233_devc * devc) +{ + int my_mixer, adev, opts; + via8233_portc *portc; + int i; + char tmp_name[50]; + int first_dev = 0; + + /* allocate the Scatter Gather Engine buffers */ + if (via8233_alloc_engines (devc) < 0) + { + cmn_err (CE_WARN, "Unable to allocate engines\n"); + return OSS_ENOSPC; + } + + /* + * Init mixer + */ + my_mixer = + ac97_install (&devc->ac97devc, "VIA823x AC97 Mixer", ac97_read, + ac97_write, devc, devc->osdev); + + if (my_mixer == -1) + { + cmn_err (CE_WARN, "AC97 mixer installation failed\n"); + return 0; /* No mixer */ + } + + devc->mixer_dev = my_mixer; + mixer_devs[my_mixer]->priority = 10; /* Known motherboard device */ + + /* enable S/PDIF */ + devc->ac97devc.spdif_slot = SPDIF_SLOT34; + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 1); + + for (i = 0; i < MAX_PORTC; i++) + { + opts = ADEV_AUTOMODE; + + if (!ac97_varrate (&devc->ac97devc)) + { + opts |= ADEV_FIXEDRATE; + } + + portc = &devc->portc[i]; + if (i == 0) + { + opts |= ADEV_DUPLEX; + strcpy (tmp_name, devc->chip_name); + } + else + { + opts |= ADEV_DUPLEX | ADEV_SHADOW; + strcpy (tmp_name, devc->chip_name); + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &via8233_audio_driver, + sizeof (audiodrv_t), + opts, + AFMT_U8 | AFMT_S16_LE | AFMT_AC3, + devc, -1)) < 0) + { + adev = -1; + return 1; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + audio_engines[adev]->min_channels = 2; + audio_engines[adev]->max_channels = 6; + if (opts & ADEV_FIXEDRATE) + { + audio_engines[adev]->fixed_rate = 48000; + audio_engines[adev]->min_rate = 48000; + audio_engines[adev]->max_rate = 48000; + } + + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = adev; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + } + + return 1; +} + +int +oss_via823x_attach (oss_device_t * osdev) +{ + unsigned char pci_irq_line, pci_revision, bTmp /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + via8233_devc *devc; + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + DDB (cmn_err + (CE_CONT, "oss_via823x_attach(Vendor %x, device %x)\n", vendor, device)); + if ((vendor != VIA_VENDOR_ID) + || (device != VIA_8233_ID && device != VIA_8233A_ID)) + { + + cmn_err (CE_WARN, "Hardware not recognized (vendor=%x, dev=%x)\n", + vendor, device); + return 0; + } + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &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->chip_type = CHIP_8233; + devc->chip_name = "VIA VT8233"; + + if (pci_revision == 0x50) + devc->chip_name = "VIA VT8235"; + + if (pci_revision == 0x60) + devc->chip_name = "VIA VT8237"; + + if ((device == VIA_8233A_ID) || + (device == VIA_8233_ID && pci_revision == 0x40)) + { + devc->chip_type = CHIP_8233A; + devc->chip_name = "VIA VT8233A"; + } + + pci_write_config_byte (osdev, 0x41, 0xc0); /*ENAC97 & deassert RESET */ + + oss_udelay (10); + pci_read_config_byte (osdev, 0x41, &bTmp); + oss_udelay (10); + if (devc->chip_type == CHIP_8233A) + bTmp |= 0x0C; /* Enable var rate support */ + else + bTmp |= 0x0f; /* enable VRA,SB,DX */ + pci_write_config_byte (osdev, 0x41, bTmp); + oss_udelay (10); + + if (devc->chip_type == CHIP_8233A) + { + pci_read_config_byte (osdev, 0x49, &bTmp); + oss_udelay (10); + pci_write_config_byte (osdev, 0x49, 0x0); + } + else + { + /* set slot 3,4 as SPDIF on VIA8235 - AC3 passthrough magic! */ + pci_write_config_byte (osdev, 0x49, 0x1); + } + + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + /* Remove I/O space marker in bit 0. */ + devc->base &= ~0x3; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->irq = pci_irq_line; + + 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 (oss_register_interrupts (devc->osdev, 0, via8233intr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to register interrupts\n"); + return 0; + } + + return via8233_init (devc); /* Detected */ +} + +int +oss_via823x_detach (oss_device_t * osdev) +{ + via8233_devc *devc = (via8233_devc *) osdev->devc; + engine_desc *eng; + int i; + + if (oss_disable_device (devc->osdev) < 0) + return 0; + + + /* disable S/PDIF */ + if (devc->mixer_dev > 0) + ac97_spdifout_ctl (devc->mixer_dev, SPDIFOUT_ENABLE, SNDCTL_MIX_WRITE, 0); + + oss_unregister_interrupts (devc->osdev); + + for (i = 0; i < MAX_ENGINES; i++) + { + eng = &devc->engines[i]; + if (eng->sgd != NULL) + { + CONTIG_FREE (devc->osdev, eng->sgd, SGD_ALLOC, eng->sgd_dma_handle); + eng->sgd = NULL; + } + } + + 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/kernel/drv/oss_via823x/oss_via823x.man b/kernel/drv/oss_via823x/oss_via823x.man new file mode 100644 index 0000000..90aa34c --- /dev/null +++ b/kernel/drv/oss_via823x/oss_via823x.man @@ -0,0 +1,20 @@ +NAME +oss_via823x - Open Sound System driver for VIA 8233/8235/8237 audio controllers. + +DESCRIPTION + +VIA823x device characteristics: + o 8/16 bit playback/record + o mono/stereo/4/5.1 (Dolby) playback + o mono/stereo recording + o 8KHz to 48Khz sample rate. + o SPDIF input/output capability based on AC97 codec attech to the + VIA823x controller. +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_via823x.conf Device configuration + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_via823x/via8233.h b/kernel/drv/oss_via823x/via8233.h new file mode 100644 index 0000000..7d2ad37 --- /dev/null +++ b/kernel/drv/oss_via823x/via8233.h @@ -0,0 +1,97 @@ +/* + * Purpose: Definitions for the via8233 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 VIA_VENDOR_ID 0x1106 +#define VIA_8233_ID 0x3059 +#define VIA_8233A_ID 0x7059 + +#define PLAY_SGD_NUM 1 +#define REC_SGD_NUM 0 +#define MAX_ENGINES 2 +#define MAX_PORTC 2 + +#define SGD_SIZE 256 +#define SGD_ALLOC 4096 +#define SGD_EOL 0x80000000 +#define SGD_FLAG 0x40000000 + +#define CODEC_TIMEOUT_COUNT 500 +#define AC97CODEC 0x80 /*Access AC97 Codec */ +#define IN_CMD 0x01000000 /*busy in sending */ +#define STA_VALID 0x02000000 /*1:status data is valid */ +#define CODEC_RD 0x00800000 /*Read CODEC status */ +#define CODEC_INDEX 0x007F0000 /*Index of command register to access */ +#define CODEC_DATA 0x0000FFFF /*AC97 status register data */ + +typedef struct +{ + unsigned int phaddr; + unsigned int flags; +} +SGD_entry; + +struct via8233_portc; + +typedef struct +{ + int sgd_num, base; + oss_dma_handle_t sgd_dma_handle; + int mode; + SGD_entry *sgd; + oss_native_word sgd_phys; + int sgd_ptr; + int prev_sgd; + int cfrag; + unsigned int prevpos; + short frags[SGD_SIZE]; + struct via8233_portc *portc; +} +engine_desc; + +typedef struct via8233_portc +{ + int audiodev; + int open_mode; + int mode_mask; + int speed, bits, channels; + engine_desc *play_engine, *rec_engine; + int trigger_bits; + int audio_enabled; +} +via8233_portc; + + +typedef struct via8233_devc +{ + oss_device_t *osdev; + int chip_type; +#define CHIP_8233 0 +#define CHIP_8233A 1 + char *chip_name; + int multi_channel_active; + oss_native_word base; + int irq; + int open_mode; + oss_mutex_t mutex; /* For normal locking */ + oss_mutex_t low_mutex; /* For low level routines */ +/* + * Mixer + */ + ac97_devc ac97devc; + int mixer_dev; + + via8233_portc portc[MAX_PORTC]; + engine_desc engines[MAX_ENGINES]; +} +via8233_devc; diff --git a/kernel/drv/oss_via97/.config b/kernel/drv/oss_via97/.config new file mode 100644 index 0000000..5280084 --- /dev/null +++ b/kernel/drv/oss_via97/.config @@ -0,0 +1 @@ +platform=i86pc diff --git a/kernel/drv/oss_via97/.devices b/kernel/drv/oss_via97/.devices new file mode 100644 index 0000000..d2dfc0f --- /dev/null +++ b/kernel/drv/oss_via97/.devices @@ -0,0 +1 @@ +oss_via97 pci1106,3058 VIA VT82C686 diff --git a/kernel/drv/oss_via97/.name b/kernel/drv/oss_via97/.name new file mode 100644 index 0000000..3860aeb --- /dev/null +++ b/kernel/drv/oss_via97/.name @@ -0,0 +1 @@ +VIA VT82C686 (via97) diff --git a/kernel/drv/oss_via97/oss_via97.c b/kernel/drv/oss_via97/oss_via97.c new file mode 100644 index 0000000..ce79841 --- /dev/null +++ b/kernel/drv/oss_via97/oss_via97.c @@ -0,0 +1,944 @@ +/* + * uPurpose: Driver for the VIA VT82C686A AC97 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_via97_cfg.h" +#include "oss_pci.h" +#include "ac97.h" + +#define VIA_VENDOR_ID 0x1106 +#define VIA_82C686 0x3058 + +#define CODEC_TIMEOUT_COUNT 500 +#define AC97CODEC 0x80 /*Access AC97 Codec */ +#define IN_CMD 0x01000000 /*busy in sending */ +#define STA_VALID 0x02000000 /*1:status data is valid */ +#define CODEC_RD 0x00800000 /*Read CODEC status */ +#define CODEC_INDEX 0x007F0000 /*Index of command register to access */ +#define CODEC_DATA 0x0000FFFF /*AC97 status register data */ + +typedef struct +{ + unsigned int phaddr; + unsigned int flags; +} +SGD_entry; + +typedef struct +{ + int open_mode; + int speed, bits, channels; + int audiodev; + int audio_enabled; + int trigger_bits; +} +via97_portc; + +typedef struct via97_devc +{ + oss_device_t *osdev; + oss_native_word base; + int irq; + int open_mode; + char *chip_name; +/* + * Mixer + */ + ac97_devc ac97devc; + +/* + * MIDI + */ + + int mpu_base; + int mpu_attached; + + /* Audio parameters */ + via97_portc portc[2]; + oss_mutex_t mutex; /* For normal locking */ + oss_mutex_t low_mutex; /* For low level routines */ + + /* Memory allocation and scatter/gather info */ +#define BUFFER_SIZE (128*1024) + +/* NOTE! Check SGD_ALLOC if changing SGD_SIZE */ +#define MIN_BLOCK 64 +#define SGD_SIZE (BUFFER_SIZE/MIN_BLOCK) +#define SGD_TOTAL_SIZE (2*SGD_SIZE) +#define SGD_ALLOC (SGD_TOTAL_SIZE*8) + + SGD_entry *SGD_table; + oss_native_word SGD_table_phys; + int play_sgd_ptr, rec_sgd_ptr; + oss_dma_handle_t sgd_dma_handle; + unsigned int play_sgd_phys, rec_sgd_phys; +} +via97_devc; + +static int +ac97_read (void *devc_, int wIndex) +{ + oss_native_word dwWriteValue = 0, dwTmpValue; + unsigned int i = 0; + oss_native_word flags; + via97_devc *devc = devc_; + + /* Index has only 7 bit */ + if (wIndex > 0x7F) + return 0; + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + dwWriteValue = ((oss_native_word) wIndex << 16) + CODEC_RD; + OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC); + oss_udelay (100); + /* Check AC CODEC access time out */ + for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) + { + /* if send command over, break */ + if (INL (devc->osdev, devc->base + AC97CODEC) & STA_VALID) + break; + oss_udelay (50); + } + if (i == CODEC_TIMEOUT_COUNT) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + } + + /* Check if Index still ours? If yes, return data, else return FAIL */ + dwTmpValue = INL (devc->osdev, devc->base + AC97CODEC); + OUTB (devc->osdev, 0x02, devc->base + AC97CODEC + 3); + if (((dwTmpValue & CODEC_INDEX) >> 16) == wIndex) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ((int) dwTmpValue & CODEC_DATA); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; + +} + +static int +ac97_write (void *devc_, int wIndex, int wData) +{ + oss_native_word dwWriteValue = 0; + unsigned int i = 0; + oss_native_word flags; + via97_devc *devc = devc_; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + dwWriteValue = ((oss_native_word) wIndex << 16) + wData; + OUTL (devc->osdev, dwWriteValue, devc->base + AC97CODEC); + oss_udelay (100); + + /* Check AC CODEC access time out */ + for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) + { + /* if send command over, break */ + if (!(INL (devc->osdev, devc->base + AC97CODEC) & IN_CMD)) + break; + oss_udelay (50); + } + if (i == CODEC_TIMEOUT_COUNT) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return (-1); + } + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; +} + +static int +via97intr (oss_device_t * osdev) +{ + via97_devc *devc = (via97_devc *) osdev->devc; + via97_portc *portc; + unsigned char status; + int serviced = 0; + int i; + +#ifdef OBSOLETED_STUFF + if (devc->mpu_attached) + { + if (uart401intr (INT_HANDLER_CALL (devc->irq))) + serviced = 1; + } +#endif + + /* Handle playback interrupt */ + status = INB (devc->osdev, devc->base + 0x00); + + if (status & 0x01) + { + serviced = 1; + for (i = 0; i < 2; i++) + { + portc = &devc->portc[i]; + /* IOC Interrupt */ + if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && (status & 0x01)) + oss_audio_outputintr (portc->audiodev, 0); + } + } + OUTB (devc->osdev, status | 0x01, devc->base + 0x00); + + + /* Handle record interrupt */ + status = INB (devc->osdev, devc->base + 0x10); + + if (status & 0x01) + { + serviced = 1; + for (i = 0; i < 2; i++) + { + portc = &devc->portc[i]; + /* IOC Interrupt */ + if ((portc->trigger_bits & PCM_ENABLE_INPUT) && (status & 0x01)) + oss_audio_inputintr (portc->audiodev, 0); + } + } + + OUTB (devc->osdev, status | 0x01, devc->base + 0x10); + return serviced; +} + +/* + * Audio routines + */ + +static int +via97_audio_set_rate (int dev, int arg) +{ + via97_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 +via97_audio_set_channels (int dev, short arg) +{ + via97_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->channels; + + + if ((arg != 1) && (arg != 2)) + return portc->channels = 2; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +via97_audio_set_format (int dev, unsigned int arg) +{ + via97_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE))) + return portc->bits = AFMT_S16_LE; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +via97_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void via97_audio_trigger (int dev, int state); + +static void +via97_audio_reset (int dev) +{ + via97_audio_trigger (dev, 0); +} + +static void +via97_audio_reset_input (int dev) +{ + via97_portc *portc = audio_engines[dev]->portc; + via97_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +via97_audio_reset_output (int dev) +{ + via97_portc *portc = audio_engines[dev]->portc; + via97_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +via97_audio_open (int dev, int mode, int open_flags) +{ + via97_portc *portc = audio_engines[dev]->portc; + via97_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; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +via97_audio_close (int dev, int mode) +{ + via97_portc *portc = audio_engines[dev]->portc; + via97_devc *devc = audio_engines[dev]->devc; + + via97_audio_reset (dev); + portc->open_mode = 0; + devc->open_mode &= ~mode; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +via97_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + via97_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + +} + +/*ARGSUSED*/ +static void +via97_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + via97_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + +} + +static void +via97_audio_trigger (int dev, int state) +{ + via97_devc *devc = audio_engines[dev]->devc; + via97_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + 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)) + { + OUTB (devc->osdev, 0x80, devc->base + 0x01); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + OUTB (devc->osdev, 0x40, devc->base + 0x01); + } + } + } + + if (portc->open_mode & OPEN_READ) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + + OUTB (devc->osdev, 0x80, devc->base + 0x11); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + OUTB (devc->osdev, 0x40, devc->base + 0x11); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +/*ARGSUSED*/ +static int +via97_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + via97_devc *devc = audio_engines[dev]->devc; + via97_portc *portc = audio_engines[dev]->portc; + int i, sgd_ptr; + dmap_t *dmap = audio_engines[dev]->dmap_in; + unsigned char tmp; + oss_native_word flags; + + if (audio_engines[dev]->dmap_in->dmabuf_phys == 0) + return OSS_ENOSPC; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + tmp = 0x81; /* Auto start at EOL, interrupt on FLAG */ + + if (portc->bits != AFMT_U8) + tmp |= 0x20; + if (portc->channels != 1) + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->base + 0x12); + + ac97_recrate (&devc->ac97devc, portc->speed); + + sgd_ptr = devc->rec_sgd_ptr; + for (i = 0; i < dmap->nfrags; i++) + { + if (sgd_ptr >= SGD_TOTAL_SIZE) + { + cmn_err (CE_WARN, "Out of Record SGD entries\n"); + return OSS_ENOSPC; + } + + devc->SGD_table[sgd_ptr].phaddr = + dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->SGD_table[sgd_ptr].flags = 0x40000000 | dmap->fragment_size; + + sgd_ptr++; + } + + devc->SGD_table[sgd_ptr - 1].flags |= 0x80000000; /* EOL */ + devc->rec_sgd_phys = + devc->SGD_table_phys + devc->rec_sgd_ptr * sizeof (SGD_entry); + OUTL (devc->osdev, devc->rec_sgd_phys, devc->base + 0x14); + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +via97_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + via97_devc *devc = audio_engines[dev]->devc; + via97_portc *portc = audio_engines[dev]->portc; + int i, sgd_ptr; + dmap_t *dmap = audio_engines[dev]->dmap_out; + unsigned char tmp; + oss_native_word flags; + + if (audio_engines[dev]->dmap_out->dmabuf_phys == 0) + return OSS_ENOSPC; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + tmp = 0x81; /* Auto start at EOL, interrupt on FLAG */ + + if (portc->bits != AFMT_U8) + tmp |= 0x20; + if (portc->channels != 1) + tmp |= 0x10; + OUTB (devc->osdev, tmp, devc->base + 0x02); + + ac97_playrate (&devc->ac97devc, portc->speed); + + sgd_ptr = devc->play_sgd_ptr; + + for (i = 0; i < dmap->nfrags; i++) + { + if (sgd_ptr >= SGD_TOTAL_SIZE) + { + cmn_err (CE_WARN, "Out of Playback SGD entries\n"); + return OSS_ENOSPC; + } + + devc->SGD_table[sgd_ptr].phaddr = + dmap->dmabuf_phys + (i * dmap->fragment_size); + devc->SGD_table[sgd_ptr].flags = 0x40000000 | dmap->fragment_size; + + sgd_ptr++; + } + + devc->SGD_table[sgd_ptr - 1].flags |= 0x80000000; /* EOL */ + devc->play_sgd_phys = + devc->SGD_table_phys + devc->play_sgd_ptr * sizeof (SGD_entry); + OUTL (devc->osdev, devc->play_sgd_phys, devc->base + 0x04); + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +static int +via97_alloc_buffer (int dev, dmap_t * dmap, int direction) +{ + int err; + + if (dmap->dmabuf != NULL) + return 0; + if ((err = oss_alloc_dmabuf (dev, dmap, direction)) < 0) + return err; + + if (dmap->buffsize > BUFFER_SIZE) + { + cmn_err (CE_WARN, "Too large DMA buffer (%d/%d) - truncated\n", + dmap->buffsize, BUFFER_SIZE); + dmap->buffsize = BUFFER_SIZE; + } + + return 0; +} + +static int +via97_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ +/* + * Unfortunately the VIA chip seems to raise interrupt about 32 bytes before + * the DMA pointer moves to a new fragment. This means that the bytes value + * returned by SNDCTL_DSP_GET[]PTR will be bogus during few samples before + * the pointer wraps back to the beginning of buffer. + * + * If mmap() is not being used this routine will return 0 during this period. + */ + via97_devc *devc = audio_engines[dev]->devc; + unsigned int ptr, sgd; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + + if (direction == PCM_ENABLE_OUTPUT) + { + ptr = INL (devc->osdev, devc->base + 0x0c) & 0xffffff; + sgd = + ((INL (devc->osdev, devc->base + 0x04) - devc->play_sgd_phys) / 8) - + 1; + + ptr = dmap->fragment_size - ptr; + ptr = ptr + (sgd * dmap->fragment_size); +//cmn_err(CE_CONT, "%d/%d\n", sgd, ptr); + } + else + { + ptr = INL (devc->osdev, devc->base + 0x1c) & 0xffffff; + sgd = + ((INL (devc->osdev, devc->base + 0x14) - devc->rec_sgd_phys) / 8) - 1; + + ptr = dmap->fragment_size - ptr; + ptr = ptr + (sgd * dmap->fragment_size); + } + + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return ptr; +} + +static const audiodrv_t via97_audio_driver = { + via97_audio_open, + via97_audio_close, + via97_audio_output_block, + via97_audio_start_input, + via97_audio_ioctl, + via97_audio_prepare_for_input, + via97_audio_prepare_for_output, + via97_audio_reset, + NULL, + NULL, + via97_audio_reset_input, + via97_audio_reset_output, + via97_audio_trigger, + via97_audio_set_rate, + via97_audio_set_format, + via97_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + via97_alloc_buffer, + NULL, /* via97_free_buffer, */ + NULL, + NULL, + via97_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_mpu (via97_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 = "VIA97 external MIDI"; + 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 1 + if (!probe_uart401 (&hw_config)) + { + cmn_err (CE_WARN, "MPU-401 was not detected\n"); + return; + } +#endif + DDB (cmn_err (CE_WARN, "MPU-401 detected - Good\n")); + attach_uart401 (&hw_config); + devc->mpu_attached = 1; +} + +static void +unload_mpu (via97_devc * devc) +{ + struct address_info hw_config; + + if (devc == NULL || !devc->mpu_attached) + return; + + devc->mpu_attached = 0; + 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 = "VIA97"; + 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; + + unload_uart401 (&hw_config); + +} +#endif + +static int +init_via97 (via97_devc * devc) +{ + int my_mixer, adev, opts, i; + int first_dev = 0; + oss_native_word phaddr; + + +/* + * Allocate the SGD buffers + */ + + if (devc->SGD_table == NULL) + { + devc->SGD_table = + CONTIG_MALLOC (devc->osdev, SGD_ALLOC, MEMLIMIT_32BITS, &phaddr, devc->sgd_dma_handle); + + if (devc->SGD_table == NULL) + return OSS_ENOSPC; + devc->SGD_table_phys = phaddr; + } + + /* + * Allocate SGD entries for recording and playback. + */ + devc->rec_sgd_ptr = 0; + devc->play_sgd_ptr = SGD_SIZE; +/* + * Init mixer + */ + my_mixer = + ac97_install (&devc->ac97devc, "VIA82C686 AC97 Mixer", ac97_read, + ac97_write, devc, devc->osdev); + if (my_mixer == -1) + return 0; /* No mixer */ + + mixer_devs[my_mixer]->priority = 10; /* Known motherboard device */ + + /* enable variable rate */ + ac97_write (devc, 0x2a, 0x01); + +#ifdef OBSOLETED_STUFF + DDB (cmn_err (CE_WARN, "Probing UART401 at 0x%x\n", devc->mpu_base)); + attach_mpu (devc); +#endif + + for (i = 0; i < 2; i++) + { + via97_portc *portc = &devc->portc[i]; + char tmp_name[100]; + + opts = ADEV_AUTOMODE; + + if (!ac97_varrate (&devc->ac97devc)) + { + opts |= ADEV_FIXEDRATE; + } + + if (i == 0) + { + opts |= ADEV_DUPLEX; + strcpy (tmp_name, "VIA 82C686 AC97 Controller"); + } + else + { + opts |= ADEV_DUPLEX | ADEV_SHADOW; + strcpy (tmp_name, "VIA 82C686 AC97 Controller"); + } + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &via97_audio_driver, + sizeof (audiodrv_t), + opts, + 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]->rate_source = first_dev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->min_rate = 8000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + portc->open_mode = 0; + portc->audio_enabled = 0; + portc->audiodev = adev; + audio_engines[adev]->min_block = MIN_BLOCK; + audio_engines[adev]->max_block = 4 * 1024; + audio_engines[adev]->max_fragments = SGD_SIZE; + if (opts & ADEV_FIXEDRATE) + { + audio_engines[adev]->fixed_rate = 48000; + audio_engines[adev]->min_rate = 48000; + audio_engines[adev]->max_rate = 48000; + } +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + } + return 1; +} + +int +oss_via97_attach (oss_device_t * osdev) +{ + unsigned char tmp, pci_irq_line, pci_revision /*, pci_latency */ ; + unsigned short pci_command, vendor, device; + unsigned int pci_ioaddr; + int mpu_base; + via97_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered VT82C686 probe routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (vendor != VIA_VENDOR_ID || device != VIA_82C686) + return 0; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &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->chip_name = "VIA VT82C686"; + + /* Enable codec, etc */ + + pci_write_config_byte (osdev, 0x41, 0xc0); + oss_udelay (10); + pci_read_config_byte (osdev, 0x41, &tmp); + pci_write_config_byte (osdev, 0x41, tmp | 0x0c); + oss_udelay (10); + + /* setup game port/MIDI */ + pci_write_config_byte (osdev, 0x42, 0x2a); + /* disable FM io */ + pci_write_config_byte (osdev, 0x48, 0x00); + + /* Enable interrupt on FLAG and on EOL */ + tmp = INB (devc->osdev, devc->base + 0x22); + OUTB (devc->osdev, tmp | 0x83, devc->base + 0x22); + + + /* Enable MPU401 */ + pci_read_config_byte (osdev, 0x8, &tmp); + if ((tmp & 0xff) >= 0x20) + { + pci_read_config_byte (osdev, 0x42, &tmp); + pci_write_config_byte (osdev, 0x42, tmp & 0x3f); + } + + pci_read_config_byte (osdev, 0x43, &tmp); + switch ((tmp & 0x0c) >> 2) + { + case 0: + mpu_base = 0x300; + break; + case 1: + mpu_base = 0x310; + break; + case 2: + mpu_base = 0x320; + break; + default: + mpu_base = 0x330; + break; + } + + /* map PCI IO address space */ + devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr); + /* Remove I/O space marker in bit 0. */ + devc->base &= ~0x3; + + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + devc->irq = pci_irq_line; + devc->mpu_base = mpu_base; + devc->SGD_table = NULL; + devc->mpu_attached = 0; + devc->open_mode = 0; + + 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 (oss_register_interrupts (devc->osdev, 0, via97intr, NULL) < 0) + { + cmn_err (CE_WARN, "Unable to register interrupts\n"); + return 0; + } + + return init_via97 (devc); /* Detected */ +} + + +int +oss_via97_detach (oss_device_t * osdev) +{ + via97_devc *devc = (via97_devc *) osdev->devc; + + + if (oss_disable_device (devc->osdev) < 0) + return 0; + + OUTB (devc->osdev, 0x40, devc->base + 0x01); + OUTB (devc->osdev, 0x40, devc->base + 0x11); + OUTB (devc->osdev, 0, devc->base + 0x02); + OUTB (devc->osdev, 0, devc->base + 0x12); + OUTL (devc->osdev, 0, devc->base + 0x04); + OUTL (devc->osdev, 0, devc->base + 0x14); + OUTL (devc->osdev, 0, devc->base + 0x22); + oss_udelay (30); + +#ifdef OBSOLETED_STUFF + if (devc->mpu_attached) + unload_mpu (devc); +#endif + + oss_unregister_interrupts (devc->osdev); + + if (devc->SGD_table != NULL) + { + CONTIG_FREE (devc->osdev, devc->SGD_table, SGD_ALLOC, devc->sgd_dma_handle); + devc->SGD_table = NULL; + } + + 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/kernel/drv/oss_via97/oss_via97.man b/kernel/drv/oss_via97/oss_via97.man new file mode 100644 index 0000000..075390b --- /dev/null +++ b/kernel/drv/oss_via97/oss_via97.man @@ -0,0 +1,19 @@ +NAME +oss_via97 - VIA 82C686 audio driver + +DESCRIPTION +Open Sound System driver for VIA 82C686A and 82C686B audio controllers. + +VIA97 device characteristics: + o 8/16 bit playback/record + o mono/stereo playback/recording + o 8KHz to 48Khz sample rate. + +OPTIONS +None + +FILES +CONFIGFILEPATH/oss_via97.conf Device configuration file. + +AUTHOR +4Front Technologies diff --git a/kernel/drv/oss_ymf7xx/.devices b/kernel/drv/oss_ymf7xx/.devices new file mode 100644 index 0000000..fd55bd0 --- /dev/null +++ b/kernel/drv/oss_ymf7xx/.devices @@ -0,0 +1,7 @@ +oss_ymf7xx pci1073,10 Yamaha DS-XG YMF744 +oss_ymf7xx pci1073,12 Yamaha DS-XG YMF754 +oss_ymf7xx pci1073,4 Yamaha DS-XG YMF724 +oss_ymf7xx pci1073,5 Yamaha DS-XG YMF734 +oss_ymf7xx pci1073,a Yamaha DS-XG YMF740 +oss_ymf7xx pci1073,c Yamaha DS-XG YMF740C +oss_ymf7xx pci1073,d Yamaha DS-XG YMF724F diff --git a/kernel/drv/oss_ymf7xx/.name b/kernel/drv/oss_ymf7xx/.name new file mode 100644 index 0000000..5544929 --- /dev/null +++ b/kernel/drv/oss_ymf7xx/.name @@ -0,0 +1 @@ +Yamaha DS-XG YMF7xx diff --git a/kernel/drv/oss_ymf7xx/.params b/kernel/drv/oss_ymf7xx/.params new file mode 100644 index 0000000..26f99d1 --- /dev/null +++ b/kernel/drv/oss_ymf7xx/.params @@ -0,0 +1,17 @@ +int yamaha_mpu_ioaddr=0; +/* + * Yamaha DSXG MPU I/O Address + * Values: 0x300, 0x330, 0x332, 0x334 Default: 0 + */ + +int yamaha_mpu_irq=0; +/* + * Yamaha DSXG MPU IRQ + * Values: 5, 7, 9, 10, 11 Default: 0 + */ + +int yamaha_fm_ioaddr=0; +/* + * Yamaha DSXG FM IO Address + * Values: 0x388, 0x398, 0x3a0, 0x3a8 Default: 0 + */ diff --git a/kernel/drv/oss_ymf7xx/oss_ymf7xx.c b/kernel/drv/oss_ymf7xx/oss_ymf7xx.c new file mode 100644 index 0000000..8369c2a --- /dev/null +++ b/kernel/drv/oss_ymf7xx/oss_ymf7xx.c @@ -0,0 +1,1625 @@ +/* + * Purpose: Driver for Yamaha YMF7xx 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_ymf7xx_cfg.h" +#include "ymf7xx.h" +#include "oss_pci.h" +#include "ac97.h" +#include "uart401.h" + +#define YAMAHA_VENDOR_ID 0x1073 +#define YAMAHA_YMF724_ID 0x0004 +#define YAMAHA_YMF724F_ID 0x000d +#define YAMAHA_YMF734_ID 0x0005 +#define YAMAHA_YMF740_ID 0x000a +#define YAMAHA_YMF740C_ID 0x000c +#define YAMAHA_YMF744_ID 0x0010 +#define YAMAHA_YMF754_ID 0x0012 + +#define WRITEB(a,d) devc->bRegister[a] = d +#define READB(a) devc->bRegister[a] +#define WRITEW(a,d) devc->wRegister[a>>1] = d +#define READW(a) devc->wRegister[a>>1] +#define WRITEL(a,d) devc->dwRegister[a>>2] = d +#define READL(a) (devc->dwRegister[a>>2]) + +#ifdef OSS_BIG_ENDIAN +static __inline__ unsigned int +ymf_swap (unsigned int x) +{ + return ((x & 0x000000ff) << 24) | + ((x & 0x0000ff00) << 8) | + ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24); +} + +#define LSWAP(x) ymf_swap(x) +#else +#define LSWAP(x) x +#endif + +#define MAX_PORTC 8 + +extern int yamaha_mpu_ioaddr; +extern int yamaha_mpu_irq; +extern int yamaha_fm_ioaddr; + + +typedef struct ymf7xx_portc +{ + int speed, bits, channels; + int open_mode; + int trigger_bits; + int audio_enabled; + int audiodev; + int devs_opened; + int devnum; + PLAY_BANK *bank1, *bank2, *bank3, *bank4; + EFFECT_CNTRL_SLOT effectslot; + REC_CNTRL_SLOT recslot; + int dacfmt; +} +ymf7xx_portc; + +typedef struct ymf7xx_devc +{ + oss_device_t *osdev; + char *chip_name; + int deviceid; + unsigned int base0addr; + unsigned int *base0virt; + volatile unsigned int *dwRegister; + volatile unsigned short *wRegister; + volatile unsigned char *bRegister; + int irq; + oss_mutex_t mutex; + oss_mutex_t low_mutex; + + /* Legacy */ + int mpu_base, mpu_irq; + int fm_base; + int fm_attached, mpu_attached; + + /* Mixer parameters */ + ac97_devc ac97devc, ac97devc2; + int mixer_dev; + int mixlevels[10]; + + /* Audio parameters */ + int audio_initialized; + ymf7xx_portc portc[MAX_PORTC]; + + /* Play Table */ + volatile oss_native_word slt; + oss_native_word slt_phys; + volatile unsigned int *tab; + oss_native_word play_table; + oss_native_word play_table_virt; + unsigned char *dmabuf1; + oss_dma_handle_t dmabuf1_dma_handle; + + /* Effect Table */ + volatile unsigned int *effecttab; + oss_native_word effect_table; + oss_native_word effect_table_virt, eff_buf_phys; + unsigned char *dmabuf2, *eff_buf; + oss_dma_handle_t dmabuf2_dma_handle; + oss_dma_handle_t eff_buf_dma_handle; + + /* Recording Table */ + volatile unsigned int *rectab; + oss_native_word rec_table; + oss_native_word rec_table_virt; + unsigned char *dmabuf3; + oss_dma_handle_t dmabuf3_dma_handle; + int spdif_in; +} +ymf7xx_devc; + +int SetupPlaySlot (int dev, int slot); +int ymf7xx_spdif_control (int dev, int ctrl, unsigned int cmd, int value); + +static int +ac97_read (void *devc_, int addr) +{ + ymf7xx_devc *devc = devc_; + int count; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + WRITEW (AC97_CMD_ADDRESS, addr | 0x8000); + + for (count = 0; count < 1000; count++) + if ((READW (AC97_STATUS_ADDRESS) >> 15) == 0) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return READW (AC97_STATUS_DATA); + } + DDB (cmn_err (CE_WARN, "AC97 mixer read timed out\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return OSS_EIO; +} + +static int +ac97_write (void *devc_, int addr, int data) +{ + ymf7xx_devc *devc = devc_; + oss_native_word flags; + int count; + + MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags); + WRITEW (AC97_CMD_ADDRESS, addr); + WRITEW (AC97_CMD_DATA, data); + + for (count = 0; count < 1000; count++) + if ((READW (AC97_STATUS_ADDRESS) >> 15) == 0) + { + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 1; + } + DDB (cmn_err (CE_WARN, "AC97 mixer write timed out\n")); + MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags); + return 0; +} + +static void +install_ucode (ymf7xx_devc * devc, int addr, unsigned int *src, int len) +{ + int i; + + for (i = 0; i < len; i++) + { + WRITEL (addr, *src); + addr += 4; + src++; + } +} + +static int +ymf7xxintr (oss_device_t * osdev) +{ + ymf7xx_devc *devc = (ymf7xx_devc *) osdev->devc; + ymf7xx_portc *portc; + dmap_t *dmapin, *dmapout; + unsigned int status; + int i, n; + int currdac = 0; + int curradc = 0; + int serviced = 0; + + + status = READL (STATUS); + + if ((status & 0x80000000)) + { + serviced = 1; + for (i = 0; i < MAX_PORTC; i++) + { + portc = &devc->portc[i]; + + if (portc->trigger_bits & PCM_ENABLE_OUTPUT) + { + dmapout = audio_engines[portc->audiodev]->dmap_out; + currdac = LSWAP (portc->bank1->PgStart); + currdac /= dmapout->fragment_size / portc->dacfmt; + + if (currdac < 0 || currdac >= dmapout->nfrags) + currdac = 0; + n = 0; + while (dmap_get_qhead (dmapout) != currdac + && n++ < dmapout->nfrags) + oss_audio_outputintr (portc->audiodev, 1); + } + if (portc->trigger_bits & PCM_ENABLE_INPUT) + { + dmapin = audio_engines[portc->audiodev]->dmap_in; + + if (devc->spdif_in) + curradc = LSWAP (portc->recslot.bank1->PgStartAdr); + else + curradc = LSWAP (portc->recslot.bank3->PgStartAdr); + + curradc /= dmapin->fragment_size; + + if (curradc < 0 || curradc >= dmapin->nfrags) + curradc = 0; + n = 0; + while (dmap_get_qtail (dmapin) != curradc + && n++ < dmapin->nfrags) + oss_audio_inputintr (portc->audiodev, 0); + } + WRITEL (STATUS, 0x80000000); + WRITEL (MODE, READL (MODE) | 0x00000002); + } + } + + return serviced; +} + +/* + ***************************************************************************** + */ + +static int +ymf7xx_audio_set_rate (int dev, int arg) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->speed; + + if (arg > 48000) + arg = 48000; + if (arg < 5000) + arg = 5000; + portc->speed = arg; + return portc->speed; +} + +static short +ymf7xx_audio_set_channels (int dev, short arg) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + if ((arg != 1) && (arg != 2)) + return portc->channels; + portc->channels = arg; + + return portc->channels; +} + +static unsigned int +ymf7xx_audio_set_format (int dev, unsigned int arg) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + if (arg == 0) + return portc->bits; + + if (!(arg & (AFMT_U8 | AFMT_S16_LE | AFMT_AC3))) + return portc->bits; + portc->bits = arg; + + return portc->bits; +} + +/*ARGSUSED*/ +static int +ymf7xx_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg) +{ + return OSS_EINVAL; +} + +static void ymf7xx_audio_trigger (int dev, int state); + +static void +ymf7xx_audio_reset (int dev) +{ + ymf7xx_audio_trigger (dev, 0); +} + +static void +ymf7xx_audio_reset_input (int dev) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + ymf7xx_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT); +} + +static void +ymf7xx_audio_reset_output (int dev) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + ymf7xx_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT); +} + +/*ARGSUSED*/ +static int +ymf7xx_audio_open (int dev, int mode, int open_flags) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + ymf7xx_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; + } + + portc->open_mode = mode; + portc->audio_enabled = ~mode; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + + return 0; +} + +static void +ymf7xx_audio_close (int dev, int mode) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + ymf7xx_audio_reset (dev); + portc->open_mode = 0; + portc->audio_enabled &= ~mode; +} + +/*ARGSUSED*/ +static void +ymf7xx_audio_output_block (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; +} + +/*ARGSUSED*/ +static void +ymf7xx_audio_start_input (int dev, oss_native_word buf, int count, + int fragsize, int intrflag) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + portc->audio_enabled |= PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; +} + +static void +ymf7xx_audio_trigger (int dev, int state) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + 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)) + { + portc->devs_opened = SetupPlaySlot (dev, portc->devnum); + + WRITEL (CONTROL_SELECT, 1); + WRITEL (MODE, READL (MODE) | 0x00000003); + portc->trigger_bits |= PCM_ENABLE_OUTPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) && + (portc->trigger_bits & PCM_ENABLE_OUTPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + + devc->tab[portc->devs_opened] = 0; + if (portc->channels > 1) + devc->tab[portc->devs_opened - 1] = 0; + } + } + } + + if ((portc->open_mode & OPEN_READ) + && !(audio_engines[dev]->flags & ADEV_NOINPUT)) + { + if (state & PCM_ENABLE_INPUT) + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + !(portc->trigger_bits & PCM_ENABLE_INPUT)) + { + /* 0x01 = REC SLOT, 0x02 = ADC SLOT */ + if (devc->spdif_in) + WRITEL (MAP_OF_REC, 0x1); + else + WRITEL (MAP_OF_REC, 0x2); + WRITEL (CONTROL_SELECT, 0); + WRITEL (MODE, READL (MODE) | 0x00000003); + portc->trigger_bits |= PCM_ENABLE_INPUT; + } + } + else + { + if ((portc->audio_enabled & PCM_ENABLE_INPUT) && + (portc->trigger_bits & PCM_ENABLE_INPUT)) + { + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + + /* set the map of rec 0 */ + WRITEL (MAP_OF_REC, 0x0); + } + } + } + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); +} + +static unsigned int +SetFormatField (ymf7xx_portc * portc) +{ + unsigned int val; + + val = 0x00000000; + if (portc->bits == 8) + val |= 0x80000000; + if (portc->channels > 1) + val |= 0x00010000; + return val; +} + +static unsigned int +SetPgDeltaField (ymf7xx_portc * portc) +{ + unsigned int val; + +#if 0 + double x; + x = (double) portc->speed / 48000.0; + val = (int) (x * (1 << 28)) & 0x7FFFFF00; +#else + oss_native_word x; + x = (portc->speed * (1 << 15) + 187) / 375; + val = (x * (1 << 6)) & 0x7FFFFF00; +#endif + return val; +} + +static unsigned int +SetLpfKField (ymf7xx_portc * portc) +{ + unsigned int i, val = 0, sr = portc->speed; + int freq[8] = { 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000 }; + int LpfK[8] = + { 0x0057, 0x06aa, 0x18B2, 0x2093, 0x2b9a, 0x35a1, 0x3eaa, 0x4000 }; + + if (sr == 44100) + { + val = 0x4646 << 16; + } + else + { + for (i = 0; i < 8; i++) + { + if (sr <= freq[i]) + { + val = LpfK[i] << 16; + break; + } + } + } + return val; +} + +static unsigned int +SetLpfQField (ymf7xx_portc * portc) +{ + unsigned int i, val = 0, sr = portc->speed; + int freq[8] = { 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000 }; + int LpfQ[8] = + { 0x3528, 0x34a7, 0x3202, 0x3177, 0x3139, 0x31c9, 0x33d0, 0x4000 }; + + if (sr == 44100) + { + val = 0x370A << 16; + } + else + { + for (i = 0; i < 8; i++) + { + if (sr <= freq[i]) + { + val = LpfQ[i] << 16; + break; + } + } + } + return val; +} + +void +SetupRecSlot (int dev) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_in; + int banksize; + + banksize = READL (REC_CNTRL_SIZE); + portc->recslot.base = (devc->rec_table_virt); + + /* banks 1 and 2 are for REC Slot and 3 and 4 are for ADC Slot */ + if (devc->spdif_in) + { + portc->recslot.bank1 = + (REC_BANK *) (portc->recslot.base + (banksize * 0)); + portc->recslot.bank2 = + (REC_BANK *) (portc->recslot.base + (banksize * 4)); + + WRITEB (REC_FORMAT, + (unsigned char) ((portc->channels & 0x02) + + ((portc->bits & 0x08) >> 3))); + WRITEW (REC_SAMPLING_RATE, + (unsigned short) (48000 * 4096 / portc->speed) - 1); + + portc->recslot.bank1->PgBase = portc->recslot.bank2->PgBase = LSWAP (dmap->dmabuf_phys); /* use the REC slot */ + + portc->recslot.bank1->PgLoopEndAdr = portc->recslot.bank2->PgLoopEndAdr = LSWAP (dmap->bytes_in_use); /* use the REC slot */ + } + else + { + portc->recslot.bank3 = + (REC_BANK *) (portc->recslot.base + (banksize * 8)); + portc->recslot.bank4 = + (REC_BANK *) (portc->recslot.base + (banksize * 12)); + + WRITEB (ADC_FORMAT, + (unsigned char) ((portc->channels & 0x02) + + ((portc->bits & 0x08) >> 3))); + WRITEW (ADC_SAMPLING_RATE, + (unsigned short) (48000 * 4096 / portc->speed) - 1); + + portc->recslot.bank3->PgBase = portc->recslot.bank4->PgBase = LSWAP (dmap->dmabuf_phys); /* use the ADC slot */ + + portc->recslot.bank3->PgLoopEndAdr = portc->recslot.bank4->PgLoopEndAdr = LSWAP (dmap->bytes_in_use); /* use the ADC slot */ + } + +} + +/*ARGSUSED*/ +static int +ymf7xx_audio_prepare_for_input (int dev, int bsize, int bcount) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + SetupRecSlot (dev); + + /* set the input level to max and go! */ + WRITEL (NATIVE_REC_INPUT, 0xffffffff); + WRITEL (NATIVE_ADC_INPUT, 0xffffffff); + portc->audio_enabled &= ~PCM_ENABLE_INPUT; + portc->trigger_bits &= ~PCM_ENABLE_INPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +void +SetupEffectSlot (int dev) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + + int banksize; + + banksize = READL (EFF_CNTRL_SIZE); + portc->effectslot.base = (devc->effect_table_virt); + + /* slots 1-5 each having 2 banks */ + portc->effectslot.bank1 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 0)); + portc->effectslot.bank2 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 4)); + portc->effectslot.bank3 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 8)); + portc->effectslot.bank4 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 12)); + portc->effectslot.bank5 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 16)); + portc->effectslot.bank6 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 20)); + portc->effectslot.bank7 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 24)); + portc->effectslot.bank8 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 28)); + portc->effectslot.bank9 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 32)); + portc->effectslot.bank10 = + (EFFECT_BANK *) (portc->effectslot.base + (banksize * 36)); + +#if 0 +/* Dry Left Channel */ + portc->effectslot.bank1->PgBase = portc->effectslot.bank2->PgBase = + LSWAP (devc->eff_buf_phys + 0 * 8192); + portc->effectslot.bank1->PgLoopEnd = portc->effectslot.bank2->PgLoopEnd = + LSWAP (4096); + portc->effectslot.bank1->PgStart = portc->effectslot.bank2->PgStart = 0; + +/* Dry Right Channel */ + portc->effectslot.bank3->PgBase = portc->effectslot.bank4->PgBase = + LSWAP (devc->eff_buf_phys + 1 * 8192); + portc->effectslot.bank3->PgLoopEnd = portc->effectslot.bank4->PgLoopEnd = + LSWAP (4096); + portc->effectslot.bank3->PgStart = portc->effectslot.bank4->PgStart = 0; + +/* Effect 1 */ + portc->effectslot.bank5->PgBase = portc->effectslot.bank6->PgBase = + LSWAP (devc->eff_buf_phys + 2 * 8192); + portc->effectslot.bank5->PgLoopEnd = portc->effectslot.bank6->PgLoopEnd = + LSWAP (4096); + portc->effectslot.bank5->PgStart = portc->effectslot.bank6->PgStart = 0; + +#endif + +/* Effect 2 */ + portc->effectslot.bank7->PgBase = portc->effectslot.bank8->PgBase = + LSWAP (devc->eff_buf_phys + 0 * 8192); + portc->effectslot.bank7->PgLoopEnd = portc->effectslot.bank8->PgLoopEnd = + LSWAP (4096); + portc->effectslot.bank7->PgStart = portc->effectslot.bank8->PgStart = 0; + +/* Effect 3 */ + portc->effectslot.bank9->PgBase = portc->effectslot.bank10->PgBase = + LSWAP (devc->eff_buf_phys + 1 * 8192); + portc->effectslot.bank9->PgLoopEnd = portc->effectslot.bank10->PgLoopEnd = + LSWAP (4096); + portc->effectslot.bank9->PgStart = portc->effectslot.bank10->PgStart = 0; + + WRITEL (AC97_SEC_CONFIG, (READL (AC97_SEC_CONFIG) & ~0x0030) | 0x0010); + WRITEL (MAP_OF_EFFECTS, 0x18); /* effect 2,3 */ + WRITEL (MODE, READL (MODE) | (1 << 30)); /* AC3 Setup */ +} + + +void +SetupPlayBank (int dev, int slot, oss_native_word sbase) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + dmap_t *dmap = audio_engines[dev]->dmap_out; + + PLAY_BANK *bank1; + PLAY_BANK *bank2; + bank1 = (PLAY_BANK *) sbase; + bank2 = + (PLAY_BANK *) (sbase + READL (PLAY_CNTRL_SIZE) * sizeof (unsigned int)); + + memset ((void *) bank1, 0, sizeof (PLAY_BANK)); + memset ((void *) bank2, 0, sizeof (PLAY_BANK)); + + if (slot == 2) + { + portc->bank3 = bank1; + portc->bank4 = bank2; + } + else + { + portc->bank1 = bank1; + portc->bank2 = bank2; + } + + /* setup format field */ + bank1->Format = LSWAP (SetFormatField (portc)); + bank1->EgGain = bank1->EgGainEnd = LSWAP (0x40000000); + + if (portc->channels == 1) + { + /* Gain */ + bank1->LchGain = bank1->LchGainEnd = LSWAP (0x40000000); + bank1->RchGain = bank1->RchGainEnd = LSWAP (0x40000000); + bank1->Effect2Gain = bank1->Effect2GainEnd = LSWAP (0x40000000); + bank1->Effect3Gain = bank1->Effect3GainEnd = LSWAP (0x40000000); + } + else + { + if (slot == 2) + { + bank1->Format = LSWAP (LSWAP (bank1->Format) + 1); + bank1->RchGain = bank1->RchGainEnd = LSWAP (0x40000000); + bank1->Effect2Gain = bank1->Effect2GainEnd = LSWAP (0x40000000); + } + else + { + bank1->LchGain = bank1->LchGainEnd = LSWAP (0x40000000); + bank1->Effect3Gain = bank1->Effect3GainEnd = LSWAP (0x40000000); + } + } + + bank1->LoopDefault = 0; + bank1->NumOfFrames = 0; + bank1->LoopCount = 0; + bank1->PgStart = 0; + bank1->PgLoop = 0; + + /* PgBase */ + bank1->PgBase = LSWAP (dmap->dmabuf_phys); + + /* PgLoopEnd */ + bank1->PgLoopEnd = LSWAP (dmap->bytes_in_use / portc->dacfmt); + + /* PgDelta & PgDeltaEnd */ + bank1->PgDelta = bank1->PgDeltaEnd = LSWAP (SetPgDeltaField (portc)); + + if (portc->channels == 4) + bank1->PgDelta = bank1->PgDeltaEnd *= 2; + + /* LpfK & LpfKEnd */ + bank1->LpfK = bank1->LpfKEnd = LSWAP (SetLpfKField (portc)); + + /* LpfQ */ + bank1->LpfQ = LSWAP (SetLpfQField (portc)); + + memcpy (bank2, bank1, sizeof (PLAY_BANK)); +} + +int +SetupPlaySlot (int dev, int slot) +{ + int tmp; + oss_native_word sltbase; + oss_native_word physbase; + + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + + tmp = slot * 2 + 1; + sltbase = (oss_native_word) devc->slt + (tmp * 0x120); + physbase = devc->slt_phys + (tmp * 0x120); + SetupPlayBank (dev, 1, sltbase); + devc->tab[tmp] = LSWAP (physbase); + + if (portc->channels > 1) + { + sltbase += 0x120; + physbase += 0x120; + SetupPlayBank (dev, 2, sltbase); + tmp++; + devc->tab[tmp] = LSWAP (physbase); + } + return tmp; +} + +/*ARGSUSED*/ +static int +ymf7xx_audio_prepare_for_output (int dev, int bsize, int bcount) +{ + ymf7xx_devc *devc = audio_engines[dev]->devc; + ymf7xx_portc *portc = audio_engines[dev]->portc; + oss_native_word flags; + + MUTEX_ENTER_IRQDISABLE (devc->mutex, flags); + + if (portc->bits == AFMT_AC3) + { + portc->channels = 2; + portc->bits = 16; + ymf7xx_spdif_control (devc->mixer_dev, 1, SNDCTL_MIX_WRITE, 1); /* enable SPDIF */ + ymf7xx_spdif_control (devc->mixer_dev, 4, SNDCTL_MIX_WRITE, 1); /* enable AC3 */ + } + else + ymf7xx_spdif_control (devc->mixer_dev, 4, SNDCTL_MIX_WRITE, 0); /* enable AC3 */ + + + portc->dacfmt = portc->channels * (portc->bits / 8); + + if (portc->dacfmt > 4) + portc->dacfmt = 4; + /* portc->devs_opened = SetupPlaySlot (dev, portc->devnum); -> trigger */ + /* set effects slot */ + SetupEffectSlot (dev); + + if (portc->bits != AFMT_AC3) + WRITEL (NATIVE_DAC, 0xFFFFFFFF); + else + WRITEL (NATIVE_DAC, 0x00000000); + + portc->audio_enabled &= ~PCM_ENABLE_OUTPUT; + portc->trigger_bits &= ~PCM_ENABLE_OUTPUT; + MUTEX_EXIT_IRQRESTORE (devc->mutex, flags); + return 0; +} + +/*ARGSUSED*/ +static int +ymf7xx_get_buffer_pointer (int dev, dmap_t * dmap, int direction) +{ + ymf7xx_portc *portc = audio_engines[dev]->portc; + + unsigned int ptr = 0; + + if (direction == PCM_ENABLE_OUTPUT) + { + ptr = LSWAP (portc->bank1->PgStart); + ptr *= portc->dacfmt; + } + if (direction == PCM_ENABLE_INPUT) + { + ptr = LSWAP (portc->recslot.bank3->PgStartAdr); + } + return ptr; +} + +static audiodrv_t ymf7xx_audio_driver = { + ymf7xx_audio_open, + ymf7xx_audio_close, + ymf7xx_audio_output_block, + ymf7xx_audio_start_input, + ymf7xx_audio_ioctl, + ymf7xx_audio_prepare_for_input, + ymf7xx_audio_prepare_for_output, + ymf7xx_audio_reset, + NULL, + NULL, + ymf7xx_audio_reset_input, + ymf7xx_audio_reset_output, + ymf7xx_audio_trigger, + ymf7xx_audio_set_rate, + ymf7xx_audio_set_format, + ymf7xx_audio_set_channels, + NULL, + NULL, + NULL, + NULL, + NULL, /* ymf7xx_alloc_buffer */ + NULL, /* ymf7xx_free_buffer */ + NULL, + NULL, + ymf7xx_get_buffer_pointer +}; + +#if 0 +static void +init_audio (ymf7xx_devc * devc) +{ + devc->audio_initialized = 1; +} + +uninit_audio (ymf7xx_devc * devc) +{ + devc->audio_initialized = 0; + WRITEL (CONFIG, 0); + WRITEL (MODE, 0); +} +#endif + +#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 (ymf7xx_devc * devc) +{ + devc->fm_attached = 0; + if (!opl3_detect (0x388, devc->osdev)) + { + cmn_err (CE_WARN, "OPL3 not detected\n"); + return; + } + opl3_init (0x388, devc->osdev); + devc->fm_attached = 1; +} + + +static void +attach_mpu (ymf7xx_devc * devc) +{ + struct address_info hw_config; + + hw_config.io_base = devc->mpu_base; + hw_config.irq = devc->mpu_irq; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = "Yamaha DS-XG MPU401"; + 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; + } + DDB (cmn_err (CE_WARN, "MPU-401 detected - Good\n")); + devc->mpu_attached = 1; + attach_uart401 (&hw_config); +} + +static void +unload_mpu (ymf7xx_devc * devc) +{ + struct address_info hw_config; + + hw_config.io_base = devc->mpu_base; + hw_config.irq = devc->mpu_irq; + hw_config.dma = -1; + hw_config.dma2 = -1; + hw_config.always_detect = 0; + hw_config.name = "Yahama DS-XG MPU401"; + 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 + +int +ymf7xx_spdif_control (int dev, int ctrl, unsigned int cmd, int value) +{ + ymf7xx_devc *devc = mixer_devs[dev]->hw_devc; +/* int left, right; */ + + if (cmd == SNDCTL_MIX_READ) + { + value = 0; + switch (ctrl) + { + case 1: /* S/PDIF Enable/Disable */ + value = READL (SPDIFOUT_CONTROL) & 0x1; + break; + + case 2: /* S/PDIF Record Enable */ + value = devc->spdif_in; + break; + + case 3: /* S/PDIF Loopback */ + value = READL (SPDIFIN_CONTROL) & (1 << 4); + break; + + case 4: /* AC3 Output */ + value = READL (SPDIFOUT_CONTROL) & (1 << 1); + break; +#if 0 + case 5: /* CopyProtection Bit */ + value = READL (SPDIFOUT_STATUS) & (1 << 2); + break; + case 6: /* SPDIF OUTVOL */ + value = devc->mixlevels[0]; + break; + case 7: /* SPDIF LOOPVOL */ + value = devc->mixlevels[1]; + break; + case 8: /* SPDIF AC3VOL */ + value = devc->mixlevels[2]; + break; +#endif + } + } + if (cmd == SNDCTL_MIX_WRITE) + { + switch (ctrl) + { + case 1: /* S/PDIF OUTPUT ENABLE/DISABLE */ + if (value) + WRITEL (SPDIFOUT_CONTROL, READL (SPDIFOUT_CONTROL) | 0x1); + else + WRITEL (SPDIFOUT_CONTROL, READL (SPDIFOUT_CONTROL) & ~0x1); + break; + + case 2: /* Record S/PDIF IN ENABLE DISABLE */ + if (value) + { + WRITEL (SPDIFIN_CONTROL, READL (SPDIFIN_CONTROL) | 0x1); + devc->spdif_in = 1; + } + else + { + WRITEL (SPDIFIN_CONTROL, READL (SPDIFIN_CONTROL) & ~0x1); + devc->spdif_in = 0; + } + break; + + case 3: /* S/PDIF Loopback Mode */ + if (value) + WRITEL (SPDIFIN_CONTROL, READL (SPDIFIN_CONTROL) | (1 << 4)); + else + WRITEL (SPDIFIN_CONTROL, READL (SPDIFIN_CONTROL) & ~(1 << 4)); + break; + + case 4: /* AC3 Output Mode */ + if (value) + WRITEL (SPDIFOUT_CONTROL, READL (SPDIFOUT_CONTROL) | (1 << 1)); + else + WRITEL (SPDIFOUT_CONTROL, READL (SPDIFOUT_CONTROL) & ~(1 << 1)); + break; + +#if 0 + case 5: /* Copy Protect Mode */ + { + int ac3_mode; + + ac3_mode = READL (SPDIFOUT_CONTROL) & (1 << 1); + + if (value) + { + if (ac3_mode) + WRITEL (SPDIFOUT_STATUS, + READL (SPDIFOUT_STATUS) | (1 << 1)); + else + WRITEL (SPDIFOUT_STATUS, READL (SPDIFOUT_STATUS) & ~0x3E); + } + else + { + if (ac3_mode) + WRITEL (SPDIFOUT_STATUS, + READL (SPDIFOUT_STATUS) | (3 << 1)); + else + + WRITEL (SPDIFOUT_STATUS, + READL (SPDIFOUT_STATUS) | (1 << 2)); + } + } + break; + + case 6: + left = value & 0xff; + right = (value >> 8) & 0xff; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + value = left | (right << 8); + left = left * 0xFFFF / 100; + right = right * 0xFFFF / 100; + WRITEL (SPDIFOUTVOL, left << 16 | right); + devc->mixlevels[0] = value; + break; + case 7: + left = value & 0xff; + right = (value >> 8) & 0xff; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + value = left | (right << 8); + left = left * 0xFFFF / 100; + right = right * 0xFFFF / 100; + WRITEL (SPDIFLOOPVOL, left << 16 | right); + devc->mixlevels[1] = value; + break; + case 8: + left = value & 0xff; + right = (value >> 8) & 0xff; + if (left > 100) + left = 100; + if (right > 100) + right = 100; + value = left | (right << 8); + left = left * 0xFFFF / 100; + right = right * 0xFFFF / 100; + WRITEL (AC3_OUTPUT, left << 16 | right); + devc->mixlevels[2] = value; + break; +#endif + } + } + return value; +} + +static int +ymf7xx_mix_init (int dev) +{ + int group, err; + + if ((group = mixer_ext_create_group (dev, 0, "SPDIF")) < 0) + return group; + + if ((err = mixer_ext_create_control (dev, group, 1, ymf7xx_spdif_control, + MIXT_ONOFF, "ENABLE", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 2, ymf7xx_spdif_control, + MIXT_ONOFF, "RECORD", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 3, ymf7xx_spdif_control, + MIXT_ONOFF, "LOOP", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + +#if 0 + if ((err = mixer_ext_create_control (dev, group, 4, ymf7xx_spdif_control, + MIXT_ONOFF, "AC3", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = mixer_ext_create_control (dev, group, 5, ymf7xx_spdif_control, + MIXT_ONOFF, "COPYPROT", 1, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + + if ((err = mixer_ext_create_control (dev, group, 6, ymf7xx_spdif_control, + MIXT_STEREOSLIDER, "OUTVOL", 100, + MIXF_MAINVOL | MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = mixer_ext_create_control (dev, group, 7, ymf7xx_spdif_control, + MIXT_STEREOSLIDER, "LOOPVOL", 100, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; + if ((err = mixer_ext_create_control (dev, group, 8, ymf7xx_spdif_control, + MIXT_STEREOSLIDER, "AC3VOL", 100, + MIXF_READABLE | MIXF_WRITEABLE)) < 0) + return err; +#endif + + return 0; +} + +static int +init_ymf7xx (ymf7xx_devc * devc) +{ + + int my_mixer, i; + int first_dev = 0; + + WRITEL (NATIVE_DAC, 0x00000000); + WRITEL (MODE, 0x00010000); + WRITEL (MODE, 0x00000000); + WRITEL (MAP_OF_REC, 0x00000000); + WRITEL (MAP_OF_EFFECTS, 0x00000000); + WRITEL (PLAY_CNTRL_BASE, 0x00000000); + WRITEL (REC_CNTRL_BASE, 0x00000000); + WRITEL (EFF_CNTRL_BASE, 0x00000000); + WRITEL (CONTROL_SELECT, 1); + WRITEL (GLOBAL_CONTROL, READL (GLOBAL_CONTROL) & ~0x0007); + WRITEL (ZVOUTVOL, 0xFFFFFFFF); + WRITEL (ZVLOOPVOL, 0xFFFFFFFF); + WRITEL (SPDIFOUTVOL, 0xFFFFFFFF); + WRITEL (SPDIFLOOPVOL, 0x3FFF3FFF); + devc->spdif_in = 0; + + if (ac97_read (devc, 0x02) == 0xFFFF) + { + for (i = 0; i < 100; i++) + if (ac97_read (devc, 0x02) != 0xFFFF) + { + break; + } + } + + install_ucode (devc, 0x1000, dsp, dsp_size); + switch (devc->deviceid) + { + case YAMAHA_YMF724F_ID: + case YAMAHA_YMF740C_ID: + case YAMAHA_YMF744_ID: + case YAMAHA_YMF754_ID: + install_ucode (devc, 0x4000, cntrl1E, cntrl1E_size); + break; + default: + install_ucode (devc, 0x4000, cntrl, cntrl_size); + } + WRITEL (CONFIG, 1); + +/* add an extra reset to init the mixers */ + ac97_write (devc, 0x02, 0x0000); + ac97_write (devc, 0x18, 0x0808); + +/* Now check to see if the DSP is started or not */ + { + int fEnd; + i = 10000; + do + { + if (i-- <= 0) + { + cmn_err (CE_WARN, "CTR/DSP Init/ TimeOut\n"); + return 0; + } + fEnd = READL (CONTROL_SELECT) & 0x1; + } + while (fEnd == 0x1); + } + + my_mixer = + ac97_install (&devc->ac97devc, "Yamaha DS-XG", ac97_read, ac97_write, + devc, devc->osdev); + if (my_mixer >= 0) + { + devc->mixer_dev = my_mixer; + mixer_ext_set_init_fn (my_mixer, ymf7xx_mix_init, 20); + } + else + return 0; + +#ifdef OBSOLETED_STUFF + if (devc->fm_base > 0) + attach_fm (devc); + if (devc->mpu_base > 0) + attach_mpu (devc); +#endif + + if (devc->play_table_virt == 0) + { + /* Allocate the Play Table */ + oss_native_word phaddr; + devc->dmabuf1 = + CONTIG_MALLOC (devc->osdev, 0x1000, MEMLIMIT_32BITS, &phaddr, devc->dmabuf1_dma_handle); + devc->play_table_virt = (oss_native_word) devc->dmabuf1; + devc->play_table = phaddr; + + /* Allocate Effect Table */ + devc->dmabuf2 = + CONTIG_MALLOC (devc->osdev, 1024, MEMLIMIT_32BITS, &phaddr, devc->dmabuf2_dma_handle); + devc->effect_table_virt = (oss_native_word) devc->dmabuf2; + devc->effect_table = phaddr; + + /* Allocate Effect Scratch Buffer */ + devc->eff_buf = + CONTIG_MALLOC (devc->osdev, 2 * 8192, MEMLIMIT_32BITS, &phaddr, devc->eff_buf_dma_handle); + devc->eff_buf_phys = phaddr; + + /* Allocate the Record Table */ + devc->dmabuf3 = + CONTIG_MALLOC (devc->osdev, 1024, MEMLIMIT_32BITS, &phaddr, devc->dmabuf3_dma_handle); + devc->rec_table_virt = (oss_native_word) devc->dmabuf3; + devc->rec_table = phaddr; + + /* Setup Play Table */ + devc->tab = (unsigned int *) devc->play_table_virt; + devc->slt = (oss_native_word) (devc->play_table_virt + 0x100); + devc->slt_phys = (devc->play_table + 0x100); + memset ((void *) devc->tab, 0, 0x1000); + WRITEL (PLAY_CNTRL_BASE, (unsigned int) devc->play_table); + devc->tab[0] = LSWAP (20); /* setup 20 slots for 8 playback devices */ + /* Setup Effect Table and init Effect Slots */ + devc->effecttab = (unsigned int *) devc->effect_table_virt; + memset ((void *) devc->effecttab, 0, 1024); + WRITEL (EFF_CNTRL_BASE, (unsigned int) devc->effect_table); + + //SetupEffectSlot (dev); + + /* Setup Record Table */ + devc->rectab = (unsigned int *) devc->rec_table_virt; + memset ((void *) devc->rectab, 0, 1024); + WRITEL (REC_CNTRL_BASE, (unsigned int) devc->rec_table); + } + + for (i = 0; i < MAX_PORTC; i++) + { + int adev; + char tmp_name[100]; + ymf7xx_portc *portc = &devc->portc[i]; + int caps = ADEV_AUTOMODE | ADEV_NOVIRTUAL; + + if (i == 0) + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_DUPLEX; + } + else + { + strcpy (tmp_name, devc->chip_name); + caps |= ADEV_NOINPUT; + if (i > 1) + caps |= ADEV_SHADOW; + } + + + if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION, + devc->osdev, + devc->osdev, + tmp_name, + &ymf7xx_audio_driver, + sizeof (audiodrv_t), + caps, + AFMT_U8 | AFMT_S16_LE | AFMT_AC3, + devc, -1)) < 0) + { + adev = -1; + return 0; + } + else + { + if (i == 0) + first_dev = adev; + audio_engines[adev]->mixer_dev = my_mixer; + audio_engines[adev]->portc = portc; + audio_engines[adev]->rate_source = first_dev; + audio_engines[adev]->min_block = 64; + audio_engines[adev]->min_rate = 5000; + audio_engines[adev]->max_rate = 48000; + audio_engines[adev]->vmix_flags |= VMIX_MULTIFRAG; + audio_engines[adev]->caps |= PCM_CAP_FREERATE; + audio_engines[adev]->min_channels = 2; + audio_engines[adev]->max_channels = 4; + portc->open_mode = 0; + portc->audiodev = adev; + portc->devnum = i; +#ifdef CONFIG_OSS_VMIX + if (i == 0) + vmix_attach_audiodev(devc->osdev, adev, -1, 0); +#endif + } + } + return 1; +} + +int +oss_ymf7xx_attach (oss_device_t * osdev) +{ + + + unsigned char pci_irq_line, pci_revision; + unsigned short pci_command, vendor, device; + unsigned char pci_reset; + unsigned short pci_legacy; + ymf7xx_devc *devc; + + DDB (cmn_err (CE_WARN, "Entered DS-XG attach routine\n")); + + pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word (osdev, PCI_DEVICE_ID, &device); + + if (((vendor != YAMAHA_VENDOR_ID)) || + (device != YAMAHA_YMF740_ID && + device != YAMAHA_YMF744_ID && + device != YAMAHA_YMF754_ID && + device != YAMAHA_YMF740C_ID && + device != YAMAHA_YMF724_ID && + device != YAMAHA_YMF734_ID && device != YAMAHA_YMF724F_ID)) + return 0; + + oss_pci_byteswap (osdev, 1); + + if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL) + { + cmn_err (CE_WARN, "Out of memory\n"); + return 0; + } + + devc->osdev = osdev; + osdev->devc = devc; + + pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision); + pci_read_config_word (osdev, PCI_COMMAND, &pci_command); + pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line); + pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &devc->base0addr); + + if (devc->base0addr == 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; + } + + DDB (cmn_err + (CE_WARN, "rev %x I/O base %04x\n", pci_revision, devc->base0addr)); + + devc->deviceid = device; + switch (device) + { + case YAMAHA_YMF724_ID: + devc->chip_name = "Yamaha YMF724"; + break; + + case YAMAHA_YMF724F_ID: + devc->chip_name = "Yamaha YMF724F"; + break; + + case YAMAHA_YMF734_ID: + devc->chip_name = "Yamaha YMF734"; + break; + + case YAMAHA_YMF740_ID: + devc->chip_name = "Yamaha YMF740"; + break; + + case YAMAHA_YMF740C_ID: + devc->chip_name = "Yamaha YMF740C"; + break; + + case YAMAHA_YMF744_ID: + devc->chip_name = "Yamaha YMF744"; + break; + + case YAMAHA_YMF754_ID: + devc->chip_name = "Yamaha YMF754"; + break; + + default: + devc->chip_name = "Yamaha DS-XG"; + } + + devc->fm_base = yamaha_fm_ioaddr; + devc->mpu_base = yamaha_mpu_ioaddr; + devc->mpu_irq = yamaha_mpu_irq; + + /* reset the device */ + pci_read_config_byte (osdev, 0x48, &pci_reset); + + if (pci_reset & 0x03) + { + pci_write_config_byte (osdev, 0x48, pci_reset & 0xFC); + pci_write_config_byte (osdev, 0x48, pci_reset | 0x03); + pci_write_config_byte (osdev, 0x48, pci_reset & 0xFC); + } + +/* Legacy I/O setup - setup MPU and FM io/irq values */ + devc->fm_attached = 0; + devc->mpu_attached = 0; + /*pcipci_legacy = 0x0020|0x00C0|0x0004; // 10 bit address decode and Joystick */ + pci_legacy = 0x4; + if (devc->fm_base) + pci_legacy |= 0x0002; /* FM enable */ + + if (devc->mpu_base) + { + pci_legacy |= 0x0008; /* MPU I/O enable */ + + switch (devc->mpu_irq) + { + case 5: + pci_legacy |= 0x0010; + break; + case 7: + pci_legacy |= 0x0810; + break; + case 9: + pci_legacy |= 0x1010; + break; + case 10: + pci_legacy |= 0x1810; + break; + case 11: + pci_legacy |= 0x2010; + break; + default: + devc->mpu_irq = 0; + } + } + + pci_write_config_word (osdev, 0x40, pci_legacy); + + pci_legacy = 0x0000; + + switch (devc->fm_base) + { + case 0x388: + pci_legacy |= 0x0000; + break; + case 0x398: + pci_legacy |= 0x0001; + break; + case 0x3a0: + pci_legacy |= 0x0002; + break; + case 0x3a8: + pci_legacy |= 0x0003; + break; + default: + devc->fm_base = 0; + } + + switch (devc->mpu_base) + { + case 0x330: + pci_legacy |= 0x0000; + break; + case 0x300: + pci_legacy |= 0x0010; + break; + case 0x332: + pci_legacy |= 0x0020; + break; + case 0x334: + pci_legacy |= 0x0020; + break; + default: + devc->mpu_base = 0; + } + pci_write_config_word (osdev, 0x42, pci_legacy); + + /* activate the device */ + pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word (osdev, PCI_COMMAND, pci_command); + + /* Map the shared memory area */ + devc->base0virt = + (unsigned int *) MAP_PCI_MEM (devc->osdev, 0, devc->base0addr, 32 * 1024); + devc->dwRegister = (unsigned int *) devc->base0virt; + devc->wRegister = (unsigned short *) devc->base0virt; + devc->bRegister = (unsigned char *) devc->base0virt; + + + 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 (oss_register_interrupts (devc->osdev, 0, ymf7xxintr, NULL) < 0) + { + cmn_err (CE_WARN, "Can't allocate IRQ%d\n", pci_irq_line); + return 0; + } + + return init_ymf7xx (devc); /* Detected */ +} + + +int +oss_ymf7xx_detach (oss_device_t * osdev) +{ + ymf7xx_devc *devc = (ymf7xx_devc *) osdev->devc; + + if (oss_disable_device (osdev) < 0) + return 0; + + WRITEL (CONFIG, 0); + WRITEL (MODE, 0); + + if (devc->dmabuf1) + { + CONTIG_FREE (devc->osdev, devc->dmabuf1, 0x1000, devc->dmabuf1_dma_handle); + devc->dmabuf1 = 0; + } + + if (devc->dmabuf2) + { + CONTIG_FREE (devc->osdev, devc->dmabuf2, 1024, devc->dmabuf2_dma_handle); + devc->dmabuf2 = 0; + } + + if (devc->eff_buf) + { + CONTIG_FREE (devc->osdev, devc->eff_buf, 16 * 1024, devc->eff_buf_dma_handle); + devc->eff_buf = 0; + } + + if (devc->dmabuf3) + { + CONTIG_FREE (devc->osdev, devc->dmabuf3, 1024, devc->dmabuf3_dma_handle); + devc->dmabuf3 = 0; + } + + devc->play_table_virt = 0; + devc->effect_table_virt = 0; + devc->rec_table_virt = 0; + +#ifdef OBSOLETED_STUFF + if (devc->mpu_attached) + { + unload_mpu (devc); + devc->mpu_attached = 0; + } +#endif + + oss_unregister_interrupts (devc->osdev); + + MUTEX_CLEANUP (devc->mutex); + MUTEX_CLEANUP (devc->low_mutex); + + if (devc->base0addr != 0) + { + UNMAP_PCI_MEM (devc->osdev, 0, devc->base0addr, devc->base0virt, + 32 * 1024); + devc->base0addr = 0; + } + oss_unregister_device (devc->osdev); + return 1; +} diff --git a/kernel/drv/oss_ymf7xx/oss_ymf7xx.man b/kernel/drv/oss_ymf7xx/oss_ymf7xx.man new file mode 100644 index 0000000..fc62efb --- /dev/null +++ b/kernel/drv/oss_ymf7xx/oss_ymf7xx.man @@ -0,0 +1,33 @@ +NAME +oss_ymf7xx - Yamaha DS-XG audio driver. + +DESCRIPTION +Open Sound System driver for Yamaha DS-XG YMF724/740/744/754 audio controllers. + +ymf7xx device characteristics: + o 8/16 bit playback/record + o mono/stereo/4 channel playback + o mono/stereo recording + o 8KHz to 48Khz sample rate. + + MIXER +The Yamaha DSXG models 744 and 754 supports SPDIF and AC3 multichannel output +and the Mixer extentions will allow you to enable/disable SPDIF output. + +CONFIG OPTIONS +o yamaha_mpu_ioaddr=<xxx> +MPU I/O address. Refer to the device conf file (see below) for legal values. + +o yamaha_mpu_irq=<xx> +MPU IRQ. Refer to device conf file (see below) for legal values + +o yamaha_fm_ioaddr=<xxx> +Yamaha FM SYnthesizer IO address. Refer to driver conf file (see below) for +possible values. + +FILES +CONFIGFILEPATH/oss_ymf7xx.conf Device configuration file + +AUTHOR +4Front Technologies + diff --git a/kernel/drv/oss_ymf7xx/ymf7xx.h b/kernel/drv/oss_ymf7xx/ymf7xx.h new file mode 100644 index 0000000..2318e9e --- /dev/null +++ b/kernel/drv/oss_ymf7xx/ymf7xx.h @@ -0,0 +1,1845 @@ +/* + * Purpose: Definitions for the ymf7xx 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. + * + */ + /*///////////////////////////////////////////////////////// */ + /* */ + /* Global Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define INTERRUPT_FLAG 0x04 +#define ACTIVITY 0x06 +#define GLOBAL_CONTROL 0x08 + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* Timer Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define TIMER_CONTROL 0x10 +#define TIMER_COUNT 0x12 + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* SPDIF Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define SPDIFOUT_CONTROL 0x18 +#define SPDIFOUT_STATUS 0x1c +#define SPDIFIN_CONTROL 0x34 +#define SPDIFIN_STATUS 0x38 + + /*///////////////////////////////////////////////////////// */ + /* */ + /* EEPROM Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define EEPROM_CONTROL 0x2c + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* AC3 Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define AC3_DATA 0x40 +#define AC3_ADDRESS 0x42 +#define AC3_STATUS 0x44 + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* AC97 Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define AC97_CMD_DATA 0x60 +#define AC97_CMD_ADDRESS 0x62 +#define AC97_STATUS_DATA 0x64 +#define AC97_STATUS_ADDRESS 0x66 +#define AC97_SEC_STATUS_DATA 0x68 +#define AC97_SEC_STATUS_ADDR 0x6A +#define AC97_SEC_CONFIG 0x70 + + /*///////////////////////////////////////////////////////// */ + /* */ + /* Volume Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define LEGACY_OUTPUT 0x80 +#define LEGACY_OUTPUT_LCH 0x80 +#define LEGACY_OUTPUT_RCH 0x82 +#define NATIVE_DAC 0x84 +#define NATIVE_DAC_LCH 0x84 +#define NATIVE_DAC_RCH 0x86 +#define ZVOUTVOL 0x88 +#define ZV_OUTPUT_LCH 0x88 +#define ZV_OUTPUT_RCH 0x8a +#define AC3_OUTPUT 0x8c +#define AC3_OUTPUT_LCH 0x8c +#define AC3_OUTPUT_RCH 0x8e +#define ADC_OUTPUT 0x90 +#define ADC_OUTPUT_LCH 0x90 +#define ADC_OUTPUT_RCH 0x92 +#define LEGACY_LOOPBACK 0x94 +#define LEGACY_LOOPBACK_LCH 0x94 +#define LEGACY_LOOPBACK_RCH 0x96 +#define NATIVE_LOOPBACK 0x98 +#define NATIVE_LOOPBACK_LCH 0x98 +#define NATIVE_LOOPBACK_RCH 0x9a +#define ZVLOOPVOL 0x9c +#define ZVLOOPBACK_LCH 0x9c +#define ZVLOOPBACK_RCH 0x9e +#define AC3_LOOPBACK 0xa0 +#define AC3_LOOPBACK_LCH 0xa0 +#define AC3_LOOPBACK_RCH 0xa2 +#define ADC_LOOPBACK 0xa4 +#define ADC_LOOPBACK_LCH 0xa4 +#define ADC_LOOPBACK_RCH 0xa6 +#define NATIVE_ADC_INPUT 0xa8 +#define NATIVE_ADC_INPUT_LCH 0xa8 +#define NATIVE_ADC_INPUT_RCH 0xaa +#define NATIVE_REC_INPUT 0xac +#define NATIVE_REC_INPUT_LCH 0xac +#define NATIVE_REC_INPUT_RCH 0xae +#define BUF441OUTVOL 0xB0 +#define BUF441OUTVOLL 0xB0 +#define BUF441OUTVOLR 0xB2 +#define BUF441LOOPVOL 0xB4 +#define BUF441LOOPVOLL 0xB4 +#define BUF441LOOPVOLR 0xB6 +#define SPDIFOUTVOL 0xB8 +#define SPDIFOUTVOLL 0xB8 +#define SPDIFOUTVOLR 0xBA +#define SPDIFLOOPVOL 0xBC +#define SPDIFLOOPVOLL 0xBC +#define SPDIFLOOPVOLR 0xBE + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* Sampling Rate Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define ADC_SAMPLING_RATE 0xc0 +#define REC_SAMPLING_RATE 0xc4 +#define ADC_FORMAT 0xc8 +#define REC_FORMAT 0xcc + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* PCI Native Audio Control Register */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define STATUS 0x100 +#define CONTROL_SELECT 0x104 +#define MODE 0x108 +#define SAMPLE_COUNT 0x10c +#define NUM_OF_SAMPLES 0x110 +#define CONFIG 0x114 +#define PLAY_CNTRL_SIZE 0x140 +#define REC_CNTRL_SIZE 0x144 +#define EFF_CNTRL_SIZE 0x148 +#define WORK_SIZE 0x14c +#define MAP_OF_REC 0x150 +#define MAP_OF_EFFECTS 0x154 +#define PLAY_CNTRL_BASE 0x158 +#define REC_CNTRL_BASE 0x15c +#define EFF_CNTRL_BASE 0x160 +#define WORK_BASE 0x164 + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* Instruction RAM */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define DSP_INST_RAM 0x1000 +#define CONTROL_INST_RAM 0x4000 + + + /*///////////////////////////////////////////////////////// */ + /* */ + /* Map Length */ + /* */ + /*///////////////////////////////////////////////////////// */ +#define MAP_LENGTH 0x8000 + + +/*============================================================================= */ +/* Copyright (c) 1997 Yamaha Corporation. All Rights Reserved. */ +/* */ +/* Title: */ +/* hwmcode.c */ +/* Desc: */ +/* micro-code for CTRL & DSP */ +/* HISTORY: */ +/* April 03, 1997: 1st try by M. Mukojima */ +/*============================================================================= */ + +static unsigned int dsp_size = 0x0020; +static unsigned int dsp[] = { + 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, + 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, + 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, + 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static unsigned int cntrl_size = 0x0c00; +static unsigned int cntrl[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x001A82, 0x033B8D, 0x000810, 0x10043A, + 0x02D90D, 0x000810, 0x18043A, 0x00010D, + 0x020015, 0x0000FD, 0x000020, 0x038860, + 0x039060, 0x038060, 0x038040, 0x038040, + 0x038040, 0x018040, 0x000A7D, 0x038040, + 0x038040, 0x018040, 0x200402, 0x000882, + 0x08001A, 0x000904, 0x015986, 0x000007, + 0x260007, 0x000007, 0x000007, 0x018A06, + 0x000007, 0x03120D, 0x000810, 0x18043A, + 0x260007, 0x00087D, 0x018042, 0x00160A, + 0x04A206, 0x000007, 0x00218D, 0x000810, + 0x08043A, 0x220A06, 0x000007, 0x0007FD, + 0x018042, 0x08000A, 0x000904, 0x029386, + 0x000195, 0x090D04, 0x000007, 0x000820, + 0x0000F5, 0x000B7D, 0x01F060, 0x0000FD, + 0x032206, 0x018040, 0x000A7D, 0x038042, + 0x13804A, 0x18000A, 0x001820, 0x059060, + 0x058860, 0x018040, 0x0000FD, 0x018042, + 0x70000A, 0x000115, 0x071144, 0x032386, + 0x030000, 0x007020, 0x034A06, 0x018040, + 0x00348D, 0x000810, 0x08043A, 0x223206, + 0x000007, 0x02D90D, 0x000810, 0x18043A, + 0x018206, 0x000007, 0x240007, 0x000F8D, + 0x000810, 0x00163A, 0x002402, 0x005C02, + 0x0028FD, 0x000020, 0x018040, 0x08000D, + 0x000815, 0x510984, 0x000007, 0x00004D, + 0x000E5D, 0x000E02, 0x00418D, 0x000810, + 0x08043A, 0x2CE206, 0x000007, 0x00008D, + 0x000924, 0x000F02, 0x00458D, 0x000810, + 0x08043A, 0x2CE206, 0x000007, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x018386, 0x000007, 0x01AA06, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x21C886, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x055A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x034986, 0x000007, 0x002104, 0x034986, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x06C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00688D, 0x000810, 0x08043A, 0x28D206, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x060206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x21A086, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x216886, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x07DA86, 0x00057D, 0x002820, + 0x03B060, 0x07F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x07FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x008D8D, 0x000810, + 0x08043A, 0x28D206, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x095186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x007FBD, 0x383DC4, + 0x000007, 0x001A7D, 0x001375, 0x018042, + 0x09004A, 0x10000A, 0x0B8D04, 0x139504, + 0x000007, 0x000820, 0x019060, 0x001104, + 0x216886, 0x010040, 0x0017FD, 0x018042, + 0x08000A, 0x000904, 0x216A86, 0x000007, + 0x00197D, 0x038042, 0x09804A, 0x10000A, + 0x000924, 0x001664, 0x0011FD, 0x038042, + 0x2B804A, 0x19804A, 0x30000A, 0x00008D, + 0x218944, 0x000007, 0x002244, 0x0AF186, + 0x000007, 0x001A64, 0x002A24, 0x003664, + 0x00197D, 0x080102, 0x100122, 0x000820, + 0x039060, 0x018040, 0x003DFD, 0x00008D, + 0x000820, 0x018040, 0x001375, 0x001A7D, + 0x010042, 0x09804A, 0x10000A, 0x00021D, + 0x0189E4, 0x2992E4, 0x309144, 0x000007, + 0x00060D, 0x000A15, 0x000C1D, 0x001025, + 0x00A9E4, 0x012BE4, 0x000464, 0x01B3E4, + 0x0232E4, 0x000464, 0x000464, 0x000464, + 0x000464, 0x00040D, 0x08B1C4, 0x000007, + 0x000820, 0x000BF5, 0x030040, 0x00197D, + 0x038042, 0x09804A, 0x000A24, 0x08000A, + 0x080E64, 0x000007, 0x100122, 0x000820, + 0x031060, 0x010040, 0x0064AC, 0x00027D, + 0x000020, 0x018040, 0x00107D, 0x018042, + 0x0011FD, 0x3B804A, 0x09804A, 0x20000A, + 0x000095, 0x1A1144, 0x00A144, 0x0D3086, + 0x00040D, 0x00B984, 0x0D3186, 0x0018FD, + 0x018042, 0x0010FD, 0x09804A, 0x28000A, + 0x000095, 0x010924, 0x002A64, 0x0D2186, + 0x000007, 0x002904, 0x0D3286, 0x000007, + 0x0D3A06, 0x080002, 0x00008D, 0x00387D, + 0x000820, 0x018040, 0x00127D, 0x018042, + 0x10000A, 0x003904, 0x0DE186, 0x00080D, + 0x7FFFB5, 0x00B984, 0x0DB186, 0x000025, + 0x0E8A06, 0x00002D, 0x000015, 0x00082D, + 0x02CD0D, 0x000820, 0x0ED206, 0x00000D, + 0x7F8035, 0x00B984, 0x0E8186, 0x400025, + 0x00008D, 0x110944, 0x000007, 0x00018D, + 0x109504, 0x000007, 0x009164, 0x000424, + 0x000424, 0x000424, 0x100102, 0x280002, + 0x02CC0D, 0x000820, 0x0ED206, 0x00018D, + 0x00042D, 0x00008D, 0x109504, 0x000007, + 0x00020D, 0x109184, 0x000007, 0x02CC8D, + 0x000820, 0x00008D, 0x0038FD, 0x018040, + 0x003BFD, 0x001020, 0x03A860, 0x000815, + 0x313184, 0x212184, 0x000007, 0x03B060, + 0x03A060, 0x018040, 0x0022FD, 0x000095, + 0x010924, 0x000424, 0x000424, 0x001264, + 0x100102, 0x000820, 0x039060, 0x018040, + 0x001924, 0x00FC8D, 0x00397D, 0x000820, + 0x058040, 0x038042, 0x09844A, 0x000606, + 0x08040A, 0x000424, 0x000424, 0x00117D, + 0x018042, 0x08000A, 0x000A24, 0x280502, + 0x280C02, 0x09800D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x0022FD, 0x018042, + 0x08000A, 0x000095, 0x280DC4, 0x011924, + 0x00197D, 0x018042, 0x0011FD, 0x09804A, + 0x10000A, 0x0000B5, 0x113144, 0x0A8D04, + 0x000007, 0x080A44, 0x129504, 0x000007, + 0x0023FD, 0x001020, 0x038040, 0x101244, + 0x000007, 0x000820, 0x039060, 0x018040, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x110A86, 0x000007, 0x003BFD, 0x000100, + 0x000A10, 0x0B807A, 0x13804A, 0x090984, + 0x000007, 0x000095, 0x013D04, 0x119086, + 0x10000A, 0x100002, 0x090984, 0x000007, + 0x038042, 0x11804A, 0x090D04, 0x000007, + 0x10000A, 0x090D84, 0x000007, 0x00257D, + 0x000820, 0x018040, 0x00010D, 0x000810, + 0x28143A, 0x00127D, 0x018042, 0x20000A, + 0x00197D, 0x018042, 0x00117D, 0x31804A, + 0x10000A, 0x003124, 0x01290D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x300102, 0x003124, + 0x000424, 0x000424, 0x001224, 0x280502, + 0x001A4C, 0x131186, 0x700002, 0x00002D, + 0x030000, 0x00387D, 0x018042, 0x10000A, + 0x133A06, 0x002124, 0x0000AD, 0x100002, + 0x00010D, 0x000924, 0x006B24, 0x01378D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x003264, + 0x00008D, 0x000A24, 0x001020, 0x00227D, + 0x018040, 0x013D0D, 0x000810, 0x08043A, + 0x2A1A06, 0x000007, 0x002820, 0x00207D, + 0x018040, 0x00387D, 0x018042, 0x08000A, + 0x000904, 0x166286, 0x000007, 0x00117D, + 0x038042, 0x13804A, 0x33800A, 0x018042, + 0x28000A, 0x00008D, 0x030964, 0x01498D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x380102, + 0x000424, 0x000424, 0x001224, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x14C286, + 0x000007, 0x280502, 0x001A4C, 0x166186, + 0x000007, 0x032164, 0x002E64, 0x00632C, + 0x003DFD, 0x018042, 0x08000A, 0x000095, + 0x090904, 0x000007, 0x000820, 0x001A4C, + 0x158986, 0x018040, 0x030000, 0x15A206, + 0x002124, 0x00010D, 0x000924, 0x006B24, + 0x015E0D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x003A64, 0x000095, 0x001224, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x160286, + 0x000007, 0x01650D, 0x000810, 0x08043A, + 0x2A1A06, 0x000007, 0x14F206, 0x000007, + 0x007020, 0x08010A, 0x10012A, 0x0020FD, + 0x038860, 0x039060, 0x018040, 0x00227D, + 0x018042, 0x003DFD, 0x31844A, 0x18008B, + 0x00324C, 0x172386, 0x000007, 0x001904, + 0x172086, 0x000007, 0x000095, 0x199144, + 0x00222C, 0x003124, 0x002E64, 0x00636C, + 0x000E3D, 0x001375, 0x000BFD, 0x010042, + 0x09804A, 0x10000A, 0x038AEC, 0x0393EC, + 0x00224C, 0x17A186, 0x000007, 0x00008D, + 0x189904, 0x00226C, 0x00322C, 0x002E6C, + 0x00227D, 0x018042, 0x08000A, 0x000904, + 0x17E086, 0x000007, 0x00312C, 0x002A2C, + 0x30050A, 0x301DAB, 0x002083, 0x0018FD, + 0x018042, 0x08000A, 0x018924, 0x300502, + 0x001083, 0x001875, 0x010042, 0x10000A, + 0x00008D, 0x010924, 0x001375, 0x330542, + 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB, + 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B, + 0x006083, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x18B286, 0x000007, 0x001E2D, + 0x0005FD, 0x058042, 0x08000A, 0x028924, + 0x280502, 0x00060D, 0x000810, 0x280C3A, + 0x00008D, 0x000810, 0x28143A, 0x0A808D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x002275, 0x010042, 0x20000A, 0x002104, + 0x1A2886, 0x000007, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x199A86, 0x000007, + 0x002010, 0x30043A, 0x000083, 0x018042, + 0x08000A, 0x028924, 0x280502, 0x280C02, + 0x0A810D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x001275, 0x030042, 0x21004A, + 0x28000A, 0x00008D, 0x1A0944, 0x000007, + 0x01A88D, 0x000810, 0x08043A, 0x2B6A06, + 0x000007, 0x0001F5, 0x030042, 0x0D004A, + 0x10000A, 0x089144, 0x000007, 0x000820, + 0x010040, 0x0025F5, 0x0A3144, 0x000007, + 0x000820, 0x032860, 0x030040, 0x00217D, + 0x038042, 0x0B804A, 0x10000A, 0x000820, + 0x031060, 0x030040, 0x00008D, 0x000124, + 0x00012C, 0x000E64, 0x001A64, 0x00636C, + 0x08010A, 0x10012A, 0x000820, 0x031060, + 0x030040, 0x0020FD, 0x018042, 0x08000A, + 0x00227D, 0x018042, 0x10000A, 0x000820, + 0x031060, 0x030040, 0x00197D, 0x018042, + 0x08000A, 0x0022FD, 0x038042, 0x10000A, + 0x000820, 0x031060, 0x030040, 0x090D04, + 0x000007, 0x000820, 0x030040, 0x038042, + 0x0B804A, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x038042, 0x13804A, 0x19804A, + 0x110D04, 0x198D04, 0x000007, 0x08000A, + 0x001020, 0x031860, 0x030860, 0x030040, + 0x00008D, 0x0B0944, 0x000007, 0x000820, + 0x010040, 0x0005F5, 0x030042, 0x08000A, + 0x000820, 0x010040, 0x0000F5, 0x010042, + 0x08000A, 0x000904, 0x1D6886, 0x001E75, + 0x030042, 0x01044A, 0x000C0A, 0x1D7A06, + 0x000007, 0x000402, 0x000C02, 0x00177D, + 0x001AF5, 0x018042, 0x03144A, 0x031C4A, + 0x03244A, 0x032C4A, 0x03344A, 0x033C4A, + 0x03444A, 0x004C0A, 0x00043D, 0x0013F5, + 0x001AFD, 0x030042, 0x0B004A, 0x1B804A, + 0x13804A, 0x20000A, 0x089144, 0x19A144, + 0x0389E4, 0x0399EC, 0x005502, 0x005D0A, + 0x030042, 0x0B004A, 0x1B804A, 0x13804A, + 0x20000A, 0x089144, 0x19A144, 0x0389E4, + 0x0399EC, 0x006502, 0x006D0A, 0x030042, + 0x0B004A, 0x19004A, 0x2B804A, 0x13804A, + 0x21804A, 0x30000A, 0x089144, 0x19A144, + 0x2AB144, 0x0389E4, 0x0399EC, 0x007502, + 0x007D0A, 0x03A9E4, 0x000702, 0x00107D, + 0x000415, 0x018042, 0x08000A, 0x0109E4, + 0x000F02, 0x002AF5, 0x0019FD, 0x010042, + 0x09804A, 0x10000A, 0x000934, 0x001674, + 0x0029F5, 0x010042, 0x10000A, 0x00917C, + 0x002075, 0x010042, 0x08000A, 0x000904, + 0x1FDA86, 0x0026F5, 0x0027F5, 0x030042, + 0x09004A, 0x10000A, 0x000A3C, 0x00167C, + 0x801A75, 0x800BFD, 0x810042, 0xD1804A, + 0xC8000A, 0x960007, 0x801075, 0x810042, + 0xA82C0A, 0xA81D12, 0xA82512, 0x801F32, + 0x9E0007, 0x8E0007, 0x801975, 0x810042, + 0x802DF5, 0x8D004A, 0x90000A, 0x809144, + 0xA0BA86, 0x810042, 0xA8340A, 0x800E5D, + 0x80008D, 0x800375, 0x800820, 0x810040, + 0x85D2F4, 0xD4D104, 0x800007, 0x80735C, + 0xA16386, 0x800007, 0x8C0007, 0x880007, + 0x8A0007, 0x82150D, 0x800810, 0x88043A, + 0xB40A06, 0x800007, 0xA16A06, 0x800007, + 0x880007, 0x8004FD, 0x818042, 0xF0000A, + 0x830000, 0x807020, 0x86FA06, 0x818040, + 0x821C8D, 0x800810, 0x88043A, 0xAB6A06, + 0x800007, 0x8002FD, 0x818042, 0x88000A, + 0x800904, 0xA1D286, 0x800007, 0x81F206, + 0x800007, 0x800875, 0x8009FD, 0x80010D, + 0xA25206, 0x800295, 0x800B75, 0x80097D, + 0x80000D, 0x800515, 0x810042, 0x98000A, + 0x801904, 0xA8C086, 0x8006F5, 0x801020, + 0x810040, 0x8004F5, 0x800820, 0x810040, + 0x800775, 0x810042, 0x89804A, 0x90000A, + 0x801124, 0x800904, 0xA30286, 0x800815, + 0x880102, 0x901204, 0xA32206, 0x800575, + 0x881204, 0x800007, 0x900102, 0x800575, + 0x800425, 0x821124, 0x900102, 0x800820, + 0x831060, 0x810040, 0x801924, 0xA8C086, + 0x80008D, 0x800464, 0x809D04, 0xA7D086, + 0x980102, 0x800575, 0x810042, 0xA8040A, + 0x80018D, 0x800924, 0xA80D02, 0x80000D, + 0x800924, 0xA81502, 0x90000D, 0x800820, + 0x8002F5, 0x810040, 0xA00007, 0x801175, + 0x8002FD, 0x818042, 0x88000A, 0x800904, + 0xA40A86, 0x800007, 0x800100, 0x880B20, + 0x930B60, 0x9B0B60, 0x830A60, 0x810040, + 0x850042, 0xBD004A, 0xB5004A, 0xAD004A, + 0xA0000A, 0x8006F5, 0x810042, 0xA8140A, + 0x8004F5, 0x810042, 0x88000A, 0x800315, + 0x810D04, 0xA51286, 0x804015, 0x800095, + 0x810D04, 0xA50086, 0x900022, 0x90002A, + 0xA52A06, 0x800007, 0xB33104, 0xAAA904, + 0x800007, 0x832124, 0xA80502, 0x801124, + 0x800424, 0x800424, 0x803224, 0x80292C, + 0x80636C, 0xA63B86, 0x800007, 0x82B164, + 0x800464, 0x800464, 0x80008D, 0x800A64, + 0xA80D02, 0x90008D, 0x800820, 0x8002F5, + 0x810040, 0xA20007, 0x80008D, 0xB8B904, + 0x800007, 0x83296C, 0xB0010A, 0x8002F5, + 0x810042, 0x88000A, 0x800904, 0xA60286, + 0x800007, 0x82312C, 0xA8050A, 0x80008D, + 0x81096C, 0xA80D0A, 0x90010D, 0x800820, + 0x8002F5, 0x810040, 0xA20007, 0x801124, + 0x800424, 0x800424, 0x803224, 0xB00102, + 0x832944, 0xA6C286, 0x800007, 0xB00002, + 0x8004F5, 0x810042, 0x88000A, 0x800315, + 0x810D04, 0xA70886, 0x803124, 0x800464, + 0xB00102, 0x8002F5, 0x810042, 0x88000A, + 0x800904, 0xA71286, 0x800007, 0x803124, + 0xB00502, 0x803924, 0xB00583, 0x800883, + 0x8005F5, 0x810042, 0xA8040A, 0x80008D, + 0x808124, 0xA80D02, 0x80008D, 0x808124, + 0xA81502, 0x90018D, 0x800820, 0x8002F5, + 0x810040, 0xA20007, 0x801025, 0x800575, + 0x830042, 0x89004A, 0x90000A, 0x8A0904, + 0x921104, 0x800007, 0x801020, 0x850860, + 0x850040, 0x8006FD, 0x818042, 0x89004A, + 0x90000A, 0x8000A5, 0x8A0904, 0x921104, + 0x800007, 0x800820, 0x819060, 0x810040, + 0x8002F5, 0x810042, 0x88000A, 0x800904, + 0xA88A86, 0x800007, 0xA35206, 0x800007, + 0x800606, 0x800007, 0x8002F5, 0x810042, + 0x88000A, 0x800904, 0xA8DA86, 0x800007, + 0x800100, 0x880B20, 0x938B60, 0x9B8B60, + 0xA38B60, 0xAB8B60, 0xB38B60, 0xBB8B60, + 0xC38B60, 0xCB8B60, 0xD38B60, 0xDB8B60, + 0xE38B60, 0xEB8B60, 0xF38B60, 0xFB8B60, + 0x838F60, 0x8B8F60, 0x938F60, 0x9B8F60, + 0xA38F60, 0xAB8F60, 0xB38F60, 0xBB8F60, + 0xC38F60, 0xCB8F60, 0xD38F60, 0xDB8F60, + 0xE38F60, 0xEB8F60, 0xF38F60, 0xFB8F60, + 0x838A60, 0x800606, 0x818040, 0x80008D, + 0x800A64, 0xA80D02, 0x800A24, 0x80027D, + 0x818042, 0x90000A, 0x801224, 0x8003FD, + 0x818042, 0x88000A, 0x800904, 0xAACA86, + 0x800007, 0x80018D, 0x800A24, 0x800464, + 0x800464, 0x880102, 0x800924, 0x800424, + 0x800424, 0x900102, 0x82000D, 0x809144, + 0xAB2186, 0x800007, 0x8001FD, 0x818042, + 0x88000A, 0x800A44, 0xAB0386, 0x818042, + 0x8A000D, 0x800820, 0x8002FD, 0x818040, + 0xA00007, 0x80027D, 0x801020, 0x800606, + 0x818040, 0x8002F5, 0x810042, 0x88000A, + 0x800904, 0xAB7286, 0x800007, 0x80037D, + 0x818042, 0x88000A, 0x800904, 0xABA286, + 0x800007, 0x800075, 0x802E7D, 0x810042, + 0x8B804A, 0x800020, 0x800904, 0x810040, + 0x800686, 0x800007, 0xB1844A, 0xB0048B, + 0x800883, 0x80008D, 0x800810, 0xA8143A, + 0x80008D, 0x800810, 0xA80C3A, 0x800675, + 0x810042, 0x88000A, 0x803815, 0x810924, + 0xA80502, 0x8B000D, 0x800820, 0x8002F5, + 0x810040, 0xA20007, 0x800606, 0x800007, + 0x800464, 0x800464, 0x800606, 0x800007, + 0x800134, 0x807F8D, 0x80093C, 0xA81D12, + 0xA82512, 0x801F32, 0x8E0007, 0x80010D, + 0x80037D, 0x800820, 0x818040, 0x85D2F4, + 0x800007, 0x880007, 0x80037D, 0x818042, + 0x88000A, 0x800904, 0xAD5A86, 0x800007, + 0x800606, 0x800007, 0x800007, 0x800012, + 0x900007, 0xB20007, 0xE00007, 0x900080, + 0xC8001A, 0x804904, 0xADB986, 0x800007, + 0x801210, 0xD8003A, 0x800145, 0xDC5D04, + 0x800007, 0x800080, 0xC8001A, 0x804904, + 0xAE0986, 0x800007, 0x801210, 0xD0003A, + 0x805904, 0xAE6086, 0x800045, 0x8000C5, + 0xFFFFF5, 0xFFFF7D, 0x87D524, 0x804224, + 0xD00102, 0xA00502, 0x800082, 0xC0001A, + 0x804104, 0xAE9186, 0x800007, 0x803865, + 0xC0001A, 0x804020, 0x80104D, 0x84C184, + 0xB07386, 0x800040, 0x840007, 0x800165, + 0x800145, 0x804020, 0x800040, 0x800765, + 0x880080, 0xC0001A, 0x804104, 0xAF2186, + 0x800007, 0x801210, 0xC0003A, 0x804104, + 0xAF7A86, 0x80004D, 0x8000CD, 0x804810, + 0xA0043A, 0x800882, 0xC0001A, 0x804104, + 0xAF8986, 0x800007, 0x804820, 0x805904, + 0xB06086, 0x800040, 0x8007E5, 0xA00480, + 0xA816A0, 0xB216E0, 0xBA16E0, 0xC216E0, + 0x821260, 0x800040, 0x800032, 0xC00075, + 0x80007D, 0x87D574, 0xA00512, 0x800082, + 0xC0001A, 0x804104, 0xB03986, 0x800007, + 0x837206, 0xE40007, 0x860007, 0x8000E5, + 0x800020, 0x800040, 0x800A65, 0x800020, + 0x820040, 0x820040, 0x800040, 0x800165, + 0x800042, 0xF0000A, 0x807104, 0xB0FA86, + 0x800007, 0x818206, 0xE40007, 0x850000, + 0x807020, 0x800040, 0x837206, 0xE40007, + 0x800007, 0x80306D, 0x828860, 0x829060, + 0x829860, 0x88000A, 0x828860, 0x880102, + 0x900122, 0x828860, 0x829060, 0x808040, + 0x900012, 0x801020, 0x803B6D, 0x808040, + 0x80100D, 0x809184, 0xB1E186, 0x800007, + 0x800E0D, 0x809184, 0xB2B986, 0x800007, + 0xB00007, 0x800080, 0x88001A, 0x800904, + 0xB1E986, 0x800007, 0x801220, 0x800DED, + 0x808040, 0x808042, 0x98000A, 0xC0000D, + 0x809D64, 0xA00502, 0x800082, 0x88001A, + 0x800904, 0xB25186, 0x800007, 0x803B6D, + 0x808042, 0x88000A, 0x800E15, 0x810984, + 0xE00007, 0xB33B86, 0x800007, 0x8003ED, + 0x808042, 0x88000A, 0x800904, 0xB31A86, + 0x800007, 0x88001A, 0x800C15, 0x810984, + 0xB31B86, 0x800007, 0x9A0007, 0x8002ED, + 0x800020, 0x808040, 0xE20007, 0x8032ED, + 0x828042, 0x88804A, 0x90000A, 0x800924, + 0x801664, 0x800007, 0x80306D, 0x828042, + 0x8A804A, 0x800820, 0x8A804A, 0x92804A, + 0x9A804A, 0x800606, 0x800007, 0x800007, + 0xA82512, 0x801F32, 0x85D2F4, 0xD4D104, + 0x80735C, 0x800786, 0x800007, 0x8C0007, + 0x8A0007, 0x9C0007, 0x803465, 0x820040, + 0x804820, 0x825060, 0xC0000A, 0x824060, + 0x800040, 0xC54944, 0x800007, 0x804020, + 0x803AE5, 0x800040, 0x8028E5, 0x820042, + 0xC8000A, 0x804904, 0xB9A886, 0x800007, + 0x800042, 0xC0000A, 0x804104, 0xB4E086, + 0x800007, 0x802402, 0xB7EA06, 0x805C02, + 0x802C65, 0x800042, 0xC0000A, 0x8000D5, + 0xC54104, 0x800007, 0x800655, 0x854504, + 0xB67286, 0x800007, 0x8001D5, 0x854504, + 0xB67086, 0x800007, 0x802B65, 0x800042, + 0xD0000A, 0x803AE5, 0x800042, 0xC0000A, + 0xC5C3D4, 0x800007, 0xC54504, 0x800007, + 0x803A65, 0x805820, 0x800040, 0x8000DD, + 0xC45944, 0x800007, 0xC54504, 0x800007, + 0x80015D, 0xD55944, 0x800007, 0x845144, + 0xB65186, 0x800007, 0x802C65, 0x800042, + 0xD8000A, 0xDDD104, 0x800007, 0x85C144, + 0xB65B86, 0x800007, 0x960007, 0x803A65, + 0x800042, 0xD8000A, 0x802CE5, 0x840042, + 0xC0000A, 0x804020, 0x800040, 0x8025E5, + 0x820042, 0xC0004A, 0xD0000A, 0x804274, + 0x805674, 0x802AE5, 0x800042, 0xC0000A, + 0x804274, 0xD00112, 0x8029E5, 0x800042, + 0xC0000A, 0x804234, 0xC54104, 0x800007, + 0x804020, 0x800040, 0x803EE5, 0x800020, + 0x800040, 0x802DE5, 0xC00152, 0xD0000A, + 0x845144, 0xB79286, 0x8000C5, 0x803EE5, + 0x804020, 0x800040, 0x802BE5, 0x800042, + 0xC0000A, 0xC04254, 0x800007, 0x802AE5, + 0x804020, 0x800040, 0xD00132, 0x840134, + 0x805674, 0x8029E5, 0x820042, 0xC2000A, + 0x800042, 0xD0000A, 0x85417C, 0x8000C5, + 0xCCC144, 0xB84086, 0x8026E5, 0x8027E5, + 0x820042, 0xC0004A, 0xD0000A, 0x80423C, + 0x80567C, 0x8028E5, 0x804820, 0x800040, + 0xA81D12, 0xA82512, 0x801F72, 0x802965, + 0x800042, 0xC0000A, 0x804104, 0xB8DA86, + 0x800007, 0x960007, 0x9E0007, 0x8E0007, + 0x803EE5, 0x800042, 0xC0000A, 0x804104, + 0xB92086, 0x802D65, 0x800042, 0xA8340A, + 0x803465, 0x820042, 0xC2004A, 0x804020, + 0xCA004A, 0xD0004A, 0x85D2F4, 0xD4D104, + 0x800007, 0x80735C, 0xB99186, 0x800007, + 0x800606, 0x880007, 0x8C0007, 0x880007, + 0x8A0007, 0x8001E5, 0x820045, 0x804020, + 0x800060, 0x800365, 0x800040, 0x802E65, + 0x801A20, 0x8A1A60, 0x800040, 0x803465, + 0x820042, 0xC2004A, 0x804020, 0xCA004A, + 0x800606, 0xD0004A, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +static unsigned int cntrl1E_size = 0x0c00; +static unsigned int cntrl1E[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x00800D, 0x000810, 0x20043A, 0x001A82, + 0x03460D, 0x000810, 0x10043A, 0x02EC0D, + 0x000810, 0x18043A, 0x00010D, 0x020015, + 0x0000FD, 0x000020, 0x038860, 0x039060, + 0x038060, 0x038040, 0x038040, 0x038040, + 0x018040, 0x000A7D, 0x038040, 0x038040, + 0x018040, 0x200402, 0x000882, 0x08001A, + 0x000904, 0x017186, 0x000007, 0x260007, + 0x400007, 0x000007, 0x03258D, 0x000810, + 0x18043A, 0x260007, 0x284402, 0x00087D, + 0x018042, 0x00160A, 0x05A206, 0x000007, + 0x440007, 0x00230D, 0x000810, 0x08043A, + 0x22FA06, 0x000007, 0x0007FD, 0x018042, + 0x08000A, 0x000904, 0x02AB86, 0x000195, + 0x090D04, 0x000007, 0x000820, 0x0000F5, + 0x000B7D, 0x01F060, 0x0000FD, 0x033A06, + 0x018040, 0x000A7D, 0x038042, 0x13804A, + 0x18000A, 0x001820, 0x059060, 0x058860, + 0x018040, 0x0000FD, 0x018042, 0x70000A, + 0x000115, 0x071144, 0x033B86, 0x030000, + 0x007020, 0x036206, 0x018040, 0x00360D, + 0x000810, 0x08043A, 0x232206, 0x000007, + 0x02EC0D, 0x000810, 0x18043A, 0x019A06, + 0x000007, 0x240007, 0x000F8D, 0x000810, + 0x00163A, 0x002402, 0x005C02, 0x0028FD, + 0x000020, 0x018040, 0x08000D, 0x000815, + 0x510984, 0x000007, 0x00004D, 0x000E5D, + 0x000E02, 0x00430D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x00008D, 0x000924, + 0x000F02, 0x00470D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x480480, 0x001210, + 0x28043A, 0x00778D, 0x000810, 0x280C3A, + 0x00068D, 0x000810, 0x28143A, 0x284402, + 0x03258D, 0x000810, 0x18043A, 0x07FF8D, + 0x000820, 0x0002FD, 0x018040, 0x260007, + 0x200007, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x051286, 0x000007, 0x240007, + 0x02EC0D, 0x000810, 0x18043A, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x019B86, 0x000007, 0x01B206, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x22B886, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x065A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x036186, 0x000007, 0x002104, 0x036186, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x07C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00788D, 0x000810, 0x08043A, 0x2A1206, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x070206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x229086, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x225886, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x08DA86, 0x00057D, 0x002820, + 0x03B060, 0x08F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x08FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x009D8D, 0x000810, + 0x08043A, 0x2A1206, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x0A5186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x00107D, 0x018042, + 0x08000A, 0x000215, 0x010984, 0x3A8186, + 0x000007, 0x007FBD, 0x383DC4, 0x000007, + 0x001A7D, 0x001375, 0x018042, 0x09004A, + 0x10000A, 0x0B8D04, 0x139504, 0x000007, + 0x000820, 0x019060, 0x001104, 0x225886, + 0x010040, 0x0017FD, 0x018042, 0x08000A, + 0x000904, 0x225A86, 0x000007, 0x00197D, + 0x038042, 0x09804A, 0x10000A, 0x000924, + 0x001664, 0x0011FD, 0x038042, 0x2B804A, + 0x19804A, 0x00008D, 0x218944, 0x000007, + 0x002244, 0x0C1986, 0x000007, 0x001A64, + 0x002A24, 0x00197D, 0x080102, 0x100122, + 0x000820, 0x039060, 0x018040, 0x003DFD, + 0x00008D, 0x000820, 0x018040, 0x001375, + 0x001A7D, 0x010042, 0x09804A, 0x10000A, + 0x00021D, 0x0189E4, 0x2992E4, 0x309144, + 0x000007, 0x00060D, 0x000A15, 0x000C1D, + 0x001025, 0x00A9E4, 0x012BE4, 0x000464, + 0x01B3E4, 0x0232E4, 0x000464, 0x000464, + 0x000464, 0x000464, 0x00040D, 0x08B1C4, + 0x000007, 0x000820, 0x000BF5, 0x030040, + 0x00197D, 0x038042, 0x09804A, 0x000A24, + 0x08000A, 0x080E64, 0x000007, 0x100122, + 0x000820, 0x031060, 0x010040, 0x0064AC, + 0x00027D, 0x000020, 0x018040, 0x00107D, + 0x018042, 0x0011FD, 0x3B804A, 0x09804A, + 0x20000A, 0x000095, 0x1A1144, 0x00A144, + 0x0E5886, 0x00040D, 0x00B984, 0x0E5986, + 0x0018FD, 0x018042, 0x0010FD, 0x09804A, + 0x28000A, 0x000095, 0x010924, 0x002A64, + 0x0E4986, 0x000007, 0x002904, 0x0E5A86, + 0x000007, 0x0E6206, 0x080002, 0x00008D, + 0x00387D, 0x000820, 0x018040, 0x00127D, + 0x018042, 0x10000A, 0x003904, 0x0F0986, + 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986, + 0x000025, 0x0FB206, 0x00002D, 0x000015, + 0x00082D, 0x02E00D, 0x000820, 0x0FFA06, + 0x00000D, 0x7F8035, 0x00B984, 0x0FA986, + 0x400025, 0x00008D, 0x110944, 0x000007, + 0x00018D, 0x109504, 0x000007, 0x009164, + 0x000424, 0x000424, 0x000424, 0x100102, + 0x280002, 0x02DF0D, 0x000820, 0x0FFA06, + 0x00018D, 0x00042D, 0x00008D, 0x109504, + 0x000007, 0x00020D, 0x109184, 0x000007, + 0x02DF8D, 0x000820, 0x00008D, 0x0038FD, + 0x018040, 0x003BFD, 0x001020, 0x03A860, + 0x000815, 0x313184, 0x212184, 0x000007, + 0x03B060, 0x03A060, 0x018040, 0x0022FD, + 0x000095, 0x010924, 0x000424, 0x000424, + 0x001264, 0x100102, 0x000820, 0x039060, + 0x018040, 0x001924, 0x010F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x000424, 0x000424, + 0x00117D, 0x018042, 0x08000A, 0x000A24, + 0x280502, 0x280C02, 0x09800D, 0x000820, + 0x0002FD, 0x018040, 0x200007, 0x0022FD, + 0x018042, 0x08000A, 0x000095, 0x280DC4, + 0x011924, 0x00197D, 0x018042, 0x0011FD, + 0x09804A, 0x10000A, 0x0000B5, 0x113144, + 0x0A8D04, 0x000007, 0x080A44, 0x129504, + 0x000007, 0x0023FD, 0x001020, 0x038040, + 0x101244, 0x000007, 0x000820, 0x039060, + 0x018040, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x123286, 0x000007, 0x003BFD, + 0x000100, 0x000A10, 0x0B807A, 0x13804A, + 0x090984, 0x000007, 0x000095, 0x013D04, + 0x12B886, 0x10000A, 0x100002, 0x090984, + 0x000007, 0x038042, 0x11804A, 0x090D04, + 0x000007, 0x10000A, 0x090D84, 0x000007, + 0x00257D, 0x000820, 0x018040, 0x00010D, + 0x000810, 0x28143A, 0x00127D, 0x018042, + 0x20000A, 0x00197D, 0x018042, 0x00117D, + 0x31804A, 0x10000A, 0x003124, 0x013B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x300102, + 0x003124, 0x000424, 0x000424, 0x001224, + 0x280502, 0x001A4C, 0x143986, 0x700002, + 0x00002D, 0x030000, 0x00387D, 0x018042, + 0x10000A, 0x146206, 0x002124, 0x0000AD, + 0x100002, 0x00010D, 0x000924, 0x006B24, + 0x014A0D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x003264, 0x00008D, 0x000A24, 0x001020, + 0x00227D, 0x018040, 0x014F8D, 0x000810, + 0x08043A, 0x2B5A06, 0x000007, 0x002820, + 0x00207D, 0x018040, 0x00117D, 0x038042, + 0x13804A, 0x33800A, 0x00387D, 0x018042, + 0x08000A, 0x000904, 0x177286, 0x000007, + 0x00008D, 0x030964, 0x015B0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x380102, 0x000424, + 0x000424, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x280502, 0x001A4C, 0x177186, 0x000007, + 0x032164, 0x00632C, 0x003DFD, 0x018042, + 0x08000A, 0x000095, 0x090904, 0x000007, + 0x000820, 0x001A4C, 0x169986, 0x018040, + 0x030000, 0x16B206, 0x002124, 0x00010D, + 0x000924, 0x006B24, 0x016F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x003A64, 0x000095, + 0x001224, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x171286, 0x000007, 0x01760D, + 0x000810, 0x08043A, 0x2B5A06, 0x000007, + 0x160A06, 0x000007, 0x007020, 0x08010A, + 0x10012A, 0x0020FD, 0x038860, 0x039060, + 0x018040, 0x00227D, 0x018042, 0x003DFD, + 0x08000A, 0x31844A, 0x000904, 0x181086, + 0x18008B, 0x00008D, 0x189904, 0x00312C, + 0x18E206, 0x000007, 0x00324C, 0x186B86, + 0x000007, 0x001904, 0x186886, 0x000007, + 0x000095, 0x199144, 0x00222C, 0x003124, + 0x00636C, 0x000E3D, 0x001375, 0x000BFD, + 0x010042, 0x09804A, 0x10000A, 0x038AEC, + 0x0393EC, 0x00224C, 0x18E186, 0x000007, + 0x00008D, 0x189904, 0x00226C, 0x00322C, + 0x30050A, 0x301DAB, 0x002083, 0x0018FD, + 0x018042, 0x08000A, 0x018924, 0x300502, + 0x001083, 0x001875, 0x010042, 0x10000A, + 0x00008D, 0x010924, 0x001375, 0x330542, + 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB, + 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B, + 0x006083, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x19B286, 0x000007, 0x001E2D, + 0x0005FD, 0x018042, 0x08000A, 0x028924, + 0x280502, 0x00060D, 0x000810, 0x280C3A, + 0x00008D, 0x000810, 0x28143A, 0x0A808D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x001275, 0x030042, 0x21004A, 0x00008D, + 0x1A0944, 0x000007, 0x01AB8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0001F5, + 0x030042, 0x0D004A, 0x10000A, 0x089144, + 0x000007, 0x000820, 0x010040, 0x0025F5, + 0x0A3144, 0x000007, 0x000820, 0x032860, + 0x030040, 0x00217D, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00008D, 0x000124, 0x00012C, 0x000E64, + 0x001A64, 0x00636C, 0x08010A, 0x10012A, + 0x000820, 0x031060, 0x030040, 0x0020FD, + 0x018042, 0x08000A, 0x00227D, 0x018042, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00197D, 0x018042, 0x08000A, 0x0022FD, + 0x038042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x090D04, 0x000007, 0x000820, + 0x030040, 0x038042, 0x0B804A, 0x10000A, + 0x000820, 0x031060, 0x030040, 0x038042, + 0x13804A, 0x19804A, 0x110D04, 0x198D04, + 0x000007, 0x08000A, 0x001020, 0x031860, + 0x030860, 0x030040, 0x00008D, 0x0B0944, + 0x000007, 0x000820, 0x010040, 0x0005F5, + 0x030042, 0x08000A, 0x000820, 0x010040, + 0x0000F5, 0x010042, 0x08000A, 0x000904, + 0x1D9886, 0x001E75, 0x030042, 0x01044A, + 0x000C0A, 0x1DAA06, 0x000007, 0x000402, + 0x000C02, 0x00177D, 0x001AF5, 0x018042, + 0x03144A, 0x031C4A, 0x03244A, 0x032C4A, + 0x03344A, 0x033C4A, 0x03444A, 0x004C0A, + 0x00043D, 0x0013F5, 0x001AFD, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x005502, 0x005D0A, 0x030042, 0x0B004A, + 0x1B804A, 0x13804A, 0x20000A, 0x089144, + 0x19A144, 0x0389E4, 0x0399EC, 0x006502, + 0x006D0A, 0x030042, 0x0B004A, 0x19004A, + 0x2B804A, 0x13804A, 0x21804A, 0x30000A, + 0x089144, 0x19A144, 0x2AB144, 0x0389E4, + 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4, + 0x000702, 0x00107D, 0x000415, 0x018042, + 0x08000A, 0x0109E4, 0x000F02, 0x002AF5, + 0x0019FD, 0x010042, 0x09804A, 0x10000A, + 0x000934, 0x001674, 0x0029F5, 0x010042, + 0x10000A, 0x00917C, 0x002075, 0x010042, + 0x08000A, 0x000904, 0x200A86, 0x0026F5, + 0x0027F5, 0x030042, 0x09004A, 0x10000A, + 0x000A3C, 0x00167C, 0x001A75, 0x000BFD, + 0x010042, 0x51804A, 0x48000A, 0x160007, + 0x001075, 0x010042, 0x282C0A, 0x281D12, + 0x282512, 0x001F32, 0x1E0007, 0x0E0007, + 0x001975, 0x010042, 0x002DF5, 0x0D004A, + 0x10000A, 0x009144, 0x20EA86, 0x010042, + 0x28340A, 0x000E5D, 0x00008D, 0x000375, + 0x000820, 0x010040, 0x05D2F4, 0x54D104, + 0x00735C, 0x218B86, 0x000007, 0x0C0007, + 0x080007, 0x0A0007, 0x02178D, 0x000810, + 0x08043A, 0x34B206, 0x000007, 0x219206, + 0x000007, 0x080007, 0x002275, 0x010042, + 0x20000A, 0x002104, 0x225886, 0x001E2D, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x21CA86, 0x000007, 0x002010, 0x30043A, + 0x00057D, 0x0180C3, 0x08000A, 0x028924, + 0x280502, 0x280C02, 0x0A810D, 0x000820, + 0x0002F5, 0x010040, 0x220007, 0x0004FD, + 0x018042, 0x70000A, 0x030000, 0x007020, + 0x07FA06, 0x018040, 0x022B8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x22C286, + 0x000007, 0x020206, 0x000007, 0x000875, + 0x0009FD, 0x00010D, 0x234206, 0x000295, + 0x000B75, 0x00097D, 0x00000D, 0x000515, + 0x010042, 0x18000A, 0x001904, 0x2A0086, + 0x0006F5, 0x001020, 0x010040, 0x0004F5, + 0x000820, 0x010040, 0x000775, 0x010042, + 0x09804A, 0x10000A, 0x001124, 0x000904, + 0x23F286, 0x000815, 0x080102, 0x101204, + 0x241206, 0x000575, 0x081204, 0x000007, + 0x100102, 0x000575, 0x000425, 0x021124, + 0x100102, 0x000820, 0x031060, 0x010040, + 0x001924, 0x2A0086, 0x00008D, 0x000464, + 0x009D04, 0x291086, 0x180102, 0x000575, + 0x010042, 0x28040A, 0x00018D, 0x000924, + 0x280D02, 0x00000D, 0x000924, 0x281502, + 0x10000D, 0x000820, 0x0002F5, 0x010040, + 0x200007, 0x001175, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x24FA86, 0x000007, + 0x000100, 0x080B20, 0x130B60, 0x1B0B60, + 0x030A60, 0x010040, 0x050042, 0x3D004A, + 0x35004A, 0x2D004A, 0x20000A, 0x0006F5, + 0x010042, 0x28140A, 0x0004F5, 0x010042, + 0x08000A, 0x000315, 0x010D04, 0x260286, + 0x004015, 0x000095, 0x010D04, 0x25F086, + 0x100022, 0x10002A, 0x261A06, 0x000007, + 0x333104, 0x2AA904, 0x000007, 0x032124, + 0x280502, 0x284402, 0x001124, 0x400102, + 0x000424, 0x000424, 0x003224, 0x00292C, + 0x00636C, 0x277386, 0x000007, 0x02B164, + 0x000464, 0x000464, 0x00008D, 0x000A64, + 0x280D02, 0x10008D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x00008D, 0x38B904, + 0x000007, 0x03296C, 0x30010A, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x270286, + 0x000007, 0x00212C, 0x28050A, 0x00316C, + 0x00046C, 0x00046C, 0x28450A, 0x001124, + 0x006B64, 0x100102, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x004124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x27FA86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x284086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x284A86, 0x000007, 0x284402, 0x003124, + 0x300502, 0x003924, 0x300583, 0x000883, + 0x0005F5, 0x010042, 0x28040A, 0x00008D, + 0x008124, 0x280D02, 0x00008D, 0x008124, + 0x281502, 0x10018D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001025, 0x000575, + 0x030042, 0x09004A, 0x10000A, 0x0A0904, + 0x121104, 0x000007, 0x001020, 0x050860, + 0x050040, 0x0006FD, 0x018042, 0x09004A, + 0x10000A, 0x0000A5, 0x0A0904, 0x121104, + 0x000007, 0x000820, 0x019060, 0x010040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x29CA86, 0x000007, 0x244206, 0x000007, + 0x000606, 0x000007, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x2A1A86, 0x000007, + 0x000100, 0x080B20, 0x138B60, 0x1B8B60, + 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60, + 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60, + 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60, + 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60, + 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60, + 0x038A60, 0x000606, 0x018040, 0x00008D, + 0x000A64, 0x280D02, 0x000A24, 0x00027D, + 0x018042, 0x10000A, 0x001224, 0x0003FD, + 0x018042, 0x08000A, 0x000904, 0x2C0A86, + 0x000007, 0x00018D, 0x000A24, 0x000464, + 0x000464, 0x080102, 0x000924, 0x000424, + 0x000424, 0x100102, 0x02000D, 0x009144, + 0x2C6186, 0x000007, 0x0001FD, 0x018042, + 0x08000A, 0x000A44, 0x2C4386, 0x018042, + 0x0A000D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00027D, 0x001020, 0x000606, + 0x018040, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x2CB286, 0x000007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2CE286, + 0x000007, 0x000075, 0x002E7D, 0x010042, + 0x0B804A, 0x000020, 0x000904, 0x000686, + 0x010040, 0x31844A, 0x30048B, 0x000883, + 0x00008D, 0x000810, 0x28143A, 0x00008D, + 0x000810, 0x280C3A, 0x000675, 0x010042, + 0x08000A, 0x003815, 0x010924, 0x280502, + 0x0B000D, 0x000820, 0x0002F5, 0x010040, + 0x000606, 0x220007, 0x000464, 0x000464, + 0x000606, 0x000007, 0x000134, 0x007F8D, + 0x00093C, 0x281D12, 0x282512, 0x001F32, + 0x0E0007, 0x00010D, 0x00037D, 0x000820, + 0x018040, 0x05D2F4, 0x000007, 0x080007, + 0x00037D, 0x018042, 0x08000A, 0x000904, + 0x2E8A86, 0x000007, 0x000606, 0x000007, + 0x000007, 0x000012, 0x100007, 0x320007, + 0x600007, 0x460007, 0x100080, 0x48001A, + 0x004904, 0x2EF186, 0x000007, 0x001210, + 0x58003A, 0x000145, 0x5C5D04, 0x000007, + 0x000080, 0x48001A, 0x004904, 0x2F4186, + 0x000007, 0x001210, 0x50003A, 0x005904, + 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5, + 0x7FFF7D, 0x07D524, 0x004224, 0x500102, + 0x200502, 0x000082, 0x40001A, 0x004104, + 0x2FC986, 0x000007, 0x003865, 0x40001A, + 0x004020, 0x00104D, 0x04C184, 0x31AB86, + 0x000040, 0x040007, 0x000165, 0x000145, + 0x004020, 0x000040, 0x000765, 0x080080, + 0x40001A, 0x004104, 0x305986, 0x000007, + 0x001210, 0x40003A, 0x004104, 0x30B286, + 0x00004D, 0x0000CD, 0x004810, 0x20043A, + 0x000882, 0x40001A, 0x004104, 0x30C186, + 0x000007, 0x004820, 0x005904, 0x319886, + 0x000040, 0x0007E5, 0x200480, 0x2816A0, + 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260, + 0x000040, 0x000032, 0x400075, 0x00007D, + 0x07D574, 0x200512, 0x000082, 0x40001A, + 0x004104, 0x317186, 0x000007, 0x038A06, + 0x640007, 0x0000E5, 0x000020, 0x000040, + 0x000A65, 0x000020, 0x020040, 0x020040, + 0x000040, 0x000165, 0x000042, 0x70000A, + 0x007104, 0x323286, 0x000007, 0x060007, + 0x019A06, 0x640007, 0x050000, 0x007020, + 0x000040, 0x038A06, 0x640007, 0x000007, + 0x00306D, 0x028860, 0x029060, 0x08000A, + 0x028860, 0x008040, 0x100012, 0x00100D, + 0x009184, 0x32D186, 0x000E0D, 0x009184, + 0x33E186, 0x000007, 0x300007, 0x001020, + 0x003B6D, 0x008040, 0x000080, 0x08001A, + 0x000904, 0x32F186, 0x000007, 0x001220, + 0x000DED, 0x008040, 0x008042, 0x10000A, + 0x40000D, 0x109544, 0x000007, 0x001020, + 0x000DED, 0x008040, 0x008042, 0x20040A, + 0x000082, 0x08001A, 0x000904, 0x338186, + 0x000007, 0x003B6D, 0x008042, 0x08000A, + 0x000E15, 0x010984, 0x342B86, 0x600007, + 0x08001A, 0x000C15, 0x010984, 0x341386, + 0x000020, 0x1A0007, 0x0002ED, 0x008040, + 0x620007, 0x00306D, 0x028042, 0x0A804A, + 0x000820, 0x0A804A, 0x000606, 0x10804A, + 0x000007, 0x282512, 0x001F32, 0x05D2F4, + 0x54D104, 0x00735C, 0x000786, 0x000007, + 0x0C0007, 0x0A0007, 0x1C0007, 0x003465, + 0x020040, 0x004820, 0x025060, 0x40000A, + 0x024060, 0x000040, 0x454944, 0x000007, + 0x004020, 0x003AE5, 0x000040, 0x0028E5, + 0x000042, 0x48000A, 0x004904, 0x39F886, + 0x002C65, 0x000042, 0x40000A, 0x0000D5, + 0x454104, 0x000007, 0x000655, 0x054504, + 0x368286, 0x0001D5, 0x054504, 0x368086, + 0x002B65, 0x000042, 0x003AE5, 0x50004A, + 0x40000A, 0x45C3D4, 0x000007, 0x454504, + 0x000007, 0x0000CD, 0x444944, 0x000007, + 0x454504, 0x000007, 0x00014D, 0x554944, + 0x000007, 0x045144, 0x367986, 0x002C65, + 0x000042, 0x48000A, 0x4CD104, 0x000007, + 0x04C144, 0x368386, 0x000007, 0x160007, + 0x002CE5, 0x040042, 0x40000A, 0x004020, + 0x000040, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x36F086, 0x000007, 0x002402, + 0x383206, 0x005C02, 0x0025E5, 0x000042, + 0x40000A, 0x004274, 0x002AE5, 0x000042, + 0x40000A, 0x004274, 0x500112, 0x0029E5, + 0x000042, 0x40000A, 0x004234, 0x454104, + 0x000007, 0x004020, 0x000040, 0x003EE5, + 0x000020, 0x000040, 0x002DE5, 0x400152, + 0x50000A, 0x045144, 0x37DA86, 0x0000C5, + 0x003EE5, 0x004020, 0x000040, 0x002BE5, + 0x000042, 0x40000A, 0x404254, 0x000007, + 0x002AE5, 0x004020, 0x000040, 0x500132, + 0x040134, 0x005674, 0x0029E5, 0x020042, + 0x42000A, 0x000042, 0x50000A, 0x05417C, + 0x0028E5, 0x000042, 0x48000A, 0x0000C5, + 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5, + 0x020042, 0x40004A, 0x50000A, 0x00423C, + 0x00567C, 0x0028E5, 0x004820, 0x000040, + 0x281D12, 0x282512, 0x001F72, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x393A86, + 0x0E0007, 0x160007, 0x1E0007, 0x003EE5, + 0x000042, 0x40000A, 0x004104, 0x397886, + 0x002D65, 0x000042, 0x28340A, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x50004A, 0x05D2F4, 0x54D104, 0x00735C, + 0x39E186, 0x000007, 0x000606, 0x080007, + 0x0C0007, 0x080007, 0x0A0007, 0x0001E5, + 0x020045, 0x004020, 0x000060, 0x000365, + 0x000040, 0x002E65, 0x001A20, 0x0A1A60, + 0x000040, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x000606, 0x50004A, + 0x0017FD, 0x018042, 0x08000A, 0x000904, + 0x225A86, 0x000007, 0x00107D, 0x018042, + 0x0011FD, 0x33804A, 0x19804A, 0x20000A, + 0x000095, 0x2A1144, 0x01A144, 0x3B9086, + 0x00040D, 0x00B184, 0x3B9186, 0x0018FD, + 0x018042, 0x0010FD, 0x09804A, 0x38000A, + 0x000095, 0x010924, 0x003A64, 0x3B8186, + 0x000007, 0x003904, 0x3B9286, 0x000007, + 0x3B9A06, 0x00000D, 0x00008D, 0x000820, + 0x00387D, 0x018040, 0x700002, 0x00117D, + 0x018042, 0x00197D, 0x29804A, 0x30000A, + 0x380002, 0x003124, 0x000424, 0x000424, + 0x002A24, 0x280502, 0x00068D, 0x000810, + 0x28143A, 0x00750D, 0x00B124, 0x002264, + 0x3D0386, 0x284402, 0x000810, 0x280C3A, + 0x0B800D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00758D, 0x00B124, 0x100102, + 0x012144, 0x3E4986, 0x001810, 0x10003A, + 0x00387D, 0x018042, 0x08000A, 0x000904, + 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD, + 0x00008D, 0x023164, 0x000A64, 0x280D02, + 0x0B808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00387D, 0x018042, 0x08000A, + 0x000904, 0x3E3286, 0x030000, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x3D8286, + 0x000007, 0x002810, 0x28043A, 0x00750D, + 0x030924, 0x002264, 0x280D02, 0x02316C, + 0x28450A, 0x0B810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x00008D, 0x000A24, + 0x3E4A06, 0x100102, 0x001810, 0x10003A, + 0x0000BD, 0x003810, 0x30043A, 0x00187D, + 0x018042, 0x0018FD, 0x09804A, 0x20000A, + 0x0000AD, 0x028924, 0x07212C, 0x001010, + 0x300583, 0x300D8B, 0x3014BB, 0x301C83, + 0x002083, 0x00137D, 0x038042, 0x33844A, + 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB, + 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083, + 0x001E0D, 0x0005FD, 0x018042, 0x20000A, + 0x020924, 0x00068D, 0x00A96C, 0x00009D, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x3F6A86, 0x000007, 0x280502, 0x280D0A, + 0x284402, 0x001810, 0x28143A, 0x0C008D, + 0x000820, 0x0002FD, 0x018040, 0x220007, + 0x003904, 0x225886, 0x001E0D, 0x00057D, + 0x018042, 0x20000A, 0x020924, 0x0000A5, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x402A86, 0x000007, 0x280502, 0x280C02, + 0x002010, 0x28143A, 0x0C010D, 0x000820, + 0x0002FD, 0x018040, 0x225A06, 0x220007, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +#define PLAY_TABLE_SIZE 0x200 +#define DMA_BUFF_SIZE 0x2000 +#define RIGHT 0 +#define LEFT 1 + +typedef struct +{ + unsigned int *table; +} +PLAY_CNTRL_TABLE; + + +typedef struct +{ + unsigned int Format; + unsigned int LoopDefault; + unsigned int PgBase; + unsigned int PgLoop; + unsigned int PgLoopEnd; + unsigned int PgLoopFrac; + unsigned int PgDeltaEnd; + unsigned int LpfKEnd; + unsigned int EgGainEnd; + unsigned int LchGainEnd; + unsigned int RchGainEnd; + unsigned int Effect1GainEnd; + unsigned int Effect2GainEnd; + unsigned int Effect3GainEnd; + unsigned int LpfQ; + unsigned int Status; + unsigned int NumOfFrames; + unsigned int LoopCount; + unsigned int PgStart; + unsigned int PgStartFrac; + unsigned int PgDelta; + unsigned int LpfK; + unsigned int EgGain; + unsigned int LchGain; + unsigned int RchGain; + unsigned int Effect1Gain; + unsigned int Effect2Gain; + unsigned int Effect3Gain; + unsigned int LpfDelay1; + unsigned int LpfDelay2; +} +PLAY_BANK; + +typedef struct +{ + unsigned int PgBase; + unsigned int PgLoopEndAdr; + unsigned int PgStartAdr; + unsigned int NumOfLoops; +} +REC_BANK; + +typedef struct +{ + unsigned int PgBase; + unsigned int PgLoopEnd; + unsigned int PgStart; + unsigned int Temp; + +} +EFFECT_BANK; + +typedef struct +{ + PLAY_BANK *bank1; + PLAY_BANK *bank2; +} +PLAY_CNTRL_SLOT; + +typedef struct +{ + oss_native_word base; + REC_BANK *bank1; + REC_BANK *bank2; + REC_BANK *bank3; + REC_BANK *bank4; +} +REC_CNTRL_SLOT; + +typedef struct +{ + oss_native_word base; + EFFECT_BANK *bank1; + EFFECT_BANK *bank2; + EFFECT_BANK *bank3; + EFFECT_BANK *bank4; + EFFECT_BANK *bank5; + EFFECT_BANK *bank6; + EFFECT_BANK *bank7; + EFFECT_BANK *bank8; + EFFECT_BANK *bank9; + EFFECT_BANK *bank10; +} +EFFECT_CNTRL_SLOT; diff --git a/kernel/drv/osscore/.config b/kernel/drv/osscore/.config new file mode 100644 index 0000000..95833c8 --- /dev/null +++ b/kernel/drv/osscore/.config @@ -0,0 +1,2 @@ +bus=VIRTUAL +targetos=SunOS diff --git a/kernel/drv/osscore/.devices b/kernel/drv/osscore/.devices new file mode 100644 index 0000000..c435d26 --- /dev/null +++ b/kernel/drv/osscore/.devices @@ -0,0 +1 @@ +osscore OSSCORE OSS Core services diff --git a/kernel/drv/osscore/.name b/kernel/drv/osscore/.name new file mode 100644 index 0000000..8d69ed6 --- /dev/null +++ b/kernel/drv/osscore/.name @@ -0,0 +1 @@ +OSS Core services diff --git a/kernel/drv/osscore/.params b/kernel/drv/osscore/.params new file mode 100644 index 0000000..62e4af5 --- /dev/null +++ b/kernel/drv/osscore/.params @@ -0,0 +1,133 @@ +int detect_trace=0; +/* + * Detect Trace will trace the audio device detection and operation. However + * this feature should only be enabled when requested by the technical support + * personnell. + */ +int max_intrate=100; +/* + * Max intrate sets up the maximum number of interrupts/second. This + * in turn sets up the minimum buffer fragment size. The default value is 100 + * It equals to about 50 fps frame rate which should be good for most + * applications (including games). However some special applications + * may require lower latencies. In such cases a higher value such as 500 or 1000 + * may be needed. The minimum latency will be roughly 2/max_intrate + * seconds. However the exactl latency depends on what the application has + * requested using ioctl(SNDCTL_DSP_SETFRAGMENT). A value of zero means + * OSS doesn't try to limit interrupt rate. + * + * Lower latencies require higher interrupt rates which in turn causes higher + * system overhead. In addition using max_intrate values higher than system's + * internal clock rate (HZ) may not make any actual improvement. + * + * Some devices use fixed fragment size and this parameter will not have any + * effect with them. For example the Digi32 and Digi96 devices work in this way. + */ +int src_quality=3; +/* + * The src_quality setting defines the precision of the software based sample + * rate conversion algorithm used by OSS. This setting doesn't affect possible + * hardware level conversions done by the devices themselves. Using higher + * quality setting gives better quality while lower settings consume less + * CPU time. + * + * Possible values are: + * 0 - D lowest quality (normally equals to 1=low quality) + * 1 - L low quality (spline interpolation) + * 2 - M medium quality (lagrange interpolation) + * 3 - H high quality (DEFAULT) + * 4 - HX high quality (high quality with extra precision) + * 5 - P production quality + * 6 - PX production quality (prod quality with extra precision) + */ +int ac97_amplifier=-1; +/* + * When set to 1 this option enables the speaker power amplifier feature of + * AC97 codec (if available). Some boards have this inverted, so if necessary + * this feature can be disabled by setting this option to 0. + * Affects all AC97 based audio devices in the system. + * Default: -1=autodetect correct setting. + */ +int ac97_recselect=0; +/* + * When set to 1 this option enables independent recording source + * selection for the left and the right channel on AC97 devices. In this way + * it's possible to record audio streams so that (for example) the left + * channel signal comes from the microphone and the right channel signal from + * line-in. However when this option is enabled it's only possible to + * select the recording source by using a fully OSS 4.0 compatible mixer + * program such as ossxmix. + */ +int cooked_enable=1; +/* + * By default OSS will let applications to use sampling rates and formats + * that are not supported by the hardware. Instead OSS performs the necessary + * format conversions in software. Applications that don't tolerate this kind + * of conversions usually disable them by using features of the OSS API + * (SNDCTL_DSP_COOKEDMODE). If this option is set to 0 then the format + * conversions will be disabled for all applications and devices unless the + * application explicitly enables them. This option should not be changed + * without wery strong reason. + */ +int dma_buffsize=0; +/* + * By default OSS will allocate audio DMA buffers with some system dependent + * default size (usually 64k but sometimes smaller). It is possible to change + * this default allocation by setting this option. Value of 0 means that the + * default size will be used. Value between 16 and 128 (kilobytes) can be used + * if the default size is not suitable for some reason. This option must not be + * changed unless it's absolutely necessary. + */ +int flat_device_model=0; +/* + * OSS version 4.0 and later use two level device model where multiple audio + * engines supported by the device (hardware mixing or vmix) are hidden behind + * the same device file. When this device file is opened OSS will connect the + * application to the first available subdevice. In this way multiple + * applications can use the same device file at the same time. + * + * If this option is set to 0 OSS will use the earlier (OSS 3.x) device scheme + * where all devices are directly visible to the applications. This may be + * necessary with some custom applications that depend on the old + * behaviour. + */ +int vmix_disabled=0; +/* + * The virtual mixer subsystem can be disabled by setting this configuration + * option to 1. By default the value is 0 which enables virtual mixer. + */ +int vmix_loopdevs=0; +/* + * Optionally the virtual mixer subsystem can create special loopback audio + * devices that can be used to record the output mix sent to the device. + * This option tells how many loopback devices will be created (0, 1 or 2). + * If there are multiple audio devices in the system the all of them will have + * the same number of loopback devices. This setting should be left to 0 unless + * there are specific reasons to enable the loopback devices. + */ +int vmix_no_autoattach=0; +/* + * By default (0) the low level drivers for most sound cards will automatically + * attach virtual mixer (vmix) to the primary audio devices of the cards. + * In some situations it may be necessary to attach virtual mixer using + * nonstandard parameters. If vmix_no_autoattach is set to 1 then user + * can use vmixctl attach command to attach virtual mixer manually to + * the device(s). + */ +int excl_policy=0; +/* + * By default the O_EXCL open() flag can be used to bypass the virtual mixer. + * Setting excl_policy to 1 or 2 makes OSS ignore O_EXCL. A setting of 1 + * ignores O_EXCL from all but root processes, while a setting of 2 always + * ignores O_EXCL. + */ +int mixer_muted=0; +/* + * By default mixer volume controls will be set to audible levels + * when OSS drivers are loaded. However in some systems it may + * be necessary to default to lower levels to avoid feedback or + * noise. Set mixer_muted to 1 to use low default levels and to + * 0 to select audible levels. + * + * Note that just few OSS drivers support this option. + */ diff --git a/kernel/drv/osscore/osscore.c b/kernel/drv/osscore/osscore.c new file mode 100644 index 0000000..30ee133 --- /dev/null +++ b/kernel/drv/osscore/osscore.c @@ -0,0 +1,39 @@ +/* + * Purpose: OSS core pseudo driver (for Solaris) + * + * The osscore driver is used under Solaris to load the configuration settings + * (osscore.conf) and to install the /dev/sndstat device. + */ +/* + * + * 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 "osscore_cfg.h" + +int +osscore_attach (oss_device_t * osdev) +{ + oss_register_device (osdev, "OSS common devices"); + install_sndstat (osdev); + install_dev_mixer (osdev); + return 1; +} + +int +osscore_detach (oss_device_t * osdev) +{ + if (oss_disable_device (osdev) < 0) + return 0; + + oss_unregister_device (osdev); + + return 1; +} diff --git a/kernel/drv/osscore/osscore.man b/kernel/drv/osscore/osscore.man new file mode 100644 index 0000000..5af4ca2 --- /dev/null +++ b/kernel/drv/osscore/osscore.man @@ -0,0 +1,86 @@ +NAME +osscore - Open Sound Sytem core audio framework. + +DESCRIPTION +Open Sound System core audio support psudo driver. This driver implements the core Open Sound System API for audio, midi, mixer and synth functions. This driver also implements the OS driver interface as well as device configuration and setup. +More information on programming on the OSS API is avaialable at: +http://manuals.opensound.com/ + +OPTIONS +o ac97_recselect When set to 1 this option enables independent + recording source selection for the left and the right channel + on AC97 devices. In this way it's possible to record audio + streams so that (for example) the left channel signal comes + from the microphone and + the right channel signal from line-in. However when this + option is enabled it's only possible to select the recording + source by using a fully OSS 4.0 compatible mixer program such + as ossxmix. + Default: 0 - recording source is common to both channels. +o ac97_amplifier When set to 1 this option enables the speaker power + amplifier feature of AC97 codec (if available). + Some boards have this inverted, so this feature can be + disabled by setting this option to 0. + Affects all AC97 based audio devices in the system. + Default: -1=autodetect correct setting. +o cooked_enable By default OSS will let applications to use sampling + rates and formats that are not supported by the hardware. + Instead OSS performs the necessary format conversions in + software. Applications that don't tolerate this kind of + conversions usually disable them by using features of the OSS + API (SNDCTL_DSP_COOKEDMODE). If this option is set to 0 then + the format conversions will be disabled for all applications + and devices unless the application explicitly enables them. + Default: 1 - conversions are enabled. + This option should not be changed without very strong reasons. +o detect_trace Internal debugging (do not change). Default: 0 +o dma_buffsize By default OSS will allocate audio DMA buffers with some + system dependent default size (usually 64k but sometimes + smaller). It is possible to change this default allocation by + setting this option. Value of 0 means that the default size + will be used. Value between 16 and 128 (kilobytes) can be used + if the default size is not suitable for some reason. + Default: 0 - system dependent buffsize. + This option mustn't be changed unless it's absolutely necessary. +o max_intrate Set the maximum number of interrupts per second. + A value of 0 means the number is unlimited. + Default: 100 interrupts per second which equals to about + 10 msec minimum latencies. +o vmix_disabled The virtual mixer subsystem can be disabled by setting + this configuration option to 1. + Default: 0 - virtual mixer is enabled. +o vmix_loopdevs Optionally the virtual mixer subsystem can create + special loopback audio devices that can be used to record the + output mix sent to the device. This option tells how many + loopback devices will be created (0, 1 or 2). If there are + multiple audio devices in the system the all of them will have + the same number of loopback devices. + Default: 0 - no loopback devices are created. + This setting should be left to 0 unless there are specific + reasons to enable the loopback devices. +o vmix_no_autoattach By default (0) the low level + drivers for most sound cards will automatically + attach virtual mixer (vmix) to the primary audio devices of the cards. + In some situations it may be necessary to attach virtual mixer using + nonstandard parameters. If vmix_no_autoattach is set to 1 then user + can use vmixctl attach command to attach virtual mixer manually to + the device(s). + Default: 0 - Automatically attach virtual mixer. +o excl_policy The O_EXCL open() flag can be used by programs to bypass the + virtual mixer. Setting excl_policy to 1 or 2 makes OSS ignore O_EXCL. + A setting of 1 ignores O_EXCL from all but root processes, + while a setting of 2 always ignores O_EXCL. + Default: 0 - Do not ignore O_EXCL. +o mixer_muted By default OSS will set most volume controls to audible level. + If this causes problems then it's possible to ask OSS to set + the levels to zero when the drivers are loaded. However the + levels saved with the savemixer utility will get loaded few + moments later when all OSS drivers have been started. Note that + just some of the OSS drivers honor this setting. + Values: 0 (default) - Use audible volumes, 1 - Set volumes to low. + +FILES +CONFIGFILEPATH/osscore.conf Device configuration file + +AUTHOR +4Front Technologies |