* added C-Media CMI8338/8738-based sound card device driver, it originates
from C-Media itself, and was later improved upon by Marko Koscak * includes some fixes by Dr. Hartmut Reh * uses old audio driver API * builds, but I don't know if it works yet. I do have such a card, but on another computer... will check if it works and add it to the image if it does git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21536 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c1071005c9
commit
028e368c21
@ -1,6 +1,7 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers audio ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers audio cmedia ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers audio echo ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers audio emuxki ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers audio hda ;
|
||||
|
22
src/add-ons/kernel/drivers/audio/cmedia/Jamfile
Normal file
22
src/add-ons/kernel/drivers/audio/cmedia/Jamfile
Normal file
@ -0,0 +1,22 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers audio cmedia ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
UsePrivateHeaders audio ;
|
||||
|
||||
KernelAddon cmedia :
|
||||
cm.c
|
||||
joy.c
|
||||
midi.c
|
||||
mixer.c
|
||||
mux.c
|
||||
pcm.c
|
||||
;
|
||||
|
||||
Package haiku-cmedia-cvs
|
||||
:
|
||||
cmedia
|
||||
:
|
||||
boot home config add-ons kernel drivers bin ;
|
||||
|
||||
PackageDriverSymLink haiku-cmedia-cvs : audio cmedia ;
|
784
src/add-ons/kernel/drivers/audio/cmedia/cm.c
Normal file
784
src/add-ons/kernel/drivers/audio/cmedia/cm.c
Normal file
@ -0,0 +1,784 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include "cmedia_pci.h"
|
||||
#include "cm_private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(_KERNEL_EXPORT_H)
|
||||
#include <KernelExport.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#define KPRINTF(x) kprintf x
|
||||
#else
|
||||
#define KPRINTF(x)
|
||||
#endif
|
||||
|
||||
EXPORT status_t init_hardware(void);
|
||||
EXPORT status_t init_driver(void);
|
||||
EXPORT void uninit_driver(void);
|
||||
EXPORT const char ** publish_devices(void);
|
||||
EXPORT device_hooks * find_device(const char *);
|
||||
|
||||
|
||||
static char pci_name[] = B_PCI_MODULE_NAME;
|
||||
static pci_module_info *pci;
|
||||
static char gameport_name[] = "generic/gameport/v1";
|
||||
generic_gameport_module * gameport;
|
||||
static char mpu401_name[] = B_MPU_401_MODULE_NAME;
|
||||
generic_mpu401_module * mpu401;
|
||||
|
||||
#define DO_JOY 1
|
||||
#define DO_MIDI 1
|
||||
#define DO_PCM 1
|
||||
#define DO_MUX 0
|
||||
#define DO_MIXER 0
|
||||
|
||||
#if DO_MIDI
|
||||
extern device_hooks midi_hooks;
|
||||
#endif /* DO_MIDI */
|
||||
#if DO_JOY
|
||||
extern device_hooks joy_hooks;
|
||||
#endif /* DO_JOY */
|
||||
#if DO_PCM
|
||||
extern device_hooks pcm_hooks;
|
||||
#endif /* DO_PCM */
|
||||
#if DO_MUX
|
||||
extern device_hooks mux_hooks;
|
||||
#endif /* DO_MUX */
|
||||
#if DO_MIXER
|
||||
extern device_hooks mixer_hooks;
|
||||
#endif /* DO_MIXER */
|
||||
|
||||
|
||||
int32 num_cards;
|
||||
cmedia_pci_dev cards[NUM_CARDS];
|
||||
int num_names;
|
||||
char * names[NUM_CARDS*7+1];
|
||||
/* vuchar *io_base; */
|
||||
|
||||
|
||||
/* ----------
|
||||
PCI_IO_RD - read a byte from pci i/o space
|
||||
----- */
|
||||
|
||||
uint8
|
||||
PCI_IO_RD (int offset)
|
||||
{
|
||||
return (*pci->read_io_8) (offset);
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
PCI_IO_RD_32 - read a 32 bit value from pci i/o space
|
||||
----- */
|
||||
|
||||
uint32
|
||||
PCI_IO_RD_32 (int offset)
|
||||
{
|
||||
return (*pci->read_io_32) (offset);
|
||||
}
|
||||
/* ----------
|
||||
PCI_IO_WR - write a byte to pci i/o space
|
||||
----- */
|
||||
|
||||
void
|
||||
PCI_IO_WR (int offset, uint8 val)
|
||||
{
|
||||
(*pci->write_io_8) (offset, val);
|
||||
}
|
||||
|
||||
|
||||
/* detect presence of our hardware */
|
||||
status_t
|
||||
init_hardware(void)
|
||||
{
|
||||
int ix=0;
|
||||
pci_info info;
|
||||
status_t err = ENODEV;
|
||||
|
||||
ddprintf(("cmedia_pci: init_hardware()\n"));
|
||||
|
||||
if (get_module(pci_name, (module_info **)&pci))
|
||||
return ENOSYS;
|
||||
|
||||
while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
|
||||
if (info.vendor_id == CMEDIA_PCI_VENDOR_ID &&
|
||||
(info.device_id == CMEDIA_8338A_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8338B_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8738A_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8738B_DEVICE_ID )) {
|
||||
err = B_OK;
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
#if defined(__POWERPC__) && 0
|
||||
{
|
||||
char area_name [32];
|
||||
area_info area;
|
||||
area_id id;
|
||||
|
||||
sprintf (area_name, "pci_bus%d_isa_io", info.bus);
|
||||
id = find_area (area_name);
|
||||
if (id < 0)
|
||||
err = id;
|
||||
else if ((err = get_area_info (id, &area)) == B_OK)
|
||||
io_base = area.address;
|
||||
}
|
||||
#endif
|
||||
|
||||
put_module(pci_name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void set_direct( cmedia_pci_dev * card, int regno, uchar value, uchar mask)
|
||||
{
|
||||
if (mask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mask != 0xff)
|
||||
{
|
||||
uchar old = PCI_IO_RD(card->enhanced+regno);
|
||||
value = (value&mask)|(old&~mask);
|
||||
}
|
||||
PCI_IO_WR(card->enhanced+regno, value);
|
||||
ddprintf(("cmedia_pci: CM%02x = %02x\n", regno, value));
|
||||
}
|
||||
|
||||
|
||||
uchar get_direct(cmedia_pci_dev * card, int regno)
|
||||
{
|
||||
uchar ret = PCI_IO_RD(card->enhanced+regno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void set_indirect(cmedia_pci_dev * card, int regno, uchar value, uchar mask)
|
||||
{
|
||||
PCI_IO_WR(card->enhanced+0x23, regno);
|
||||
EIEIO();
|
||||
if (mask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (mask != 0xff)
|
||||
{
|
||||
uchar old = PCI_IO_RD(card->enhanced+0x22);
|
||||
value = (value&mask)|(old&~mask);
|
||||
}
|
||||
PCI_IO_WR(card->enhanced+0x22, value);
|
||||
EIEIO();
|
||||
ddprintf(("cmedia_pci: CMX%02x = %02x\n", regno, value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
uchar get_indirect(cmedia_pci_dev * card,int regno)
|
||||
{
|
||||
uchar ret;
|
||||
PCI_IO_WR(card->enhanced+0x23, regno);
|
||||
EIEIO();
|
||||
ret = PCI_IO_RD(card->enhanced+0x22);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void dump_card(cmedia_pci_dev * card)
|
||||
{
|
||||
int ix;
|
||||
dprintf("\n");
|
||||
dprintf("CM: ");
|
||||
for (ix=0; ix<6; ix++) {
|
||||
if (ix == 2 || ix == 3) dprintf(" ");
|
||||
else dprintf(" %02x", get_direct(card, ix));
|
||||
}
|
||||
for (ix=0; ix<0x32; ix++) {
|
||||
if (!(ix & 7)) {
|
||||
dprintf("\nCMX%02x:", ix);
|
||||
}
|
||||
dprintf(" %02x", get_indirect(card, ix));
|
||||
}
|
||||
dprintf("\n");
|
||||
dprintf("\n");
|
||||
}
|
||||
#else
|
||||
void dump_card(cmedia_pci_dev * card)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
disable_card_interrupts(cmedia_pci_dev * card)
|
||||
{
|
||||
set_direct(card, 0x0e, 0x00, 0x03);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
setup_dma(cmedia_pci_dev * card)
|
||||
{
|
||||
/* we're appropriating some ISA space here... */
|
||||
/* need kernel support to do it right */
|
||||
const uint16 base = card->enhanced+0x80;
|
||||
ddprintf(("cmedia_pci: dma base is 0x%04x\n", base));
|
||||
if(0 == base)
|
||||
return B_DEV_RESOURCE_CONFLICT;
|
||||
card->dma_base = base;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_default_registers(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
static uchar values[] = {
|
||||
#ifdef DO_JOY
|
||||
0x04, 0x02, 0x02, /* enable joystick */
|
||||
#endif
|
||||
|
||||
0x0a, 0x01, 0x01, /* enable SPDIF inverse before SPDIF_LOOP */
|
||||
0x04, 0x80, 0x80, /* enable SPDIF_LOOP */
|
||||
|
||||
0x1a, 0x00, 0x20, /* SPD32SEL disable */
|
||||
0x1a, 0x00, 0x10, /* SPDFLOOPI disable */
|
||||
|
||||
0x1b, 0x04, 0x04, /* dual channel mode enable */
|
||||
0x1a, 0x00, 0x80, /* Double DAC structure disable */
|
||||
|
||||
0x24, 0x00, 0x02, /* 3D surround disable */
|
||||
|
||||
0x24, 0x00, 0x01, /* disable SPDIF_IN PCM to DAC */
|
||||
#ifdef DO_MIDI
|
||||
0x04, 0x04, 0x04, /* enable MPU-401 */
|
||||
0x17, 0x00, 0x60, /* default at 0x330 */
|
||||
#endif
|
||||
};
|
||||
uchar * ptr = values;
|
||||
|
||||
while (ptr < values+sizeof(values)) {
|
||||
set_direct(card, ptr[0], ptr[1], ptr[2]);
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_device_names(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
char * name = card->name;
|
||||
sprintf(name, "cmedia_pci/%ld", card-cards+1);
|
||||
|
||||
#if DO_MIDI
|
||||
sprintf(card->midi.name, "midi/%s", name);
|
||||
names[num_names++] = card->midi.name;
|
||||
#endif /* DO_MIDI */
|
||||
#if DO_JOY
|
||||
sprintf(card->joy.name1, "joystick/%s", name);
|
||||
names[num_names++] = card->joy.name1;
|
||||
#endif /* DO_JOY */
|
||||
#if DO_PCM
|
||||
/* cmedia_pci DMA doesn't work when physical NULL isn't NULL from PCI */
|
||||
/* this is a hack to not export bad devices on BeBox hardware */
|
||||
if ((*pci->ram_address)(NULL) == NULL) {
|
||||
sprintf(card->pcm.name, "audio/raw/%s", name);
|
||||
names[num_names++] = card->pcm.name;
|
||||
sprintf(card->pcm.oldname, "audio/old/%s", name);
|
||||
names[num_names++] = card->pcm.oldname;
|
||||
}
|
||||
#endif /* DO_PCM */
|
||||
#if DO_MUX
|
||||
sprintf(card->mux.name, "audio/mux/%s", name);
|
||||
names[num_names++] = card->mux.name;
|
||||
#endif /* DO_MUX */
|
||||
#if DO_MIXER
|
||||
sprintf(card->mixer.name, "audio/mix/%s", name);
|
||||
names[num_names++] = card->mixer.name;
|
||||
#endif /* DO_MIXER */
|
||||
names[num_names] = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* We use the SV chip in ISA DMA addressing mode, which is 24 bits */
|
||||
/* so we need to find suitable, locked, contiguous memory in that */
|
||||
/* physical address range. */
|
||||
|
||||
static status_t
|
||||
find_low_memory(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
size_t low_size = (MIN_MEMORY_SIZE+(B_PAGE_SIZE-1))&~(B_PAGE_SIZE-1);
|
||||
physical_entry where;
|
||||
size_t trysize;
|
||||
area_id curarea;
|
||||
void * addr;
|
||||
char name[DEVNAME];
|
||||
|
||||
sprintf(name, "%s_low", card->name);
|
||||
if (low_size < MIN_MEMORY_SIZE) {
|
||||
low_size = MIN_MEMORY_SIZE;
|
||||
}
|
||||
trysize = low_size;
|
||||
|
||||
curarea = find_area(name);
|
||||
if (curarea >= 0) { /* area there from previous run */
|
||||
area_info ainfo;
|
||||
ddprintf(("cmedia_pci: testing likely candidate...\n"));
|
||||
if (get_area_info(curarea, &ainfo)) {
|
||||
ddprintf(("cmedia_pci: no info\n"));
|
||||
goto allocate;
|
||||
}
|
||||
/* test area we found */
|
||||
trysize = ainfo.size;
|
||||
addr = ainfo.address;
|
||||
if (trysize < low_size) {
|
||||
ddprintf(("cmedia_pci: too small (%lx)\n", trysize));
|
||||
goto allocate;
|
||||
}
|
||||
if (get_memory_map(addr, trysize, &where, 1) < B_OK) {
|
||||
ddprintf(("cmedia_pci: no memory map\n"));
|
||||
goto allocate;
|
||||
}
|
||||
if ((uint32)where.address & 0xff000000) {
|
||||
ddprintf(("cmedia_pci: bad physical address\n"));
|
||||
goto allocate;
|
||||
}
|
||||
if (ainfo.lock < B_FULL_LOCK || where.size < low_size) {
|
||||
ddprintf(("cmedia_pci: lock not contiguous\n"));
|
||||
goto allocate;
|
||||
}
|
||||
dprintf("cmedia_pci: physical %p logical %p\n", where.address, ainfo.address);
|
||||
goto a_o_k;
|
||||
}
|
||||
|
||||
allocate:
|
||||
if (curarea >= 0) {
|
||||
delete_area(curarea); /* area didn't work */
|
||||
curarea = -1;
|
||||
}
|
||||
ddprintf(("cmedia_pci: allocating new low area\n"));
|
||||
|
||||
curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS,
|
||||
trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA);
|
||||
ddprintf(("cmedia_pci: create_area(%lx) returned %lx logical %p\n",
|
||||
trysize, curarea, addr));
|
||||
if (curarea < 0) {
|
||||
goto oops;
|
||||
}
|
||||
if (get_memory_map(addr, low_size, &where, 1) < 0) {
|
||||
delete_area(curarea);
|
||||
curarea = B_ERROR;
|
||||
goto oops;
|
||||
}
|
||||
ddprintf(("cmedia_pci: physical %p\n", where.address));
|
||||
if ((uint32)where.address & 0xff000000) {
|
||||
delete_area(curarea);
|
||||
curarea = B_ERROR;
|
||||
goto oops;
|
||||
}
|
||||
if ((((uint32)where.address)+low_size) & 0xff000000) {
|
||||
delete_area(curarea);
|
||||
curarea = B_ERROR;
|
||||
goto oops;
|
||||
}
|
||||
/* hey, it worked! */
|
||||
if (trysize > low_size) { /* don't waste */
|
||||
resize_area(curarea, low_size);
|
||||
}
|
||||
|
||||
oops:
|
||||
if (curarea < 0) {
|
||||
dprintf("cmedia_pci: failed to create low_mem area\n");
|
||||
return curarea;
|
||||
}
|
||||
a_o_k:
|
||||
ddprintf(("cmedia_pci: successfully found or created low area!\n"));
|
||||
card->low_size = low_size;
|
||||
card->low_mem = addr;
|
||||
card->low_phys = (vuchar *)where.address;
|
||||
card->map_low = curarea;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
setup_cmedia_pci(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
status_t err = B_OK;
|
||||
/* cpu_status cp; */
|
||||
|
||||
ddprintf(("cmedia_pci: setup_cmedia_pci(%p)\n", card));
|
||||
|
||||
if ((card->pcm.init_sem = create_sem(1, "cm pcm init")) < B_OK)
|
||||
goto bail;
|
||||
#if 1
|
||||
if ((*mpu401->create_device)(0x330, &card->midi.driver,
|
||||
#else
|
||||
if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver,
|
||||
#endif
|
||||
0, midi_interrupt_op, &card->midi) < B_OK)
|
||||
goto bail3;
|
||||
#if 1
|
||||
if ((*gameport->create_device)(0x201, &card->joy.driver) < B_OK)
|
||||
#else
|
||||
if ((*gameport->create_device)(card->info.u.h0.base_registers[4], &card->joy.driver) < B_OK)
|
||||
#endif
|
||||
goto bail4;
|
||||
ddprintf(("midi %p gameport %p\n", card->midi.driver, card->joy.driver));
|
||||
card->midi.card = card;
|
||||
|
||||
err = find_low_memory(card);
|
||||
if (err < B_OK) {
|
||||
goto bail5;
|
||||
}
|
||||
|
||||
//cp = disable_interrupts();
|
||||
//acquire_spinlock(&card->hardware);
|
||||
|
||||
make_device_names(card);
|
||||
card->enhanced = card->info.u.h0.base_registers[0];
|
||||
ddprintf(("cmedia_pci: %s enhanced at %x\n", card->name, card->enhanced));
|
||||
|
||||
ddprintf(("cmedia_pci: revision %x\n", get_indirect(card, 0x15)));
|
||||
|
||||
disable_card_interrupts(card);
|
||||
if (setup_dma(card) != B_OK)
|
||||
{
|
||||
dprintf("cmedia pci: can't setup DMA\n");
|
||||
goto bail6;
|
||||
}
|
||||
|
||||
set_default_registers(card);
|
||||
|
||||
//release_spinlock(&card->hardware);
|
||||
//restore_interrupts(cp);
|
||||
|
||||
return B_OK;
|
||||
|
||||
bail6:
|
||||
// deallocate low memory
|
||||
bail5:
|
||||
(*gameport->delete_device)(card->joy.driver);
|
||||
bail4:
|
||||
(*mpu401->delete_device)(card->midi.driver);
|
||||
bail3:
|
||||
delete_sem(card->pcm.init_sem);
|
||||
bail:
|
||||
return err < B_OK ? err : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
debug_cmedia(
|
||||
int argc,
|
||||
char * argv[])
|
||||
{
|
||||
int ix = 0;
|
||||
if (argc == 2) {
|
||||
ix = parse_expression(argv[1])-1;
|
||||
}
|
||||
if (argc > 2 || ix < 0 || ix >= num_cards) {
|
||||
dprintf("cmedia_pci: dude, you gotta watch your syntax!\n");
|
||||
return -1;
|
||||
}
|
||||
dprintf("%s: enhanced registers at 0x%x\n", cards[ix].name,
|
||||
cards[ix].enhanced);
|
||||
dprintf("%s: open %ld dma_a at 0x%x dma_c 0x%x\n", cards[ix].pcm.name,
|
||||
cards[ix].pcm.open_count, cards[ix].pcm.dma_a, cards[ix].pcm.dma_c);
|
||||
if (cards[ix].pcm.open_count) {
|
||||
dprintf(" dma_a: 0x%lx+0x%lx dma_c: 0x%lx+0x%lx\n",
|
||||
PCI_IO_RD_32((int)cards[ix].pcm.dma_a), PCI_IO_RD_32((int)cards[ix].pcm.dma_a+4),
|
||||
PCI_IO_RD_32((int)cards[ix].pcm.dma_c), PCI_IO_RD_32((int)cards[ix].pcm.dma_c+4));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
init_driver(void)
|
||||
{
|
||||
int ix=0;
|
||||
pci_info info;
|
||||
num_cards = 0;
|
||||
|
||||
ddprintf(("cmedia_pci: init_driver()\n"));
|
||||
load_driver_symbols("cmedia_pci");
|
||||
|
||||
if (get_module(pci_name, (module_info **) &pci))
|
||||
return ENOSYS;
|
||||
|
||||
if (get_module(gameport_name, (module_info **) &gameport)) {
|
||||
put_module(pci_name);
|
||||
return ENOSYS;
|
||||
}
|
||||
ddprintf(("MPU\n"));
|
||||
if (get_module(mpu401_name, (module_info **) &mpu401)) {
|
||||
put_module(gameport_name);
|
||||
put_module(pci_name);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
ddprintf(("MPU: %p\n", mpu401));
|
||||
|
||||
while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
|
||||
if (info.vendor_id == CMEDIA_PCI_VENDOR_ID &&
|
||||
(info.device_id == CMEDIA_8338A_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8338B_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8738A_DEVICE_ID ||
|
||||
info.device_id == CMEDIA_8738B_DEVICE_ID )) {
|
||||
if (num_cards == NUM_CARDS) {
|
||||
dprintf("Too many C-Media cards installed!\n");
|
||||
break;
|
||||
}
|
||||
memset(&cards[num_cards], 0, sizeof(cmedia_pci_dev));
|
||||
cards[num_cards].info = info;
|
||||
if (setup_cmedia_pci(&cards[num_cards])) {
|
||||
dprintf("Setup of C-Media %ld failed\n", num_cards+1);
|
||||
}
|
||||
else {
|
||||
num_cards++;
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
if (!num_cards) {
|
||||
KPRINTF(("no cards\n"));
|
||||
put_module(mpu401_name);
|
||||
put_module(gameport_name);
|
||||
put_module(pci_name);
|
||||
ddprintf(("cmedia_pci: no suitable cards found\n"));
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
add_debugger_command("cmedia", debug_cmedia, "cmedia [card# (1-n)]");
|
||||
#endif
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
teardown_cmedia_pci(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
static uchar regs[] = {
|
||||
#ifdef DO_JOY
|
||||
0x04, 0x00, 0x02, /* enable joystick */
|
||||
#endif
|
||||
#ifdef DO_MIDI
|
||||
0x04, 0x00, 0x04, /* enable MPU-401 */
|
||||
#endif
|
||||
};
|
||||
uchar * ptr = regs;
|
||||
cpu_status cp;
|
||||
|
||||
/* remove created devices */
|
||||
(*gameport->delete_device)(card->joy.driver);
|
||||
(*mpu401->delete_device)(card->midi.driver);
|
||||
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&card->hardware);
|
||||
|
||||
while (ptr < regs+sizeof(regs)) {
|
||||
set_direct(card, ptr[0], ptr[1], ptr[2]);
|
||||
ptr += 3;
|
||||
}
|
||||
disable_card_interrupts(card);
|
||||
|
||||
release_spinlock(&card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
delete_sem(card->pcm.init_sem);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver(void)
|
||||
{
|
||||
int ix, cnt = num_cards;
|
||||
num_cards = 0;
|
||||
|
||||
ddprintf(("cmedia_pci: uninit_driver()\n"));
|
||||
remove_debugger_command("cmedia", debug_cmedia);
|
||||
|
||||
for (ix=0; ix<cnt; ix++) {
|
||||
teardown_cmedia_pci(&cards[ix]);
|
||||
}
|
||||
memset(&cards, 0, sizeof(cards));
|
||||
put_module(mpu401_name);
|
||||
put_module(gameport_name);
|
||||
put_module(pci_name);
|
||||
}
|
||||
|
||||
|
||||
const char **
|
||||
publish_devices(void)
|
||||
{
|
||||
int ix = 0;
|
||||
ddprintf(("cmedia_pci: publish_devices()\n"));
|
||||
|
||||
for (ix=0; names[ix]; ix++) {
|
||||
ddprintf(("cmedia_pci: publish %s\n", names[ix]));
|
||||
}
|
||||
return (const char **)names;
|
||||
}
|
||||
|
||||
|
||||
device_hooks *
|
||||
find_device(
|
||||
const char * name)
|
||||
{
|
||||
int ix;
|
||||
|
||||
ddprintf(("cmedia_pci: find_device(%s)\n", name));
|
||||
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
#if DO_MIDI
|
||||
if (!strcmp(cards[ix].midi.name, name)) {
|
||||
return &midi_hooks;
|
||||
}
|
||||
#endif /* DO_MIDI */
|
||||
#if DO_JOY
|
||||
if (!strcmp(cards[ix].joy.name1, name)) {
|
||||
return &joy_hooks;
|
||||
}
|
||||
#endif /* DO_JOY */
|
||||
#if DO_PCM
|
||||
if (!strcmp(cards[ix].pcm.name, name)) {
|
||||
return &pcm_hooks;
|
||||
}
|
||||
if (!strcmp(cards[ix].pcm.oldname, name)) {
|
||||
return &pcm_hooks;
|
||||
}
|
||||
#endif /* DO_PCM */
|
||||
#if DO_MUX
|
||||
if (!strcmp(cards[ix].mux.name, name)) {
|
||||
return &mux_hooks;
|
||||
}
|
||||
|
||||
#endif /* DO_MUX */
|
||||
#if DO_MIXER
|
||||
if (!strcmp(cards[ix].mixer.name, name)) {
|
||||
return &mixer_hooks;
|
||||
}
|
||||
#endif /* DO_MIXER */
|
||||
}
|
||||
ddprintf(("cmedia_pci: find_device(%s) failed\n", name));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
static int32
|
||||
cmedia_pci_interrupt(
|
||||
void * data)
|
||||
{
|
||||
cpu_status cp = disable_interrupts();
|
||||
cmedia_pci_dev * card = (cmedia_pci_dev *)data;
|
||||
uchar status;
|
||||
int32 handled = B_UNHANDLED_INTERRUPT;
|
||||
|
||||
/* KTRACE(); / * */
|
||||
acquire_spinlock(&card->hardware);
|
||||
|
||||
status = get_direct(card, 0x10);
|
||||
|
||||
#if DEBUG
|
||||
/* kprintf("%x\n", status); / * */
|
||||
#endif
|
||||
#if DO_PCM
|
||||
if (status & 0x02) {
|
||||
if (dma_c_interrupt(card)) {
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
}
|
||||
else {
|
||||
handled = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
/* acknowledge interrupt */
|
||||
set_direct(card, 0x0e, 0x00, 0x02);
|
||||
set_direct(card, 0x0e, 0x02, 0x02);
|
||||
}
|
||||
if (status & 0x01) {
|
||||
if (dma_a_interrupt(card)) {
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
}
|
||||
else {
|
||||
handled = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
/* acknowledge interrupt */
|
||||
set_direct(card, 0x0e, 0x00, 0x01);
|
||||
set_direct(card, 0x0e, 0x01, 0x01);
|
||||
}
|
||||
#endif
|
||||
#if DO_MIDI
|
||||
status = get_direct(card, 0x12);
|
||||
if (status & 0x01) {
|
||||
if (midi_interrupt(card)) {
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
} else {
|
||||
handled = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sometimes, the Sonic Vibes will receive a byte of Midi data...
|
||||
** And duly note it in the MPU401 status register...
|
||||
** And generate an interrupt...
|
||||
** But not bother setting the midi interrupt bit in the ISR.
|
||||
** Thanks a lot, S3.
|
||||
*/
|
||||
if(handled == B_UNHANDLED_INTERRUPT){
|
||||
if (midi_interrupt(card)) {
|
||||
handled = B_INVOKE_SCHEDULER;
|
||||
}
|
||||
}
|
||||
|
||||
/* KTRACE(); / * */
|
||||
release_spinlock(&card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
return handled;
|
||||
// return (handled == B_INVOKE_SCHEDULER) ? B_HANDLED_INTERRUPT : handled;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
increment_interrupt_handler(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
KPRINTF(("cmedia_pci: increment_interrupt_handler()\n"));
|
||||
if (atomic_add(&card->inth_count, 1) == 0) {
|
||||
// !!!
|
||||
KPRINTF(("cmedia_pci: intline %d int %p\n", card->info.u.h0.interrupt_line, cmedia_pci_interrupt));
|
||||
install_io_interrupt_handler(card->info.u.h0.interrupt_line,
|
||||
cmedia_pci_interrupt, card, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
decrement_interrupt_handler(
|
||||
cmedia_pci_dev * card)
|
||||
{
|
||||
KPRINTF(("cmedia_pci: decrement_interrupt_handler()\n"));
|
||||
if (atomic_add(&card->inth_count, -1) == 1) {
|
||||
KPRINTF(("cmedia_pci: remove_io_interrupt_handler()\n"));
|
||||
remove_io_interrupt_handler(card->info.u.h0.interrupt_line, cmedia_pci_interrupt, card);
|
||||
}
|
||||
}
|
||||
|
||||
|
194
src/add-ons/kernel/drivers/audio/cmedia/cm_private.h
Normal file
194
src/add-ons/kernel/drivers/audio/cmedia/cm_private.h
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#if !defined(_CM_PRIVATE_H)
|
||||
#define _CM_PRIVATE_H
|
||||
|
||||
#if !defined(_CMEDIA_PCI_H)
|
||||
#include "cmedia_pci.h"
|
||||
#endif
|
||||
|
||||
#if !defined(_PCI_H)
|
||||
#include <PCI.h>
|
||||
#endif
|
||||
|
||||
#if !defined(DEBUG)
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
|
||||
#define NUM_CARDS 3
|
||||
#define DEVNAME 32
|
||||
|
||||
|
||||
#define EXPORT __declspec(dllexport)
|
||||
|
||||
#if defined(__INTEL__)
|
||||
#define EIEIO()
|
||||
#elif defined(__POWERPC__)
|
||||
#define EIEIO() __eieio()
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define ddprintf(x) dprintf x
|
||||
#define KTRACE() kprintf("%s %d\n", __FILE__, __LINE__)
|
||||
#else
|
||||
#define ddprintf(x)
|
||||
#define KTRACE()
|
||||
#endif
|
||||
|
||||
/* neither value may be larger than 65536 */
|
||||
#define PLAYBACK_BUF_SIZE 2048
|
||||
#define RECORD_BUF_SIZE PLAYBACK_BUF_SIZE
|
||||
/* always create this much, so larger buffers can be requested */
|
||||
#define MIN_MEMORY_SIZE 32768
|
||||
|
||||
/* clock crystal frequency */
|
||||
#define F_REF 24576000
|
||||
/* data book says 80 MHz ... */
|
||||
#define MIN_FREQ 80000000
|
||||
/* tolerance for sample rate clock derivation - book has this at 0.005 */
|
||||
#define TOLERANCE 0.001
|
||||
|
||||
/* there are five logical devices: midi, joystick, pcm, mux and mixer */
|
||||
|
||||
typedef struct _midi_dev
|
||||
{
|
||||
struct _cmedia_pci_dev *card;
|
||||
void * driver;
|
||||
void * cookie;
|
||||
int32 count;
|
||||
char name[64];
|
||||
} midi_dev;
|
||||
|
||||
typedef struct _joy_dev
|
||||
{
|
||||
void * driver;
|
||||
char name1[64];
|
||||
} joy_dev;
|
||||
|
||||
typedef cmedia_pci_audio_format pcm_cfg;
|
||||
typedef cmedia_pci_audio_buf_header pcm_buf_hdr;
|
||||
|
||||
enum
|
||||
{ /* these map to the mode enable bits in the CMX13 register */
|
||||
kPlayback = 1,
|
||||
kRecord = 2
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _cmedia_pci_dev * card;
|
||||
char name[DEVNAME];
|
||||
char oldname[DEVNAME];
|
||||
sem_id init_sem;
|
||||
int32 open_count;
|
||||
int32 open_mode;
|
||||
|
||||
/* playback from a cyclic, small-ish buffer */
|
||||
|
||||
int32 wr_lock;
|
||||
int dma_a;
|
||||
vuchar * wr_1;
|
||||
vuchar * wr_2;
|
||||
vuchar * wr_cur;
|
||||
size_t wr_size;
|
||||
int wr_silence;
|
||||
int32 write_waiting;
|
||||
sem_id write_sem;
|
||||
size_t was_written;
|
||||
uint32 wr_skipped;
|
||||
sem_id wr_entry;
|
||||
bigtime_t wr_time;
|
||||
uint64 wr_total;
|
||||
sem_id wr_time_sem;
|
||||
int32 wr_time_wait;
|
||||
|
||||
/* recording into a cyclic, somewhat larger buffer */
|
||||
|
||||
int32 rd_lock;
|
||||
int dma_c;
|
||||
vuchar * rd_1;
|
||||
vuchar * rd_2;
|
||||
vuchar * rd_cur;
|
||||
size_t rd_size;
|
||||
int32 read_waiting;
|
||||
sem_id read_sem;
|
||||
size_t was_read;
|
||||
bigtime_t next_rd_time;
|
||||
bigtime_t rd_time;
|
||||
uint32 rd_skipped; /* count of misses */
|
||||
sem_id rd_entry;
|
||||
uint64 rd_total;
|
||||
sem_id rd_time_sem;
|
||||
int32 rd_time_wait;
|
||||
|
||||
/* buffers are owned by the device record (because of allocation) */
|
||||
|
||||
pcm_cfg config;
|
||||
|
||||
sem_id old_cap_sem;
|
||||
sem_id old_play_sem;
|
||||
} pcm_dev;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _cmedia_pci_dev * card;
|
||||
char name[DEVNAME];
|
||||
int32 open_count;
|
||||
} mux_dev;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct _cmedia_pci_dev * card;
|
||||
char name[DEVNAME];
|
||||
int32 open_count;
|
||||
} mixer_dev;
|
||||
|
||||
typedef struct _cmedia_pci_dev
|
||||
{
|
||||
char name[DEVNAME]; /* used for resources */
|
||||
int32 hardware; /* spinlock */
|
||||
int enhanced; /* offset to port */
|
||||
int32 inth_count;
|
||||
int dma_base;
|
||||
size_t low_size; /* size of low memory */
|
||||
vuchar * low_mem;
|
||||
vuchar * low_phys; /* physical address */
|
||||
area_id map_low; /* area pointing to low memory */
|
||||
pci_info info;
|
||||
midi_dev midi;
|
||||
joy_dev joy;
|
||||
pcm_dev pcm;
|
||||
mux_dev mux;
|
||||
mixer_dev mixer;
|
||||
} cmedia_pci_dev;
|
||||
|
||||
|
||||
extern int32 num_cards;
|
||||
extern cmedia_pci_dev cards[NUM_CARDS];
|
||||
|
||||
|
||||
extern void set_direct(cmedia_pci_dev *, int, uchar, uchar);
|
||||
extern uchar get_direct(cmedia_pci_dev *, int);
|
||||
extern void set_indirect(cmedia_pci_dev *, int, uchar, uchar);
|
||||
extern uchar get_indirect(cmedia_pci_dev *, int);
|
||||
extern void increment_interrupt_handler(cmedia_pci_dev *);
|
||||
extern void decrement_interrupt_handler(cmedia_pci_dev *);
|
||||
|
||||
|
||||
extern bool midi_interrupt(cmedia_pci_dev *);
|
||||
extern void midi_interrupt_op(int32 op, void * data);
|
||||
extern bool dma_a_interrupt(cmedia_pci_dev *);
|
||||
extern bool dma_c_interrupt(cmedia_pci_dev *);
|
||||
|
||||
extern void PCI_IO_WR(int offset, uint8 val);
|
||||
extern uint8 PCI_IO_RD(int offset);
|
||||
extern uint32 PCI_IO_RD_32(int offset);
|
||||
|
||||
extern generic_gameport_module * gameport;
|
||||
|
||||
#endif /* _CM_PRIVATE_H */
|
||||
|
112
src/add-ons/kernel/drivers/audio/cmedia/cmedia_pci.h
Normal file
112
src/add-ons/kernel/drivers/audio/cmedia/cmedia_pci.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* cmedia_pci.h -- specifics for S3-based PCI audio cards */
|
||||
/* $Id: cmedia_pci.h,v 1.3 1999/10/13 02:29:19 cltien Exp $ */
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#if !defined(_CMEDIA_PCI_H)
|
||||
#define _CMEDIA_PCI_H
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <OS.h>
|
||||
#include "audio_driver.h"
|
||||
#include "midi_driver.h"
|
||||
#include "joystick_driver.h"
|
||||
|
||||
|
||||
#define CMEDIA_PCI_VENDOR_ID 0x13F6 /* C-Media Inc */
|
||||
#define CMEDIA_8338A_DEVICE_ID 0x0100 /* CM8338A */
|
||||
#define CMEDIA_8338B_DEVICE_ID 0x0101 /* CM8338B */
|
||||
#define CMEDIA_8738A_DEVICE_ID 0x0111 /* CM8738A */
|
||||
#define CMEDIA_8738B_DEVICE_ID 0x0112 /* CM8738B */
|
||||
|
||||
#define CMEDIA_PCI_JOYSTICK_MIN_LATENCY 5000 /* 200 times a second! */
|
||||
#define CMEDIA_PCI_JOYSTICK_MAX_LATENCY 100000 /* 10 times a second */
|
||||
|
||||
typedef struct joystick cmedia_pci_joystick;
|
||||
|
||||
|
||||
typedef struct audio_format cmedia_pci_audio_format;
|
||||
typedef struct audio_buf_header cmedia_pci_audio_buf_header;
|
||||
|
||||
|
||||
/* the mux devices use these records */
|
||||
typedef audio_routing cmedia_pci_routing;
|
||||
|
||||
/* this is the argument for ioctl() */
|
||||
typedef audio_routing_cmd cmedia_pci_routing_cmd;
|
||||
|
||||
|
||||
/* selectors for routing */
|
||||
#define CMEDIA_PCI_INPUT_MUX B_AUDIO_INPUT_SELECT
|
||||
#define CMEDIA_PCI_MIC_BOOST B_AUDIO_MIC_BOOST
|
||||
#define CMEDIA_PCI_MIDI_OUTPUT_TO_SYNTH B_AUDIO_MIDI_OUTPUT_TO_SYNTH
|
||||
#define CMEDIA_PCI_MIDI_INPUT_TO_SYNTH B_AUDIO_MIDI_INPUT_TO_SYNTH
|
||||
#define CMEDIA_PCI_MIDI_OUTPUT_TO_PORT B_AUDIO_MIDI_OUTPUT_TO_PORT
|
||||
|
||||
/* input MUX source values */
|
||||
#define CMEDIA_PCI_INPUT_CD B_AUDIO_INPUT_CD
|
||||
#define CMEDIA_PCI_INPUT_DAC B_AUDIO_INPUT_DAC
|
||||
#define CMEDIA_PCI_INPUT_AUX2 B_AUDIO_INPUT_AUX2
|
||||
#define CMEDIA_PCI_INPUT_LINE B_AUDIO_INPUT_LINE_IN
|
||||
#define CMEDIA_PCI_INPUT_AUX1 B_AUDIO_INPUT_AUX1
|
||||
#define CMEDIA_PCI_INPUT_MIC B_AUDIO_INPUT_MIC
|
||||
#define CMEDIA_PCI_INPUT_MIX_OUT B_AUDIO_INPUT_MIX_OUT
|
||||
|
||||
|
||||
/* the mixer devices use these records */
|
||||
typedef audio_level cmedia_pci_level;
|
||||
|
||||
/* this is the arg to ioctl() */
|
||||
typedef audio_level_cmd cmedia_pci_level_cmd;
|
||||
|
||||
/* bitmask for the flags */
|
||||
#define CMEDIA_PCI_LEVEL_MUTED B_AUDIO_LEVEL_MUTED
|
||||
|
||||
/* selectors for levels */
|
||||
#define CMEDIA_PCI_LEFT_ADC_INPUT_G B_AUDIO_MIX_ADC_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_ADC_INPUT_G B_AUDIO_MIX_ADC_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_AUX1_LOOPBACK_GAM B_AUDIO_MIX_VIDEO_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_AUX1_LOOPBACK_GAM B_AUDIO_MIX_VIDEO_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_CD_LOOPBACK_GAM B_AUDIO_MIX_CD_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_CD_LOOPBACK_GAM B_AUDIO_MIX_CD_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_LINE_LOOPBACK_GAM B_AUDIO_MIX_LINE_IN_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_LINE_LOOPBACK_GAM B_AUDIO_MIX_LINE_IN_RIGHT
|
||||
#define CMEDIA_PCI_MIC_LOOPBACK_GAM B_AUDIO_MIX_MIC
|
||||
#define CMEDIA_PCI_LEFT_SYNTH_OUTPUT_GAM B_AUDIO_MIX_SYNTH_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_SYNTH_OUTPUT_GAM B_AUDIO_MIX_SYNTH_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_AUX2_LOOPBACK_GAM B_AUDIO_MIX_AUX_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_AUX2_LOOPBACK_GAM B_AUDIO_MIX_AUX_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_MASTER_VOLUME_AM B_AUDIO_MIX_LINE_OUT_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_MASTER_VOLUME_AM B_AUDIO_MIX_LINE_OUT_RIGHT
|
||||
#define CMEDIA_PCI_LEFT_PCM_OUTPUT_GAM B_AUDIO_MIX_DAC_LEFT
|
||||
#define CMEDIA_PCI_RIGHT_PCM_OUTPUT_GAM B_AUDIO_MIX_DAC_RIGHT
|
||||
#define CMEDIA_PCI_DIGITAL_LOOPBACK_AM B_AUDIO_MIX_LOOPBACK_LEVEL
|
||||
|
||||
|
||||
/* secret handshake ioctl()s */
|
||||
#define SV_SECRET_HANDSHAKE 10100
|
||||
typedef struct {
|
||||
bigtime_t wr_time;
|
||||
bigtime_t rd_time;
|
||||
uint32 wr_skipped;
|
||||
uint32 rd_skipped;
|
||||
uint64 wr_total;
|
||||
uint64 rd_total;
|
||||
uint32 _reserved_[6];
|
||||
} sv_handshake;
|
||||
#define SV_RD_TIME_WAIT 10101
|
||||
#define SV_WR_TIME_WAIT 10102
|
||||
typedef struct {
|
||||
bigtime_t time;
|
||||
bigtime_t bytes;
|
||||
uint32 skipped;
|
||||
uint32 _reserved_[3];
|
||||
} sv_timing;
|
||||
|
||||
|
||||
|
||||
#endif /* _CMEDIA_PCI_H */
|
||||
|
112
src/add-ons/kernel/drivers/audio/cmedia/joy.c
Normal file
112
src/add-ons/kernel/drivers/audio/cmedia/joy.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include "cm_private.h"
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_KERNEL_EXPORT_H)
|
||||
#include <KernelExport.h>
|
||||
#endif /* _KERNEL_EXPORT_H */
|
||||
|
||||
|
||||
static status_t joy_open(const char *name, uint32 flags, void **cookie);
|
||||
static status_t joy_close(void *cookie);
|
||||
static status_t joy_free(void *cookie);
|
||||
static status_t joy_control(void *cookie, uint32 op, void *data, size_t len);
|
||||
static status_t joy_read(void *cookie, off_t pos, void *data, size_t *len);
|
||||
static status_t joy_write(void *cookie, off_t pos, const void *data, size_t *len);
|
||||
|
||||
|
||||
#define MIN_COMP -7
|
||||
#define MAX_COMP 8
|
||||
|
||||
|
||||
device_hooks joy_hooks = {
|
||||
&joy_open,
|
||||
&joy_close,
|
||||
&joy_free,
|
||||
&joy_control,
|
||||
&joy_read,
|
||||
&joy_write,
|
||||
NULL, /* select */
|
||||
NULL, /* deselect */
|
||||
NULL, /* readv */
|
||||
NULL /* writev */
|
||||
};
|
||||
|
||||
|
||||
static status_t
|
||||
joy_open(
|
||||
const char * name,
|
||||
uint32 flags,
|
||||
void ** cookie)
|
||||
{
|
||||
int ix;
|
||||
int offset = -1;
|
||||
|
||||
ddprintf(("cmedia_pci: joy_open()\n"));
|
||||
|
||||
*cookie = NULL;
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
if (!strcmp(name, cards[ix].joy.name1)) {
|
||||
offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (offset < 0) {
|
||||
return ENODEV;
|
||||
}
|
||||
return (*gameport->open_hook)(cards[ix].joy.driver, flags, cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
joy_close(
|
||||
void * cookie)
|
||||
{
|
||||
return (*gameport->close_hook)(cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
joy_free(
|
||||
void * cookie)
|
||||
{
|
||||
return (*gameport->free_hook)(cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
joy_control(
|
||||
void * cookie,
|
||||
uint32 iop,
|
||||
void * data,
|
||||
size_t len)
|
||||
{
|
||||
return (*gameport->control_hook)(cookie, iop, data, len);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
joy_read(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
void * data,
|
||||
size_t * nread)
|
||||
{
|
||||
return (*gameport->read_hook)(cookie, pos, data, nread);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
joy_write(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
const void * data,
|
||||
size_t * nwritten)
|
||||
{
|
||||
return (*gameport->write_hook)(cookie, pos, data, nwritten);
|
||||
}
|
||||
|
113
src/add-ons/kernel/drivers/audio/cmedia/joystick_driver.h
Normal file
113
src/add-ons/kernel/drivers/audio/cmedia/joystick_driver.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef _JOYSTICK_DRIVER_H
|
||||
#define _JOYSTICK_DRIVER_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Drivers.h>
|
||||
#include <module.h>
|
||||
|
||||
typedef struct _joystick {
|
||||
bigtime_t timestamp;
|
||||
uint32 horizontal;
|
||||
uint32 vertical;
|
||||
bool button1;
|
||||
bool button2;
|
||||
} joystick;
|
||||
|
||||
/* maximum number of axes on one controller (pads count as 2 axes each) */
|
||||
#define MAX_AXES 12
|
||||
/* maximum number of hats on one controller -- PADS SHOULD BE RETURNED AS AXES! */
|
||||
#define MAX_HATS 8
|
||||
/* maximum number of buttons on one controller */
|
||||
#define MAX_BUTTONS 32
|
||||
/* maximum number of controllers on one port */
|
||||
#define MAX_STICKS 4
|
||||
|
||||
typedef struct _extended_joystick {
|
||||
bigtime_t timestamp; /* system_time when it was read */
|
||||
uint32 buttons; /* lsb to msb, 1 == on */
|
||||
int16 axes[MAX_AXES]; /* -32768 to 32767, X, Y, Z, U, V, W */
|
||||
uint8 hats[MAX_HATS]; /* 0 through 8 (1 == N, 3 == E, 5 == S, 7 == W) */
|
||||
} extended_joystick;
|
||||
|
||||
#define MAX_CONFIG_SIZE 100
|
||||
|
||||
enum { /* flags for joystick module info */
|
||||
js_flag_force_feedback = 0x1,
|
||||
js_flag_force_feedback_directional = 0x2
|
||||
};
|
||||
|
||||
typedef struct _joystick_module_info {
|
||||
char module_name[64];
|
||||
char device_name[64];
|
||||
int16 num_axes;
|
||||
int16 num_buttons;
|
||||
int16 num_hats;
|
||||
uint16 _reserved[7];
|
||||
uint32 flags;
|
||||
uint16 num_sticks;
|
||||
int16 config_size;
|
||||
char device_config[MAX_CONFIG_SIZE]; /* device specific */
|
||||
} joystick_module_info;
|
||||
|
||||
/* Note that joystick_module is something used by the game port driver */
|
||||
/* to talk to digital joysticks; if you're writing a sound card driver */
|
||||
/* and want to add support for a /dev/joystick device, use the generic_gameport */
|
||||
/* module. */
|
||||
|
||||
typedef struct _joystick_module {
|
||||
module_info minfo;
|
||||
/** "configure" might change the "info" if it auto-detects a device */
|
||||
int (*configure)(int port, joystick_module_info * info, size_t size, void ** out_cookie);
|
||||
/** "read" actual data from device into "data" */
|
||||
int (*read)(void * cookie, int port, extended_joystick * data, size_t size);
|
||||
/** "crumble" the cookie (deallocate) when done */
|
||||
int (*crumble)(void * cookie, int port);
|
||||
/** "force" tells the joystick to exert force on the same axes as input for the specified duration */
|
||||
int (*force)(void * cookie, int port, bigtime_t duration, extended_joystick * force, size_t size);
|
||||
int _reserved_;
|
||||
} joystick_module;
|
||||
|
||||
/** Doing force feedback means writing an extended_joystick to the device with force values.
|
||||
The "timestamp" should be the duration of the feedback. Successive writes will be queued
|
||||
by the device module. */
|
||||
enum { /* Joystick driver ioctl() opcodes */
|
||||
B_JOYSTICK_GET_SPEED_COMPENSATION = B_JOYSTICK_DRIVER_BASE,
|
||||
/* arg -> ptr to int32 */
|
||||
B_JOYSTICK_SET_SPEED_COMPENSATION, /* arg -> ptr to int32 */
|
||||
B_JOYSTICK_GET_MAX_LATENCY, /* arg -> ptr to long long */
|
||||
B_JOYSTICK_SET_MAX_LATENCY, /* arg -> ptr to long long */
|
||||
B_JOYSTICK_SET_DEVICE_MODULE, /* arg -> ptr to joystick_module; also enters enhanced mode */
|
||||
B_JOYSTICK_GET_DEVICE_MODULE, /* arg -> ptr to joystick_module */
|
||||
B_JOYSTICK_SET_RAW_MODE /* arg -> ptr to bool (true or false) */
|
||||
};
|
||||
|
||||
/* Speed compensation is not generally necessary, because the joystick */
|
||||
/* driver is measuring using real time, not just # cycles. "0" means the */
|
||||
/* default, center value. + typically returns higher values; - returns lower */
|
||||
/* A typical range might be from -10 to +10, but it varies by driver */
|
||||
|
||||
/* Lower latency will make for more overhead in reading the joystick */
|
||||
/* ideally, you set this value to just short of how long it takes you */
|
||||
/* to calculate and render a frame. 30 fps -> latency 33000 */
|
||||
|
||||
|
||||
typedef struct _generic_gameport_module {
|
||||
module_info minfo;
|
||||
status_t (*create_device)(int port, void ** out_storage);
|
||||
status_t (*delete_device)(void * storage);
|
||||
status_t (*open_hook)(void * storage, uint32 flags, void ** out_cookie);
|
||||
status_t (*close_hook)(void * cookie);
|
||||
status_t (*free_hook)(void * cookie);
|
||||
status_t (*control_hook)(void * cookie, uint32 op, void * data, size_t len);
|
||||
status_t (*read_hook)(void * cookie, off_t pos, void * data, size_t * len);
|
||||
status_t (*write_hook)(void * cookie, off_t pos, const void * data, size_t * len);
|
||||
int _reserved_;
|
||||
} generic_gameport_module;
|
||||
|
||||
|
||||
#endif
|
186
src/add-ons/kernel/drivers/audio/cmedia/midi.c
Normal file
186
src/add-ons/kernel/drivers/audio/cmedia/midi.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "cm_private.h"
|
||||
|
||||
|
||||
extern void dump_card(cmedia_pci_dev * card);
|
||||
|
||||
#if !defined(_KERNEL_EXPORT_H)
|
||||
#include <KernelExport.h>
|
||||
#endif /* _KERNEL_EXPORT_H */
|
||||
|
||||
#define MIDI_ACTIVE_SENSE 0xfe
|
||||
#define SNOOZE_GRANULARITY 500
|
||||
|
||||
extern generic_mpu401_module * mpu401;
|
||||
|
||||
void
|
||||
midi_interrupt_op(
|
||||
int32 op,
|
||||
void * data)
|
||||
{
|
||||
midi_dev * port = (midi_dev *)data;
|
||||
ddprintf(("port = %p\n", port));
|
||||
if (op == B_MPU_401_ENABLE_CARD_INT) {
|
||||
cpu_status cp;
|
||||
ddprintf(("cmedia_pci: B_MPU_401_ENABLE_CARD_INT\n"));
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&port->card->hardware);
|
||||
increment_interrupt_handler(port->card);
|
||||
set_direct(port->card, 0x01, 0x00, 0x80);
|
||||
set_indirect(port->card, 0x2A, 0x04, 0xff);
|
||||
release_spinlock(&port->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
}
|
||||
else if (op == B_MPU_401_DISABLE_CARD_INT) {
|
||||
/* turn off MPU interrupts */
|
||||
cpu_status cp;
|
||||
ddprintf(("cmedia_pci: B_MPU_401_DISABLE_CARD_INT\n"));
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&port->card->hardware);
|
||||
set_direct(port->card, 0x01, 0x80, 0x80);
|
||||
/* remove interrupt handler if necessary */
|
||||
decrement_interrupt_handler(port->card);
|
||||
release_spinlock(&port->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
}
|
||||
ddprintf(("cmedia_pci: midi_interrupt_op() done\n"));
|
||||
}
|
||||
|
||||
static status_t midi_open(const char *name, uint32 flags, void **cookie);
|
||||
static status_t midi_close(void *cookie);
|
||||
static status_t midi_free(void *cookie);
|
||||
static status_t midi_control(void *cookie, uint32 op, void *data, size_t len);
|
||||
static status_t midi_read(void *cookie, off_t pos, void *data, size_t *len);
|
||||
static status_t midi_write(void *cookie, off_t pos, const void *data, size_t *len);
|
||||
|
||||
|
||||
device_hooks midi_hooks = {
|
||||
&midi_open,
|
||||
&midi_close,
|
||||
&midi_free,
|
||||
&midi_control,
|
||||
&midi_read,
|
||||
&midi_write,
|
||||
NULL, /* select */
|
||||
NULL, /* deselect */
|
||||
NULL, /* readv */
|
||||
NULL /* writev */
|
||||
};
|
||||
|
||||
static status_t
|
||||
midi_open(
|
||||
const char * name,
|
||||
uint32 flags,
|
||||
void ** cookie)
|
||||
{
|
||||
int ix;
|
||||
int ret;
|
||||
|
||||
ddprintf(("cmedia_pci: midi_open()\n"));
|
||||
|
||||
*cookie = NULL;
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
if (!strcmp(name, cards[ix].midi.name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ix >= num_cards) {
|
||||
ddprintf(("bad device\n"));
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
ddprintf(("cmedia_pci: mpu401: %p open(): %p driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi.driver));
|
||||
ret = (*mpu401->open_hook)(cards[ix].midi.driver, flags, cookie);
|
||||
if (ret >= B_OK) {
|
||||
cards[ix].midi.cookie = *cookie;
|
||||
atomic_add(&cards[ix].midi.count, 1);
|
||||
}
|
||||
ddprintf(("cmedia_pci: mpu401: open returns %x / %p\n", ret, *cookie));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
midi_close(
|
||||
void * cookie)
|
||||
{
|
||||
ddprintf(("cmedia_pci: midi_close()\n"));
|
||||
return (*mpu401->close_hook)(cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
midi_free(
|
||||
void * cookie)
|
||||
{
|
||||
int ix;
|
||||
status_t f;
|
||||
ddprintf(("cmedia_pci: midi_free()\n"));
|
||||
f = (*mpu401->free_hook)(cookie);
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
if (cards[ix].midi.cookie == cookie) {
|
||||
if (atomic_add(&cards[ix].midi.count, -1) == 1) {
|
||||
cards[ix].midi.cookie = NULL;
|
||||
ddprintf(("cleared %p card %d\n", cookie, ix));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ddprintf(("cmedia_pci: midi_free() done\n"));
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
midi_control(
|
||||
void * cookie,
|
||||
uint32 iop,
|
||||
void * data,
|
||||
size_t len)
|
||||
{
|
||||
return (*mpu401->control_hook)(cookie, iop, data, len);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
midi_read(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
void * ptr,
|
||||
size_t * nread)
|
||||
{
|
||||
return (*mpu401->read_hook)(cookie, pos, ptr, nread);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
midi_write(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
const void * ptr,
|
||||
size_t * nwritten)
|
||||
{
|
||||
return (*mpu401->write_hook)(cookie, pos, ptr, nwritten);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
midi_interrupt(
|
||||
cmedia_pci_dev * dev)
|
||||
{
|
||||
if (!dev->midi.driver) {
|
||||
// kprintf("aiigh\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return (*mpu401->interrupt_hook)(dev->midi.driver);
|
||||
}
|
||||
|
110
src/add-ons/kernel/drivers/audio/cmedia/midi_driver.h
Normal file
110
src/add-ons/kernel/drivers/audio/cmedia/midi_driver.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef _MIDI_DRIVER_H
|
||||
#define _MIDI_DRIVER_H
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <module.h>
|
||||
|
||||
/* -----
|
||||
ioctl codes
|
||||
----- */
|
||||
|
||||
/* the old opcodes are deprecated, and may or may not work
|
||||
in newer drivers */
|
||||
enum {
|
||||
B_MIDI_GET_READ_TIMEOUT = B_MIDI_DRIVER_BASE,
|
||||
B_MIDI_SET_READ_TIMEOUT,
|
||||
B_MIDI_TIMED_READ,
|
||||
B_MIDI_TIMED_WRITE,
|
||||
B_MIDI_WRITE_SYNC,
|
||||
B_MIDI_WRITE_CLEAR,
|
||||
B_MIDI_GET_READ_TIMEOUT_OLD = B_DEVICE_OP_CODES_END + 1,
|
||||
B_MIDI_SET_READ_TIMEOUT_OLD
|
||||
};
|
||||
|
||||
/* the default timeout when you open a midi driver */
|
||||
#define B_MIDI_DEFAULT_TIMEOUT 1000000000000000LL
|
||||
|
||||
/* Usage:
|
||||
To read, set "data" to a pointer to your buffer, and "size" to the
|
||||
maximum size of this buffer. On return, "when" will contain the time
|
||||
at which the data was received (first byte) and "size" will contain
|
||||
the actual amount of data read.
|
||||
Call ioctl(fd, B_MIDI_TIMED_READ, &midi_timed_data, sizeof(midi_timed_data));
|
||||
To write, set "when" to when you want the first byte to go out the
|
||||
wire, set "data" to point to your data, and set "size" to the size
|
||||
of your data.
|
||||
Call ioctl(fd, B_MIDI_TIMED_WRITE, &midi_timed_data, sizeof(midi_timed_data));
|
||||
*/
|
||||
typedef struct {
|
||||
bigtime_t when;
|
||||
size_t size;
|
||||
unsigned char * data;
|
||||
} midi_timed_data;
|
||||
|
||||
|
||||
/* The MIDI parser returns the number of bytes that a message contains, given the */
|
||||
/* initial byte. For some messages, this is not known until the second byte is seen. */
|
||||
/* For such messages, a state > 0 is returned as well as some count > 0. When state */
|
||||
/* is > 0, you should call (*parse) for the next byte as well, which might modify */
|
||||
/* the returned message size. Message size will always be returned with the current */
|
||||
/* byte being counted as byte 1. A return of 0 means that the byte initiates a new */
|
||||
/* message. SysX is handled by returning max_size until the end or next initial message */
|
||||
/* is seen. So your loop looks something like: */
|
||||
/*
|
||||
uint32 state = 0; // Only set this to 0 the first time you call the parser.
|
||||
// preserve the 'state' between invocations of your read() hook.
|
||||
int todo = 0;
|
||||
unsigned char * end = in_buf+buf_size
|
||||
unsigned char * out_buf = in_buf;
|
||||
while (true) {
|
||||
uchar byte = read_midi();
|
||||
if (!todo || state) {
|
||||
todo = (*parser->parse)(&state, byte, end-out_buf);
|
||||
}
|
||||
if (todo < 1) {
|
||||
unput_midi(byte);
|
||||
} else {
|
||||
*(out_buf++) = byte;
|
||||
todo--;
|
||||
}
|
||||
if (todo < 1 || out_buf >= end) {
|
||||
received_midi_message(in_buf, out_buf-in_buf);
|
||||
todo = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#define B_MIDI_PARSER_MODULE_NAME "media/midiparser/v1"
|
||||
|
||||
typedef struct _midi_parser_module_info {
|
||||
module_info minfo;
|
||||
int (*parse)(uint32 * state, uchar byte, size_t max_size);
|
||||
int _reserved_;
|
||||
} midi_parser_module_info;
|
||||
|
||||
#define B_MPU_401_MODULE_NAME "generic/mpu401/v1"
|
||||
|
||||
enum {
|
||||
B_MPU_401_ENABLE_CARD_INT = 1,
|
||||
B_MPU_401_DISABLE_CARD_INT
|
||||
};
|
||||
typedef struct _generic_mpu401_module {
|
||||
module_info minfo;
|
||||
status_t (*create_device)(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card);
|
||||
status_t (*delete_device)(void * storage);
|
||||
status_t (*open_hook)(void * storage, uint32 flags, void ** out_cookie);
|
||||
status_t (*close_hook)(void * cookie);
|
||||
status_t (*free_hook)(void * cookie);
|
||||
status_t (*control_hook)(void * cookie, uint32 op, void * data, size_t len);
|
||||
status_t (*read_hook)(void * cookie, off_t pos, void * data, size_t * len);
|
||||
status_t (*write_hook)(void * cookie, off_t pos, const void * data, size_t * len);
|
||||
bool (*interrupt_hook)(void * cookie);
|
||||
int _reserved_;
|
||||
} generic_mpu401_module;
|
||||
|
||||
#endif
|
304
src/add-ons/kernel/drivers/audio/cmedia/mixer.c
Normal file
304
src/add-ons/kernel/drivers/audio/cmedia/mixer.c
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include "cm_private.h"
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_KERNEL_EXPORT_H)
|
||||
#include <KernelExport.h>
|
||||
#endif /* _KERNEL_EXPORT_H */
|
||||
|
||||
|
||||
static status_t mixer_open(const char *name, uint32 flags, void **cookie);
|
||||
static status_t mixer_close(void *cookie);
|
||||
static status_t mixer_free(void *cookie);
|
||||
static status_t mixer_control(void *cookie, uint32 op, void *data, size_t len);
|
||||
static status_t mixer_read(void *cookie, off_t pos, void *data, size_t *len);
|
||||
static status_t mixer_write(void *cookie, off_t pos, const void *data, size_t *len);
|
||||
|
||||
device_hooks mixer_hooks = {
|
||||
&mixer_open,
|
||||
&mixer_close,
|
||||
&mixer_free,
|
||||
&mixer_control,
|
||||
&mixer_read,
|
||||
&mixer_write,
|
||||
NULL, /* select */
|
||||
NULL, /* deselect */
|
||||
NULL, /* readv */
|
||||
NULL /* writev */
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
int selector;
|
||||
int port;
|
||||
float div;
|
||||
float sub;
|
||||
int minval;
|
||||
int maxval;
|
||||
int leftshift;
|
||||
int mask;
|
||||
int mutemask;
|
||||
} mixer_info;
|
||||
|
||||
/* mute is special -- when it's 0x01, it means enable... */
|
||||
mixer_info the_mixers[] = {
|
||||
{CMEDIA_PCI_LEFT_ADC_INPUT_G, 0, 1.5, 0.0, 0, 15, 0, 0x0f, 0x00},
|
||||
{CMEDIA_PCI_RIGHT_ADC_INPUT_G, 1, 1.5, 0.0, 0, 15, 0, 0x0f, 0x00},
|
||||
{CMEDIA_PCI_LEFT_AUX1_LOOPBACK_GAM, 2, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_AUX1_LOOPBACK_GAM, 3, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_CD_LOOPBACK_GAM, 4, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_CD_LOOPBACK_GAM, 5, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_LINE_LOOPBACK_GAM, 6, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_LINE_LOOPBACK_GAM, 7, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_MIC_LOOPBACK_GAM, 8, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_SYNTH_OUTPUT_GAM, 0xa, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_SYNTH_OUTPUT_GAM, 0xb, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_AUX2_LOOPBACK_GAM, 0xc, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_AUX2_LOOPBACK_GAM, 0xd, -1.5, 12.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_MASTER_VOLUME_AM, 0xe, -1.5, 0.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_MASTER_VOLUME_AM, 0xf, -1.5, 0.0, 0, 31, 0, 0x1f, 0x80},
|
||||
{CMEDIA_PCI_LEFT_PCM_OUTPUT_GAM, 0x10, -1.5, 0.0, 0, 63, 0, 0x3f, 0x80},
|
||||
{CMEDIA_PCI_RIGHT_PCM_OUTPUT_GAM, 0x11, -1.5, 0.0, 0, 63, 0, 0x3f, 0x80},
|
||||
{CMEDIA_PCI_DIGITAL_LOOPBACK_AM, 0x16, -1.5, 0.0, 0, 63, 2, 0xfc, 0x01},
|
||||
};
|
||||
#define N_MIXERS (sizeof(the_mixers) / sizeof(the_mixers[0]))
|
||||
|
||||
static int
|
||||
map_mixer(int selector) {
|
||||
int i;
|
||||
for (i = 0; i < N_MIXERS; i++)
|
||||
if (the_mixers[i].selector == selector)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_open(
|
||||
const char * name,
|
||||
uint32 flags,
|
||||
void ** cookie)
|
||||
{
|
||||
int ix;
|
||||
/* mixer_dev * it = NULL; */
|
||||
|
||||
ddprintf(("cmedia_pci: mixer_open()\n"));
|
||||
|
||||
*cookie = NULL;
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
if (!strcmp(name, cards[ix].mixer.name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ix == num_cards) {
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
atomic_add(&cards[ix].mixer.open_count, 1);
|
||||
cards[ix].mixer.card = &cards[ix];
|
||||
*cookie = &cards[ix].mixer;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_close(
|
||||
void * cookie)
|
||||
{
|
||||
mixer_dev * it = (mixer_dev *)cookie;
|
||||
|
||||
atomic_add(&it->open_count, -1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_free(
|
||||
void * cookie)
|
||||
{
|
||||
ddprintf(("cmedia_pci: mixer_free()\n"));
|
||||
|
||||
if (((mixer_dev *)cookie)->open_count != 0) {
|
||||
dprintf("cmedia_pci: mixer open_count is bad in mixer_free()!\n");
|
||||
}
|
||||
return B_OK; /* already done in close */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_mixer_value(
|
||||
cmedia_pci_dev * card,
|
||||
cmedia_pci_level * lev)
|
||||
{
|
||||
int ix = map_mixer(lev->selector);
|
||||
uchar val;
|
||||
if (ix < 0) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
val = get_indirect(card, the_mixers[ix].port);
|
||||
lev->flags = 0;
|
||||
if (!the_mixers[ix].mutemask) {
|
||||
/* no change */
|
||||
}
|
||||
else if (the_mixers[ix].mutemask == 0x01) {
|
||||
if (!(val & 0x01)) {
|
||||
lev->flags |= CMEDIA_PCI_LEVEL_MUTED;
|
||||
}
|
||||
}
|
||||
else if (val & the_mixers[ix].mutemask) {
|
||||
lev->flags |= CMEDIA_PCI_LEVEL_MUTED;
|
||||
}
|
||||
val &= the_mixers[ix].mask;
|
||||
val >>= the_mixers[ix].leftshift;
|
||||
lev->value = ((float)val)*the_mixers[ix].div+the_mixers[ix].sub;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gather_info(
|
||||
mixer_dev * mixer,
|
||||
cmedia_pci_level * data,
|
||||
int count)
|
||||
{
|
||||
int ix;
|
||||
cpu_status cp;
|
||||
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&mixer->card->hardware);
|
||||
|
||||
for (ix=0; ix<count; ix++) {
|
||||
if (get_mixer_value(mixer->card, &data[ix]) < B_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
release_spinlock(&mixer->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
set_mixer_value(
|
||||
cmedia_pci_dev * card,
|
||||
cmedia_pci_level * lev)
|
||||
{
|
||||
int selector = map_mixer(lev->selector);
|
||||
int value;
|
||||
int mask;
|
||||
if (selector < 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
value = (lev->value-the_mixers[selector].sub)/the_mixers[selector].div;
|
||||
if (value < the_mixers[selector].minval) {
|
||||
value = the_mixers[selector].minval;
|
||||
}
|
||||
if (value > the_mixers[selector].maxval) {
|
||||
value = the_mixers[selector].maxval;
|
||||
}
|
||||
value <<= the_mixers[selector].leftshift;
|
||||
if (the_mixers[selector].mutemask) {
|
||||
if (the_mixers[selector].mutemask == 0x01) {
|
||||
if (!(lev->flags & CMEDIA_PCI_LEVEL_MUTED)) {
|
||||
value |= the_mixers[selector].mutemask;
|
||||
}
|
||||
} else {
|
||||
if (lev->flags & CMEDIA_PCI_LEVEL_MUTED) {
|
||||
value |= the_mixers[selector].mutemask;
|
||||
}
|
||||
}
|
||||
}
|
||||
mask = the_mixers[selector].mutemask | the_mixers[selector].mask;
|
||||
set_indirect(card, the_mixers[selector].port, value, mask);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
disperse_info(
|
||||
mixer_dev * mixer,
|
||||
cmedia_pci_level * data,
|
||||
int count)
|
||||
{
|
||||
int ix;
|
||||
cpu_status cp;
|
||||
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&mixer->card->hardware);
|
||||
|
||||
for (ix=0; ix<count; ix++) {
|
||||
if (set_mixer_value(mixer->card, &data[ix]) < B_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
release_spinlock(&mixer->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_control(
|
||||
void * cookie,
|
||||
uint32 iop,
|
||||
void * data,
|
||||
size_t len)
|
||||
{
|
||||
mixer_dev * it = (mixer_dev *)cookie;
|
||||
status_t err = B_OK;
|
||||
|
||||
if (!data) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
ddprintf(("cmedia_pci: mixer_control()\n")); /* slow printing */
|
||||
|
||||
switch (iop) {
|
||||
case B_MIXER_GET_VALUES:
|
||||
((cmedia_pci_level_cmd *)data)->count =
|
||||
gather_info(it, ((cmedia_pci_level_cmd *)data)->data,
|
||||
((cmedia_pci_level_cmd *)data)->count);
|
||||
break;
|
||||
case B_MIXER_SET_VALUES:
|
||||
((cmedia_pci_level_cmd *)data)->count =
|
||||
disperse_info(it, ((cmedia_pci_level_cmd *)data)->data,
|
||||
((cmedia_pci_level_cmd *)data)->count);
|
||||
break;
|
||||
default:
|
||||
err = B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_read(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
void * data,
|
||||
size_t * nread)
|
||||
{
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mixer_write(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
const void * data,
|
||||
size_t * nwritten)
|
||||
{
|
||||
return EPERM;
|
||||
}
|
||||
|
281
src/add-ons/kernel/drivers/audio/cmedia/mux.c
Normal file
281
src/add-ons/kernel/drivers/audio/cmedia/mux.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include "cm_private.h"
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_KERNEL_EXPORT_H)
|
||||
#include <KernelExport.h>
|
||||
#endif /* _KERNEL_EXPORT_H */
|
||||
|
||||
|
||||
static status_t mux_open(const char *name, uint32 flags, void **cookie);
|
||||
static status_t mux_close(void *cookie);
|
||||
static status_t mux_free(void *cookie);
|
||||
static status_t mux_control(void *cookie, uint32 op, void *data, size_t len);
|
||||
static status_t mux_read(void *cookie, off_t pos, void *data, size_t *len);
|
||||
static status_t mux_write(void *cookie, off_t pos, const void *data, size_t *len);
|
||||
|
||||
device_hooks mux_hooks = {
|
||||
&mux_open,
|
||||
&mux_close,
|
||||
&mux_free,
|
||||
&mux_control,
|
||||
&mux_read,
|
||||
&mux_write,
|
||||
NULL, /* select */
|
||||
NULL, /* deselect */
|
||||
NULL, /* readv */
|
||||
NULL /* writev */
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
int port_l;
|
||||
int port_r;
|
||||
int minval;
|
||||
int maxval;
|
||||
int leftshift;
|
||||
int mask;
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
} mux_info;
|
||||
|
||||
const mux_info the_muxes[] = {
|
||||
{ 0, 1, 1, 7, 5, 0xe0, "Sampling Input" },
|
||||
{ 0, -1, 0, 1, 4, 0x10, "Mic +20dB Selection" },
|
||||
{ 0x2a, -1, 0, 1, 0, 0x01, "MIDI Output To Synth" },
|
||||
{ 0x2a, -1, 0, 1, 1, 0x02, "MIDI Input To Synth" },
|
||||
{ 0x2a, -1, 0, 1, 2, 0x04, "MIDI Output To Port" },
|
||||
};
|
||||
|
||||
static const uchar unmap_input[] = {
|
||||
0,
|
||||
CMEDIA_PCI_INPUT_CD,
|
||||
CMEDIA_PCI_INPUT_DAC,
|
||||
CMEDIA_PCI_INPUT_AUX2,
|
||||
CMEDIA_PCI_INPUT_LINE,
|
||||
CMEDIA_PCI_INPUT_AUX1,
|
||||
CMEDIA_PCI_INPUT_MIC,
|
||||
CMEDIA_PCI_INPUT_MIX_OUT
|
||||
};
|
||||
|
||||
static uchar
|
||||
map_input(uchar val) {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++)
|
||||
if (unmap_input[i] == val)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_open(
|
||||
const char * name,
|
||||
uint32 flags,
|
||||
void ** cookie)
|
||||
{
|
||||
int ix;
|
||||
/* mux_dev * plex = NULL; */
|
||||
|
||||
ddprintf(("cmedia_pci: mux_open()\n"));
|
||||
|
||||
*cookie = NULL;
|
||||
for (ix=0; ix<num_cards; ix++) {
|
||||
if (!strcmp(name, cards[ix].mux.name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ix == num_cards) {
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
atomic_add(&cards[ix].mux.open_count, 1);
|
||||
cards[ix].mux.card = &cards[ix];
|
||||
*cookie = &cards[ix].mux;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_close(
|
||||
void * cookie)
|
||||
{
|
||||
mux_dev * plex = (mux_dev *)cookie;
|
||||
|
||||
atomic_add(&plex->open_count, -1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_free(
|
||||
void * cookie)
|
||||
{
|
||||
ddprintf(("cmedia_pci: mux_free()\n"));
|
||||
|
||||
if (((mux_dev *)cookie)->open_count != 0) {
|
||||
dprintf("cmedia_pci: mux open_count is bad in mux_free()!\n");
|
||||
}
|
||||
return B_OK; /* already done in close */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_mux_value(
|
||||
cmedia_pci_dev * card,
|
||||
int ix)
|
||||
{
|
||||
uchar val;
|
||||
if (ix < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (ix > 4) {
|
||||
return -1;
|
||||
}
|
||||
val = get_indirect(card, the_muxes[ix].port_l);
|
||||
val &= the_muxes[ix].mask;
|
||||
val >>= the_muxes[ix].leftshift;
|
||||
if (ix == CMEDIA_PCI_INPUT_MUX)
|
||||
return unmap_input[val];
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gather_info(
|
||||
mux_dev * mux,
|
||||
cmedia_pci_routing * data,
|
||||
int count)
|
||||
{
|
||||
int ix;
|
||||
cpu_status cp;
|
||||
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&mux->card->hardware);
|
||||
|
||||
for (ix=0; ix<count; ix++) {
|
||||
data[ix].value = get_mux_value(mux->card, data[ix].selector);
|
||||
if (data[ix].value < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
release_spinlock(&mux->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
set_mux_value(
|
||||
cmedia_pci_dev * card,
|
||||
int selector,
|
||||
int value)
|
||||
{
|
||||
ddprintf(("set_mux_value(%d,%d)\n", selector, value));
|
||||
if (selector < 0 || selector > 4) {
|
||||
ddprintf(("selector EINVAL\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
if (selector == CMEDIA_PCI_INPUT_MUX)
|
||||
value = map_input(value);
|
||||
if (value < the_muxes[selector].minval ||
|
||||
value > the_muxes[selector].maxval) {
|
||||
ddprintf(("value EINVAL\n"));
|
||||
return EINVAL;
|
||||
}
|
||||
set_indirect(card, the_muxes[selector].port_l,
|
||||
(value << the_muxes[selector].leftshift),
|
||||
the_muxes[selector].mask);
|
||||
if (the_muxes[selector].port_r > -1) {
|
||||
set_indirect(card, the_muxes[selector].port_r,
|
||||
(value << the_muxes[selector].leftshift),
|
||||
the_muxes[selector].mask);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
disperse_info(
|
||||
mux_dev * mux,
|
||||
cmedia_pci_routing * data,
|
||||
int count)
|
||||
{
|
||||
int ix;
|
||||
cpu_status cp;
|
||||
|
||||
cp = disable_interrupts();
|
||||
acquire_spinlock(&mux->card->hardware);
|
||||
|
||||
for (ix=0; ix<count; ix++) {
|
||||
if (set_mux_value(mux->card, data[ix].selector, data[ix].value) < B_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
release_spinlock(&mux->card->hardware);
|
||||
restore_interrupts(cp);
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_control(
|
||||
void * cookie,
|
||||
uint32 iop,
|
||||
void * data,
|
||||
size_t len)
|
||||
{
|
||||
mux_dev * plex = (mux_dev *)cookie;
|
||||
status_t err = B_OK;
|
||||
|
||||
ddprintf(("cmedia_pci: mux_control()\n")); /* slow printing */
|
||||
|
||||
switch (iop) {
|
||||
case B_ROUTING_GET_VALUES:
|
||||
((cmedia_pci_routing_cmd *)data)->count =
|
||||
gather_info(plex, ((cmedia_pci_routing_cmd *)data)->data,
|
||||
((cmedia_pci_routing_cmd *)data)->count);
|
||||
break;
|
||||
case B_ROUTING_SET_VALUES:
|
||||
((cmedia_pci_routing_cmd *)data)->count =
|
||||
disperse_info(plex, ((cmedia_pci_routing_cmd *)data)->data,
|
||||
((cmedia_pci_routing_cmd *)data)->count);
|
||||
break;
|
||||
default:
|
||||
err = B_BAD_VALUE;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_read(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
void * data,
|
||||
size_t * nread)
|
||||
{
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
mux_write(
|
||||
void * cookie,
|
||||
off_t pos,
|
||||
const void * data,
|
||||
size_t * nwritten)
|
||||
{
|
||||
return EPERM;
|
||||
}
|
||||
|
1710
src/add-ons/kernel/drivers/audio/cmedia/pcm.c
Normal file
1710
src/add-ons/kernel/drivers/audio/cmedia/pcm.c
Normal file
File diff suppressed because it is too large
Load Diff
118
src/add-ons/kernel/drivers/audio/cmedia/sound.h
Normal file
118
src/add-ons/kernel/drivers/audio/cmedia/sound.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* ++++++++++
|
||||
$Source: /home/cltien/cvs/BeOS/inc/sound.h,v $
|
||||
$Revision: 1.1.1.1 $
|
||||
$Author: cltien $
|
||||
$Date: 1999/10/12 18:38:08 $
|
||||
|
||||
Data structures and control calls for using the sound driver
|
||||
+++++ */
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef _SOUND_H
|
||||
#define _SOUND_H
|
||||
|
||||
#ifndef _DRIVERS_H
|
||||
#include <Drivers.h>
|
||||
#endif
|
||||
|
||||
enum adc_source {
|
||||
line=0, aux1, mic, loopback
|
||||
};
|
||||
|
||||
enum sample_rate {
|
||||
kHz_8_0 = 0, kHz_5_51, kHz_16_0, kHz_11_025, kHz_27_42, kHz_18_9,
|
||||
kHz_32_0, kHz_22_05, kHz_37_8 = 9, kHz_44_1 = 11, kHz_48_0, kHz_33_075,
|
||||
kHz_9_6, kHz_6_62
|
||||
};
|
||||
|
||||
enum sample_format {
|
||||
linear_8bit_unsigned_mono = 0, linear_8bit_unsigned_stereo,
|
||||
ulaw_8bit_companded_mono, ulaw_8bit_companded_stereo,
|
||||
linear_16bit_little_endian_mono, linear_16bit_little_endian_stereo,
|
||||
alaw_8bit_companded_mono, alaw_8bit_companded_stereo,
|
||||
sample_format_reserved_1, sample_format_reserved_2,
|
||||
adpcm_4bit_mono, adpcm_4bit_stereo,
|
||||
linear_16bit_big_endian_mono, linear_16bit_big_endian_stereo,
|
||||
sample_format_reserved_3, sample_format_reserved_4
|
||||
};
|
||||
|
||||
struct channel {
|
||||
enum adc_source adc_source; /* adc input source */
|
||||
char adc_gain; /* 0..15 adc gain, in 1.5 dB steps */
|
||||
char mic_gain_enable; /* non-zero enables 20 dB MIC input gain */
|
||||
char aux1_mix_gain; /* 0..31 aux1 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */
|
||||
char aux1_mix_mute; /* non-zero mutes aux1 mix */
|
||||
char aux2_mix_gain; /* 0..31 aux2 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */
|
||||
char aux2_mix_mute; /* non-zero mutes aux2 mix */
|
||||
char line_mix_gain; /* 0..31 line mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */
|
||||
char line_mix_mute; /* non-zero mutes line mix */
|
||||
char dac_attn; /* 0..61 dac attenuation, in -1.5 dB steps */
|
||||
char dac_mute; /* non-zero mutes dac output */
|
||||
};
|
||||
|
||||
typedef struct sound_setup {
|
||||
struct channel left; /* left channel setup */
|
||||
struct channel right; /* right channel setup */
|
||||
enum sample_rate sample_rate; /* sample rate */
|
||||
enum sample_format playback_format;/* sample format for playback */
|
||||
enum sample_format capture_format; /* sample format for capture */
|
||||
char dither_enable; /* non-zero enables dither on 16 => 8 bit */
|
||||
char loop_attn; /* 0..64 adc to dac loopback attenuation, in -1.5 dB steps */
|
||||
char loop_enable; /* non-zero enables loopback */
|
||||
char output_boost; /* zero (2.0 Vpp) non-zero (2.8 Vpp) output level boost */
|
||||
char highpass_enable;/* non-zero enables highpass filter in adc */
|
||||
char mono_gain; /* 0..64 mono speaker gain */
|
||||
char mono_mute; /* non-zero mutes speaker */
|
||||
// char spdif_mute; /* non-zero mutes spdif out */
|
||||
} sound_setup;
|
||||
|
||||
|
||||
/* -----
|
||||
control opcodes for sound driver
|
||||
----- */
|
||||
|
||||
enum {
|
||||
SOUND_GET_PARAMS = B_DEVICE_OP_CODES_END,
|
||||
SOUND_SET_PARAMS, /* 10000 */
|
||||
SOUND_SET_PLAYBACK_COMPLETION_SEM,
|
||||
SOUND_SET_CAPTURE_COMPLETION_SEM,
|
||||
SOUND_GET_PLAYBACK_TIMESTAMP, /* 10003 */
|
||||
SOUND_GET_CAPTURE_TIMESTAMP,
|
||||
SOUND_DEBUG_ON,
|
||||
SOUND_DEBUG_OFF, /* 10006 */
|
||||
SOUND_UNSAFE_WRITE,
|
||||
SOUND_UNSAFE_READ,
|
||||
SOUND_LOCK_FOR_DMA, /* 10009 */
|
||||
SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE,
|
||||
SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE,
|
||||
SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, /* 10012 */
|
||||
SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE,
|
||||
|
||||
// control ports for SPDIF settings
|
||||
SOUND_GET_SPDIF_IN_OUT_LOOPBACK,
|
||||
SOUND_SET_SPDIF_IN_OUT_LOOPBACK,
|
||||
SOUND_GET_SPDIF_OUT,
|
||||
SOUND_SET_SPDIF_OUT,
|
||||
SOUND_GET_SPDIF_MONITOR,
|
||||
SOUND_SET_SPDIF_MONITOR,
|
||||
SOUND_GET_SPDIF_OUT_LEVEL,
|
||||
SOUND_SET_SPDIF_OUT_LEVEL,
|
||||
SOUND_GET_SPDIF_IN_FORMAT,
|
||||
SOUND_SET_SPDIF_IN_FORMAT,
|
||||
SOUND_GET_SPDIF_IN_OUT_COPYRIGHT,
|
||||
SOUND_SET_SPDIF_IN_OUT_COPYRIGHT,
|
||||
SOUND_GET_SPDIF_IN_VALIDITY,
|
||||
SOUND_SET_SPDIF_IN_VALIDITY,
|
||||
// control ports for analog settings
|
||||
SOUND_GET_4_CHANNEL_DUPLICATE,
|
||||
SOUND_SET_4_CHANNEL_DUPLICATE,
|
||||
// control ports for additional info
|
||||
SOUND_GET_DEVICE_ID,
|
||||
SOUND_GET_INTERNAL_CHIP_ID,
|
||||
SOUND_GET_DRIVER_VERSION
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user