patch-1.3.58 linux/drivers/sound/ad1848.c
Next file: linux/drivers/sound/ad1848_mixer.h
Previous file: linux/drivers/sound/Readme.modules
Back to the patch index
Back to the overall index
- Lines: 445
- Date:
Tue Jan 9 00:37:06 1996
- Orig file:
v1.3.57/linux/drivers/sound/ad1848.c
- Orig date:
Wed Nov 8 07:11:35 1995
diff -u --recursive --new-file v1.3.57/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
@@ -44,7 +44,7 @@
#define DEB1(x)
#include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AD1848)
+#if defined(CONFIG_AD1848)
#include "ad1848_mixer.h"
@@ -72,6 +72,7 @@
#define MD_4231 2
#define MD_4231A 3
#define MD_1845 4
+#define MD_4232 5
/* Mixer parameters */
int recmask;
@@ -153,7 +154,8 @@
unsigned long flags;
int timeout = 90000;
- while (timeout > 0 && inb (devc->base) == 0x80) /*Are we initializing */
+ while (timeout > 0 &&
+ inb (devc->base) == 0x80) /*Are we initializing */
timeout--;
save_flags (flags);
@@ -436,11 +438,19 @@
{
int i;
- devc->recmask = 0;
- if (devc->mode != MD_1848)
- devc->supported_devices = MODE2_MIXER_DEVICES;
- else
- devc->supported_devices = MODE1_MIXER_DEVICES;
+ switch (devc->mode)
+ {
+ case MD_4231:
+ devc->supported_devices = MODE2_MIXER_DEVICES;
+ break;
+
+ case MD_4232:
+ devc->supported_devices = MODE3_MIXER_DEVICES;
+ break;
+
+ default:
+ devc->supported_devices = MODE1_MIXER_DEVICES;
+ }
devc->supported_rec_devices = MODE1_REC_DEVICES;
@@ -466,7 +476,8 @@
if (((cmd >> 8) & 0xff) == 'M')
{
- if (cmd & IOC_IN)
+
+ if (_IOC_DIR (cmd) & _IOC_WRITE)
switch (cmd & 0xff)
{
case SOUND_MIXER_RECSRC:
@@ -570,6 +581,7 @@
devc->intr_active = 0;
devc->opened = 1;
devc->irq_mode = 0;
+ ad1848_trigger (dev, 0);
restore_flags (flags);
/*
* Mute output until the playback really starts. This decreases clicking.
@@ -991,7 +1003,7 @@
restore_flags (flags);
devc->xfer_count = 0;
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
if (dev == timer_installed && devc->timer_running)
if ((fs & 0x01) != (old_fs & 0x01))
{
@@ -1012,11 +1024,14 @@
{
ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
unsigned long flags;
+ int timeout;
save_flags (flags);
cli ();
ad_mute (devc);
+ ad_enter_MCE (devc);
+ ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */
ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */
ad_write (devc, 15, 0); /* Clear DMA counter */
@@ -1028,11 +1043,14 @@
ad_write (devc, 31, 0); /* Clear DMA counter */
}
- ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */
+ for (timeout = 0; timeout < 1000 && !(inb (io_Status (devc)) & 0x80);
+ timeout++); /* Wait for interrupt */
+ ad_write (devc, 9, ad_read (devc, 9) & ~0x03); /* Stop DMA */
outb (0, io_Status (devc)); /* Clear interrupt status */
outb (0, io_Status (devc)); /* Clear interrupt status */
devc->irq_mode = 0;
+ ad_leave_MCE (devc);
/* DMAbuf_reset_dma (dev); */
restore_flags (flags);
@@ -1116,6 +1134,8 @@
ad1848_info *devc = &dev_info[nr_ad1848_devs];
unsigned char tmp1 = 0xff, tmp2 = 0xff;
+ DDB (printk ("ad1848_detect(%x)\n", io_base));
+
if (ad_flags)
*ad_flags = 0;
@@ -1149,6 +1169,8 @@
*
* If the I/O address is unused, it typically returns 0xff.
*/
+
+ DDB (printk ("ad1848_detect() - step A\n"));
if ((inb (devc->base) & 0x80) != 0x00) /* Not a AD1848 */
{
DDB (printk ("ad1848 detect error - step A (%02x)\n",
@@ -1162,6 +1184,7 @@
* so try to avoid using it.
*/
+ DDB (printk ("ad1848_detect() - step B\n"));
ad_write (devc, 0, 0xaa);
ad_write (devc, 1, 0x45); /* 0x55 with bit 0x10 clear */
@@ -1171,6 +1194,7 @@
return 0;
}
+ DDB (printk ("ad1848_detect() - step C\n"));
ad_write (devc, 0, 0x45);
ad_write (devc, 1, 0xaa);
@@ -1185,6 +1209,7 @@
* try to change them.
*/
+ DDB (printk ("ad1848_detect() - step D\n"));
tmp = ad_read (devc, 12);
ad_write (devc, 12, (~tmp) & 0x0f);
@@ -1206,6 +1231,7 @@
* with CS4231.
*/
+ DDB (printk ("ad1848_detect() - step F\n"));
ad_write (devc, 12, 0); /* Mode2=disabled */
for (i = 0; i < 16; i++)
@@ -1220,6 +1246,7 @@
* The bit 0x80 is always 1 in CS4248 and CS4231.
*/
+ DDB (printk ("ad1848_detect() - step G\n"));
ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */
tmp1 = ad_read (devc, 12);
@@ -1238,6 +1265,7 @@
*
* Verify that setting I0 doesn't change I16.
*/
+ DDB (printk ("ad1848_detect() - step H\n"));
ad_write (devc, 16, 0); /* Set I16 to known value */
ad_write (devc, 0, 0x45);
@@ -1255,6 +1283,7 @@
* Verify that some bits of I25 are read only.
*/
+ DDB (printk ("ad1848_detect() - step I\n"));
tmp1 = ad_read (devc, 25); /* Original bits */
ad_write (devc, 25, ~tmp1); /* Invert all bits */
if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7))
@@ -1266,10 +1295,7 @@
*/
devc->chip_name = "CS4231";
-#ifdef MOZART_PORT
- if (devc->base != MOZART_PORT + 4)
-#endif
- devc->mode = MD_4231;
+ devc->mode = MD_4231;
/*
* It could be an AD1845 or CS4231A as well.
@@ -1277,6 +1303,7 @@
* while the CS4231A reports different.
*/
+ DDB (printk ("ad1848_detect() - step I\n"));
id = ad_read (devc, 25) & 0xe7;
switch (id)
@@ -1289,12 +1316,12 @@
case 0xa2:
devc->chip_name = "CS4232";
- devc->mode = MD_4231A;
+ devc->mode = MD_4232;
break;
case 0xb2:
devc->chip_name = "CS4232A";
- devc->mode = MD_4231A;
+ devc->mode = MD_4232;
break;
case 0x80:
@@ -1326,15 +1353,18 @@
}
ad_write (devc, 25, tmp1); /* Restore bits */
+ DDB (printk ("ad1848_detect() - step K\n"));
}
}
+ DDB (printk ("ad1848_detect() - step L\n"));
if (ad_flags)
{
if (devc->mode != MD_1848)
*ad_flags |= AD_F_CS4231;
}
+ DDB (printk ("ad1848_detect() - Detected OK\n"));
return 1;
}
@@ -1360,6 +1390,7 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int i, my_dev;
+
ad1848_info *devc = &dev_info[nr_ad1848_devs];
if (!ad1848_detect (io_base, NULL, osp))
@@ -1402,14 +1433,17 @@
for (i = 16; i < 32; i++)
ad_write (devc, i, init_values[i]);
- if (devc->mode == MD_4231A)
+ if (devc->mode == MD_4231A || devc->mode == MD_4232)
ad_write (devc, 9, init_values[9] | 0x18); /* Enable full calibration */
if (devc->mode == MD_1845)
ad_write (devc, 27, init_values[27] | 0x08); /* Alternate freq select enabled */
}
else
- ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */
+ {
+ ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX;
+ ad_write (devc, 9, ad_read (devc, 9) | 0x04); /* Single DMA mode */
+ }
outb (0, io_Status (devc)); /* Clear pending interrupts */
@@ -1420,7 +1454,8 @@
sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,
"Generic audio codec (%s)", devc->chip_name);
- printk (" <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);
+ conf_printf2 (ad1848_pcm_operations[nr_ad1848_devs].name,
+ devc->base, devc->irq, dma_playback, dma_capture);
if (num_audiodevs < MAX_AUDIO_DEV)
{
@@ -1473,7 +1508,7 @@
audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];
nr_ad1848_devs++;
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
if (devc->mode != MD_1848 && devc->irq_ok)
ad1848_tmr_install (my_dev);
#endif
@@ -1546,6 +1581,7 @@
unsigned char status;
ad1848_info *devc;
int dev;
+ int alt_stat = 0xff;
if (irq < 0 || irq > 15)
{
@@ -1579,54 +1615,78 @@
if (status & 0x01)
{
- int alt_stat;
if (devc->mode != MD_1848)
- {
- alt_stat = ad_read (devc, 24);
- if (alt_stat & 0x40) /* Timer interrupt */
- {
- devc->timer_ticks++;
-#ifndef EXCLUDE_SEQUENCER
- if (timer_installed == dev && devc->timer_running)
- sound_timer_interrupt ();
-#endif
- }
- }
- else
- alt_stat = 0xff;
+ alt_stat = ad_read (devc, 24);
if (devc->opened && devc->irq_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
{
DMAbuf_inputintr (dev);
}
- if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10)
+ if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT &&
+ alt_stat & 0x10)
{
DMAbuf_outputintr (dev, 1);
}
- }
- outb (0, io_Status (devc)); /* Clear interrupt status */
+ if (devc->mode != MD_1848 && alt_stat & 0x40) /* Timer interrupt */
+ {
+ devc->timer_ticks++;
+#ifdef CONFIG_SEQUENCER
+ if (timer_installed == dev && devc->timer_running)
+ sound_timer_interrupt ();
+#endif
+ }
+ }
+ if (devc->mode != MD_1848)
+ ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat); /* Selective ack */
+ else
+ outb (0, io_Status (devc)); /* Clear interrupt status */
}
/*
* Some extra code for the MS Sound System
*/
+void
+check_opl3 (int base, struct address_info *hw_config)
+{
+
+ if (check_region (base, 4))
+ {
+ printk ("\n\nopl3.c: I/O port %x already in use\n\n", base);
+ return;
+ }
+
+ if (!opl3_detect (base, hw_config->osp))
+ return;
+
+ opl3_init (0, base, hw_config->osp);
+ request_region (base, 4, "OPL3/OPL2");
+}
+
int
probe_ms_sound (struct address_info *hw_config)
{
unsigned char tmp;
+ DDB (printk ("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
+
if (check_region (hw_config->io_base, 8))
{
printk ("MSS: I/O port conflict\n");
return 0;
}
-#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS)
+ if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */
+ {
+ /* check_opl3(0x388, hw_config); */
+ return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
+ }
+
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MSS)
/*
* Initialize Audio Excel DSP 16 to MSS: before any operation
* we must enable MSS I/O ports.
@@ -1635,9 +1695,6 @@
InitAEDSP16_MSS (hw_config);
#endif
- if (hw_config->card_subtype == 1) /* Has IRQ/DMA registers */
- return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
-
/*
* Check if the IO port returns valid signature. The original MS Sound
* system returns 0x04 while some cards (AudioTriX Pro for example)
@@ -1645,7 +1702,10 @@
*/
if ((tmp = inb (hw_config->io_base + 3)) == 0xff) /* Bus float */
- return 0;
+ {
+ DDB (printk ("I/O address is inactive (%x)\n", tmp));
+ return 0;
+ }
if ((tmp & 0x3f) != 0x04 &&
(tmp & 0x3f) != 0x0f &&
(tmp & 0x3f) != 0x00)
@@ -1700,11 +1760,22 @@
1, 2, 0, 3
};
- int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+ int config_port = hw_config->io_base + 0;
+ int version_port = hw_config->io_base + 3;
if (!ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp))
return mem_start;
+ if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */
+ {
+ ad1848_init ("MS Sound System", hw_config->io_base + 4,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma2, 0, hw_config->osp);
+ request_region (hw_config->io_base, 4, "WSS config");
+ return mem_start;
+ }
+
/*
* Set the IRQ and DMA addresses.
*/
@@ -1768,7 +1839,7 @@
release_region (hw_config->io_base, 4);
}
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
/*
* Timer stuff (for /dev/music).
*/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this