Commit b21fd933 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA update [7/10] - 2002/07/24

  - renamed snd-dt0197h to snd-dt019x
  - added support for DT0196, DT0197h and ALS007 to snd-dt019x
  - searial-u16550 - added support for generic adapter type
  - pcm.c
    - fixed the initialization of runtime->status
    - removed unnecessary check of n_register callback
  - timer.c
    - fixed kmod behaviour
  - Opti92x/93x fixes by Michael Corlett
  - fixed compilation of YMFPCI driver (PPC)
parent eb7e7cd8
......@@ -8,6 +8,7 @@ The snd_adaptor module parameter allows you to select either:
1 - Midiator MS-124T support (1)
2 - Midiator MS-124W S/A mode (2)
3 - MS-124W M/B mode support (3)
4 - Generic device with multiple input support (4)
For the Midiator MS-124W, you must set the physical M-S and A-B
switches on the Midiator to match the driver mode you select.
......@@ -82,3 +83,9 @@ compatible, nor are the other known models MS-101, MS-101B, MS-103, and MS-114.
I do have documentation (tim.mann@compaq.com) that partially covers these models,
but no units to experiment with. The MS-124W support is tested with a real unit.
The MS-124T support is untested, but should work.
The Generic driver supports multiple input and output substreams over a single
serial port. Similar to Roland Soundcanvas mode, F5 NN is used to select the
appropriate input or output stream (depending on the data direction).
Additionally, the CTS signal is used to regulate the data flow. The number of
inputs is specified by the snd_ins parameter.
......@@ -36,6 +36,7 @@ enum sb_hw_type {
SB_HW_16CSP, /* SB16 with CSP chip */
SB_HW_ALS100, /* Avance Logic ALS100 chip */
SB_HW_ALS4000, /* Avance Logic ALS4000 chip */
SB_HW_DT019X, /* Diamond Tech. DT-019X / Avance Logic ALS-007 */
};
#define SB_OPEN_PCM 0x01
......@@ -215,6 +216,24 @@ typedef struct _snd_sb sb_t;
#define SB_DSP4_3DSE 0x90
/* Registers for DT-019x / ALS-007 mixer */
#define SB_DT019X_MASTER_DEV 0x62
#define SB_DT019X_PCM_DEV 0x64
#define SB_DT019X_SYNTH_DEV 0x66
#define SB_DT019X_CD_DEV 0x68
#define SB_DT019X_MIC_DEV 0x6a
#define SB_DT019X_SPKR_DEV 0x6a
#define SB_DT019X_LINE_DEV 0x6e
#define SB_DT019X_OUTPUT_SW1 0x3c
#define SB_DT019X_OUTPUT_SW2 0x4c
#define SB_DT019X_CAPTURE_SW 0x6c
#define SB_DT019X_CAP_CD 0x02
#define SB_DT019X_CAP_MIC 0x04
#define SB_DT019X_CAP_LINE 0x06
#define SB_DT019X_CAP_SYNTH 0x07
#define SB_DT019X_CAP_MAIN 0x07
/* IRQ setting bitmap */
#define SB_IRQSETUP_IRQ9 0x01
#define SB_IRQSETUP_IRQ5 0x02
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc2"
#define CONFIG_SND_DATE " (Sat Jul 20 07:16:41 2002 UTC)"
#define CONFIG_SND_DATE " (Wed Jul 24 10:42:45 2002 UTC)"
......@@ -41,7 +41,7 @@ obj-$(CONFIG_SND_MPU401) += snd-rawmidi.o snd.o snd-timer.o
obj-$(CONFIG_SND_ALS100) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_AZT2320) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_CMI8330) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_DT0197H) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_DT019X) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_ES18XX) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_OPL3SA2) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_SGALAXY) += snd-pcm.o snd-timer.o snd.o
......
......@@ -753,16 +753,15 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
kfree(runtime);
return -ENOMEM;
}
memset((void*)runtime->status, 0, size);
size = PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t));
runtime->control = snd_malloc_pages(size, GFP_KERNEL);
if (runtime->control == NULL) {
kfree((void *)runtime->status);
snd_free_pages((void*)runtime->status, PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)));
kfree(runtime);
return -ENOMEM;
}
memset((void*)runtime->status, 0, size);
memset((void*)runtime->control, 0, size);
init_waitqueue_head(&runtime->sleep);
......@@ -840,7 +839,6 @@ int snd_pcm_dev_register(snd_device_t *device)
list_for_each(list, &snd_pcm_notify_list) {
snd_pcm_notify_t *notify;
notify = list_entry(list, snd_pcm_notify_t, list);
if (notify->n_register)
notify->n_register(-1 /* idx + SNDRV_MINOR_PCM */, pcm);
}
snd_pcm_lock(1);
......@@ -878,7 +876,6 @@ static int snd_pcm_dev_unregister(snd_device_t *device)
list_for_each(list, &snd_pcm_notify_list) {
snd_pcm_notify_t *notify;
notify = list_entry(list, snd_pcm_notify_t, list);
if (notify->n_unregister)
notify->n_unregister(-1 /* SNDRV_MINOR_PCM + idx */, pcm);
}
snd_pcm_devices[idx] = NULL;
......
......@@ -35,7 +35,7 @@ obj-$(CONFIG_SND_MTPAV) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-mid
obj-$(CONFIG_SND_MPU401) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
obj-$(CONFIG_SND_ALS100) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_AZT2320) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_DT0197H) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_DT019X) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_ES18XX) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_OPL3SA2) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_AD1816A) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
......
......@@ -13,7 +13,7 @@ snd-ainstr-iw-objs := ainstr_iw.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_ALS100) += snd-ainstr-fm.o
obj-$(CONFIG_SND_AZT2320) += snd-ainstr-fm.o
obj-$(CONFIG_SND_DT0197H) += snd-ainstr-fm.o
obj-$(CONFIG_SND_DT019X) += snd-ainstr-fm.o
obj-$(CONFIG_SND_ES18XX) += snd-ainstr-fm.o
obj-$(CONFIG_SND_OPL3SA2) += snd-ainstr-fm.o
obj-$(CONFIG_SND_AD1816A) += snd-ainstr-fm.o
......
......@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
MODULE_SUPPORTED_DEVICE("sound");
MODULE_PARM(snd_seq_client_load, "i");
MODULE_PARM(snd_seq_client_load, "1-64i");
MODULE_PARM_DESC(snd_seq_client_load, "The numbers of global (system) clients to load through kmod.");
MODULE_PARM(snd_seq_default_timer_class, "i");
MODULE_PARM_DESC(snd_seq_default_timer_class, "The default timer class.");
......
......@@ -35,13 +35,19 @@
#include <linux/kerneld.h>
#endif
int snd_timer_limit = 1;
#if !defined(CONFIG_SND_RTCTIMER) && !defined(CONFIG_SND_RTCTIMER_MODULE)
#define DEFAULT_TIMER_LIMIT 1
#else
#define DEFAULT_TIMER_LIMIT 2
#endif
int snd_timer_limit = DEFAULT_TIMER_LIMIT;
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA timer interface");
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
MODULE_PARM(snd_timer_limit, "i");
MODULE_PARM_DESC(snd_timer_limit, "Maximum global timers in system. (1 by default)");
MODULE_PARM_DESC(snd_timer_limit, "Maximum global timers in system.");
typedef struct {
snd_timer_instance_t *timeri;
......@@ -146,10 +152,14 @@ static void snd_timer_request(snd_timer_id_t *tid)
switch (tid->dev_class) {
case SNDRV_TIMER_CLASS_GLOBAL:
if (tid->device >= snd_timer_limit)
return;
sprintf(str, "snd-timer-%i", tid->device);
break;
case SNDRV_TIMER_CLASS_CARD:
case SNDRV_TIMER_CLASS_PCM:
if (tid->card >= snd_ecards_limit)
return;
sprintf(str, "snd-card-%i", tid->card);
break;
default:
......@@ -876,7 +886,7 @@ static void snd_timer_proc_read(snd_info_entry_t *entry,
}
snd_iprintf(buffer, "%s :", timer->name);
if (timer->hw.resolution)
snd_iprintf(buffer, " %lu.%luus (%lu ticks)", timer->hw.resolution / 1000, timer->hw.resolution % 1000, timer->hw.ticks);
snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", timer->hw.resolution / 1000, timer->hw.resolution % 1000, timer->hw.ticks);
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
snd_iprintf(buffer, " SLAVE");
snd_iprintf(buffer, "\n");
......
......@@ -12,7 +12,7 @@ snd-mpu401-uart-objs := mpu401_uart.o
obj-$(CONFIG_SND_MPU401) += snd-mpu401.o snd-mpu401-uart.o
obj-$(CONFIG_SND_ALS100) += snd-mpu401-uart.o
obj-$(CONFIG_SND_AZT2320) += snd-mpu401-uart.o
obj-$(CONFIG_SND_DT0197H) += snd-mpu401-uart.o
obj-$(CONFIG_SND_DT019X) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ES18XX) += snd-mpu401-uart.o
obj-$(CONFIG_SND_OPL3SA2) += snd-mpu401-uart.o
obj-$(CONFIG_SND_AD1816A) += snd-mpu401-uart.o
......
......@@ -16,7 +16,7 @@ endif
# Toplevel Module Dependency
obj-$(CONFIG_SND_ALS100) += snd-opl3-lib.o
obj-$(CONFIG_SND_AZT2320) += snd-opl3-lib.o
obj-$(CONFIG_SND_DT0197H) += snd-opl3-lib.o
obj-$(CONFIG_SND_DT019X) += snd-opl3-lib.o
obj-$(CONFIG_SND_ES18XX) += snd-opl3-lib.o
obj-$(CONFIG_SND_OPL3SA2) += snd-opl3-lib.o
obj-$(CONFIG_SND_AD1816A) += snd-opl3-lib.o
......@@ -41,7 +41,7 @@ obj-$(CONFIG_SND_YMFPCI) += snd-opl3-lib.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
obj-$(CONFIG_SND_ALS100) += snd-opl3-synth.o
obj-$(CONFIG_SND_AZT2320) += snd-opl3-synth.o
obj-$(CONFIG_SND_DT0197H) += snd-opl3-synth.o
obj-$(CONFIG_SND_DT019X) += snd-opl3-synth.o
obj-$(CONFIG_SND_ES18XX) += snd-opl3-synth.o
obj-$(CONFIG_SND_OPL3SA2) += snd-opl3-synth.o
obj-$(CONFIG_SND_AD1816A) += snd-opl3-synth.o
......
......@@ -51,12 +51,14 @@ MODULE_DEVICES("{{ALSA, MIDI serial u16550}}");
#define SNDRV_SERIAL_MS124T 1 /* Midiator MS-124T */
#define SNDRV_SERIAL_MS124W_SA 2 /* Midiator MS-124W in S/A mode */
#define SNDRV_SERIAL_MS124W_MB 3 /* Midiator MS-124W in M/B mode */
#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_MS124W_MB
#define SNDRV_SERIAL_GENERIC 4 /* Generic Interface */
#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC
static char *adaptor_names[] = {
"Soundcanvas",
"MS-124T",
"MS-124W S/A",
"MS-124W M/B"
"MS-124W M/B",
"Generic"
};
static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
......@@ -67,6 +69,7 @@ static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,4,5,7,9,10,11,14,15 *
static int snd_speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */
static int snd_base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */
static int snd_outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
static int snd_ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
static int snd_adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS};
MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
......@@ -92,17 +95,21 @@ MODULE_PARM_DESC(snd_base, "Base for divisor in bauds.");
MODULE_PARM_SYNTAX(snd_base, SNDRV_ENABLED ",allows:{57600,115200,230400,460800},dialog:list");
MODULE_PARM(snd_outs, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_outs, "Number of MIDI outputs.");
MODULE_PARM(snd_ins, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_ins, "Number of MIDI inputs.");
MODULE_PARM_SYNTAX(snd_outs, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
MODULE_PARM_SYNTAX(snd_ins, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
MODULE_PARM(snd_adaptor, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_adaptor, "Type of adaptor.");
MODULE_PARM_SYNTAX(snd_adaptor, SNDRV_ENABLED ",allows:{{0=Soundcanvas,1=MS-124T,2=MS-124W S/A,3=MS-124W M/B}},dialog:list");
MODULE_PARM_SYNTAX(snd_adaptor, SNDRV_ENABLED ",allows:{{0=Soundcanvas,1=MS-124T,2=MS-124W S/A,3=MS-124W M/B,4=Generic}},dialog:list");
/*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/ /* Address outs as 0-3 instead of bitmap */
#define SNDRV_SERIAL_MAX_OUTS 16 /* max 64, min 16 */
#define SNDRV_SERIAL_MAX_INS 16 /* max 64, min 16 */
#define TX_BUFF_SIZE (1<<9) /* Must be 2^n */
#define TX_BUFF_SIZE (1<<15) /* Must be 2^n */
#define TX_BUFF_MASK (TX_BUFF_SIZE - 1)
#define SERIAL_MODE_NOT_OPENED (0)
......@@ -115,7 +122,7 @@ typedef struct _snd_uart16550 {
snd_card_t *card;
snd_rawmidi_t *rmidi;
snd_rawmidi_substream_t *midi_output[SNDRV_SERIAL_MAX_OUTS];
snd_rawmidi_substream_t *midi_input;
snd_rawmidi_substream_t *midi_input[SNDRV_SERIAL_MAX_INS];
int filemode; //open status of file
......@@ -141,6 +148,10 @@ typedef struct _snd_uart16550 {
// type of adaptor
int adaptor;
// inputs
int prev_in;
unsigned char rstatus;
// outputs
int prev_out;
unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
......@@ -196,26 +207,52 @@ inline static void snd_uart16550_buffer_output(snd_uart16550_t *uart)
static void snd_uart16550_io_loop(snd_uart16550_t * uart)
{
unsigned char c, status;
int substream;
/* recall previous stream */
substream = uart->prev_in;
/* Read Loop */
while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) {
/* while receive data ready */
c = inb(uart->base + UART_RX);
if (uart->filemode & SERIAL_MODE_INPUT_OPEN) {
snd_rawmidi_receive(uart->midi_input, &c, 1);
/* keep track of last status byte */
if (c & 0x80) {
uart->rstatus = c;
}
/* handle stream switch */
if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
if (uart->rstatus == 0xf5) {
if (c <= SNDRV_SERIAL_MAX_INS && c > 0)
substream = c - 1;
if (c != 0xf5)
uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */
}
else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
}
} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
}
if (status & UART_LSR_OE)
snd_printk("%s: Overrun on device at 0x%lx\n",
uart->rmidi->name, uart->base);
}
/* remember the last stream */
uart->prev_in = substream;
/* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
buffer is never filled. */
/* Check write status */
if (status & UART_LSR_THRE) {
uart->fifo_count = 0;
}
if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) {
if (uart->adaptor == SNDRV_SERIAL_MS124W_SA
|| uart->adaptor == SNDRV_SERIAL_GENERIC) {
/* Can't use FIFO, must send only when CTS is true */
status = inb(uart->base + UART_MSR);
if (uart->fifo_count == 0 && (status & UART_MSR_CTS)
......@@ -395,6 +432,11 @@ static void snd_uart16550_do_open(snd_uart16550_t * uart)
byte = UART_IER_RDI /* Enable Receiver data interrupt */
| UART_IER_MSI /* Enable Modem status interrupt */
;
} else if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
byte = UART_IER_RDI /* Enable Receiver data interrupt */
| UART_IER_MSI /* Enable Modem status interrupt */
| UART_IER_THRI /* Enable Transmitter holding register empty interupt */
;
} else {
byte = UART_IER_RDI /* Enable Receiver data interupt */
| UART_IER_THRI /* Enable Transmitter holding register empty interupt */
......@@ -467,7 +509,7 @@ static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
if (uart->filemode == SERIAL_MODE_NOT_OPENED)
snd_uart16550_do_open(uart);
uart->filemode |= SERIAL_MODE_INPUT_OPEN;
uart->midi_input = substream;
uart->midi_input[substream->number] = substream;
spin_unlock_irqrestore(&uart->open_lock, flags);
return 0;
}
......@@ -479,7 +521,7 @@ static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
spin_lock_irqsave(&uart->open_lock, flags);
uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
uart->midi_input = NULL;
uart->midi_input[substream->number] = NULL;
if (uart->filemode == SERIAL_MODE_NOT_OPENED)
snd_uart16550_do_close(uart);
spin_unlock_irqrestore(&uart->open_lock, flags);
......@@ -543,7 +585,8 @@ inline static void snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned ch
static void snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte)
{
if (uart->buff_in_count == 0 /* Buffer empty? */
&& (uart->adaptor != SNDRV_SERIAL_MS124W_SA ||
&& ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
uart->adaptor != SNDRV_SERIAL_GENERIC) ||
(uart->fifo_count == 0 /* FIFO empty? */
&& (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
......@@ -577,6 +620,7 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
unsigned char midi_byte, addr_byte;
snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
char first;
static unsigned long lasttime=0;
/* Interupts are disabled during the updating of the tx_buff,
* since it is 'bad' to have two processes updating the same
......@@ -612,13 +656,17 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
} else {
first = 0;
while (1) {
/* buffer full? */
if (uart->buff_in_count >= TX_BUFF_SIZE)
break;
if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
break;
if (first == 0 && uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS &&
uart->prev_out != substream->number) {
/* Also send F5 after 3 seconds with no data to handle device disconnect */
if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
uart->adaptor == SNDRV_SERIAL_GENERIC) &&
(uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) {
/* We will need three bytes of data here (worst case). */
if (uart->buff_in_count >= TX_BUFF_SIZE - 3)
break;
/* Roland Soundcanvas part selection */
/* If this substream of the data is different previous
substream in this uart, send the change part event */
......@@ -628,15 +676,21 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
/* data */
snd_uart16550_output_byte(uart, substream, uart->prev_out + 1);
/* If midi_byte is a data byte, send the previous status byte */
if (midi_byte < 0x80)
if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS))
snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
}
/* buffer full? */
if (uart->buff_in_count >= TX_BUFF_SIZE)
break;
/* send midi byte */
snd_uart16550_output_byte(uart, substream, midi_byte);
if (midi_byte >= 0x80 && midi_byte < 0xf0)
uart->prev_status[uart->prev_out] = midi_byte;
first = 1;
}
lasttime = jiffies;
}
spin_unlock_irqrestore(&uart->open_lock, flags);
}
......@@ -728,6 +782,8 @@ static int __init snd_uart16550_create(snd_card_t * card,
uart->speed = base / (unsigned int)uart->divisor;
uart->speed_base = base;
uart->prev_out = -1;
uart->prev_in = 0;
uart->rstatus = 0;
memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
uart->buffer_timer.function = snd_uart16550_buffer_timer;
uart->buffer_timer.data = (unsigned long)uart;
......@@ -761,12 +817,12 @@ static int __init snd_uart16550_create(snd_card_t * card,
return 0;
}
static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, snd_rawmidi_t **rmidi)
static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi)
{
snd_rawmidi_t *rrawmidi;
int err;
if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, 1, &rrawmidi)) < 0)
if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0)
return err;
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
......@@ -791,13 +847,18 @@ static int __init snd_serial_probe(int dev)
switch (snd_adaptor[dev]) {
case SNDRV_SERIAL_SOUNDCANVAS:
snd_ins[dev] = 1;
break;
case SNDRV_SERIAL_MS124T:
case SNDRV_SERIAL_MS124W_SA:
snd_outs[dev] = 1;
snd_ins[dev] = 1;
break;
case SNDRV_SERIAL_MS124W_MB:
snd_outs[dev] = 16;
snd_ins[dev] = 1;
break;
case SNDRV_SERIAL_GENERIC:
break;
default:
snd_printk("Adaptor type is out of range 0-%d (%d)\n",
......@@ -811,6 +872,12 @@ static int __init snd_serial_probe(int dev)
return -ENODEV;
}
if (snd_ins[dev] < 1 || snd_ins[dev] > SNDRV_SERIAL_MAX_INS) {
snd_printk("Count of inputs is out of range 1-%d (%d)\n",
SNDRV_SERIAL_MAX_INS, snd_ins[dev]);
return -ENODEV;
}
card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
......@@ -835,18 +902,19 @@ static int __init snd_serial_probe(int dev)
return err;
}
if ((err = snd_uart16550_rmidi(uart, 0, snd_outs[dev], &uart->rmidi)) < 0) {
if ((err = snd_uart16550_rmidi(uart, 0, snd_outs[dev], snd_ins[dev], &uart->rmidi)) < 0) {
snd_card_free(card);
return err;
}
sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d adaptor %s",
sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s",
card->shortname,
uart->base,
uart->irq,
uart->speed,
(int)uart->divisor,
snd_outs[dev],
snd_ins[dev],
adaptor_names[uart->adaptor]);
if ((err = snd_card_register(card)) < 0) {
......@@ -892,7 +960,8 @@ module_exit(alsa_card_serial_exit)
#ifndef MODULE
/* format is: snd-serial=snd_enable,snd_index,snd_id,
snd_port,snd_irq,snd_speed,snd_base,snd_outs */
snd_port,snd_irq,snd_speed,snd_base,snd_outs,
snd_ins,snd_adaptor */
static int __init alsa_card_serial_setup(char *str)
{
......@@ -908,6 +977,7 @@ static int __init alsa_card_serial_setup(char *str)
get_option(&str,&snd_speed[nr_dev]) == 2 &&
get_option(&str,&snd_base[nr_dev]) == 2 &&
get_option(&str,&snd_outs[nr_dev]) == 2 &&
get_option(&str,&snd_ins[nr_dev]) == 2 &&
get_option(&str,&snd_adaptor[nr_dev]) == 2);
nr_dev++;
return 1;
......
......@@ -88,9 +88,9 @@ CONFIG_SND_AZT2320
CONFIG_SND_CMI8330
Say 'Y' or 'M' to include support for C-Media CMI8330 based soundcards.
CONFIG_SND_DT0197H
Say 'Y' or 'M' to include support for Diamond Technologies DT-0197H
soundcards.
CONFIG_SND_DT019X
Say 'Y' or 'M' to include support for Diamond Technologies DT-019X and
Avance Logic ALS-007 soundcards.
CONFIG_SND_OPL3SA2
Say 'Y' or 'M' to include support for Yamaha OPL3SA2 or OPL3SA3 chips.
......
......@@ -29,7 +29,7 @@ dep_tristate 'Turtle Beach Maui,Tropez,Tropez+ (Wavefront)' CONFIG_SND_WAVEFRONT
dep_tristate 'Avance Logic ALS100/ALS120' CONFIG_SND_ALS100 $CONFIG_SND $CONFIG_ISAPNP
dep_tristate 'Aztech Systems AZT2320' CONFIG_SND_AZT2320 $CONFIG_SND $CONFIG_ISAPNP
dep_tristate 'C-Media CMI8330' CONFIG_SND_CMI8330 $CONFIG_SND
dep_tristate 'Diamond Technologies DT-0197H' CONFIG_SND_DT0197H $CONFIG_SND $CONFIG_ISAPNP
dep_tristate 'Diamond Technologies DT-019X, Avance Logic ALS-007' CONFIG_SND_DT019X $CONFIG_SND $CONFIG_ISAPNP
dep_tristate 'Yamaha OPL3-SA2/SA3' CONFIG_SND_OPL3SA2 $CONFIG_SND
dep_tristate 'Aztech Sound Galaxy' CONFIG_SND_SGALAXY $CONFIG_SND
......
......@@ -6,7 +6,7 @@
snd-als100-objs := als100.o
snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o
snd-dt0197h-objs := dt0197h.o
snd-dt019x-objs := dt019x.o
snd-es18xx-objs := es18xx.o
snd-opl3sa2-objs := opl3sa2.o
snd-sgalaxy-objs := sgalaxy.o
......@@ -15,7 +15,7 @@ snd-sgalaxy-objs := sgalaxy.o
obj-$(CONFIG_SND_ALS100) += snd-als100.o
obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
obj-$(CONFIG_SND_DT0197H) += snd-dt0197h.o
obj-$(CONFIG_SND_DT019X) += snd-dt019x.o
obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
......
/*
card-dt0197h.c - driver for Diamond Technologies DT-0197H based soundcards.
Copyright (C) 1999 by Massimo Piccioni <dafastidio@libero.it>
dt019x.c - driver for Diamond Technologies DT-0197H based soundcards.
Copyright (C) 1999, 2002 by Massimo Piccioni <dafastidio@libero.it>
Generalised for soundcards based on DT-0196 and ALS-007 chips
by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>: June 2002.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -36,13 +39,14 @@
#define chip_t sb_t
#define PFX "dt0197h: "
#define PFX "dt019x: "
MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
MODULE_DESCRIPTION("Diamond Technologies DT-0197H");
MODULE_DESCRIPTION("Diamond Technologies DT-019X / Avance Logic ALS-007");
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
MODULE_DEVICES("{{Diamond Technologies,DT-0197H}}");
MODULE_DEVICES("{{Diamond Technologies DT-019X},"
"{Avance Logic ALS-007}}");
static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
......@@ -55,34 +59,34 @@ static int snd_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
static int snd_dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_index, "Index value for dt0197h based soundcard.");
MODULE_PARM_DESC(snd_index, "Index value for DT-019X based soundcard.");
MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
MODULE_PARM_DESC(snd_id, "ID string for dt0197h based soundcard.");
MODULE_PARM_DESC(snd_id, "ID string for DT-019X based soundcard.");
MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_enable, "Enable dt0197h based soundcard.");
MODULE_PARM_DESC(snd_enable, "Enable DT-019X based soundcard.");
MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
MODULE_PARM_DESC(snd_port, "Port # for dt0197h driver.");
MODULE_PARM_DESC(snd_port, "Port # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_port, SNDRV_PORT12_DESC);
MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for dt0197h driver.");
MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_PORT12_DESC);
MODULE_PARM(snd_fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
MODULE_PARM_DESC(snd_fm_port, "FM port # for dt0197h driver.");
MODULE_PARM_DESC(snd_fm_port, "FM port # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_fm_port, SNDRV_PORT12_DESC);
MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_irq, "IRQ # for dt0197h driver.");
MODULE_PARM_DESC(snd_irq, "IRQ # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC);
MODULE_PARM(snd_mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for dt0197h driver.");
MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_mpu_irq, SNDRV_IRQ_DESC);
MODULE_PARM(snd_dma8, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(snd_dma8, "8-bit DMA # for dt0197h driver.");
MODULE_PARM_DESC(snd_dma8, "8-bit DMA # for dt019x driver.");
MODULE_PARM_SYNTAX(snd_dma8, SNDRV_DMA8_DESC);
struct snd_card_dt0197h {
struct snd_card_dt019x {
#ifdef __ISAPNP__
struct isapnp_dev *dev;
struct isapnp_dev *devmpu;
......@@ -90,13 +94,13 @@ struct snd_card_dt0197h {
#endif /* __ISAPNP__ */
};
static snd_card_t *snd_dt0197h_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
static snd_card_t *snd_dt019x_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
#ifdef __ISAPNP__
static struct isapnp_card *snd_dt0197h_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
static const struct isapnp_card_id *snd_dt0197h_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
static struct isapnp_card *snd_dt019x_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
static const struct isapnp_card_id *snd_dt019x_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
static struct isapnp_card_id snd_dt0197h_pnpids[] __devinitdata = {
static struct isapnp_card_id snd_dt019x_pnpids[] __devinitdata = {
/* DT197A30 */
{
ISAPNP_CARD_ID('R','W','B',0x1688),
......@@ -104,21 +108,28 @@ static struct isapnp_card_id snd_dt0197h_pnpids[] __devinitdata = {
ISAPNP_DEVICE_ID('@','X','@',0x0001),
ISAPNP_DEVICE_ID('@','H','@',0x0001) }
},
/* DT0196 / ALS-007 */
{
ISAPNP_CARD_ID('A','L','S',0x0007),
devs: { ISAPNP_DEVICE_ID('@','@','@',0x0001),
ISAPNP_DEVICE_ID('@','X','@',0x0001),
ISAPNP_DEVICE_ID('@','H','@',0x0001) }
},
{ ISAPNP_CARD_END, }
};
ISAPNP_CARD_TABLE(snd_dt0197h_pnpids);
ISAPNP_CARD_TABLE(snd_dt019x_pnpids);
#endif /* __ISAPNP__ */
#define DRIVER_NAME "snd-card-dt0197h"
#define DRIVER_NAME "snd-card-dt019x"
#ifdef __ISAPNP__
static int __init snd_card_dt0197h_isapnp(int dev, struct snd_card_dt0197h *acard)
static int __init snd_card_dt019x_isapnp(int dev, struct snd_card_dt019x *acard)
{
const struct isapnp_card_id *id = snd_dt0197h_isapnp_id[dev];
struct isapnp_card *card = snd_dt0197h_isapnp_cards[dev];
const struct isapnp_card_id *id = snd_dt019x_isapnp_id[dev];
struct isapnp_card *card = snd_dt019x_isapnp_cards[dev];
struct isapnp_dev *pdev;
acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
......@@ -138,7 +149,7 @@ static int __init snd_card_dt0197h_isapnp(int dev, struct snd_card_dt0197h *acar
}
pdev = acard->dev;
if (pdev->prepare(pdev)<0)
if (!pdev || pdev->prepare(pdev)<0)
return -EAGAIN;
if (snd_port[dev] != SNDRV_AUTO_PORT)
......@@ -150,16 +161,17 @@ static int __init snd_card_dt0197h_isapnp(int dev, struct snd_card_dt0197h *acar
isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
if (pdev->activate(pdev)<0) {
printk(KERN_ERR PFX "AUDIO isapnp configure failure\n");
printk(KERN_ERR PFX "DT-019X AUDIO isapnp configure failure\n");
return -EBUSY;
}
snd_port[dev] = pdev->resource[0].start;
snd_dma8[dev] = pdev->dma_resource[0].start;
snd_irq[dev] = pdev->irq_resource[0].start;
snd_printdd("dt019x: found audio interface: port=0x%lx, irq=0x%lx, dma=0x%lx\n",
snd_port[dev],snd_irq[dev],smd_dma8[dev]);
pdev = acard->devmpu;
if (pdev || pdev->prepare(pdev)<0)
if (!pdev || pdev->prepare(pdev)<0)
return 0;
if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
......@@ -170,33 +182,36 @@ static int __init snd_card_dt0197h_isapnp(int dev, struct snd_card_dt0197h *acar
1);
if (pdev->activate(pdev)<0) {
printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
printk(KERN_ERR PFX "DT-019X MPU-401 isapnp configure failure\n");
snd_mpu_port[dev] = -1;
acard->devmpu = NULL;
} else {
snd_mpu_port[dev] = pdev->resource[0].start;
snd_mpu_irq[dev] = pdev->irq_resource[0].start;
snd_printdd("dt019x: found MPU-401: port=0x%lx, irq=0x%lx\n",
snd_mpu_port[dev],snd_mpu_irq[dev]);
}
pdev = acard->devopl;
if (pdev == NULL || pdev->prepare(pdev)<0)
if (!pdev || pdev->prepare(pdev)<0)
return 0;
if (snd_fm_port[dev] != SNDRV_AUTO_PORT)
isapnp_resource_change(&pdev->resource[0], snd_fm_port[dev], 4);
if (pdev->activate(pdev)<0) {
printk(KERN_ERR PFX "OPL isapnp configure failure\n");
printk(KERN_ERR PFX "DT-019X OPL3 isapnp configure failure\n");
snd_fm_port[dev] = -1;
acard->devopl = NULL;
} else {
snd_fm_port[dev] = pdev->resource[0].start;
snd_printdd("dt019x: found OPL3 synth: port=0x%lx\n",snd_fm_port[dev]);
}
return 0;
}
static void snd_card_dt0197h_deactivate(struct snd_card_dt0197h *acard)
static void snd_card_dt019x_deactivate(struct snd_card_dt019x *acard)
{
if (acard->dev) {
acard->dev->deactivate(acard->dev);
......@@ -213,33 +228,33 @@ static void snd_card_dt0197h_deactivate(struct snd_card_dt0197h *acard)
}
#endif /* __ISAPNP__ */
static void snd_card_dt0197h_free(snd_card_t *card)
static void snd_card_dt019x_free(snd_card_t *card)
{
struct snd_card_dt0197h *acard = (struct snd_card_dt0197h *)card->private_data;
struct snd_card_dt019x *acard = (struct snd_card_dt019x *)card->private_data;
if (acard != NULL) {
#ifdef __ISAPNP__
snd_card_dt0197h_deactivate(acard);
snd_card_dt019x_deactivate(acard);
#endif /* __ISAPNP__ */
}
}
static int __init snd_card_dt0197h_probe(int dev)
static int __init snd_card_dt019x_probe(int dev)
{
int error;
sb_t *chip;
snd_card_t *card;
struct snd_card_dt0197h *acard;
struct snd_card_dt019x *acard;
opl3_t *opl3;
if ((card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
sizeof(struct snd_card_dt0197h))) == NULL)
sizeof(struct snd_card_dt019x))) == NULL)
return -ENOMEM;
acard = (struct snd_card_dt0197h *)card->private_data;
card->private_free = snd_card_dt0197h_free;
acard = (struct snd_card_dt019x *)card->private_data;
card->private_free = snd_card_dt019x_free;
#ifdef __ISAPNP__
if ((error = snd_card_dt0197h_isapnp(dev, acard))) {
if ((error = snd_card_dt019x_isapnp(dev, acard))) {
snd_card_free(card);
return error;
}
......@@ -254,7 +269,7 @@ static int __init snd_card_dt0197h_probe(int dev)
snd_sb16dsp_interrupt,
snd_dma8[dev],
-1,
SB_HW_AUTO,
SB_HW_DT019X,
&chip)) < 0) {
snd_card_free(card);
return error;
......@@ -271,6 +286,7 @@ static int __init snd_card_dt0197h_probe(int dev)
if (snd_mpu_port[dev] > 0) {
if (snd_mpu401_uart_new(card, 0,
/* MPU401_HW_SB,*/
MPU401_HW_MPU401,
snd_mpu_port[dev], 0,
snd_mpu_irq[dev],
......@@ -299,8 +315,8 @@ static int __init snd_card_dt0197h_probe(int dev)
}
}
strcpy(card->driver, "DT-0197H");
strcpy(card->shortname, "Diamond Tech. DT-0197H");
strcpy(card->driver, "DT-019X");
strcpy(card->shortname, "Diamond Tech. DT-019X");
sprintf(card->longname, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
card->shortname, chip->name, chip->port,
snd_irq[dev], snd_dma8[dev]);
......@@ -308,12 +324,12 @@ static int __init snd_card_dt0197h_probe(int dev)
snd_card_free(card);
return error;
}
snd_dt0197h_cards[dev] = card;
snd_dt019x_cards[dev] = card;
return 0;
}
#ifdef __ISAPNP__
static int __init snd_dt0197h_isapnp_detect(struct isapnp_card *card,
static int __init snd_dt019x_isapnp_detect(struct isapnp_card *card,
const struct isapnp_card_id *id)
{
static int dev;
......@@ -322,9 +338,9 @@ static int __init snd_dt0197h_isapnp_detect(struct isapnp_card *card,
for ( ; dev < SNDRV_CARDS; dev++) {
if (!snd_enable[dev])
continue;
snd_dt0197h_isapnp_cards[dev] = card;
snd_dt0197h_isapnp_id[dev] = id;
res = snd_card_dt0197h_probe(dev);
snd_dt019x_isapnp_cards[dev] = card;
snd_dt019x_isapnp_id[dev] = id;
res = snd_card_dt019x_probe(dev);
if (res < 0)
return res;
dev++;
......@@ -334,40 +350,40 @@ static int __init snd_dt0197h_isapnp_detect(struct isapnp_card *card,
}
#endif /* __ISAPNP__ */
static int __init alsa_card_dt0197h_init(void)
static int __init alsa_card_dt019x_init(void)
{
int cards = 0;
#ifdef __ISAPNP__
cards += isapnp_probe_cards(snd_dt0197h_pnpids, snd_dt0197h_isapnp_detect);
cards += isapnp_probe_cards(snd_dt019x_pnpids, snd_dt019x_isapnp_detect);
#else
printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
#endif
#ifdef MODULE
if (!cards)
printk(KERN_ERR "no DT-0197H based soundcards found\n");
printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
#endif
return cards ? 0 : -ENODEV;
}
static void __exit alsa_card_dt0197h_exit(void)
static void __exit alsa_card_dt019x_exit(void)
{
int dev;
for (dev = 0; dev < SNDRV_CARDS; dev++)
snd_card_free(snd_dt0197h_cards[dev]);
snd_card_free(snd_dt019x_cards[dev]);
}
module_init(alsa_card_dt0197h_init)
module_exit(alsa_card_dt0197h_exit)
module_init(alsa_card_dt019x_init)
module_exit(alsa_card_dt019x_exit)
#ifndef MODULE
/* format is: snd-dt0197h=snd_enable,snd_index,snd_id,snd_isapnp,
/* format is: snd-dt019x=snd_enable,snd_index,snd_id,snd_isapnp,
snd_port,snd_mpu_port,snd_fm_port,
snd_irq,snd_mpu_irq,snd_dma8,snd_dma8_size */
static int __init alsa_card_dt0197h_setup(char *str)
static int __init alsa_card_dt019x_setup(char *str)
{
static unsigned __initdata nr_dev = 0;
......@@ -386,6 +402,6 @@ static int __init alsa_card_dt0197h_setup(char *str)
return 1;
}
__setup("snd-dt0197h=", alsa_card_dt0197h_setup);
__setup("snd-dt019x=", alsa_card_dt019x_setup);
#endif /* ifndef MODULE */
......@@ -326,9 +326,13 @@ static char * snd_opti9xx_names[] = {
static int __init snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware)
{
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
chip->hardware = hardware;
strcpy(chip->name, snd_opti9xx_names[hardware]);
chip->mc_base_size = opti9xx_mc_size[hardware];
spin_lock_init(&chip->lock);
chip->wss_base = -1;
......@@ -600,7 +604,7 @@ static int __init snd_opti9xx_configure(opti9xx_t *chip)
#endif /* CS4231 || OPTi93X */
spin_lock_irqsave(&chip->lock, flags);
outb(irq_bits << 3 | dma_bits, chip->wss_base);
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
spin_unlock_irqrestore(&chip->lock, flags);
__skip_resources:
......@@ -972,7 +976,7 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
s = s->link_next;
} while (s != substream);
spin_lock(&chip->lock);
if (SNDRV_PCM_TRIGGER_START)
if (cmd == SNDRV_PCM_TRIGGER_START)
snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);
else
snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, 0x00);
......@@ -1178,7 +1182,6 @@ static int snd_opti93x_playback_open(snd_pcm_substream_t *substream)
chip->playback_substream = substream;
runtime->hw = snd_opti93x_playback;
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
return error;
}
......@@ -1194,7 +1197,6 @@ static int snd_opti93x_capture_open(snd_pcm_substream_t *substream)
runtime->hw = snd_opti93x_capture;
snd_pcm_set_sync(substream);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
return error;
}
......@@ -1259,6 +1261,9 @@ static int snd_opti93x_free(opti93x_t *chip)
disable_dma(chip->dma2);
free_dma(chip->dma2);
}
if (chip->irq >= 0) {
free_irq(chip->irq, chip);
}
snd_magic_kfree(chip);
return 0;
}
......@@ -1312,6 +1317,11 @@ int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
}
codec->dma2 = chip->dma2;
if (request_irq(chip->irq, snd_opti93x_interrupt, SA_INTERRUPT, DRIVER_NAME" - WSS", codec)) {
snd_opti93x_free(codec);
return -EBUSY;
}
codec->card = card;
codec->port = chip->wss_base + 4;
codec->irq = chip->irq;
......@@ -1328,7 +1338,7 @@ int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
snd_opti93x_init(codec);
/* Register device */
if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {
snd_opti93x_free(codec);
return error;
}
......@@ -1439,8 +1449,8 @@ static int snd_opti93x_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
right = (chip->image[OPTi93X_MIXOUT_RIGHT] & ~OPTi93X_MIXOUT_MIXER) | right;
change = left != chip->image[OPTi93X_MIXOUT_LEFT] ||
right != chip->image[OPTi93X_MIXOUT_RIGHT];
snd_opti93x_out(chip, OPTi93X_MIXOUT_LEFT, left);
snd_opti93x_out(chip, OPTi93X_MIXOUT_RIGHT, right);
snd_opti93x_out_image(chip, OPTi93X_MIXOUT_LEFT, left);
snd_opti93x_out_image(chip, OPTi93X_MIXOUT_RIGHT, right);
spin_unlock_irqrestore(&chip->lock, flags);
return change;
}
......@@ -1520,7 +1530,7 @@ static int snd_opti93x_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
static int snd_opti93x_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
int mask = (kcontrol->private_value >> 24) & 0xff;
uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
......@@ -1576,8 +1586,8 @@ static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
snd_opti93x_out(chip, left_reg, val1);
snd_opti93x_out(chip, right_reg, val1);
snd_opti93x_out_image(chip, left_reg, val1);
snd_opti93x_out_image(chip, right_reg, val2);
spin_unlock_irqrestore(&chip->lock, flags);
return change;
}
......@@ -1586,20 +1596,20 @@ static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
static snd_kcontrol_new_t snd_opti93x_controls[] = {
OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 0, 0, 31, 1),
OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 0),
OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 1),
OPTi93X_DOUBLE("FM Playback Switch", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 7, 7, 1, 1),
OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 0, 0, 15, 1),
OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 1, 1, 15, 1),
OPTi93X_DOUBLE("Line Playback Switch", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 0, 0, 15, 1),
OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 1, 1, 15, 1),
OPTi93X_DOUBLE("Mic Playback Switch", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 0, 0, 15, 1),
OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
OPTi93X_DOUBLE("Mic Boost", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 5, 5, 1, 1),
OPTi93X_DOUBLE("CD Playback Switch", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 7, 7, 1, 1),
OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 0, 0, 15, 1),
OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 1, 1, 15, 1),
OPTi93X_DOUBLE("Aux Playback Switch", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 0, 0, 15, 1),
OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0, 0, 15, 0),
{
iface: SNDRV_CTL_ELEM_IFACE_MIXER,
......@@ -1647,7 +1657,6 @@ int snd_opti93x_mixer(opti93x_t *chip)
static int __init snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
{
int i, err;
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
#ifndef OPTi93X
for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
......@@ -1655,7 +1664,7 @@ static int __init snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
if ((err = snd_opti9xx_init(chip, i)) < 0)
return err;
chip->mc_base_size = opti9xx_mc_size[i];
if (check_region(chip->mc_base, chip->mc_base_size))
continue;
......@@ -1671,7 +1680,7 @@ static int __init snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
if ((err = snd_opti9xx_init(chip, i)) < 0)
return err;
chip->mc_base_size = opti9xx_mc_size[i];
if (check_region(chip->mc_base, chip->mc_base_size))
continue;
......@@ -1903,7 +1912,7 @@ static void snd_card_opti9xx_free(snd_card_t *card)
static int __init snd_card_opti9xx_probe(void)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x310, -1};
static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
#ifdef OPTi93X
static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
#else
......
......@@ -18,7 +18,7 @@ snd-es968-objs := es968.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_ALS100) += snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_CMI8330) += snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_DT0197H) += snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_DT019X) += snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o
......
......@@ -220,6 +220,8 @@ static struct isapnp_card_id snd_sb16_pnpids[] __devinitdata = {
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
ISAPNP_SBAWE('C','T','L',0x0045,0x0031,0x0021),
/* Sound Blaster AWE 32 PnP */
ISAPNP_SBAWE('C','T','L',0x0046,0x0031,0x0021),
/* Sound Blaster AWE 32 PnP */
ISAPNP_SBAWE('C','T','L',0x0047,0x0031,0x0021),
/* Sound Blaster AWE 32 PnP */
ISAPNP_SBAWE('C','T','L',0x0048,0x0031,0x0021),
......
......@@ -166,6 +166,9 @@ static int snd_sbdsp_probe(sb_t * chip)
case SB_HW_ALS4000:
str = "16 (ALS-4000)";
break;
case SB_HW_DT019X:
str = "(DT019X/ALS007)";
break;
default:
return -ENODEV;
}
......
......@@ -194,6 +194,98 @@ static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return change;
}
/*
* DT-019x / ALS-007 capture/input switch
*/
static int snd_dt019x_input_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[5] = {
"CD", "Mic", "Line", "Synth", "Master"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 5;
if (uinfo->value.enumerated.item > 4)
uinfo->value.enumerated.item = 4;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
return 0;
}
static int snd_dt019x_input_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
sb_t *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned char oval;
spin_lock_irqsave(&sb->mixer_lock, flags);
oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
spin_unlock_irqrestore(&sb->mixer_lock, flags);
switch (oval & 0x07) {
case SB_DT019X_CAP_CD:
ucontrol->value.enumerated.item[0] = 0;
break;
case SB_DT019X_CAP_MIC:
ucontrol->value.enumerated.item[0] = 1;
break;
case SB_DT019X_CAP_LINE:
ucontrol->value.enumerated.item[0] = 2;
break;
case SB_DT019X_CAP_MAIN:
ucontrol->value.enumerated.item[0] = 4;
break;
/* To record the synth on these cards you must record the main. */
/* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */
/* duplicate case labels if left uncommented. */
/* case SB_DT019X_CAP_SYNTH:
* ucontrol->value.enumerated.item[0] = 3;
* break;
*/
default:
ucontrol->value.enumerated.item[0] = 4;
break;
}
return 0;
}
static int snd_dt019x_input_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
sb_t *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval, oval;
if (ucontrol->value.enumerated.item[0] > 4)
return -EINVAL;
switch (ucontrol->value.enumerated.item[0]) {
case 0:
nval = SB_DT019X_CAP_CD;
break;
case 1:
nval = SB_DT019X_CAP_MIC;
break;
case 2:
nval = SB_DT019X_CAP_LINE;
break;
case 3:
nval = SB_DT019X_CAP_SYNTH;
break;
case 4:
nval = SB_DT019X_CAP_MAIN;
break;
default:
nval = SB_DT019X_CAP_MAIN;
}
spin_lock_irqsave(&sb->mixer_lock, flags);
oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
change = nval != oval;
if (change)
snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
spin_unlock_irqrestore(&sb->mixer_lock, flags);
return change;
}
/*
* SBPRO input multiplexer
*/
......@@ -422,6 +514,44 @@ static unsigned char snd_sb16_init_values[][2] = {
{ SB_DSP4_SPEAKER_DEV, 0 },
};
#define DT019X_CONTROLS (sizeof(snd_dt019x_controls)/sizeof(snd_kcontrol_new_t))
static snd_kcontrol_new_t snd_dt019x_controls[] = {
SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4,0, 15),
SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, 15),
SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4,0, 15),
SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15),
SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7),
SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7),
SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15),
SB_SINGLE("Mic Playback Switch", SB_DT019X_OUTPUT_SW1, 0, 1),
SB_DOUBLE("CD Playback Switch", SB_DT019X_OUTPUT_SW1, SB_DT019X_OUTPUT_SW1, 2,1, 1),
SB_DOUBLE("Line Playback Switch", SB_DT019X_OUTPUT_SW1, SB_DT019X_OUTPUT_SW1, 4,3, 1),
SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2,1, 1),
SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4,3, 1),
{
iface: SNDRV_CTL_ELEM_IFACE_MIXER,
name: "Capture Source",
info: snd_dt019x_input_sw_info,
get: snd_dt019x_input_sw_get,
put: snd_dt019x_input_sw_put,
},
};
#define DT019X_INIT_VALUES (sizeof(snd_dt019x_init_values)/sizeof(unsigned char)/2)
static unsigned char snd_dt019x_init_values[][2] = {
{ SB_DT019X_MASTER_DEV, 0 },
{ SB_DT019X_PCM_DEV, 0 },
{ SB_DT019X_SYNTH_DEV, 0 },
{ SB_DT019X_CD_DEV, 0 },
{ SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */
{ SB_DT019X_LINE_DEV, 0 },
{ SB_DT019X_OUTPUT_SW1, 0 },
{ SB_DT019X_OUTPUT_SW2, 0 },
{ SB_DT019X_CAPTURE_SW, 0x06 },
};
static int snd_sbmixer_init(sb_t *chip,
snd_kcontrol_new_t *controls,
int controls_count,
......@@ -490,6 +620,12 @@ int snd_sbmixer_new(sb_t *chip)
"CTL1745")) < 0)
return err;
break;
case SB_HW_DT019X:
if ((err = snd_sbmixer_init(chip,
snd_dt019x_controls, DT019X_CONTROLS,
snd_dt019x_init_values, DT019X_INIT_VALUES,
"DT019X")) < 0)
break;
default:
strcpy(card->mixername, "???");
}
......
......@@ -165,12 +165,11 @@ typedef struct {
static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
struct pci_dev *pci)
{
int i, pages, size;
int i, size;
struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL);
if (dev->table) {
pages = snd_pcm_sgbuf_pages(dev->tbl_entries * 8);
snd_free_pci_pages(pci, pages << PAGE_SHIFT, dev->table, dev->table_addr);
snd_free_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), dev->table, dev->table_addr);
dev->table = NULL;
}
......@@ -187,8 +186,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
/* the start of each lists must be aligned to 8 bytes,
* but the kernel pages are much bigger, so we don't care
*/
pages = snd_pcm_sgbuf_pages(dev->tbl_entries * 8);
dev->table = (u32*)snd_malloc_pci_pages(pci, pages << PAGE_SHIFT, &dev->table_addr);
dev->table = (u32*)snd_malloc_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), &dev->table_addr);
if (! dev->table)
return -ENOMEM;
......@@ -214,7 +212,7 @@ static void clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
struct pci_dev *pci)
{
if (dev->table) {
snd_free_pci_pages(pci, snd_pcm_sgbuf_pages(dev->tbl_entries * 8) << PAGE_SHIFT, dev->table, dev->table_addr);
snd_free_pci_pages(pci, PAGE_ALIGN(dev->tbl_entries * 8), dev->table, dev->table_addr);
dev->table = NULL;
}
}
......
......@@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment