Messages in this thread Patch in this message |  | | Date | Tue, 9 Oct 2001 21:34:24 +0200 (CEST) | From | Rui Sousa <> | Subject | Emu10k1 driver update |
| |
Hi,
Attached a patch for the emu10k1 kernel driver against 2.4.11pre6.
Changes: Mixer improvements. Fixed a dead lock in emu10k1_volxxx_irqhandler. Small code cleanup.
The patch against 2.4.10-ac10 can be found at:
ftp://opensource.creative.com/pub/dist/emu10k1-2.4.10-ac10-2.patch
(it's basically the same except for the Configure.help file)
Please apply,
Rui Sousa
diff -ur linux-2.4.11pre6.orig/Documentation/Configure.help linux-2.4.11pre6.emu10k1/Documentation/Configure.help --- linux-2.4.11pre6.orig/Documentation/Configure.help Tue Oct 9 20:48:59 2001 +++ linux-2.4.11pre6.emu10k1/Documentation/Configure.help Tue Oct 9 20:53:35 2001 @@ -15752,25 +15752,18 @@ Creative EMU10K1 based PCI sound cards CONFIG_SOUND_EMU10K1 Say Y or M if you have a PCI sound card using the EMU10K1 chipset, - such as the Creative SBLive!, SB PCI512 or Emu-APS. + such as the various Creative SBLive!, SB PCI512 or Emu-APS. - For more information about the degree of support for the different - card models please check: - - http://opensource.creative.com + For more information on this driver and the degree of support for the + different card models please check <http://opensource.creative.com>. It is now possible to load dsp microcode patches into the EMU10K1 chip. These patches are used to implement real time sound processing - effects which include for example: signal routing, bass/treble control, - AC3 passthrough, ... - Userspace tools to create new patches and load/unload them can be found - at the above link. You need to get the source snapshot and then type: - - % make tools - % make install-tools - - in the top directory. - + effects which include for example: signal routing, bass/treble + control, AC3 passthrough, ... + Userspace tools to create new patches and load/unload them can be + found at <http://opensource.creative.com/dist.html>. + Creative EMU10K1 MIDI CONFIG_MIDI_EMU10K1 Say Y if you want to be able to use the OSS /dev/sequencer interface. diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/audio.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/audio.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/audio.c Thu Oct 4 22:57:58 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/audio.c Tue Oct 9 20:53:35 2001 @@ -49,7 +49,6 @@ #include "irqmgr.h" #include "audio.h" #include "8010.h" -#include "passthrough.h" static void calculate_ofrag(struct woinst *); static void calculate_ifrag(struct wiinst *); @@ -984,6 +983,9 @@ unsigned long pgoff; int rd, wr; + DPF(4, "emu10k1_mm_nopage()\n"); + DPD(4, "addr: %#lx\n", address); + if (address > vma->vm_end) { DPF(2, "EXIT, returning NOPAGE_SIGBUS\n"); return NOPAGE_SIGBUS; /* Disallow mremap */ @@ -1013,6 +1015,8 @@ } get_page (dmapage); + + DPD(4, "page: %#lx\n", dmapage); return dmapage; } @@ -1023,14 +1027,14 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma) { struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; - unsigned long maxsize, size, offset, pgoffset; + unsigned long max_pages, n_pages, pgoffset; struct woinst *woinst = NULL; struct wiinst *wiinst = NULL; unsigned long flags; DPF(2, "emu10k1_audio_mmap()\n"); - maxsize = 0; + max_pages = 0; if (vma->vm_flags & VM_WRITE) { woinst = wave_dev->woinst; @@ -1053,7 +1057,7 @@ } woinst->mmapped = 1; - maxsize += woinst->buffer.pages * PAGE_SIZE; + max_pages += woinst->buffer.pages; spin_unlock_irqrestore(&woinst->lock, flags); } @@ -1072,21 +1076,23 @@ } wiinst->mmapped = 1; - maxsize += wiinst->buffer.pages * PAGE_SIZE; + max_pages += wiinst->buffer.pages; spin_unlock_irqrestore(&wiinst->lock, flags); } - size = vma->vm_end - vma->vm_start; + n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT; pgoffset = vma->vm_pgoff; - offset = pgoffset << PAGE_SHIFT; - if (offset + size > maxsize) + DPD(3, "vma_start: %#lx, vma_end: %#lx, vma_offset: %d\n", vma->vm_start, vma->vm_end, pgoffset); + DPD(3, "n_pages: %d, max_pages: %d\n", n_pages, max_pages); + + if (pgoffset + n_pages > max_pages) return -EINVAL; vma->vm_flags |= VM_RESERVED; vma->vm_ops = &emu10k1_mm_ops; vma->vm_private_data = wave_dev; - + return 0; } @@ -1240,9 +1246,11 @@ spin_lock_irqsave(&woinst->lock, flags); - if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE) + if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE) { + spin_lock(&card->pt.lock); emu10k1_pt_stop(card); - + spin_unlock(&card->pt.lock); + } if (woinst->state & WAVE_STATE_OPEN) { if (woinst->state & WAVE_STATE_STARTED) { if (!(file->f_flags & O_NONBLOCK)) { @@ -1259,7 +1267,7 @@ } spin_unlock_irqrestore(&woinst->lock, flags); - /* wait for the tasklet (bottom-half) to finish */ + /* remove the tasklet */ tasklet_kill(&woinst->timer.tasklet); kfree(wave_dev->woinst); } @@ -1505,9 +1513,10 @@ spin_unlock_irqrestore(&wiinst->lock, flags); - if (bytestocopy >= wiinst->buffer.fragment_size && waitqueue_active(&wiinst->wait_queue)) - wake_up_interruptible(&wiinst->wait_queue); - else + if (bytestocopy >= wiinst->buffer.fragment_size) { + if (waitqueue_active(&wiinst->wait_queue)) + wake_up_interruptible(&wiinst->wait_queue); + } else DPD(3, "Not enough transfer size, %d\n", bytestocopy); return; @@ -1539,9 +1548,10 @@ } else spin_unlock_irqrestore(&woinst->lock, flags); - if (bytestocopy >= woinst->buffer.fragment_size && waitqueue_active(&woinst->wait_queue)) - wake_up_interruptible(&woinst->wait_queue); - else + if (bytestocopy >= woinst->buffer.fragment_size) { + if (waitqueue_active(&woinst->wait_queue)) + wake_up_interruptible(&woinst->wait_queue); + } else DPD(3, "Not enough transfer size -> %d\n", bytestocopy); return; diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/efxmgr.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/efxmgr.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/efxmgr.c Sat Aug 11 06:02:18 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/efxmgr.c Tue Oct 9 20:53:35 2001 @@ -1,4 +1,4 @@ -/* +/* ********************************************************************** * efxmgr.c * Copyright 1999, 2000 Creative Labs, Inc. @@ -49,7 +49,7 @@ goto match; } - for(i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) { + for (i = 0; i < mgr->current_pages * PATCHES_PER_PAGE; i++) { patch = PATCH(mgr, i); sprintf(s,"%s", patch->name); @@ -97,77 +97,81 @@ //An internal function for setting OSS mixer controls. void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer, - unsigned int left, unsigned int right){ - - extern struct oss_scaling volume_params[SOUND_MIXER_NRDEVICES]; + unsigned int left, unsigned int right) +{ + extern char volume_params[SOUND_MIXER_NRDEVICES]; card->ac97.mixer_state[oss_mixer] = (right << 8) | left; if (!card->isaps) card->ac97.write_mixer(&card->ac97, oss_mixer, left, right); - emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, - volume_params[oss_mixer].scale, - volume_params[oss_mixer].muting); - emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, - volume_params[oss_mixer].scale, - volume_params[oss_mixer].muting); + volume_params[oss_mixer]); + emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, + volume_params[oss_mixer]); } - //FIXME: mute should unmute when pressed a second time void emu10k1_mute_irqhandler(struct emu10k1_card *card) { - struct patch_manager *mgr = &card->mgr; - unsigned long flags; + int oss_channel = VOLCTRL_CHANNEL; + int left, right; + static int val = 0; + + if (val) { + left = val & 0xff; + right = (val >> 8) & 0xff; + val = 0; + } else { + val = card->ac97.mixer_state[oss_channel]; + left = 0; + right = 0; + } - spin_lock_irqsave(&mgr->lock, flags); - emu10k1_set_oss_vol(card,VOLCTRL_CHANNEL,0,0); - spin_unlock_irqrestore(&mgr->lock, flags); + emu10k1_set_oss_vol(card, oss_channel, left, right); } void emu10k1_volincr_irqhandler(struct emu10k1_card *card) { - struct patch_manager *mgr = &card->mgr; - unsigned long flags; - unsigned int oss_channel=VOLCTRL_CHANNEL, left=0,right=0; + int oss_channel = VOLCTRL_CHANNEL; + int left, right; - spin_lock_irqsave(&mgr->lock, flags); left = card->ac97.mixer_state[oss_channel] & 0xff; right = (card->ac97.mixer_state[oss_channel] >> 8) & 0xff; - if((left+=VOLCTRL_STEP_SIZE )>100) - left=100; - if((right+=VOLCTRL_STEP_SIZE )>100) - right=100; - emu10k1_set_oss_vol(card,oss_channel,left,right); - spin_unlock_irqrestore(&mgr->lock, flags); + if ((left += VOLCTRL_STEP_SIZE) > 100) + left = 100; + + if ((right += VOLCTRL_STEP_SIZE) > 100) + right = 100; + + emu10k1_set_oss_vol(card, oss_channel, left, right); } + void emu10k1_voldecr_irqhandler(struct emu10k1_card *card) { - struct patch_manager *mgr = &card->mgr; - unsigned long flags; - int oss_channel=VOLCTRL_CHANNEL, left=0,right=0; + int oss_channel = VOLCTRL_CHANNEL; + int left, right; - spin_lock_irqsave(&mgr->lock, flags); left = card->ac97.mixer_state[oss_channel] & 0xff; right = (card->ac97.mixer_state[oss_channel] >> 8) & 0xff; - if((left-=VOLCTRL_STEP_SIZE )<0) - left=0; - if((right-=VOLCTRL_STEP_SIZE )<0) - right=0; - emu10k1_set_oss_vol(card,oss_channel,left,right); - spin_unlock_irqrestore(&mgr->lock, flags); -} + if ((left -= VOLCTRL_STEP_SIZE) < 0) + left = 0; + if ((right -= VOLCTRL_STEP_SIZE) < 0) + right = 0; -void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale, int muting) + emu10k1_set_oss_vol(card, oss_channel, left, right); +} + +void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int scale) { struct patch_manager *mgr = &card->mgr; unsigned long flags; + int muting; const s32 log2lin[5] ={ // attenuation (dB) 0x7fffffff, // 0.0 @@ -179,10 +183,12 @@ if (addr < 0) return; + muting = (scale == 0x10) ? 0x7f: scale; + vol = (100 - vol ) * scale / 100; // Thanks to the comp.dsp newsgroup for this neat trick: - vol = vol >= muting ? 0: log2lin[vol&3]>>(vol>>2); + vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); spin_lock_irqsave(&mgr->lock, flags); emu10k1_set_control_gpr(card, addr, vol, 0); @@ -197,15 +203,16 @@ u32 bc; bc = sblive_readptr(card, GPR_BASE + card->pt.intr_gpr, 0); if (bc != 0) { - spin_lock_irqsave(&card->lock, flags); + DPD(3, "pt interrupt, bc = %d\n", bc); + spin_lock_irqsave(&card->pt.lock, flags); card->pt.blocks_played = bc; if (card->pt.blocks_played >= card->pt.blocks_copied) { DPF(1, "buffer underrun in passthrough playback\n"); emu10k1_pt_stop(card); } wake_up_interruptible(&card->pt.wait); - spin_unlock_irqrestore(&card->lock, flags); - DPD(3, "pt interrupt, bc = %d\n", bc); + spin_unlock_irqrestore(&card->pt.lock, flags); } } } + diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/efxmgr.h linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/efxmgr.h --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/efxmgr.h Sat Aug 11 06:02:18 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/efxmgr.h Tue Oct 9 20:53:35 2001 @@ -66,7 +66,8 @@ u32 gpr_used[NUM_GPRS / 32]; /* bitmap of used gprs */ u32 gpr_input[NUM_GPRS / 32]; - u8 traml_istart; /* starting address of the internal tram lines used */ u8 traml_isize; /* number of internal tram lines used */ + u8 traml_istart; /* starting address of the internal tram lines used */ + u8 traml_isize; /* number of internal tram lines used */ u8 traml_estart; u8 traml_esize; @@ -97,10 +98,6 @@ #define GPR_BASE 0x100 #define OUTPUT_BASE 0x20 -//We can get this info by looking at the code start -//#define PATCH_TYPE_INPUT 0x1 -//#define PATCH_TYPE_OUTPUT 0x2 - #define MAX_PATCHES_PAGES 32 struct patch_manager { @@ -139,6 +136,14 @@ #define PCM1_IN_L 0x04 #define PCM1_IN_R 0x05 +//mutilchannel playback stream appear here: + +#define MULTI_FRONT_L 0x08 +#define MULTI_FRONT_R 0x09 +#define MULTI_REAR_L 0x0a +#define MULTI_REAR_R 0x0b +#define MULTI_CENTER 0x0c +#define MULTI_LFE 0x0d #define AC97_IN_L 0x10 #define AC97_IN_R 0x11 @@ -150,10 +155,17 @@ #define AC97_FRONT_R 0x21 #define DIGITAL_OUT_L 0x22 #define DIGITAL_OUT_R 0x23 +#define DIGITAL_CENTER 0x24 +#define DIGITAL_LFE 0x25 + #define ANALOG_REAR_L 0x28 #define ANALOG_REAR_R 0x29 #define ADC_REC_L 0x2a #define ADC_REC_R 0x2b + +#define ANALOG_CENTER 0x31 +#define ANALOG_LFE 0x32 + #define INPUT_PATCH_START(patch, nm, ln, i) \ do { \ diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/hwaccess.h linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/hwaccess.h --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/hwaccess.h Wed Aug 15 10:22:16 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/hwaccess.h Tue Oct 9 20:53:35 2001 @@ -38,8 +38,8 @@ #include <linux/ac97_codec.h> #include <linux/pci.h> -#include "passthrough.h" #include "efxmgr.h" +#include "passthrough.h" #include "midi.h" #define EMUPAGESIZE 4096 /* don't change */ @@ -122,10 +122,10 @@ #define CMD_SETGPR2OSS _IOW('D', 16, struct mixer_private_ioctl) #define CMD_SETMCH_FX _IOW('D', 17, struct mixer_private_ioctl) #define CMD_SETPASSTHROUGH _IOW('D', 18, struct mixer_private_ioctl) +#define CMD_PRIVATE3_VERSION _IOW('D', 19, struct mixer_private_ioctl) -struct oss_scaling { - char scale, muting; -}; +//up this number when breaking compatibility +#define PRIVATE3_VERSION 1 struct emu10k1_card { @@ -192,12 +192,12 @@ int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *); void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int ); -void emu10k1_set_volume_gpr(struct emu10k1_card *, int, s32, int, int); +void emu10k1_set_volume_gpr(struct emu10k1_card *, int, s32, int); -#define VOL_6BIT 0x40,0x40 -#define VOL_5BIT 0x20,0x20 -#define VOL_4BIT 0x10,0x7f +#define VOL_6BIT 0x40 +#define VOL_5BIT 0x20 +#define VOL_4BIT 0x10 #define TIMEOUT 16384 diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/main.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/main.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/main.c Tue Oct 9 20:49:30 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/main.c Tue Oct 9 20:53:35 2001 @@ -66,7 +66,10 @@ * Added Support for 5.1 cards (digital out and the third analog out) * 0.15 Added Sequencer Support (Daniel Mack) * Support for multichannel pcm playback (Eduard Hasenleithner) - * + * 0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand) + * Small code format cleanup. + * Deadlock bug fix for emu10k1_volxxx_irqhandler(). + * *********************************************************************/ /* These are only included once per module */ @@ -99,7 +102,7 @@ #define SNDCARD_EMU10K1 46 #endif -#define DRIVER_VERSION "0.15" +#define DRIVER_VERSION "0.16" /* FIXME: is this right? */ /* does the card support 32 bit bus master?*/ @@ -216,7 +219,7 @@ card->ac97.private_data = card; - if(!card->isaps) { + if (!card->isaps) { card->ac97.id = 0; card->ac97.codec_read = emu10k1_ac97_read; card->ac97.codec_write = emu10k1_ac97_write; @@ -227,8 +230,10 @@ } /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version does not support this, it shouldn't do any harm */ - sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); - + sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE); + + // Force 5bit + //card->ac97.bit_resolution=5; if (!proc_mkdir ("driver/emu10k1", 0)) { printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n"); @@ -247,6 +252,7 @@ goto err_ac97_proc; } + /* these will store the original values and never be modified */ card->ac97_supported_mixers = card->ac97.supported_mixers; card->ac97_stereo_mixers = card->ac97.stereo_mixers; } @@ -268,7 +274,7 @@ { char s[32]; - if(!card->isaps) { + if (!card->isaps) { sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name); remove_proc_entry(s, NULL); @@ -333,7 +339,7 @@ #ifdef EMU10K1_SEQUENCER card->seq_dev = sound_alloc_mididev(); - if(card->seq_dev == -1) + if (card->seq_dev == -1) printk(KERN_WARNING "emu10k1: unable to register sequencer device!"); else { std_midi_synth.midi_dev = card->seq_dev; @@ -341,22 +347,21 @@ (struct midi_operations *) kmalloc(sizeof(struct midi_operations), GFP_KERNEL); - if(midi_devs[card->seq_dev] == NULL) { - printk(KERN_ERR "emu10k1: unable to allocate memory!"); - sound_unload_mididev(card->seq_dev); - card->seq_dev = -1; - return 0; + if (midi_devs[card->seq_dev] == NULL) { + printk(KERN_ERR "emu10k1: unable to allocate memory!"); + sound_unload_mididev(card->seq_dev); + card->seq_dev = -1; + return 0; } else { - memcpy((char *)midi_devs[card->seq_dev], - (char *)&emu10k1_midi_operations, - sizeof(struct midi_operations)); - midi_devs[card->seq_dev]->devc = card; - sequencer_init(); + memcpy((char *)midi_devs[card->seq_dev], + (char *)&emu10k1_midi_operations, + sizeof(struct midi_operations)); + midi_devs[card->seq_dev]->devc = card; + sequencer_init(); } } card->seq_mididev = 0; #endif - return 0; err_out3: @@ -370,19 +375,19 @@ static void __devinit emu10k1_midi_cleanup(struct emu10k1_card *card) { - tasklet_kill(&card->mpuout->tasklet); - kfree(card->mpuout); + tasklet_kill(&card->mpuout->tasklet); + kfree(card->mpuout); - tasklet_kill(&card->mpuin->tasklet); - kfree(card->mpuin); + tasklet_kill(&card->mpuin->tasklet); + kfree(card->mpuin); #ifdef EMU10K1_SEQUENCER - if(card->seq_dev > -1) { - kfree(midi_devs[card->seq_dev]); - midi_devs[card->seq_dev] = NULL; - sound_unload_mididev(card->seq_dev); - card->seq_dev = -1; - } + if (card->seq_dev > -1) { + kfree(midi_devs[card->seq_dev]); + midi_devs[card->seq_dev] = NULL; + sound_unload_mididev(card->seq_dev); + card->seq_dev = -1; + } #endif unregister_sound_midi(card->midi_dev); @@ -447,91 +452,152 @@ TANKMEMADDRREGBASE + i, 0, TAGLIST_END); - mgr->current_pages = 5 / PATCHES_PER_PAGE + 1; - for(i = 0; i < mgr->current_pages; i++) { - mgr->patch[i] = (void *)__get_free_pages(GFP_KERNEL, 1); - if (mgr->patch[i] == NULL) { - mgr->current_pages = i; - fx_cleanup(mgr); - return -ENOMEM; - } - memset(mgr->patch[i], 0, PAGE_SIZE); - } + /* !! The number bellow must equal the number of patches, currently 11 !! */ + mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE; + for (i = 0; i < mgr->current_pages; i++) { + mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL); + if (mgr->patch[i] == NULL) { + mgr->current_pages = i; + fx_cleanup(mgr); + return -ENOMEM; + } + memset(mgr->patch[i], 0, PAGE_SIZE); + } pc = 0; patch_n = 0; + //first free GPR = 0x11b - /* FX volume correction */ - INPUT_PATCH_START(patch, "Pcm L vol correction", 0x0, 0); + /* FX volume correction and Volume control*/ + INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0); GET_OUTPUT_GPR(patch, 0x100, 0x0); - - OP(4, 0x100, 0x40, PCM_IN_L, 0x44); + GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff); + GET_DYNAMIC_GPR(patch, 0x112); + + OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4 + OP(0, 0x100, 0x040, 0x112, 0x106); //*vol INPUT_PATCH_END(patch); - INPUT_PATCH_START(patch, "Pcm R vol correction", 0x1, 0); + INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0); GET_OUTPUT_GPR(patch, 0x101, 0x1); + GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff); + GET_DYNAMIC_GPR(patch, 0x112); + + OP(4, 0x112, 0x40, PCM_IN_R, 0x44); + OP(0, 0x101, 0x040, 0x112, 0x107); - OP(4, 0x101, 0x40, PCM_IN_R, 0x44); INPUT_PATCH_END(patch); + // CD-Digital In Volume control + INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0); + GET_OUTPUT_GPR(patch, 0x10c, 0x12); + GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff); + + OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d); + INPUT_PATCH_END(patch); + + INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0); + GET_OUTPUT_GPR(patch, 0x10e, 0x13); + GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff); + + OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f); + INPUT_PATCH_END(patch); + + //Volume Correction for Multi-channel Inputs + INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0); + patch->input=patch->output=0x3F00; + + GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L); + GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R); + GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L); + GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R); + GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER); + GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE); + + OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44); + OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44); + OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44); + OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44); + OP(4, 0x117, 0x40, MULTI_CENTER, 0x44); + OP(4, 0x118, 0x40, MULTI_LFE, 0x44); + + INPUT_PATCH_END(patch); + + + //Routing patch start ROUTING_PATCH_START(rpatch, "Routing"); GET_INPUT_GPR(rpatch, 0x100, 0x0); GET_INPUT_GPR(rpatch, 0x101, 0x1); + GET_INPUT_GPR(rpatch, 0x10c, 0x12); + GET_INPUT_GPR(rpatch, 0x10e, 0x13); + GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L); + GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R); + GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L); + GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R); + GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER); + GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE); - GET_DYNAMIC_GPR(rpatch, 0x102); - GET_DYNAMIC_GPR(rpatch, 0x103); + GET_DYNAMIC_GPR(rpatch, 0x102); + GET_DYNAMIC_GPR(rpatch, 0x103); GET_OUTPUT_GPR(rpatch, 0x104, 0x8); GET_OUTPUT_GPR(rpatch, 0x105, 0x9); GET_OUTPUT_GPR(rpatch, 0x10a, 0x2); GET_OUTPUT_GPR(rpatch, 0x10b, 0x3); - GET_CONTROL_GPR(rpatch, 0x106, "Vol Pcm L:Rear L", 0, 0x7fffffff); - GET_CONTROL_GPR(rpatch, 0x107, "Vol Pcm R:Rear R", 0, 0x7fffffff); /* input buffer */ OP(6, 0x102, AC97_IN_L, 0x40, 0x40); OP(6, 0x103, AC97_IN_R, 0x40, 0x40); - /* Digital In + PCM --> AC97 out (front speakers)*/ - OP(6, AC97_FRONT_L, 0x100, SPDIF_CD_L, 0x40); + /* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/ + OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113); + + CONNECT(MULTI_FRONT_L, AC97_FRONT_L); CONNECT(PCM_IN_L, AC97_FRONT_L); - CONNECT(SPDIF_CD_L, AC97_FRONT_L); + CONNECT(SPDIF_CD_L, AC97_FRONT_L); - OP(6, AC97_FRONT_R, 0x101, SPDIF_CD_R, 0x40); + OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114); + CONNECT(MULTI_FRONT_R, AC97_FRONT_R); CONNECT(PCM_IN_R, AC97_FRONT_R); CONNECT(SPDIF_CD_R, AC97_FRONT_R); - /* Digital In + PCM + AC97 In + PCM1 --> Rear Channel */ - OP(0, 0x104, PCM1_IN_L, 0x100, 0x106); - OP(6, 0x104, 0x104, SPDIF_CD_L, 0x102); + /* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ + OP(6, 0x104, PCM1_IN_L, 0x100, 0x115); + OP(6, 0x104, 0x104, 0x10c, 0x102); + CONNECT(MULTI_REAR_L, ANALOG_REAR_L); CONNECT(AC97_IN_L, ANALOG_REAR_L); - CONNECT_V(PCM_IN_L, ANALOG_REAR_L); + CONNECT(PCM_IN_L, ANALOG_REAR_L); CONNECT(SPDIF_CD_L, ANALOG_REAR_L); CONNECT(PCM1_IN_L, ANALOG_REAR_L); - OP(0, 0x105, PCM1_IN_R, 0x101, 0x107); - OP(6, 0x105, 0x105, SPDIF_CD_R, 0x103); + OP(6, 0x105, PCM1_IN_R, 0x101, 0x116); + OP(6, 0x105, 0x105, 0x10e, 0x103); + CONNECT(MULTI_REAR_R, ANALOG_REAR_R); CONNECT(AC97_IN_R, ANALOG_REAR_R); - CONNECT_V(PCM_IN_R, ANALOG_REAR_R); - CONNECT(SPDIF_CD_R, ANALOG_REAR_R); + CONNECT(PCM_IN_R, ANALOG_REAR_R); + CONNECT(SPDIF_CD_R, ANALOG_REAR_R); CONNECT(PCM1_IN_R, ANALOG_REAR_R); - /* Digital In + PCM + AC97 In --> Digital out */ - OP(6, 0x10b, 0x100, 0x102, SPDIF_CD_L); + /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */ + OP(6, 0x10b, 0x100, 0x102, 0x10c); + OP(6, 0x10b, 0x10b, 0x113, 0x40); + CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L); CONNECT(PCM_IN_L, DIGITAL_OUT_L); - CONNECT(AC97_IN_L, DIGITAL_OUT_L); - CONNECT(SPDIF_CD_L, DIGITAL_OUT_L); + CONNECT(AC97_IN_L, DIGITAL_OUT_L); + CONNECT(SPDIF_CD_L, DIGITAL_OUT_L); - OP(6, 0x10a, 0x101, 0x103, SPDIF_CD_R); + OP(6, 0x10a, 0x101, 0x103, 0x10e); + OP(6, 0x10b, 0x10b, 0x114, 0x40); + CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R); CONNECT(PCM_IN_R, DIGITAL_OUT_R); CONNECT(AC97_IN_R, DIGITAL_OUT_R); CONNECT(SPDIF_CD_R, DIGITAL_OUT_R); @@ -545,23 +611,40 @@ CONNECT(AC97_IN_R, ADC_REC_R); + + /* fx12:Analog-Center */ + OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40); + CONNECT(MULTI_CENTER, ANALOG_CENTER); + + /* fx11:Analog-LFE */ + OP(6, ANALOG_LFE, 0x118, 0x40, 0x40); + CONNECT(MULTI_LFE, ANALOG_LFE); + + /* fx12:Digital-Center */ + OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40); + CONNECT(MULTI_CENTER, DIGITAL_CENTER); + + /* fx11:Analog-LFE */ + OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40); + CONNECT(MULTI_LFE, DIGITAL_LFE); + ROUTING_PATCH_END(rpatch); - // Master volume control on rear - OUTPUT_PATCH_START(patch, "Vol Master L", 0x8, 0); + // Rear volume control + OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0); GET_INPUT_GPR(patch, 0x104, 0x8); - GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff); + GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff); - OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x108); + OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119); OUTPUT_PATCH_END(patch); - OUTPUT_PATCH_START(patch, "Vol Master R", 0x9, 0); + OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0); GET_INPUT_GPR(patch, 0x105, 0x9); - GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff); + GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff); - OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x109); + OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a); OUTPUT_PATCH_END(patch); @@ -573,7 +656,7 @@ OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108); OUTPUT_PATCH_END(patch); - + OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1); GET_INPUT_GPR(patch, 0x10b, 0x3); GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff); @@ -590,24 +673,62 @@ mgr->lock = SPIN_LOCK_UNLOCKED; + + //Master volume mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8; mgr->ctrl_gpr[SOUND_MIXER_VOLUME][1] = 9; left = card->ac97.mixer_state[SOUND_MIXER_VOLUME] & 0xff; right = (card->ac97.mixer_state[SOUND_MIXER_VOLUME] >> 8) & 0xff; - emu10k1_set_volume_gpr(card, 8, left, VOL_6BIT); - emu10k1_set_volume_gpr(card, 9, right, VOL_6BIT); + emu10k1_set_volume_gpr(card, 8, left, 1 << card->ac97.bit_resolution); + emu10k1_set_volume_gpr(card, 9, right, 1 << card->ac97.bit_resolution); + + //Rear volume + mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][0] = 0x19; + mgr->ctrl_gpr[ SOUND_MIXER_OGAIN ][1] = 0x1a; + + left = right = 67; + card->ac97.mixer_state[SOUND_MIXER_OGAIN] = (right << 8) | left; + card->ac97.supported_mixers |= SOUND_MASK_OGAIN; + card->ac97.stereo_mixers |= SOUND_MASK_OGAIN; + + emu10k1_set_volume_gpr(card, 0x19, left, VOL_5BIT); + emu10k1_set_volume_gpr(card, 0x1a, right, VOL_5BIT); + + //PCM Volume mgr->ctrl_gpr[SOUND_MIXER_PCM][0] = 6; mgr->ctrl_gpr[SOUND_MIXER_PCM][1] = 7; left = card->ac97.mixer_state[SOUND_MIXER_PCM] & 0xff; right = (card->ac97.mixer_state[SOUND_MIXER_PCM] >> 8) & 0xff; - emu10k1_set_volume_gpr(card, 6, left, VOL_5BIT); + emu10k1_set_volume_gpr(card, 6, left, VOL_5BIT); emu10k1_set_volume_gpr(card, 7, right, VOL_5BIT); + //CD-Digital Volume + mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][0] = 0xd; + mgr->ctrl_gpr[SOUND_MIXER_DIGITAL1][1] = 0xf; + + left = right = 67; + card->ac97.mixer_state[SOUND_MIXER_DIGITAL1] = (right << 8) | left; + + card->ac97.supported_mixers |= SOUND_MASK_DIGITAL1; + card->ac97.stereo_mixers |= SOUND_MASK_DIGITAL1; + + emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT); + emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT); + + //hard wire the ac97's pcm, we'll do that in dsp code instead. + emu10k1_ac97_write(&card->ac97, 0x18, 0x0); + card->ac97_supported_mixers &= ~SOUND_MASK_PCM; + card->ac97_stereo_mixers &= ~SOUND_MASK_PCM; + + //set Igain to 0dB by default, maybe consider hardwiring it here. + emu10k1_ac97_write(&card->ac97, AC97_RECORD_GAIN, 0x0000); + card->ac97.mixer_state[SOUND_MIXER_IGAIN] = 0x101; + return 0; } @@ -775,6 +896,7 @@ card->pt.intr_gpr_name = "count"; card->pt.enable_gpr_name = "enable"; card->pt.pos_gpr_name = "ptr"; + spin_lock_init(&card->pt.lock); init_waitqueue_head(&card->pt.wait); /* tmp = sblive_readfn0(card, HCFG); @@ -1040,8 +1162,8 @@ static struct midi_operations emu10k1_midi_operations = { - THIS_MODULE, - {"EMU10K1 MIDI", 0, 0, SNDCARD_EMU10K1}, + THIS_MODULE, + {"EMU10K1 MIDI", 0, 0, SNDCARD_EMU10K1}, &std_midi_synth, {0}, emu10k1_seq_midi_open, @@ -1057,4 +1179,3 @@ }; #endif - diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/midi.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/midi.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/midi.c Sun Aug 12 19:25:31 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/midi.c Tue Oct 9 20:53:35 2001 @@ -94,7 +94,6 @@ DPF(2, "emu10k1_midi_open()\n"); - /* Check for correct device to open */ list_for_each(entry, &emu10k1_devs) { card = list_entry(entry, struct emu10k1_card, list); @@ -107,10 +106,9 @@ match: #ifdef EMU10K1_SEQUENCER - if(card->seq_mididev) /* card is opened by sequencer */ - return -EBUSY; + if (card->seq_mididev) /* card is opened by sequencer */ + return -EBUSY; #endif - /* Wait for device to become free */ down(&card->open_sem); @@ -130,9 +128,8 @@ down(&card->open_sem); } - if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) { + if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) return -EINVAL; - } midi_dev->card = card; midi_dev->mistate = MIDIIN_STATE_STOPPED; @@ -244,7 +241,6 @@ wake_up_interruptible(&card->open_wait); unlock_kernel(); - return 0; } @@ -462,24 +458,22 @@ void (*input) (int dev, unsigned char data), void (*output) (int dev)) { - struct emu10k1_card *card; - struct midi_openinfo dsCardMidiOpenInfo; + struct emu10k1_card *card; + struct midi_openinfo dsCardMidiOpenInfo; struct emu10k1_mididevice *midi_dev; - - if( midi_devs[dev] == NULL - || midi_devs[dev]->devc == NULL) - return -EINVAL; + + if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) + return -EINVAL; card = midi_devs[dev]->devc; - if(card->open_mode) /* card is opened native */ - return -EBUSY; + if (card->open_mode) /* card is opened native */ + return -EBUSY; DPF(2, "emu10k1_seq_midi_open()\n"); - if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) { + if ((midi_dev = (struct emu10k1_mididevice *) kmalloc(sizeof(*midi_dev), GFP_KERNEL)) == NULL) return -EINVAL; - } midi_dev->card = card; midi_dev->mistate = MIDIIN_STATE_STOPPED; @@ -492,10 +486,10 @@ dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev; - if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { - ERROR(); - return -ENODEV; - } + if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) { + ERROR(); + return -ENODEV; + } card->seq_mididev = midi_dev; @@ -507,29 +501,26 @@ struct emu10k1_card *card; DPF(2, "emu10k1_seq_midi_close()\n"); - if( midi_devs[dev] == NULL - || midi_devs[dev]->devc == NULL) - return; + if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) + return; card = midi_devs[dev]->devc; emu10k1_mpuout_close(card); - if(card->seq_mididev) { - kfree(card->seq_mididev); - card->seq_mididev = 0; + if (card->seq_mididev) { + kfree(card->seq_mididev); + card->seq_mididev = 0; } } int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) { - struct emu10k1_card *card; struct midi_hdr *midihdr; unsigned long flags; - if( midi_devs[dev] == NULL - || midi_devs[dev]->devc == NULL) - return -EINVAL; + if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) + return -EINVAL; card = midi_devs[dev]->devc; @@ -583,21 +574,22 @@ struct midi_queue *queue; struct emu10k1_card *card; - if( midi_devs[dev] == NULL - || midi_devs[dev]->devc == NULL) - return -EINVAL; + if (midi_devs[dev] == NULL || midi_devs[dev]->devc == NULL) + return -EINVAL; count = 0; - + card = midi_devs[dev]->devc; queue = card->mpuout->firstmidiq; - while(queue != NULL) { - count++; - if(queue == card->mpuout->lastmidiq) - break; - queue = queue->next; + while (queue != NULL) { + count++; + if (queue == card->mpuout->lastmidiq) + break; + + queue = queue->next; } + return count; } diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/mixer.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/mixer.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/mixer.c Sat Aug 11 06:02:19 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/mixer.c Tue Oct 9 20:53:35 2001 @@ -40,44 +40,149 @@ #include "8010.h" #include "recmgr.h" -//FIXME: SOUND_MIXER_VOLUME should be selectable 5 or 6 bit -const struct oss_scaling volume_params[SOUND_MIXER_NRDEVICES]= { -/* Used by the ac97 driver */ - [SOUND_MIXER_VOLUME] = {VOL_6BIT}, - [SOUND_MIXER_BASS] = {VOL_4BIT}, - [SOUND_MIXER_TREBLE] = {VOL_4BIT}, - [SOUND_MIXER_PCM] = {VOL_5BIT}, - [SOUND_MIXER_SPEAKER] = {VOL_4BIT}, - [SOUND_MIXER_LINE] = {VOL_5BIT}, - [SOUND_MIXER_MIC] = {VOL_5BIT}, - [SOUND_MIXER_CD] = {VOL_5BIT}, - [SOUND_MIXER_ALTPCM] = {VOL_6BIT}, - [SOUND_MIXER_IGAIN] = {VOL_4BIT}, - [SOUND_MIXER_LINE1] = {VOL_5BIT}, - [SOUND_MIXER_PHONEIN] = {VOL_5BIT}, - [SOUND_MIXER_PHONEOUT] = {VOL_6BIT}, - [SOUND_MIXER_VIDEO] = {VOL_5BIT}, -/* Not used by the ac97 driver */ - [SOUND_MIXER_SYNTH] = {VOL_5BIT}, - [SOUND_MIXER_IMIX] = {VOL_5BIT}, - [SOUND_MIXER_RECLEV] = {VOL_5BIT}, - [SOUND_MIXER_OGAIN] = {VOL_5BIT}, - [SOUND_MIXER_LINE2] = {VOL_5BIT}, - [SOUND_MIXER_LINE3] = {VOL_5BIT}, - [SOUND_MIXER_DIGITAL1] = {VOL_5BIT}, - [SOUND_MIXER_DIGITAL2] = {VOL_5BIT}, - [SOUND_MIXER_DIGITAL3] = {VOL_5BIT}, - [SOUND_MIXER_RADIO] = {VOL_5BIT}, - [SOUND_MIXER_MONITOR] = {VOL_5BIT} + +static const u32 bass_table[41][5] = { + { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 }, + { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d }, + { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee }, + { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c }, + { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b }, + { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 }, + { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f }, + { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 }, + { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 }, + { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 }, + { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 }, + { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be }, + { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b }, + { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c }, + { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b }, + { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 }, + { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a }, + { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 }, + { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 }, + { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e }, + { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee }, + { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 }, + { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 }, + { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 }, + { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 }, + { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e }, + { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 }, + { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 }, + { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 }, + { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 }, + { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 }, + { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca }, + { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 }, + { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 }, + { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 }, + { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 }, + { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a }, + { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f }, + { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 }, + { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 }, + { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 } +}; + +static const u32 treble_table[41][5] = { + { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 }, + { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 }, + { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 }, + { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca }, + { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 }, + { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 }, + { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 }, + { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 }, + { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 }, + { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df }, + { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff }, + { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 }, + { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c }, + { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 }, + { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 }, + { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 }, + { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 }, + { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d }, + { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 }, + { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 }, + { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f }, + { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb }, + { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 }, + { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 }, + { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd }, + { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 }, + { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad }, + { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 }, + { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 }, + { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c }, + { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 }, + { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 }, + { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 }, + { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 }, + { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 }, + { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 }, + { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d }, + { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b }, + { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 }, + { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd }, + { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } }; -static loff_t emu10k1_mixer_llseek(struct file *file, loff_t offset, int origin) + + +static void set_bass(struct emu10k1_card *card, int l, int r) { - DPF(2, "sblive_mixer_llseek() called\n"); - return -ESPIPE; + int i; + + l = (l * 40 + 50) / 100; + r = (r * 40 + 50) / 100; + + for (i = 0; i < 5; i++) + sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]); } -/* Mixer file operations */ +static void set_treble(struct emu10k1_card *card, int l, int r) +{ + int i; + + l = (l * 40 + 50) / 100; + r = (r * 40 + 50) / 100; + + for (i = 0; i < 5; i++) + sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]); +} + +const char volume_params[SOUND_MIXER_NRDEVICES]= { +/* Used by the ac97 driver */ + [SOUND_MIXER_VOLUME] = VOL_6BIT, + [SOUND_MIXER_BASS] = VOL_4BIT, + [SOUND_MIXER_TREBLE] = VOL_4BIT, + [SOUND_MIXER_PCM] = VOL_5BIT, + [SOUND_MIXER_SPEAKER] = VOL_4BIT, + [SOUND_MIXER_LINE] = VOL_5BIT, + [SOUND_MIXER_MIC] = VOL_5BIT, + [SOUND_MIXER_CD] = VOL_5BIT, + [SOUND_MIXER_ALTPCM] = VOL_6BIT, + [SOUND_MIXER_IGAIN] = VOL_4BIT, + [SOUND_MIXER_LINE1] = VOL_5BIT, + [SOUND_MIXER_PHONEIN] = VOL_5BIT, + [SOUND_MIXER_PHONEOUT] = VOL_6BIT, + [SOUND_MIXER_VIDEO] = VOL_5BIT, +/* Not used by the ac97 driver */ + [SOUND_MIXER_SYNTH] = VOL_5BIT, + [SOUND_MIXER_IMIX] = VOL_5BIT, + [SOUND_MIXER_RECLEV] = VOL_5BIT, + [SOUND_MIXER_OGAIN] = VOL_5BIT, + [SOUND_MIXER_LINE2] = VOL_5BIT, + [SOUND_MIXER_LINE3] = VOL_5BIT, + [SOUND_MIXER_DIGITAL1] = VOL_5BIT, + [SOUND_MIXER_DIGITAL2] = VOL_5BIT, + [SOUND_MIXER_DIGITAL3] = VOL_5BIT, + [SOUND_MIXER_RADIO] = VOL_5BIT, + [SOUND_MIXER_MONITOR] = VOL_5BIT +}; +/* Mixer file operations */ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg) { struct mixer_private_ioctl *ctl; @@ -150,17 +255,23 @@ ret = -EINVAL; break; } + card->wavein.recsrc = WAVERECORD_AC97; break; + case WAVERECORD_MIC: card->wavein.recsrc = WAVERECORD_MIC; break; + case WAVERECORD_FX: card->wavein.recsrc = WAVERECORD_FX; card->wavein.fxwc = ctl->val[1] & 0xffff; + if (!card->wavein.fxwc) ret = -EINVAL; + break; + default: ret = -EINVAL; break; @@ -267,8 +378,8 @@ } if (page >= card->mgr.current_pages) { - for(i = card->mgr.current_pages; i < page + 1; i++) { - card->mgr.patch[i] = (void *)__get_free_pages(GFP_KERNEL, 1); + for (i = card->mgr.current_pages; i < page + 1; i++) { + card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL); if(card->mgr.patch[i] == NULL) { card->mgr.current_pages = i; ret = -ENOMEM; @@ -283,7 +394,7 @@ memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch)); - if(patch->code_size == 0) { + if (patch->code_size == 0) { for(i = page + 1; i < card->mgr.current_pages; i++) free_page((unsigned long) card->mgr.patch[i]); @@ -306,13 +417,13 @@ emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0); break; - case CMD_SETGPOUT: - if( ctl->val[0]>2 || ctl->val[1]>1){ + if (ctl->val[0] > 2 || ctl->val[1] > 1) { ret= -EINVAL; break; } - emu10k1_writefn0(card, (1<<24)| (((ctl->val[0])+10)<<16 ) | HCFG ,ctl->val[1]); + + emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]); break; case CMD_GETGPR2OSS: @@ -328,6 +439,7 @@ if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; + break; case CMD_SETGPR2OSS: @@ -350,30 +462,43 @@ if (ch) { state >>= 8; - card->ac97.stereo_mixers |= (1<<id); + card->ac97.stereo_mixers |= (1 << id); } else { - card->ac97.supported_mixers |= (1<<id); + card->ac97.supported_mixers |= (1 << id); } - emu10k1_set_volume_gpr(card, addr, state & 0xff, - volume_params[id].scale, - volume_params[id].muting); + if (id == SOUND_MIXER_TREBLE) { + set_treble(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff); + } else if (id == SOUND_MIXER_BASS) { + set_bass(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff); + } else + emu10k1_set_volume_gpr(card, addr, state & 0xff, + volume_params[id]); } else { if (ch) { - card->ac97.stereo_mixers &= ~(1<<id); + card->ac97.stereo_mixers &= ~(1 << id); card->ac97.stereo_mixers |= card->ac97_stereo_mixers; } else { - card->ac97.supported_mixers &= ~(1<<id); + card->ac97.supported_mixers &= ~(1 << id); card->ac97.supported_mixers |= card->ac97_supported_mixers; } } break; + case CMD_SETPASSTHROUGH: card->pt.selected = ctl->val[0] ? 1 : 0; if (card->pt.state != PT_STATE_INACTIVE) break; + card->pt.spcs_to_use = ctl->val[0] & 0x07; break; + + case CMD_PRIVATE3_VERSION: + ctl->val[0]=PRIVATE3_VERSION; + if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl))) + ret = -EFAULT; + break; + default: ret = -EINVAL; break; @@ -441,42 +566,75 @@ return -EINVAL; } +static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer, unsigned long arg) +{ + unsigned int left, right; + int val; + int scale; + + if (get_user(val, (int *)arg)) + return -EFAULT; + + /* cleanse input a little */ + right = ((val >> 8) & 0xff); + left = (val & 0xff); + + if (right > 100) right = 100; + if (left > 100) left = 100; + + card->ac97.mixer_state[oss_mixer] = (right << 8) | left; + if (oss_mixer == SOUND_MIXER_TREBLE) { + set_treble(card, left, right); + return 0; + } if (oss_mixer == SOUND_MIXER_BASS) { + set_bass(card, left, right); + return 0; + } + + if (oss_mixer == SOUND_MIXER_VOLUME) + scale = 1 << card->ac97.bit_resolution; + else + scale = volume_params[oss_mixer]; + + emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, scale); + emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, scale); + + if (card->ac97_supported_mixers & (1 << oss_mixer)) + card->ac97.write_mixer(&card->ac97, oss_mixer, left, right); + + return 0; +} - static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret; struct emu10k1_card *card = file->private_data; - + unsigned int oss_mixer = _IOC_NR(cmd); + ret = -EINVAL; - if (!card->isaps) - ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg); - - if (ret < 0) - ret = emu10k1_private_mixer(card, cmd, arg); - else{ - unsigned int oss_mixer, left, right; - - oss_mixer = _IOC_NR(cmd); + if (!card->isaps) { + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + + strncpy(info.id, card->ac97.name, sizeof(info.id)); + strncpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name)); + info.modify_counter = card->ac97.modcnt; - if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer<=SOUND_MIXER_NRDEVICES ) { + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; - left = card->ac97.mixer_state[oss_mixer] & 0xff; - right = (card->ac97.mixer_state[oss_mixer] >> 8) & 0xff; - if(card->ac97.supported_mixers|(1<<oss_mixer)) - emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, - volume_params[oss_mixer].scale, - volume_params[oss_mixer].muting); - if(card->ac97.stereo_mixers |(1<<oss_mixer)) - emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, - volume_params[oss_mixer].scale, - volume_params[oss_mixer].muting); + return 0; } - + + if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES) + ret = emu10k1_dsp_mixer(card, oss_mixer, arg); + else + ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg); } - - + if (ret < 0) + ret = emu10k1_private_mixer(card, cmd, arg); + return ret; } @@ -510,7 +668,7 @@ struct file_operations emu10k1_mixer_fops = { owner: THIS_MODULE, - llseek: emu10k1_mixer_llseek, + llseek: no_llseek, ioctl: emu10k1_mixer_ioctl, open: emu10k1_mixer_open, release: emu10k1_mixer_release, diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/passthrough.c linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/passthrough.c --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/passthrough.c Thu Oct 4 22:57:58 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/passthrough.c Tue Oct 9 20:53:35 2001 @@ -47,7 +47,6 @@ #include "irqmgr.h" #include "audio.h" #include "8010.h" -#include "passthrough.h" static void pt_putsamples(struct pt_data *pt, u16 *ptr, u16 left, u16 right) { @@ -209,9 +208,7 @@ { struct pt_data *pt = &card->pt; int i; - unsigned long flags; - spin_lock_irqsave(&card->pt.lock, flags); if (pt->state != PT_STATE_INACTIVE) { DPF(2, "digital pass-through stopped\n"); sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 0); @@ -222,7 +219,6 @@ pt->state = PT_STATE_INACTIVE; kfree(pt->buf); } - spin_unlock_irqrestore(&card->pt.lock, flags); } void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev) diff -ur linux-2.4.11pre6.orig/drivers/sound/emu10k1/passthrough.h linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/passthrough.h --- linux-2.4.11pre6.orig/drivers/sound/emu10k1/passthrough.h Sun Aug 12 19:25:31 2001 +++ linux-2.4.11pre6.emu10k1/drivers/sound/emu10k1/passthrough.h Tue Oct 9 20:53:35 2001 @@ -32,7 +32,6 @@ #ifndef _PASSTHROUGH_H #define _PASSTHROUGH_H -#include "hwaccess.h" #include "audio.h" /* number of 16-bit stereo samples in XTRAM buffer */
|  |