diff options
Diffstat (limited to 'drivers/sound/ad1848.c')
-rw-r--r-- | drivers/sound/ad1848.c | 2155 |
1 files changed, 1083 insertions, 1072 deletions
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index fc4de23e6..6fdec35ec 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -21,6 +21,9 @@ * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ +/* + * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + */ #include <linux/config.h> #include <linux/module.h> @@ -37,24 +40,24 @@ #include "ad1848_mixer.h" typedef struct - { - int base; - int irq; - int dma1, dma2; - int dual_dma; /* 1, when two DMA channels allocated */ - unsigned char MCE_bit; - unsigned char saved_regs[16]; - int debug_flag; - - int audio_flags; - int record_dev, playback_dev; - - int xfer_count; - int audio_mode; - int open_mode; - int intr_active; - char *chip_name, *name; - int model; +{ + int base; + int irq; + int dma1, dma2; + int dual_dma; /* 1, when two DMA channels allocated */ + unsigned char MCE_bit; + unsigned char saved_regs[16]; + int debug_flag; + + int audio_flags; + int record_dev, playback_dev; + + int xfer_count; + int audio_mode; + int open_mode; + int intr_active; + char *chip_name, *name; + int model; #define MD_1848 1 #define MD_4231 2 #define MD_4231A 3 @@ -63,44 +66,47 @@ typedef struct #define MD_C930 6 #define MD_IWAVE 7 - /* Mixer parameters */ - int recmask; - int supported_devices, orig_devices; - int supported_rec_devices, orig_rec_devices; - int *levels; - short mixer_reroute[32]; - int dev_no; - volatile unsigned long timer_ticks; - int timer_running; - int irq_ok; - mixer_ents *mix_devices; - int mixer_output_port; - int c930_password_port; - } -ad1848_info; + /* Mixer parameters */ + int recmask; + int supported_devices, orig_devices; + int supported_rec_devices, orig_rec_devices; + int *levels; + short mixer_reroute[32]; + int dev_no; + volatile unsigned long timer_ticks; + int timer_running; + int irq_ok; + mixer_ents *mix_devices; + int mixer_output_port; + int c930_password_port; +} ad1848_info; typedef struct ad1848_port_info - { - int open_mode; - int speed; - unsigned char speed_bits; - int channels; - int audio_format; - unsigned char format_bits; - } +{ + int open_mode; + int speed; + unsigned char speed_bits; + int channels; + int audio_format; + unsigned char format_bits; +} ad1848_port_info; -static int nr_ad1848_devs = 0; -static volatile char irq2dev[17] = -{-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int nr_ad1848_devs = 0; +int deskpro_xl = 0; + +static volatile char irq2dev[17] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS) -static int timer_installed = -1; + +static int timer_installed = -1; #endif -static int ad_format_mask[8 /*devc->model */ ] = +static int ad_format_mask[8 /*devc->model */ ] = { 0, AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, @@ -121,7 +127,6 @@ static ad1848_info adev_info[MAX_AUDIO_DEV]; static int ad1848_open(int dev, int mode); static void ad1848_close(int dev); -static int ad1848_ioctl(int dev, unsigned int cmd, caddr_t arg); static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag); static void ad1848_start_input(int dev, unsigned long buf, int count, int intrflag); static int ad1848_prepare_for_output(int dev, int bsize, int bcount); @@ -132,13 +137,12 @@ static void ad1848_halt_output(int dev); static void ad1848_trigger(int dev, int bits); #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE) -static int ad1848_tmr_install(int dev); -static void ad1848_tmr_reprogram(int dev); +static int ad1848_tmr_install(int dev); +static void ad1848_tmr_reprogram(int dev); #endif -static int -ad_read(ad1848_info * devc, int reg) +static int ad_read(ad1848_info * devc, int reg) { unsigned long flags; int x; @@ -157,8 +161,7 @@ ad_read(ad1848_info * devc, int reg) return x; } -static void -ad_write(ad1848_info * devc, int reg, int data) +static void ad_write(ad1848_info * devc, int reg, int data) { unsigned long flags; int timeout = 900000; @@ -175,23 +178,22 @@ ad_write(ad1848_info * devc, int reg, int data) restore_flags(flags); } -static void -wait_for_calibration(ad1848_info * devc) +static void wait_for_calibration(ad1848_info * devc) { int timeout = 0; /* - * Wait until the auto calibration process has finished. - * - * 1) Wait until the chip becomes ready (reads don't return 0x80). - * 2) Wait until the ACI bit of I11 gets on and then off. + * Wait until the auto calibration process has finished. + * + * 1) Wait until the chip becomes ready (reads don't return 0x80). + * 2) Wait until the ACI bit of I11 gets on and then off. */ timeout = 100000; while (timeout > 0 && inb(devc->base) == 0x80) timeout--; if (inb(devc->base) & 0x80) - printk("ad1848: Auto calibration timed out(1).\n"); + printk(KERN_WARNING "ad1848: Auto calibration timed out(1).\n"); timeout = 100; while (timeout > 0 && !(ad_read(devc, 11) & 0x20)) @@ -204,36 +206,34 @@ wait_for_calibration(ad1848_info * devc) timeout--; if (ad_read(devc, 11) & 0x20) if (devc->model != MD_1845) - printk("ad1848: Auto calibration timed out(3).\n"); + printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n"); } -static void -ad_mute(ad1848_info * devc) +static void ad_mute(ad1848_info * devc) { - int i; - unsigned char prev; + int i; + unsigned char prev; /* - * Save old register settings and mute output channels + * Save old register settings and mute output channels */ + for (i = 6; i < 8; i++) - { - prev = devc->saved_regs[i] = ad_read(devc, i); - } + { + prev = devc->saved_regs[i] = ad_read(devc, i); + } } -static void -ad_unmute(ad1848_info * devc) +static void ad_unmute(ad1848_info * devc) { } -static void -ad_enter_MCE(ad1848_info * devc) +static void ad_enter_MCE(ad1848_info * devc) { - unsigned long flags; - int timeout = 1000; - unsigned short prev; + unsigned long flags; + int timeout = 1000; + unsigned short prev; while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ timeout--; @@ -244,20 +244,19 @@ ad_enter_MCE(ad1848_info * devc) devc->MCE_bit = 0x40; prev = inb(io_Index_Addr(devc)); if (prev & 0x40) - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } outb((devc->MCE_bit), io_Index_Addr(devc)); restore_flags(flags); } -static void -ad_leave_MCE(ad1848_info * devc) +static void ad_leave_MCE(ad1848_info * devc) { - unsigned long flags; - unsigned char prev, acal; - int timeout = 1000; + unsigned long flags; + unsigned char prev, acal; + int timeout = 1000; while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ timeout--; @@ -272,18 +271,17 @@ ad_leave_MCE(ad1848_info * devc) outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */ if ((prev & 0x40) == 0) /* Not in MCE mode */ - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */ if (acal & 0x08) /* Auto calibration is enabled */ wait_for_calibration(devc); restore_flags(flags); } -static int -ad1848_set_recmask(ad1848_info * devc, int mask) +static int ad1848_set_recmask(ad1848_info * devc, int mask) { unsigned char recdev; int i, n; @@ -292,12 +290,17 @@ ad1848_set_recmask(ad1848_info * devc, int mask) /* Rename the mixer bits if necessary */ for (i = 0; i < 32; i++) + { if (devc->mixer_reroute[i] != i) + { if (mask & (1 << i)) - { - mask &= ~(1 << i); - mask |= (1 << devc->mixer_reroute[i]); - } + { + mask &= ~(1 << i); + mask |= (1 << devc->mixer_reroute[i]); + } + } + } + n = 0; for (i = 0; i < 32; i++) /* Count selected device bits */ if (mask & (1 << i)) @@ -306,41 +309,41 @@ ad1848_set_recmask(ad1848_info * devc, int mask) if (n == 0) mask = SOUND_MASK_MIC; else if (n != 1) /* Too many devices selected */ - { + { mask &= ~devc->recmask; /* Filter out active settings */ - n = 0; - for (i = 0; i < 32; i++) /* Count selected device bits */ - if (mask & (1 << i)) - n++; + n = 0; + for (i = 0; i < 32; i++) /* Count selected device bits */ + if (mask & (1 << i)) + n++; - if (n != 1) - mask = SOUND_MASK_MIC; - } + if (n != 1) + mask = SOUND_MASK_MIC; + } switch (mask) - { - case SOUND_MASK_MIC: - recdev = 2; - break; - - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - recdev = 0; - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - recdev = 1; - break; - - case SOUND_MASK_IMIX: - recdev = 3; - break; - - default: - mask = SOUND_MASK_MIC; - recdev = 2; - } + { + case SOUND_MASK_MIC: + recdev = 2; + break; + + case SOUND_MASK_LINE: + case SOUND_MASK_LINE3: + recdev = 0; + break; + + case SOUND_MASK_CD: + case SOUND_MASK_LINE1: + recdev = 1; + break; + + case SOUND_MASK_IMIX: + recdev = 3; + break; + + default: + mask = SOUND_MASK_MIC; + recdev = 2; + } recdev <<= 6; ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev); @@ -348,24 +351,27 @@ ad1848_set_recmask(ad1848_info * devc, int mask) /* Rename the mixer bits back if necessary */ for (i = 0; i < 32; i++) + { if (devc->mixer_reroute[i] != i) + { if (mask & (1 << devc->mixer_reroute[i])) - { - mask &= ~(1 << devc->mixer_reroute[i]); - mask |= (1 << i); - } + { + mask &= ~(1 << devc->mixer_reroute[i]); + mask |= (1 << i); + } + } + } devc->recmask = mask; return mask; } -static void -change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval) +static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval) { - unsigned char mask; - int shift; - int mute; - int mutemask; - int set_mute_bit; + unsigned char mask; + int shift; + int mute; + int mutemask; + int set_mute_bit; set_mute_bit = (newval == 0); @@ -376,22 +382,22 @@ change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int new shift = devc->mix_devices[dev][chn].bitpos; if (devc->mix_devices[dev][chn].mutepos == 8) - { /* if there is no mute bit */ - mute = 0; /* No mute bit; do nothing special */ - mutemask = ~0; /* No mute bit; do nothing special */ - } else - { - mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos); - mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos); - } + { /* if there is no mute bit */ + mute = 0; /* No mute bit; do nothing special */ + mutemask = ~0; /* No mute bit; do nothing special */ + } + else + { + mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos); + mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos); + } newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ *regval &= (~(mask << shift)) & (mutemask); /* Clear bits */ *regval |= ((newval & mask) << shift) | mute; /* Set new value */ } -static int -ad1848_mixer_get(ad1848_info * devc, int dev) +static int ad1848_mixer_get(ad1848_info * devc, int dev) { if (!((1 << dev) & devc->supported_devices)) return -EINVAL; @@ -401,15 +407,14 @@ ad1848_mixer_get(ad1848_info * devc, int dev) return devc->levels[dev]; } -static int -ad1848_mixer_set(ad1848_info * devc, int dev, int value) +static int ad1848_mixer_set(ad1848_info * devc, int dev, int value) { - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int retvol; + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int retvol; - int regoffs; - unsigned char val; + int regoffs; + unsigned char val; if (dev > 31) return -EINVAL; @@ -443,7 +448,7 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value) devc->levels[dev] = retvol; /* - * Set the left channel + * Set the left channel */ regoffs = devc->mix_devices[dev][LEFT_CHN].regno; @@ -453,7 +458,7 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value) devc->saved_regs[regoffs] = val; /* - * Set the right channel + * Set the right channel */ if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0) @@ -468,11 +473,10 @@ ad1848_mixer_set(ad1848_info * devc, int dev, int value) return retvol; } -static void -ad1848_mixer_reset(ad1848_info * devc) +static void ad1848_mixer_reset(ad1848_info * devc) { - int i; - char name[32]; + int i; + char name[32]; devc->mix_devices = &(ad1848_mix_devices[0]); @@ -482,30 +486,30 @@ ad1848_mixer_reset(ad1848_info * devc) devc->mixer_reroute[i] = i; switch (devc->model) - { - case MD_4231: - case MD_4231A: - case MD_1845: - devc->supported_devices = MODE2_MIXER_DEVICES; - break; - - case MD_C930: - devc->supported_devices = C930_MIXER_DEVICES; - devc->mix_devices = &(c930_mix_devices[0]); - break; - - case MD_IWAVE: - devc->supported_devices = MODE3_MIXER_DEVICES; - devc->mix_devices = &(iwave_mix_devices[0]); - break; - - case MD_4232: - devc->supported_devices = MODE3_MIXER_DEVICES; - break; - - default: - devc->supported_devices = MODE1_MIXER_DEVICES; - } + { + case MD_4231: + case MD_4231A: + case MD_1845: + devc->supported_devices = MODE2_MIXER_DEVICES; + break; + + case MD_C930: + devc->supported_devices = C930_MIXER_DEVICES; + devc->mix_devices = &(c930_mix_devices[0]); + break; + + case MD_IWAVE: + devc->supported_devices = MODE3_MIXER_DEVICES; + devc->mix_devices = &(iwave_mix_devices[0]); + 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; devc->orig_devices = devc->supported_devices; @@ -514,9 +518,13 @@ ad1848_mixer_reset(ad1848_info * devc) devc->levels = load_mixer_volumes(name, default_mixer_levels, 1); for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + { if (devc->supported_devices & (1 << i)) ad1848_mixer_set(devc, i, devc->levels[i]); + } + ad1848_set_recmask(devc, SOUND_MASK_MIC); + devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT; if (devc->mixer_output_port & AUDIO_SPEAKER) ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */ @@ -524,103 +532,109 @@ ad1848_mixer_reset(ad1848_info * devc) ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */ } -static int -ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) +static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { - ad1848_info *devc = mixer_devs[dev]->devc; - - if (cmd == SOUND_MIXER_PRIVATE1) - { - int val; - - val = *(int *) arg; + ad1848_info *devc = mixer_devs[dev]->devc; + int val; - if (val == 0xffff) - return (*(int *) arg = devc->mixer_output_port); - - val &= (AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT); - - devc->mixer_output_port = val; - val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT; /* Always on */ - devc->mixer_output_port = val; + if (cmd == SOUND_MIXER_PRIVATE1) + { + if (get_user(val, (int *)arg)) + return -EFAULT; - if (val & AUDIO_SPEAKER) - ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */ - else - ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */ - - return (*(int *) arg = devc->mixer_output_port); - } - if (((cmd >> 8) & 0xff) == 'M') - { - int val; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - val = *(int *) arg; - return (*(int *) arg = ad1848_set_recmask(devc, val)); - break; - - default: - val = *(int *) arg; - return (*(int *) arg = ad1848_mixer_set(devc, cmd & 0xff, val)); - } else - switch (cmd & 0xff) /* - * Return parameters - */ - { - - case SOUND_MIXER_RECSRC: - return (*(int *) arg = devc->recmask); - break; - - case SOUND_MIXER_DEVMASK: - return (*(int *) arg = devc->supported_devices); - break; - - case SOUND_MIXER_STEREODEVS: - if (devc->model == MD_C930) - return (*(int *) arg = devc->supported_devices); - else - return (*(int *) arg = devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX)); - break; - - case SOUND_MIXER_RECMASK: - return (*(int *) arg = devc->supported_rec_devices); - break; - - case SOUND_MIXER_CAPS: - return (*(int *) arg = SOUND_CAP_EXCL_INPUT); - break; - - default: - return (*(int *) arg = ad1848_mixer_get(devc, cmd & 0xff)); - } - } else + if (val != 0xffff) + { + val &= (AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT); + devc->mixer_output_port = val; + val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT; /* Always on */ + devc->mixer_output_port = val; + if (val & AUDIO_SPEAKER) + ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */ + else + ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */ + } + val = devc->mixer_output_port; + return put_user(val, (int *)arg); + } + if (((cmd >> 8) & 0xff) == 'M') + { + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + { + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = ad1848_set_recmask(devc, val); + break; + + default: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = ad1848_mixer_set(devc, cmd & 0xff, val); + break; + } + return put_user(val, (int *)arg); + } + else + { + switch (cmd & 0xff) + { + /* + * Return parameters + */ + + case SOUND_MIXER_RECSRC: + val = devc->recmask; + break; + + case SOUND_MIXER_DEVMASK: + val = devc->supported_devices; + break; + + case SOUND_MIXER_STEREODEVS: + val = devc->supported_devices; + if (devc->model != MD_C930) + val &= ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); + break; + + case SOUND_MIXER_RECMASK: + val = devc->supported_rec_devices; + break; + + case SOUND_MIXER_CAPS: + val=SOUND_CAP_EXCL_INPUT; + break; + + default: + val = ad1848_mixer_get(devc, cmd & 0xff); + break; + } + return put_user(val, (int *)arg); + } + } + else return -EINVAL; } -static int -ad1848_set_speed(int dev, int arg) +static int ad1848_set_speed(int dev, int arg) { - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; /* - * The sampling speed is encoded in the least significant nibble of I8. The - * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other - * three bits select the divisor (indirectly): - * - * The available speeds are in the following table. Keep the speeds in - * the increasing order. + * The sampling speed is encoded in the least significant nibble of I8. The + * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other + * three bits select the divisor (indirectly): + * + * The available speeds are in the following table. Keep the speeds in + * the increasing order. */ typedef struct - { - int speed; - unsigned char bits; - } + { + int speed; + unsigned char bits; + } speed_struct; static speed_struct speed_table[] = @@ -642,7 +656,7 @@ ad1848_set_speed(int dev, int arg) {48000, (6 << 1) | 0} }; - int i, n, selected = -1; + int i, n, selected = -1; n = sizeof(speed_table) / sizeof(speed_struct); @@ -650,48 +664,49 @@ ad1848_set_speed(int dev, int arg) return portc->speed; if (devc->model == MD_1845) /* AD1845 has different timer than others */ - { - if (arg < 4000) - arg = 4000; - if (arg > 50000) - arg = 50000; - - portc->speed = arg; - portc->speed_bits = speed_table[3].bits; - return portc->speed; - } + { + if (arg < 4000) + arg = 4000; + if (arg > 50000) + arg = 50000; + + portc->speed = arg; + portc->speed_bits = speed_table[3].bits; + return portc->speed; + } if (arg < speed_table[0].speed) selected = 0; if (arg > speed_table[n - 1].speed) selected = n - 1; for (i = 1 /*really */ ; selected == -1 && i < n; i++) + { if (speed_table[i].speed == arg) selected = i; else if (speed_table[i].speed > arg) - { - int diff1, diff2; + { + int diff1, diff2; - diff1 = arg - speed_table[i - 1].speed; - diff2 = speed_table[i].speed - arg; + diff1 = arg - speed_table[i - 1].speed; + diff2 = speed_table[i].speed - arg; - if (diff1 < diff2) - selected = i - 1; - else - selected = i; - } + if (diff1 < diff2) + selected = i - 1; + else + selected = i; + } + } if (selected == -1) - { - printk("ad1848: Can't find speed???\n"); - selected = 3; - } + { + printk(KERN_WARNING "ad1848: Can't find speed???\n"); + selected = 3; + } portc->speed = speed_table[selected].speed; portc->speed_bits = speed_table[selected].bits; return portc->speed; } -static short -ad1848_set_channels(int dev, short arg) +static short ad1848_set_channels(int dev, short arg) { ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; @@ -702,17 +717,16 @@ ad1848_set_channels(int dev, short arg) return arg; } -static unsigned int -ad1848_set_bits(int dev, unsigned int arg) +static unsigned int ad1848_set_bits(int dev, unsigned int arg) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; static struct format_tbl - { + { int format; unsigned char bits; - } + } format2bits[] = { { @@ -755,7 +769,7 @@ ad1848_set_bits(int dev, unsigned int arg) AFMT_U16_BE, 0 } }; - int i, n = sizeof(format2bits) / sizeof(struct format_tbl); + int i, n = sizeof(format2bits) / sizeof(struct format_tbl); if (arg == 0) return portc->audio_format; @@ -767,12 +781,12 @@ ad1848_set_bits(int dev, unsigned int arg) for (i = 0; i < n; i++) if (format2bits[i].format == arg) - { - if ((portc->format_bits = format2bits[i].bits) == 0) - return portc->audio_format = AFMT_U8; /* Was not supported */ + { + if ((portc->format_bits = format2bits[i].bits) == 0) + return portc->audio_format = AFMT_U8; /* Was not supported */ - return arg; - } + return arg; + } /* Still hanging here. Something must be terribly wrong */ portc->format_bits = 0; return portc->audio_format = AFMT_U8; @@ -784,7 +798,7 @@ static struct audio_driver ad1848_audio_driver = ad1848_close, ad1848_output_block, ad1848_start_input, - ad1848_ioctl, + NULL, ad1848_prepare_for_input, ad1848_prepare_for_output, ad1848_halt, @@ -805,8 +819,7 @@ static struct mixer_operations ad1848_mixer_operations = ad1848_mixer_ioctl }; -static int -ad1848_open(int dev, int mode) +static int ad1848_open(int dev, int mode) { ad1848_info *devc = NULL; ad1848_port_info *portc; @@ -821,16 +834,16 @@ ad1848_open(int dev, int mode) save_flags(flags); cli(); if (portc->open_mode || (devc->open_mode & mode)) - { - restore_flags(flags); - return -EBUSY; - } + { + restore_flags(flags); + return -EBUSY; + } devc->dual_dma = 0; if (audio_devs[dev]->flags & DMA_DUPLEX) - { - devc->dual_dma = 1; - } + { + devc->dual_dma = 1; + } devc->intr_active = 0; devc->audio_mode = 0; devc->open_mode |= mode; @@ -850,8 +863,7 @@ ad1848_open(int dev, int mode) return 0; } -static void -ad1848_close(int dev) +static void ad1848_close(int dev) { unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -873,14 +885,7 @@ ad1848_close(int dev) restore_flags(flags); } -static int -ad1848_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - return -EINVAL; -} - -static void -ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) +static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) { unsigned long flags, cnt; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -889,13 +894,14 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) cnt = count; if (portc->audio_format == AFMT_IMA_ADPCM) - { - cnt /= 4; - } else - { - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ - cnt >>= 1; - } + { + cnt /= 4; + } + else + { + if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ + cnt >>= 1; + } if (portc->channels > 1) cnt >>= 1; cnt--; @@ -903,13 +909,13 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) if (devc->audio_mode & PCM_ENABLE_OUTPUT && audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == devc->xfer_count) - { - devc->audio_mode |= PCM_ENABLE_OUTPUT; - devc->intr_active = 1; - return; /* - * Auto DMA mode on. No need to react - */ - } + { + devc->audio_mode |= PCM_ENABLE_OUTPUT; + devc->intr_active = 1; + return; /* + * Auto DMA mode on. No need to react + */ + } save_flags(flags); cli(); @@ -922,8 +928,7 @@ ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) restore_flags(flags); } -static void -ad1848_start_input(int dev, unsigned long buf, int count, int intrflag) +static void ad1848_start_input(int dev, unsigned long buf, int count, int intrflag) { unsigned long flags, cnt; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -931,39 +936,41 @@ ad1848_start_input(int dev, unsigned long buf, int count, int intrflag) cnt = count; if (portc->audio_format == AFMT_IMA_ADPCM) - { - cnt /= 4; - } else - { - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ - cnt >>= 1; - } + { + cnt /= 4; + } + else + { + if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ + cnt >>= 1; + } if (portc->channels > 1) cnt >>= 1; cnt--; if (devc->audio_mode & PCM_ENABLE_INPUT && audio_devs[dev]->flags & DMA_AUTOMODE && - intrflag && - cnt == devc->xfer_count) - { - devc->audio_mode |= PCM_ENABLE_INPUT; - devc->intr_active = 1; - return; /* - * Auto DMA mode on. No need to react - */ - } + intrflag && + cnt == devc->xfer_count) + { + devc->audio_mode |= PCM_ENABLE_INPUT; + devc->intr_active = 1; + return; /* + * Auto DMA mode on. No need to react + */ + } save_flags(flags); cli(); if (devc->model == MD_1848) - { + { ad_write(devc, 15, (unsigned char) (cnt & 0xff)); ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); - } else - { + } + else + { ad_write(devc, 31, (unsigned char) (cnt & 0xff)); ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff)); - } + } ad_unmute(devc); @@ -973,8 +980,7 @@ ad1848_start_input(int dev, unsigned long buf, int count, int intrflag) restore_flags(flags); } -static int -ad1848_prepare_for_output(int dev, int bsize, int bcount) +static int ad1848_prepare_for_output(int dev, int bsize, int bcount) { int timeout; unsigned char fs, old_fs, tmp = 0; @@ -994,26 +1000,28 @@ ad1848_prepare_for_output(int dev, int bsize, int bcount) ad_enter_MCE(devc); /* Enables changes to the format select reg */ if (devc->model == MD_1845) /* Use alternate speed select registers */ - { - fs &= 0xf0; /* Mask off the rate select bits */ + { + fs &= 0xf0; /* Mask off the rate select bits */ - ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ - ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ - } + ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ + ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ + } old_fs = ad_read(devc, 8); if (devc->model == MD_4232) - { - tmp = ad_read(devc, 16); - ad_write(devc, 16, tmp | 0x30); - } + { + tmp = ad_read(devc, 16); + ad_write(devc, 16, tmp | 0x30); + } if (devc->model == MD_IWAVE) ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ ad_write(devc, 8, fs); + /* * Write to I8 starts resynchronization. Wait until it completes. */ + timeout = 0; while (timeout < 100 && inb(devc->base) != 0x80) timeout++; @@ -1033,21 +1041,20 @@ ad1848_prepare_for_output(int dev, int bsize, int bcount) #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE) if (dev == timer_installed && devc->timer_running) if ((fs & 0x01) != (old_fs & 0x01)) - { - ad1848_tmr_reprogram(dev); - } + { + ad1848_tmr_reprogram(dev); + } #endif ad1848_halt_output(dev); return 0; } -static int -ad1848_prepare_for_input(int dev, int bsize, int bcount) +static int ad1848_prepare_for_input(int dev, int bsize, int bcount) { - int timeout; - unsigned char fs, old_fs, tmp = 0; - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + int timeout; + unsigned char fs, old_fs, tmp = 0; + unsigned long flags; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; if (devc->audio_mode) @@ -1063,75 +1070,78 @@ ad1848_prepare_for_input(int dev, int bsize, int bcount) ad_enter_MCE(devc); /* Enables changes to the format select reg */ if (devc->model == MD_1845) /* Use alternate speed select registers */ - { - fs &= 0xf0; /* Mask off the rate select bits */ + { + fs &= 0xf0; /* Mask off the rate select bits */ - ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ - ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ - } + ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ + ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ + } if (devc->model == MD_4232) - { - tmp = ad_read(devc, 16); - ad_write(devc, 16, tmp | 0x30); - } + { + tmp = ad_read(devc, 16); + ad_write(devc, 16, tmp | 0x30); + } if (devc->model == MD_IWAVE) ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ /* * If mode >= 2 (CS4231), set I28. It's the capture format register. */ + if (devc->model != MD_1848) - { - old_fs = ad_read(devc, 28); - ad_write(devc, 28, fs); - - /* - * Write to I28 starts resynchronization. Wait until it completes. - */ - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - - if (devc->model != MD_1848 && devc->model != MD_1845) - { - /* - * CS4231 compatible devices don't have separate sampling rate selection - * register for recording an playback. The I8 register is shared so we have to - * set the speed encoding bits of it too. - */ - unsigned char tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0); - - ad_write(devc, 8, tmp); - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - } - } else - { /* For AD1848 set I8. */ - - old_fs = ad_read(devc, 8); - ad_write(devc, 8, fs); - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - } + { + old_fs = ad_read(devc, 28); + ad_write(devc, 28, fs); + + /* + * Write to I28 starts resynchronization. Wait until it completes. + */ + + timeout = 0; + while (timeout < 100 && inb(devc->base) != 0x80) + timeout++; + + timeout = 0; + while (timeout < 10000 && inb(devc->base) == 0x80) + timeout++; + + if (devc->model != MD_1848 && devc->model != MD_1845) + { + /* + * CS4231 compatible devices don't have separate sampling rate selection + * register for recording an playback. The I8 register is shared so we have to + * set the speed encoding bits of it too. + */ + unsigned char tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0); + + ad_write(devc, 8, tmp); + /* + * Write to I8 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && inb(devc->base) != 0x80) + timeout++; + + timeout = 0; + while (timeout < 10000 && inb(devc->base) == 0x80) + timeout++; + } + } + else + { /* For AD1848 set I8. */ + + old_fs = ad_read(devc, 8); + ad_write(devc, 8, fs); + /* + * Write to I8 starts resynchronization. Wait until it completes. + */ + timeout = 0; + while (timeout < 100 && inb(devc->base) != 0x80) + timeout++; + timeout = 0; + while (timeout < 10000 && inb(devc->base) == 0x80) + timeout++; + } if (devc->model == MD_4232) ad_write(devc, 16, tmp & ~0x30); @@ -1144,19 +1154,20 @@ ad1848_prepare_for_input(int dev, int bsize, int bcount) #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS) if (dev == timer_installed && devc->timer_running) + { if ((fs & 0x01) != (old_fs & 0x01)) - { - ad1848_tmr_reprogram(dev); - } + { + ad1848_tmr_reprogram(dev); + } + } #endif ad1848_halt_input(dev); return 0; } -static void -ad1848_halt(int dev) +static void ad1848_halt(int dev) { - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; unsigned char bits = ad_read(devc, 9); @@ -1169,8 +1180,7 @@ ad1848_halt(int dev) devc->audio_mode = 0; } -static void -ad1848_halt_input(int dev) +static void ad1848_halt_input(int dev) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; unsigned long flags; @@ -1197,19 +1207,18 @@ ad1848_halt_input(int dev) devc->audio_mode &= ~PCM_ENABLE_INPUT; } - outb((0), io_Status(devc)); /* Clear interrupt status */ - outb((0), io_Status(devc)); /* Clear interrupt status */ + outb(0, io_Status(devc)); /* Clear interrupt status */ + outb(0, io_Status(devc)); /* Clear interrupt status */ devc->audio_mode &= ~PCM_ENABLE_INPUT; restore_flags(flags); } -static void -ad1848_halt_output(int dev) +static void ad1848_halt_output(int dev) { - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - unsigned long flags; + ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned long flags; if (!(ad_read(devc, 9) & 0x01)) return; /* Playback not enabled */ @@ -1240,8 +1249,7 @@ ad1848_halt_output(int dev) restore_flags(flags); } -static void -ad1848_trigger(int dev, int state) +static void ad1848_trigger(int dev, int state) { ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; @@ -1255,32 +1263,31 @@ ad1848_trigger(int dev, int state) tmp = old = ad_read(devc, 9); if (portc->open_mode & OPEN_READ) - { + { if (state & PCM_ENABLE_INPUT) tmp |= 0x02; else tmp &= ~0x02; - } + } if (portc->open_mode & OPEN_WRITE) - { - if (state & PCM_ENABLE_OUTPUT) - tmp |= 0x01; - else - tmp &= ~0x01; - } + { + if (state & PCM_ENABLE_OUTPUT) + tmp |= 0x01; + else + tmp &= ~0x01; + } /* ad_mute(devc); */ if (tmp != old) - { + { ad_write(devc, 9, tmp); ad_unmute(devc); - } + } restore_flags(flags); } -static void -ad1848_init_hw(ad1848_info * devc) +static void ad1848_init_hw(ad1848_info * devc) { - int i; + int i; /* * Initial values for the indirect registers of CS4248/AD1848. @@ -1304,40 +1311,40 @@ ad1848_init_hw(ad1848_info * devc) ad_unmute(devc); /* Leave it unmuted now */ if (devc->model > MD_1848) - { - ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ - - if (devc->model == MD_IWAVE) - ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ + { + ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ - for (i = 16; i < 32; i++) - ad_write(devc, i, init_values[i]); + if (devc->model == MD_IWAVE) + ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ - if (devc->model == MD_IWAVE) - ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ + for (i = 16; i < 32; i++) + ad_write(devc, i, init_values[i]); - } + if (devc->model == MD_IWAVE) + ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ + } if (devc->model > MD_1848) - { - if (devc->audio_flags & DMA_DUPLEX) - ad_write(devc, 9, ad_read(devc, 9) & ~0x04); /* Dual DMA mode */ - else - ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ + { + if (devc->audio_flags & DMA_DUPLEX) + ad_write(devc, 9, ad_read(devc, 9) & ~0x04); /* Dual DMA mode */ + else + ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ - if (devc->model == MD_1845) - ad_write(devc, 27, ad_read(devc, 27) | 0x08); /* Alternate freq select enabled */ + if (devc->model == MD_1845) + ad_write(devc, 27, ad_read(devc, 27) | 0x08); /* Alternate freq select enabled */ - if (devc->model == MD_IWAVE) - { /* Some magic Interwave specific initialization */ - ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ - ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ - ad_write(devc, 17, 0xc2); /* Alternate feature enable */ - } - } else - { + if (devc->model == MD_IWAVE) + { /* Some magic Interwave specific initialization */ + ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ + ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ + ad_write(devc, 17, 0xc2); /* Alternate feature enable */ + } + } + else + { devc->audio_flags &= ~DMA_DUPLEX; ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ - } + } outb((0), io_Status(devc)); /* Clear pending interrupts */ @@ -1351,45 +1358,43 @@ ad1848_init_hw(ad1848_info * devc) ad1848_mixer_reset(devc); } -int -ad1848_detect(int io_base, int *ad_flags, int *osp) +int ad1848_detect(int io_base, int *ad_flags, int *osp) { + unsigned char tmp; + ad1848_info *devc = &adev_info[nr_ad1848_devs]; + unsigned char tmp1 = 0xff, tmp2 = 0xff; + int optiC930 = 0; /* OPTi 82C930 flag */ + int interwave = 0; + int ad1847_flag = 0; + int cs4248_flag = 0; - unsigned char tmp; - ad1848_info *devc = &adev_info[nr_ad1848_devs]; - unsigned char tmp1 = 0xff, tmp2 = 0xff; - int optiC930 = 0; /* OPTi 82C930 flag */ - int interwave = 0; - int ad1847_flag = 0; - int cs4248_flag = 0; - - int i; + int i; DDB(printk("ad1848_detect(%x)\n", io_base)); if (ad_flags) - { - if (*ad_flags == 0x12345678) - { - interwave = 1; - *ad_flags = 0; - } - if (*ad_flags == 0x12345677) - { - cs4248_flag = 1; - *ad_flags = 0; - } - } + { + if (*ad_flags == 0x12345678) + { + interwave = 1; + *ad_flags = 0; + } + if (*ad_flags == 0x12345677) + { + cs4248_flag = 1; + *ad_flags = 0; + } + } if (nr_ad1848_devs >= MAX_AUDIO_DEV) - { - printk("ad1848 - Too many audio devices\n"); - return 0; - } + { + printk(KERN_ERR "ad1848 - Too many audio devices\n"); + return 0; + } if (check_region(io_base, 4)) - { - printk("ad1848.c: Port %x not free.\n", io_base); - return 0; - } + { + printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base); + return 0; + } devc->base = io_base; devc->irq_ok = 0; devc->timer_running = 0; @@ -1403,31 +1408,33 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) devc->debug_flag = 0; /* - * Check that the I/O address is in use. - * - * The bit 0x80 of the base I/O port is known to be 0 after the - * chip has performed its power on initialization. Just assume - * this has happened before the OS is starting. - * - * If the I/O address is unused, it typically returns 0xff. + * Check that the I/O address is in use. + * + * The bit 0x80 of the base I/O port is known to be 0 after the + * chip has performed its power on initialization. Just assume + * this has happened before the OS is starting. + * + * If the I/O address is unused, it typically returns 0xff. */ if (inb(devc->base) == 0xff) - { - DDB(printk("ad1848_detect: The base I/O address appears to be dead\n")); - } -/* - * Wait for the device to stop initialization - */ + { + DDB(printk("ad1848_detect: The base I/O address appears to be dead\n")); + } + + /* + * Wait for the device to stop initialization + */ + DDB(printk("ad1848_detect() - step 0\n")); for (i = 0; i < 10000000; i++) - { - unsigned char x = inb(devc->base); + { + unsigned char x = inb(devc->base); - if (x == 0xff || !(x & 0x80)) - break; - } + if (x == 0xff || !(x & 0x80)) + break; + } DDB(printk("ad1848_detect() - step A\n")); @@ -1435,14 +1442,15 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) ad_leave_MCE(devc); if ((inb(devc->base) & 0x80) != 0x00) /* Not a AD1848 */ - { - DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base))); - return 0; - } + { + DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base))); + return 0; + } + /* - * Test if it's possible to change contents of the indirect registers. - * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only - * so try to avoid using it. + * Test if it's possible to change contents of the indirect registers. + * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only + * so try to avoid using it. */ DDB(printk("ad1848_detect() - step B\n")); @@ -1450,28 +1458,33 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) ad_write(devc, 1, 0x45); /* 0x55 with bit 0x10 clear */ if ((tmp1 = ad_read(devc, 0)) != 0xaa || (tmp2 = ad_read(devc, 1)) != 0x45) + { if (tmp2 == 0x65) /* AD1847 has couple of bits hardcoded to 1 */ ad1847_flag = 1; else - { - DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2)); - return 0; - } + { + DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2)); + return 0; + } + } DDB(printk("ad1848_detect() - step C\n")); ad_write(devc, 0, 0x45); ad_write(devc, 1, 0xaa); if ((tmp1 = ad_read(devc, 0)) != 0x45 || (tmp2 = ad_read(devc, 1)) != 0xaa) + { if (tmp2 == 0x8a) /* AD1847 has few bits hardcoded to 1 */ ad1847_flag = 1; else - { - DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2)); - return 0; - } + { + DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2)); + return 0; + } + } + /* - * The indirect register I12 has some read only bits. Lets - * try to change them. + * The indirect register I12 has some read only bits. Lets + * try to change them. */ DDB(printk("ad1848_detect() - step D\n")); @@ -1479,43 +1492,47 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) ad_write(devc, 12, (~tmp) & 0x0f); if ((tmp & 0x0f) != ((tmp1 = ad_read(devc, 12)) & 0x0f)) - { - DDB(printk("ad1848 detect error - step D (%x)\n", tmp1)); - return 0; - } + { + DDB(printk("ad1848 detect error - step D (%x)\n", tmp1)); + return 0; + } + /* - * NOTE! Last 4 bits of the reg I12 tell the chip revision. - * 0x01=RevB and 0x0A=RevC. + * NOTE! Last 4 bits of the reg I12 tell the chip revision. + * 0x01=RevB and 0x0A=RevC. */ /* - * The original AD1848/CS4248 has just 15 indirect registers. This means - * that I0 and I16 should return the same value (etc.). - * However this doesn't work with CS4248. Actually it seems to be impossible - * to detect if the chip is a CS4231 or CS4248. - * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails - * with CS4231. + * The original AD1848/CS4248 has just 15 indirect registers. This means + * that I0 and I16 should return the same value (etc.). + * However this doesn't work with CS4248. Actually it seems to be impossible + * to detect if the chip is a CS4231 or CS4248. + * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails + * with CS4231. */ -/* - * OPTi 82C930 has mode2 control bit in another place. This test will fail - * with it. Accept this situation as a possible indication of this chip. - */ + /* + * OPTi 82C930 has mode2 control bit in another place. This test will fail + * with it. Accept this situation as a possible indication of this chip. + */ DDB(printk("ad1848_detect() - step F\n")); ad_write(devc, 12, 0); /* Mode2=disabled */ for (i = 0; i < 16; i++) + { if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) - { - DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2)); - if (!ad1847_flag) - optiC930 = 1; - break; - } + { + DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2)); + if (!ad1847_flag) + optiC930 = 1; + break; + } + } + /* - * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40). - * The bit 0x80 is always 1 in CS4248 and CS4231. + * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40). + * The bit 0x80 is always 1 in CS4248 and CS4231. */ DDB(printk("ad1848_detect() - step G\n")); @@ -1531,66 +1548,67 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) tmp1 = ad_read(devc, 12); if (tmp1 & 0x80) - { - if (ad_flags) - *ad_flags |= AD_F_CS4248; + { + if (ad_flags) + *ad_flags |= AD_F_CS4248; - devc->chip_name = "CS4248"; /* Our best knowledge just now */ - } + devc->chip_name = "CS4248"; /* Our best knowledge just now */ + } if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40)) - { - /* - * CS4231 detected - is it? - * - * 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); - if ((tmp1 = ad_read(devc, 16)) != 0x45) /* No change -> CS4231? */ - { - - ad_write(devc, 0, 0xaa); - if ((tmp1 = ad_read(devc, 16)) == 0xaa) /* Rotten bits? */ - { - DDB(printk("ad1848 detect error - step H(%x)\n", tmp1)); - return 0; - } - /* - * 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)) - { - int id, full_id; - - /* - * It's at least CS4231 - */ - devc->chip_name = "CS4231"; - - devc->model = MD_4231; - - /* - * It could be an AD1845 or CS4231A as well. - * CS4231 and AD1845 report the same revision info in I25 - * while the CS4231A reports different. - */ - - id = ad_read(devc, 25) & 0xe7; - full_id = ad_read(devc, 25); - if (id == 0x80) /* Device busy??? */ - id = ad_read(devc, 25) & 0xe7; - if (id == 0x80) /* Device still busy??? */ - id = ad_read(devc, 25) & 0xe7; - DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25))); - - switch (id) - { + { + /* + * CS4231 detected - is it? + * + * 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); + if ((tmp1 = ad_read(devc, 16)) != 0x45) /* No change -> CS4231? */ + { + ad_write(devc, 0, 0xaa); + if ((tmp1 = ad_read(devc, 16)) == 0xaa) /* Rotten bits? */ + { + DDB(printk("ad1848 detect error - step H(%x)\n", tmp1)); + return 0; + } + + /* + * 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)) + { + int id, full_id; + + /* + * It's at least CS4231 + */ + + devc->chip_name = "CS4231"; + devc->model = MD_4231; + + /* + * It could be an AD1845 or CS4231A as well. + * CS4231 and AD1845 report the same revision info in I25 + * while the CS4231A reports different. + */ + + id = ad_read(devc, 25) & 0xe7; + full_id = ad_read(devc, 25); + if (id == 0x80) /* Device busy??? */ + id = ad_read(devc, 25) & 0xe7; + if (id == 0x80) /* Device still busy??? */ + id = ad_read(devc, 25) & 0xe7; + DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25))); + + switch (id) + { case 0xa0: devc->chip_name = "CS4231A"; @@ -1628,25 +1646,26 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) */ unsigned char tmp = ad_read(devc, 23); - ad_write(devc, 23, ~tmp); + if (interwave) - { - devc->model = MD_IWAVE; - devc->chip_name = "IWave"; - } else if (ad_read(devc, 23) != tmp) /* AD1845 ? */ - { - devc->chip_name = "AD1845"; - devc->model = MD_1845; - } else if (cs4248_flag) - { - if (ad_flags) + { + devc->model = MD_IWAVE; + devc->chip_name = "IWave"; + } + else if (ad_read(devc, 23) != tmp) /* AD1845 ? */ + { + devc->chip_name = "AD1845"; + devc->model = MD_1845; + } + else if (cs4248_flag) + { + if (ad_flags) *ad_flags |= AD_F_CS4248; - - devc->chip_name = "CS4248"; - devc->model = MD_1848; - ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */ - } + devc->chip_name = "CS4248"; + devc->model = MD_1848; + ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */ + } ad_write(devc, 23, tmp); /* Restore */ } break; @@ -1654,27 +1673,27 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) default: /* Assume CS4231 or OPTi 82C930 */ DDB(printk("ad1848: I25 = %02x/%02x\n", ad_read(devc, 25), ad_read(devc, 25) & 0xe7)); if (optiC930) - { - devc->chip_name = "82C930"; - devc->model = MD_C930; - } else - { - devc->model = MD_4231; - } - - } - } - ad_write(devc, 25, tmp1); /* Restore bits */ - - DDB(printk("ad1848_detect() - step K\n")); - } - } + { + devc->chip_name = "82C930"; + devc->model = MD_C930; + } + else + { + devc->model = MD_4231; + } + } + } + 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->model != MD_1848) *ad_flags |= AD_F_CS4231; - } + } DDB(printk("ad1848_detect() - Detected OK\n")); if (devc->model == MD_1848 && ad1847_flag) @@ -1684,21 +1703,20 @@ ad1848_detect(int io_base, int *ad_flags, int *osp) return 1; } -int -ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp) +int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp) { /* - * NOTE! If irq < 0, there is another driver which has allocated the IRQ - * so that this driver doesn't need to allocate/deallocate it. - * The actually used IRQ is ABS(irq). + * NOTE! If irq < 0, there is another driver which has allocated the IRQ + * so that this driver doesn't need to allocate/deallocate it. + * The actually used IRQ is ABS(irq). */ - int my_dev; - char dev_name[100]; - int e; + int my_dev; + char dev_name[100]; + int e; - ad1848_info *devc = &adev_info[nr_ad1848_devs]; + ad1848_info *devc = &adev_info[nr_ad1848_devs]; ad1848_port_info *portc = NULL; @@ -1721,19 +1739,19 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, request_region(devc->base, 4, devc->name); - conf_printf2(dev_name, - devc->base, devc->irq, dma_playback, dma_capture); + conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture); if (devc->model == MD_1848 || devc->model == MD_C930) devc->audio_flags |= DMA_HARDSTOP; if (devc->model > MD_1848) - { - if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1) - devc->audio_flags &= ~DMA_DUPLEX; - else - devc->audio_flags |= DMA_DUPLEX; - } + { + if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1) + devc->audio_flags &= ~DMA_DUPLEX; + else + devc->audio_flags |= DMA_DUPLEX; + } + if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name, &ad1848_audio_driver, @@ -1743,9 +1761,9 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, devc, dma_playback, dma_capture)) < 0) - { - return -1; - } + { + return -1; + } portc = (ad1848_port_info *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(ad1848_port_info))); sound_mem_sizes[sound_nblocks] = sizeof(ad1848_port_info); if (sound_nblocks < 1024) @@ -1758,37 +1776,38 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, ad1848_init_hw(devc); if (irq > 0) - { - irq2dev[irq] = devc->dev_no = my_dev; - if (snd_set_irq_handler(devc->irq, adintr, + { + irq2dev[irq] = devc->dev_no = my_dev; + if (snd_set_irq_handler(devc->irq, adintr, devc->name, NULL) < 0) - { - printk(KERN_WARNING "ad1848: IRQ in use\n"); - } - if (devc->model != MD_1848 && devc->model != MD_C930) - { - int x; - unsigned char tmp = ad_read(devc, 16); - - devc->timer_ticks = 0; - - ad_write(devc, 21, 0x00); /* Timer MSB */ - ad_write(devc, 20, 0x10); /* Timer LSB */ - - ad_write(devc, 16, tmp | 0x40); /* Enable timer */ - for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); - ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ - - if (devc->timer_ticks == 0) - printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq); - else - { - DDB(printk("Interrupt test OK\n")); - devc->irq_ok = 1; - } - } else - devc->irq_ok = 1; /* Couldn't test. assume it's OK */ + { + printk(KERN_WARNING "ad1848: IRQ in use\n"); + } + if (devc->model != MD_1848 && devc->model != MD_C930) + { + int x; + unsigned char tmp = ad_read(devc, 16); + + devc->timer_ticks = 0; + + ad_write(devc, 21, 0x00); /* Timer MSB */ + ad_write(devc, 20, 0x10); /* Timer LSB */ + + ad_write(devc, 16, tmp | 0x40); /* Enable timer */ + for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); + ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ + + if (devc->timer_ticks == 0) + printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq); + else + { + DDB(printk("Interrupt test OK\n")); + devc->irq_ok = 1; + } + } + else + devc->irq_ok = 1; /* Couldn't test. assume it's OK */ } else if (irq < 0) irq2dev[-irq] = devc->dev_no = my_dev; @@ -1799,22 +1818,22 @@ ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capture, #endif if (!share_dma) - { - if (sound_alloc_dma(dma_playback, devc->name)) - printk("ad1848.c: Can't allocate DMA%d\n", dma_playback); - - if (dma_capture != dma_playback) - if (sound_alloc_dma(dma_capture, devc->name)) - printk("ad1848.c: Can't allocate DMA%d\n", dma_capture); - } + { + if (sound_alloc_dma(dma_playback, devc->name)) + printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback); + + if (dma_capture != dma_playback) + if (sound_alloc_dma(dma_capture, devc->name)) + printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_capture); + } if ((e = sound_install_mixer(MIXER_DRIVER_VERSION, dev_name, &ad1848_mixer_operations, sizeof(struct mixer_operations), devc)) >= 0) - { - audio_devs[my_dev]->mixer_dev = e; - } + { + audio_devs[my_dev]->mixer_dev = e; + } MOD_INC_USE_COUNT; return my_dev; } @@ -1829,76 +1848,79 @@ void ad1848_control(int cmd, int arg) devc = &adev_info[nr_ad1848_devs - 1]; switch (cmd) - { - case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ - if (devc->model != MD_1845) - return; - ad_enter_MCE(devc); - ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); - ad_leave_MCE(devc); - break; - - case AD1848_MIXER_REROUTE: - { - int o = (arg >> 8) & 0xff; - int n = arg & 0xff; - - if (n == SOUND_MIXER_NONE) - { /* Just hide this control */ - ad1848_mixer_set(devc, o, 0); /* Shut up it */ - devc->supported_devices &= ~(1 << o); - devc->supported_rec_devices &= ~(1 << o); - return; - } - /* Make the mixer control identified by o to appear as n */ - - if (o < 0 || o > SOUND_MIXER_NRDEVICES) - return; - if (n < 0 || n > SOUND_MIXER_NRDEVICES) - return; - if (!(devc->supported_devices & (1 << o))) - return; /* Not supported */ - - devc->mixer_reroute[n] = o; /* Rename the control */ - devc->supported_devices &= ~(1 << o); - devc->supported_devices |= (1 << n); - if (devc->supported_rec_devices & (1 << o)) - devc->supported_rec_devices |= (1 << n); - devc->supported_rec_devices &= ~(1 << o); - } - break; - } + { + case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ + if (devc->model != MD_1845) + return; + ad_enter_MCE(devc); + ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); + ad_leave_MCE(devc); + break; + + case AD1848_MIXER_REROUTE: + { + int o = (arg >> 8) & 0xff; + int n = arg & 0xff; + + if (n == SOUND_MIXER_NONE) + { /* Just hide this control */ + ad1848_mixer_set(devc, o, 0); /* Shut up it */ + devc->supported_devices &= ~(1 << o); + devc->supported_rec_devices &= ~(1 << o); + return; + } + /* Make the mixer control identified by o to appear as n */ + + if (o < 0 || o > SOUND_MIXER_NRDEVICES) + return; + if (n < 0 || n > SOUND_MIXER_NRDEVICES) + return; + if (!(devc->supported_devices & (1 << o))) + return; /* Not supported */ + + devc->mixer_reroute[n] = o; /* Rename the control */ + devc->supported_devices &= ~(1 << o); + devc->supported_devices |= (1 << n); + if (devc->supported_rec_devices & (1 << o)) + devc->supported_rec_devices |= (1 << n); + devc->supported_rec_devices &= ~(1 << o); + } + break; + } return; } -void -ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma) +void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma) { - int i, dev = 0; - ad1848_info *devc = NULL; + int i, dev = 0; + ad1848_info *devc = NULL; for (i = 0; devc == NULL && i < nr_ad1848_devs; i++) + { if (adev_info[i].base == io_base) - { - devc = &adev_info[i]; - dev = devc->dev_no; - } + { + devc = &adev_info[i]; + dev = devc->dev_no; + } + } + if (devc != NULL) - { - release_region(devc->base, 4); + { + release_region(devc->base, 4); - if (!share_dma) - { - if (irq > 0) - snd_release_irq(devc->irq); + if (!share_dma) + { + if (irq > 0) + snd_release_irq(devc->irq); - sound_free_dma(audio_devs[dev]->dmap_out->dma); + sound_free_dma(audio_devs[dev]->dmap_out->dma); - if (audio_devs[dev]->dmap_in->dma != audio_devs[dev]->dmap_out->dma) - sound_free_dma(audio_devs[dev]->dmap_in->dma); - } - } else - printk("ad1848: Can't find device to be unloaded. Base=%x\n", io_base); + if (audio_devs[dev]->dmap_in->dma != audio_devs[dev]->dmap_out->dma) + sound_free_dma(audio_devs[dev]->dmap_in->dma); + } + } + else + printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base); MOD_DEC_USE_COUNT; } @@ -1912,94 +1934,96 @@ void adintr(int irq, void *dev_id, struct pt_regs *dummy) int cnt = 0; if (irq < 0 || irq > 15) - { - dev = -1; - } else + { + dev = -1; + } + else dev = irq2dev[irq]; if (dev < 0 || dev >= num_audiodevs) - { - for (irq = 0; irq < 17; irq++) - if (irq2dev[irq] != -1) - break; - - if (irq > 15) - { - /* printk("ad1848.c: Bogus interrupt %d\n", irq); */ - return; - } - dev = irq2dev[irq]; - devc = (ad1848_info *) audio_devs[dev]->devc; + { + for (irq = 0; irq < 17; irq++) + if (irq2dev[irq] != -1) + break; + + if (irq > 15) + { + /* printk("ad1848.c: Bogus interrupt %d\n", irq); */ + return; + } + dev = irq2dev[irq]; + devc = (ad1848_info *) audio_devs[dev]->devc; } else devc = (ad1848_info *) audio_devs[dev]->devc; - interrupt_again: /* Jump back here if int status doesn't reset */ +interrupt_again: /* Jump back here if int status doesn't reset */ status = inb(io_Status(devc)); if (status == 0x80) - printk("adintr: Why?\n"); + printk(KERN_DEBUG "adintr: Why?\n"); if (devc->model == MD_1848) outb((0), io_Status(devc)); /* Clear interrupt status */ if (status & 0x01) - { - if (devc->model == MD_C930) - { /* 82C930 has interrupt status register in MAD16 register MC11 */ - unsigned long flags; - - save_flags(flags); - cli(); - - alt_stat = 0; - - if (devc->c930_password_port) - outb((0xe4), devc->c930_password_port); /* Password */ - outb((11), 0xe0e); - c930_stat = inb(0xe0f); - - if (c930_stat & 0x04) - alt_stat |= 0x10; /* Playback intr */ - if (c930_stat & 0x08) - alt_stat |= 0x20; /* Playback intr */ - restore_flags(flags); - } else if (devc->model != MD_1848) - alt_stat = ad_read(devc, 24); - - /* Acknowledge the intr before proceeding */ - if (devc->model == MD_C930) - { /* 82C930 has interrupt status register in MAD16 register MC11 */ - unsigned long flags; - - save_flags(flags); - cli(); - - if (devc->c930_password_port) - outb((0xe4), devc->c930_password_port); /* Password */ - outb((11), 0xe0e); - outb((~c930_stat), 0xe0f); - restore_flags(flags); - } else if (devc->model != MD_1848) - ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat); /* Selective ack */ - - if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20) - { - DMAbuf_inputintr(devc->record_dev); - } - if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT && + { + if (devc->model == MD_C930) + { /* 82C930 has interrupt status register in MAD16 register MC11 */ + unsigned long flags; + + save_flags(flags); + cli(); + + alt_stat = 0; + + if (devc->c930_password_port) + outb((0xe4), devc->c930_password_port); /* Password */ + outb(11, 0xe0e); + c930_stat = inb(0xe0f); + + if (c930_stat & 0x04) + alt_stat |= 0x10; /* Playback intr */ + if (c930_stat & 0x08) + alt_stat |= 0x20; /* Playback intr */ + restore_flags(flags); + } else if (devc->model != MD_1848) + alt_stat = ad_read(devc, 24); + + /* Acknowledge the intr before proceeding */ + if (devc->model == MD_C930) + { /* 82C930 has interrupt status register in MAD16 register MC11 */ + unsigned long flags; + + save_flags(flags); + cli(); + + if (devc->c930_password_port) + outb((0xe4), devc->c930_password_port); /* Password */ + outb((11), 0xe0e); + outb((~c930_stat), 0xe0f); + restore_flags(flags); + } + else if (devc->model != MD_1848) + ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat); /* Selective ack */ + + if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20) + { + DMAbuf_inputintr(devc->record_dev); + } + if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10) - { - DMAbuf_outputintr(devc->playback_dev, 1); - } - if (devc->model != MD_1848 && alt_stat & 0x40) /* Timer interrupt */ - { - devc->timer_ticks++; + { + DMAbuf_outputintr(devc->playback_dev, 1); + } + if (devc->model != MD_1848 && alt_stat & 0x40) /* Timer interrupt */ + { + devc->timer_ticks++; #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE) - if (timer_installed == dev && devc->timer_running) - sound_timer_interrupt(); + if (timer_installed == dev && devc->timer_running) + sound_timer_interrupt(); #endif - } - } + } + } /* * Sometimes playback or capture interrupts occur while a timer interrupt * is being handled. The interrupt will not be retriggered if we don't @@ -2007,63 +2031,61 @@ void adintr(int irq, void *dev_id, struct pt_regs *dummy) * the handler in this case. */ if (inb(io_Status(devc)) & 0x01 && cnt++ < 4) - { + { goto interrupt_again; - } + } } -#ifdef DESKPROXL /* - * Very experimental initialization sequence for the integrated sound system - * of Compaq Deskpro XL. Will be moved somewhere else in future. + * Experimental initialization sequence for the integrated sound system + * of Compaq Deskpro XL. */ -static int -init_deskpro(struct address_info *hw_config) +static int init_deskpro(struct address_info *hw_config) { unsigned char tmp; if ((tmp = inb(0xc44)) == 0xff) - { - DDB(printk("init_deskpro: Dead port 0xc44\n")); - return 0; - } + { + DDB(printk("init_deskpro: Dead port 0xc44\n")); + return 0; + } outb((tmp | 0x04), 0xc44); /* Select bank 1 */ if (inb(0xc44) != 0x04) - { - DDB(printk("init_deskpro: Invalid bank1 signature in port 0xc44\n")); - return 0; - } -/* - * OK. It looks like a Deskpro so let's proceed. - */ + { + DDB(printk("init_deskpro: Invalid bank1 signature in port 0xc44\n")); + return 0; + } + /* + * OK. It looks like a Deskpro so let's proceed. + */ -/* - * I/O port 0xc44 Audio configuration register. - * - * bits 0xc0: Audio revision bits - * 0x00 = Compaq Business Audio - * 0x40 = MS Sound System Compatible (reset default) - * 0x80 = Reserved - * 0xc0 = Reserved - * bit 0x20: No Wait State Enable - * 0x00 = Disabled (reset default, DMA mode) - * 0x20 = Enabled (programmed I/O mode) - * bit 0x10: MS Sound System Decode Enable - * 0x00 = Decoding disabled (reset default) - * 0x10 = Decoding enabled - * bit 0x08: FM Synthesis Decode Enable - * 0x00 = Decoding Disabled (reset default) - * 0x08 = Decoding enabled - * bit 0x04 Bank select - * 0x00 = Bank 0 - * 0x04 = Bank 1 - * bits 0x03 MSS Base address - * 0x00 = 0x530 (reset default) - * 0x01 = 0x604 - * 0x02 = 0xf40 - * 0x03 = 0xe80 - */ + /* + * I/O port 0xc44 Audio configuration register. + * + * bits 0xc0: Audio revision bits + * 0x00 = Compaq Business Audio + * 0x40 = MS Sound System Compatible (reset default) + * 0x80 = Reserved + * 0xc0 = Reserved + * bit 0x20: No Wait State Enable + * 0x00 = Disabled (reset default, DMA mode) + * 0x20 = Enabled (programmed I/O mode) + * bit 0x10: MS Sound System Decode Enable + * 0x00 = Decoding disabled (reset default) + * 0x10 = Decoding enabled + * bit 0x08: FM Synthesis Decode Enable + * 0x00 = Decoding Disabled (reset default) + * 0x08 = Decoding enabled + * bit 0x04 Bank select + * 0x00 = Bank 0 + * 0x04 = Bank 1 + * bits 0x03 MSS Base address + * 0x00 = 0x530 (reset default) + * 0x01 = 0x604 + * 0x02 = 0xf40 + * 0x03 = 0xe80 + */ #ifdef DEBUGXL /* Debug printing */ @@ -2078,23 +2100,23 @@ init_deskpro(struct address_info *hw_config) tmp = 0x58; /* MSS Mode, MSS&FM decode enabled */ switch (hw_config->io_base) - { - case 0x530: - tmp |= 0x00; - break; - case 0x604: - tmp |= 0x01; - break; - case 0xf40: - tmp |= 0x02; - break; - case 0xe80: - tmp |= 0x03; - break; - default: - DDB(printk("init_deskpro: Invalid MSS port %x\n", hw_config->io_base)); - return 0; - } + { + case 0x530: + tmp |= 0x00; + break; + case 0x604: + tmp |= 0x01; + break; + case 0xf40: + tmp |= 0x02; + break; + case 0xe80: + tmp |= 0x03; + break; + default: + DDB(printk("init_deskpro: Invalid MSS port %x\n", hw_config->io_base)); + return 0; + } outb((tmp & ~0x04), 0xc44); /* Write to bank=0 */ #ifdef DEBUGXL @@ -2106,15 +2128,15 @@ init_deskpro(struct address_info *hw_config) printk("%02x\n", inb(0xc44)); #endif -/* - * I/O port 0xc45 FM Address Decode/MSS ID Register. - * - * bank=0, bits 0xfe: FM synthesis Decode Compare bits 7:1 (default=0x88) - * bank=0, bit 0x01: SBIC Power Control Bit - * 0x00 = Powered up - * 0x01 = Powered down - * bank=1, bits 0xfc: MSS ID (default=0x40) - */ + /* + * I/O port 0xc45 FM Address Decode/MSS ID Register. + * + * bank=0, bits 0xfe: FM synthesis Decode Compare bits 7:1 (default=0x88) + * bank=0, bit 0x01: SBIC Power Control Bit + * 0x00 = Powered up + * 0x01 = Powered down + * bank=1, bits 0xfc: MSS ID (default=0x40) + */ #ifdef DEBUGXL /* Debug printing */ @@ -2140,12 +2162,12 @@ init_deskpro(struct address_info *hw_config) #endif -/* - * I/O port 0xc46 FM Address Decode/Address ASIC Revision Register. - * - * bank=0, bits 0xff: FM synthesis Decode Compare bits 15:8 (default=0x03) - * bank=1, bits 0xff: Audio addressing ASIC id - */ + /* + * I/O port 0xc46 FM Address Decode/Address ASIC Revision Register. + * + * bank=0, bits 0xff: FM synthesis Decode Compare bits 15:8 (default=0x03) + * bank=1, bits 0xff: Audio addressing ASIC id + */ #ifdef DEBUGXL /* Debug printing */ @@ -2170,12 +2192,12 @@ init_deskpro(struct address_info *hw_config) printk("%02x\n", inb(0xc46)); #endif -/* - * I/O port 0xc47 FM Address Decode Register. - * - * bank=0, bits 0xff: Decode enable selection for various FM address bits - * bank=1, bits 0xff: Reserved - */ + /* + * I/O port 0xc47 FM Address Decode Register. + * + * bank=0, bits 0xff: Decode enable selection for various FM address bits + * bank=1, bits 0xff: Reserved + */ #ifdef DEBUGXL /* Debug printing */ @@ -2200,9 +2222,9 @@ init_deskpro(struct address_info *hw_config) printk("%02x\n", inb(0xc47)); #endif -/* - * I/O port 0xc6f = Audio Disable Function Register - */ + /* + * I/O port 0xc6f = Audio Disable Function Register + */ #ifdef DEBUGXL printk("Port 0xc6f (before) = %02x\n", inb(0xc6f)); @@ -2216,32 +2238,29 @@ init_deskpro(struct address_info *hw_config) return 1; } -#endif -int -probe_ms_sound(struct address_info *hw_config) +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; - } + { + printk(KERN_ERR "MSS: I/O port conflict\n"); + return 0; + } 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); - } -#ifdef DESKPROXL - if (hw_config->card_subtype == 2) /* Compaq Deskpro XL */ - { - if (!init_deskpro(hw_config)) - return 0; - } -#endif + { + /* check_opl3(0x388, hw_config); */ + return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp); + } + + if (deskpro_xl && hw_config->card_subtype == 2) /* Compaq Deskpro XL */ + { + if (!init_deskpro(hw_config)) + return 0; + } /* * Check if the IO port returns valid signature. The original MS Sound @@ -2250,58 +2269,57 @@ probe_ms_sound(struct address_info *hw_config) */ if ((tmp = inb(hw_config->io_base + 3)) == 0xff) /* Bus float */ - { + { int ret; DDB(printk("I/O address is inactive (%x)\n", tmp)); if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))) return 0; return 1; - } + } DDB(printk("MSS signature = %x\n", tmp & 0x3f)); if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x0f && (tmp & 0x3f) != 0x00) - { - int ret; + { + int ret; - MDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3))); - DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n")); - if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))) - return 0; + MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3))); + DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n")); + if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp))) + return 0; - hw_config->card_subtype = 1; - return 1; - } + hw_config->card_subtype = 1; + return 1; + } if (hw_config->irq > 11) - { - printk("MSS: Bad IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); + return 0; + } if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk("MSS: Bad DMA %d\n", hw_config->dma); + { + printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma); return 0; - } + } /* - * Check that DMA0 is not in use with a 8 bit board. + * Check that DMA0 is not in use with a 8 bit board. */ if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) - { - printk("MSS: Can't use DMA0 with a 8 bit card/slot\n"); - return 0; - } + { + printk(KERN_ERR "MSS: Can't use DMA0 with a 8 bit card/slot\n"); + return 0; + } if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) - { - printk("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); + return 0; + } return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp); } -void -attach_ms_sound(struct address_info *hw_config) +void attach_ms_sound(struct address_info *hw_config) { static char interrupt_bits[12] = { @@ -2314,63 +2332,65 @@ attach_ms_sound(struct address_info *hw_config) 1, 2, 0, 3 }; - int config_port = hw_config->io_base + 0; - int version_port = hw_config->io_base + 3; - int dma = hw_config->dma; - int dma2 = hw_config->dma2; + int config_port = hw_config->io_base + 0; + int version_port = hw_config->io_base + 3; + int dma = hw_config->dma; + int dma2 = hw_config->dma2; if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ - { - hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4, + { + hw_config->slots[0] = 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; - } + request_region(hw_config->io_base, 4, "WSS config"); + return; + } /* - * Set the IRQ and DMA addresses. + * Set the IRQ and DMA addresses. */ bits = interrupt_bits[hw_config->irq]; if (bits == -1) - { - printk("MSS: Bad IRQ %d\n", hw_config->irq); - return; - } + { + printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); + return; + } outb((bits | 0x40), config_port); if ((inb(version_port) & 0x40) == 0) - printk("[MSS: IRQ Conflict?]"); + printk(KERN_ERR "[MSS: IRQ Conflict?]\n"); /* * Handle the capture DMA channel */ if (dma2 != -1 && dma2 != dma) - { - if (!((dma == 0 && dma2 == 1) || + { + if (!((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || (dma == 3 && dma2 == 0))) - { /* Unsupported combination. Try to swap channels */ - int tmp = dma; - - dma = dma2; - dma2 = tmp; - } - if ((dma == 0 && dma2 == 1) || - (dma == 1 && dma2 == 0) || - (dma == 3 && dma2 == 0)) - { - dma2_bit = 0x04; /* Enable capture DMA */ - } else - { - printk("MSS: Invalid capture DMA\n"); - dma2 = dma; - } - } else - { - dma2 = dma; - } + { /* Unsupported combination. Try to swap channels */ + int tmp = dma; + + dma = dma2; + dma2 = tmp; + } + if ((dma == 0 && dma2 == 1) || + (dma == 1 && dma2 == 0) || + (dma == 3 && dma2 == 0)) + { + dma2_bit = 0x04; /* Enable capture DMA */ + } + else + { + printk(KERN_WARNING "MSS: Invalid capture DMA\n"); + dma2 = dma; + } + } + else + { + dma2 = dma; + } hw_config->dma = dma; hw_config->dma2 = dma2; @@ -2385,8 +2405,7 @@ attach_ms_sound(struct address_info *hw_config) request_region(hw_config->io_base, 4, "WSS config"); } -void -unload_ms_sound(struct address_info *hw_config) +void unload_ms_sound(struct address_info *hw_config) { int mixer = audio_devs[hw_config->slots[0]]->mixer_dev; ad1848_unload(hw_config->io_base + 4, @@ -2397,18 +2416,17 @@ unload_ms_sound(struct address_info *hw_config) sound_unload_mixerdev(mixer); sound_unload_audiodev(hw_config->slots[0]); release_region(hw_config->io_base, 4); - } #if (defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)) || defined(MODULE) + /* * Timer stuff (for /dev/music). */ static unsigned int current_interval = 0; -static unsigned int -ad1848_tmr_start(int dev, unsigned int usecs) +static unsigned int ad1848_tmr_start(int dev, unsigned int usecs) { unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -2418,16 +2436,16 @@ ad1848_tmr_start(int dev, unsigned int usecs) save_flags(flags); cli(); -/* - * Length of the timer interval (in nanoseconds) depends on the - * selected crystal oscillator. Check this from bit 0x01 of I8. - * - * AD1845 has just one oscillator which has cycle time of 10.050 us - * (when a 24.576 MHz xtal oscillator is used). - * - * Convert requested interval to nanoseconds before computing - * the timer divider. - */ + /* + * Length of the timer interval (in nanoseconds) depends on the + * selected crystal oscillator. Check this from bit 0x01 of I8. + * + * AD1845 has just one oscillator which has cycle time of 10.050 us + * (when a 24.576 MHz xtal oscillator is used). + * + * Convert requested interval to nanoseconds before computing + * the timer divider. + */ if (devc->model == MD_1845) xtal_nsecs = 10050; @@ -2453,20 +2471,18 @@ ad1848_tmr_start(int dev, unsigned int usecs) return current_interval = (divider * xtal_nsecs + 500) / 1000; } -static void -ad1848_tmr_reprogram(int dev) +static void ad1848_tmr_reprogram(int dev) { -/* - * Audio driver has changed sampling rate so that a different xtal - * oscillator was selected. We have to reprogram the timer rate. - */ + /* + * Audio driver has changed sampling rate so that a different xtal + * oscillator was selected. We have to reprogram the timer rate. + */ ad1848_tmr_start(dev, current_interval); sound_timer_syncinterval(current_interval); } -static void -ad1848_tmr_disable(int dev) +static void ad1848_tmr_disable(int dev) { unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -2478,8 +2494,7 @@ ad1848_tmr_disable(int dev) restore_flags(flags); } -static void -ad1848_tmr_restart(int dev) +static void ad1848_tmr_restart(int dev) { unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; @@ -2503,10 +2518,8 @@ static struct sound_lowlev_timer ad1848_tmr = ad1848_tmr_restart }; -static int -ad1848_tmr_install(int dev) +static int ad1848_tmr_install(int dev) { - if (timer_installed != -1) return 0; /* Don't install another timer */ @@ -2521,6 +2534,7 @@ ad1848_tmr_install(int dev) EXPORT_SYMBOL(ad1848_detect); EXPORT_SYMBOL(ad1848_init); EXPORT_SYMBOL(ad1848_unload); +EXPORT_SYMBOL(ad1848_control); EXPORT_SYMBOL(adintr); EXPORT_SYMBOL(probe_ms_sound); EXPORT_SYMBOL(attach_ms_sound); @@ -2533,6 +2547,7 @@ MODULE_PARM(irq, "i"); MODULE_PARM(dma, "i"); MODULE_PARM(dma2, "i"); MODULE_PARM(type, "i"); +MODULE_PARM(deskpro_xl, "i"); int io = -1; int irq = -1; @@ -2547,7 +2562,7 @@ struct address_info hw_config; int init_module(void) { - printk("ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n"); + printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n"); if(io!=-1) { if(irq == -1 || dma == -1) @@ -2569,21 +2584,17 @@ int init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { SOUND_LOCK_END; if(loaded) unload_ms_sound(&hw_config); -/* unregister_symtab(&ad1848_syms); */ } #else -void -export_ad1848_syms(void) +void export_ad1848_syms(void) { - register_symtab(&ad1848_syms); } #endif |