summaryrefslogtreecommitdiffstats
path: root/drivers/sound/cs4232.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sound/cs4232.c')
-rw-r--r--drivers/sound/cs4232.c392
1 files changed, 167 insertions, 225 deletions
diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c
index eb2a5eb05..c8732dfe4 100644
--- a/drivers/sound/cs4232.c
+++ b/drivers/sound/cs4232.c
@@ -31,23 +31,22 @@
#define KEY_PORT 0x279 /* Same as LPT1 status port */
#define CSN_NUM 0x99 /* Just a random number */
-static void
-CS_OUT(unsigned char a)
+static void CS_OUT(unsigned char a)
{
- outb((a), KEY_PORT);
+ outb(a, KEY_PORT);
}
+
#define CS_OUT2(a, b) {CS_OUT(a);CS_OUT(b);}
#define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
-static int mpu_base = 0, mpu_irq = 0;
-static int mpu_detected = 0;
+static int mpu_base = 0, mpu_irq = 0;
+static int mpu_detected = 0;
-int
-probe_cs4232_mpu(struct address_info *hw_config)
+int probe_cs4232_mpu(struct address_info *hw_config)
{
-/*
- * Just write down the config values.
- */
+ /*
+ * Just write down the config values.
+ */
mpu_base = hw_config->io_base;
mpu_irq = hw_config->irq;
@@ -55,9 +54,9 @@ probe_cs4232_mpu(struct address_info *hw_config)
return 1;
}
-void
-attach_cs4232_mpu(struct address_info *hw_config)
+void attach_cs4232_mpu(struct address_info *hw_config)
{
+ /* Nothing needs doing */
}
static unsigned char crystal_key[] = /* A 32 byte magic key sequence */
@@ -68,190 +67,126 @@ static unsigned char crystal_key[] = /* A 32 byte magic key sequence */
0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
};
-int
-probe_cs4232(struct address_info *hw_config)
+static void sleep(unsigned howlong)
{
- int i, n;
- int base = hw_config->io_base, irq = hw_config->irq;
- int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + howlong;
+ schedule();
+ current->timeout = 0;
+}
- static struct wait_queue *cs_sleeper = NULL;
- static volatile struct snd_wait cs_sleep_flag =
- {0};
+int probe_cs4232(struct address_info *hw_config)
+{
+ int i, n;
+ int base = hw_config->io_base, irq = hw_config->irq;
+ int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-
-/*
- * Verify that the I/O port range is free.
- */
+ /*
+ * Verify that the I/O port range is free.
+ */
if (check_region(base, 4))
- {
- printk("cs4232.c: I/O port 0x%03x not free\n", base);
- return 0;
- }
+ {
+ printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
+ return 0;
+ }
if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
return 1; /* The card is already active */
-/*
- * This version of the driver doesn't use the PnP method when configuring
- * the card but a simplified method defined by Crystal. This means that
- * just one CS4232 compatible device can exist on the system. Also this
- * method conflicts with possible PnP support in the OS. For this reason
- * driver is just a temporary kludge.
- */
-
-/*
- * Repeat initialization few times since it doesn't always succeed in
- * first time.
- */
-
- for (n = 0; n < 4; n++)
- {
- cs_sleep_flag.opts = WK_NONE;
-/*
- * Wake up the card by sending a 32 byte Crystal key to the key port.
- */
- for (i = 0; i < 32; i++)
- CS_OUT(crystal_key[i]);
-
-
- {
- unsigned long tlimit;
-
- if (HZ / 10)
- current->timeout = tlimit = jiffies + (HZ / 10);
- else
- tlimit = (unsigned long) -1;
- cs_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on(&cs_sleeper);
- if (!(cs_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- cs_sleep_flag.opts |= WK_TIMEOUT;
- }
- cs_sleep_flag.opts &= ~WK_SLEEP;
- }; /* Delay */
+ /*
+ * This version of the driver doesn't use the PnP method when configuring
+ * the card but a simplified method defined by Crystal. This means that
+ * just one CS4232 compatible device can exist on the system. Also this
+ * method conflicts with possible PnP support in the OS. For this reason
+ * driver is just a temporary kludge.
+ */
-/*
- * Now set the CSN (Card Select Number).
- */
+ /*
+ * Repeat initialization few times since it doesn't always succeed in
+ * first time.
+ */
- CS_OUT2(0x06, CSN_NUM);
+ for (n = 0; n < 4; n++) {
+
+ /*
+ * Wake up the card by sending a 32 byte Crystal key to the key port.
+ */
+
+ for (i = 0; i < 32; i++)
+ CS_OUT(crystal_key[i]);
+ sleep(HZ / 10);
-/*
- * Then set some config bytes. First logical device 0
- */
+ /*
+ * Now set the CSN (Card Select Number).
+ */
- CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */
- CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSS base */
+ CS_OUT2(0x06, CSN_NUM);
- if (check_region(0x388, 4)) /* Not free */
- CS_OUT3(0x48, 0x00, 0x00) /* FM base off */
- else
- CS_OUT3(0x48, 0x03, 0x88); /* FM base 0x388 */
+ /*
+ * Then set some config bytes. First logical device 0
+ */
- CS_OUT3(0x42, 0x00, 0x00); /* SB base off */
- CS_OUT2(0x22, irq); /* SB+WSS IRQ */
- CS_OUT2(0x2a, dma1); /* SB+WSS DMA */
+ CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */
+ CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSS base */
- if (dma2 != -1)
- CS_OUT2(0x25, dma2) /* WSS DMA2 */
- else
- CS_OUT2(0x25, 4); /* No WSS DMA2 */
+ if (check_region(0x388, 4)) /* Not free */
+ CS_OUT3(0x48, 0x00, 0x00) /* FM base off */
+ else
+ CS_OUT3(0x48, 0x03, 0x88); /* FM base 0x388 */
- CS_OUT2(0x33, 0x01); /* Activate logical dev 0 */
+ CS_OUT3(0x42, 0x00, 0x00); /* SB base off */
+ CS_OUT2(0x22, irq); /* SB+WSS IRQ */
+ CS_OUT2(0x2a, dma1); /* SB+WSS DMA */
+ if (dma2 != -1)
+ CS_OUT2(0x25, dma2) /* WSS DMA2 */
+ else
+ CS_OUT2(0x25, 4); /* No WSS DMA2 */
- {
- unsigned long tlimit;
+ CS_OUT2(0x33, 0x01); /* Activate logical dev 0 */
- if (HZ / 10)
- current->timeout = tlimit = jiffies + (HZ / 10);
- else
- tlimit = (unsigned long) -1;
- cs_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on(&cs_sleeper);
- if (!(cs_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- cs_sleep_flag.opts |= WK_TIMEOUT;
- }
- cs_sleep_flag.opts &= ~WK_SLEEP;
- }; /* Delay */
+ sleep(HZ / 10);
-/*
- * Initialize logical device 3 (MPU)
- */
+ /*
+ * Initialize logical device 3 (MPU)
+ */
#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
- if (mpu_base != 0 && mpu_irq != 0)
- {
- CS_OUT2(0x15, 0x03); /* Select logical device 3 (MPU) */
- CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPU base */
- CS_OUT2(0x22, mpu_irq); /* MPU IRQ */
- CS_OUT2(0x33, 0x01); /* Activate logical dev 3 */
- }
+ if (mpu_base != 0 && mpu_irq != 0)
+ {
+ CS_OUT2(0x15, 0x03); /* Select logical device 3 (MPU) */
+ CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPU base */
+ CS_OUT2(0x22, mpu_irq); /* MPU IRQ */
+ CS_OUT2(0x33, 0x01); /* Activate logical dev 3 */
+ }
#endif
-/*
- * Finally activate the chip
- */
- CS_OUT(0x79);
-
-
- {
- unsigned long tlimit;
-
- if (HZ / 5)
- current->timeout = tlimit = jiffies + (HZ / 5);
- else
- tlimit = (unsigned long) -1;
- cs_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on(&cs_sleeper);
- if (!(cs_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- cs_sleep_flag.opts |= WK_TIMEOUT;
- }
- cs_sleep_flag.opts &= ~WK_SLEEP;
- }; /* Delay */
-
-/*
- * Then try to detect the codec part of the chip
- */
-
- if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
- return 1;
+ /*
+ * Finally activate the chip
+ */
+
+ CS_OUT(0x79);
+ sleep(HZ / 5);
- {
- unsigned long tlimit;
-
- if (HZ)
- current->timeout = tlimit = jiffies + (HZ);
- else
- tlimit = (unsigned long) -1;
- cs_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on(&cs_sleeper);
- if (!(cs_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- cs_sleep_flag.opts |= WK_TIMEOUT;
- }
- cs_sleep_flag.opts &= ~WK_SLEEP;
- }; /* Longer delay */
- }
+ /*
+ * Then try to detect the codec part of the chip
+ */
+ if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
+ return 1;
+
+ sleep(HZ);
+ }
return 0;
}
-void
-attach_cs4232(struct address_info *hw_config)
+void attach_cs4232(struct address_info *hw_config)
{
- int base = hw_config->io_base, irq = hw_config->irq;
- int dma1 = hw_config->dma, dma2 = hw_config->dma2;
- int old_num_mixers = num_mixers;
+ int base = hw_config->io_base, irq = hw_config->irq;
+ int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+ int old_num_mixers = num_mixers;
if (dma2 == -1)
dma2 = dma1;
@@ -264,45 +199,47 @@ attach_cs4232(struct address_info *hw_config)
hw_config->osp);
if (num_mixers > old_num_mixers)
- { /* Assume the mixer map is as suggested in the CS4232 databook */
- AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
- AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
- AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* FM synth */
- }
+ {
+ /* Assume the mixer map is as suggested in the CS4232 databook */
+ AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
+ AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+ AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* FM synth */
+ }
#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
if (mpu_base != 0 && mpu_irq != 0)
- {
- static struct address_info hw_config2 =
- {0}; /* Ensure it's initialized */
-
- hw_config2.io_base = mpu_base;
- hw_config2.irq = mpu_irq;
- hw_config2.dma = -1;
- hw_config2.dma2 = -1;
- hw_config2.always_detect = 0;
- hw_config2.name = NULL;
- hw_config2.driver_use_1 = 0;
- hw_config2.driver_use_2 = 0;
- hw_config2.card_subtype = 0;
-
- if (probe_uart401(&hw_config2))
- {
- mpu_detected = 1;
- attach_uart401(&hw_config2);
- } else
- {
- mpu_base = mpu_irq = 0;
- }
- hw_config->slots[1] = hw_config2.slots[1];
- }
+ {
+ static struct address_info hw_config2 = {
+ 0
+ }; /* Ensure it's initialized */
+
+ hw_config2.io_base = mpu_base;
+ hw_config2.irq = mpu_irq;
+ hw_config2.dma = -1;
+ hw_config2.dma2 = -1;
+ hw_config2.always_detect = 0;
+ hw_config2.name = NULL;
+ hw_config2.driver_use_1 = 0;
+ hw_config2.driver_use_2 = 0;
+ hw_config2.card_subtype = 0;
+
+ if (probe_uart401(&hw_config2))
+ {
+ mpu_detected = 1;
+ attach_uart401(&hw_config2);
+ }
+ else
+ {
+ mpu_base = mpu_irq = 0;
+ }
+ hw_config->slots[1] = hw_config2.slots[1];
+ }
#endif
}
-void
-unload_cs4232(struct address_info *hw_config)
+void unload_cs4232(struct address_info *hw_config)
{
- int base = hw_config->io_base, irq = hw_config->irq;
- int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+ int base = hw_config->io_base, irq = hw_config->irq;
+ int dma1 = hw_config->dma, dma2 = hw_config->dma2;
if (dma2 == -1)
dma2 = dma1;
@@ -315,28 +252,29 @@ unload_cs4232(struct address_info *hw_config)
sound_unload_audiodev(hw_config->slots[0]);
#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
- {
- static struct address_info hw_config2 =
- {0}; /* Ensure it's initialized */
-
- hw_config2.io_base = mpu_base;
- hw_config2.irq = mpu_irq;
- hw_config2.dma = -1;
- hw_config2.dma2 = -1;
- hw_config2.always_detect = 0;
- hw_config2.name = NULL;
- hw_config2.driver_use_1 = 0;
- hw_config2.driver_use_2 = 0;
- hw_config2.card_subtype = 0;
- hw_config2.slots[1] = hw_config->slots[1];
-
- unload_uart401(&hw_config2);
- }
+ {
+ static struct address_info hw_config2 =
+ {
+ 0
+ }; /* Ensure it's initialized */
+
+ hw_config2.io_base = mpu_base;
+ hw_config2.irq = mpu_irq;
+ hw_config2.dma = -1;
+ hw_config2.dma2 = -1;
+ hw_config2.always_detect = 0;
+ hw_config2.name = NULL;
+ hw_config2.driver_use_1 = 0;
+ hw_config2.driver_use_2 = 0;
+ hw_config2.card_subtype = 0;
+ hw_config2.slots[1] = hw_config->slots[1];
+
+ unload_uart401(&hw_config2);
+ }
#endif
}
-void
-unload_cs4232_mpu(struct address_info *hw_config)
+void unload_cs4232_mpu(struct address_info *hw_config)
{
/* Not required. Handled by cs4232_unload */
}
@@ -348,21 +286,26 @@ int irq = -1;
int dma = -1;
int dma2 = -1;
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+
struct address_info cfg;
/*
- * Install a CS4232 based card. Need to have ad1848 and mpu401
- * loaded ready.
+ * Install a CS4232 based card. Need to have ad1848 and mpu401
+ * loaded ready.
*/
int
init_module(void)
{
if (io == -1 || irq == -1 || dma == -1 || dma2 == -1)
- {
- printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
- return -EINVAL;
- }
+ {
+ printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
+ return -EINVAL;
+ }
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
@@ -379,13 +322,12 @@ init_module(void)
return 0;
}
-void
-cleanup_module(void)
+void cleanup_module(void)
{
unload_cs4232_mpu(&cfg);
unload_cs4232(&cfg);
SOUND_LOCK_END;
}
-#endif
#endif
+#endif