X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Femu10k1%2Femuproc.c;h=a65fce3bda3dd33f6bb2eda391db76de0f21d7ad;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=918bc688ab3b9dc735316266dab97204b257ebf8;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 918bc688a..a65fce3bd 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -71,31 +71,32 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, static void snd_emu10k1_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { - static char *outputs[32] = { - /* 00 */ "PCM Left", - /* 01 */ "PCM Right", - /* 02 */ "PCM Surround Left", - /* 03 */ "PCM Surround Right", - /* 04 */ "MIDI Left", - /* 05 */ "MIDI Right", - /* 06 */ "PCM Center", - /* 07 */ "PCM LFE", - /* 08 */ "???", - /* 09 */ "???", - /* 10 */ "???", - /* 11 */ "???", - /* 12 */ "MIDI Reverb", - /* 13 */ "MIDI Chorus", - /* 14 */ "???", + /* FIXME - output names are in emufx.c too */ + static char *creative_outs[32] = { + /* 00 */ "AC97 Left", + /* 01 */ "AC97 Right", + /* 02 */ "Optical IEC958 Left", + /* 03 */ "Optical IEC958 Right", + /* 04 */ "Center", + /* 05 */ "LFE", + /* 06 */ "Headphone Left", + /* 07 */ "Headphone Right", + /* 08 */ "Surround Left", + /* 09 */ "Surround Right", + /* 10 */ "PCM Capture Left", + /* 11 */ "PCM Capture Right", + /* 12 */ "MIC Capture", + /* 13 */ "AC97 Surround Left", + /* 14 */ "AC97 Surround Right", /* 15 */ "???", /* 16 */ "???", - /* 17 */ "???", - /* 18 */ "ADC Left / CDROM S/PDIF Left", - /* 19 */ "ADC Right / CDROM S/PDIF Right", - /* 20 */ "MIC / Zoom Video Left", - /* 21 */ "Zoom Video Right", - /* 22 */ "S/PDIF Left", - /* 23 */ "S/PDIF Right", + /* 17 */ "Analog Center", + /* 18 */ "Analog LFE", + /* 19 */ "???", + /* 20 */ "???", + /* 21 */ "???", + /* 22 */ "???", + /* 23 */ "???", /* 24 */ "???", /* 25 */ "???", /* 26 */ "???", @@ -105,37 +106,119 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry, /* 30 */ "???", /* 31 */ "???" }; - emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return); - unsigned int val; + + static char *audigy_outs[64] = { + /* 00 */ "Digital Front Left", + /* 01 */ "Digital Front Right", + /* 02 */ "Digital Center", + /* 03 */ "Digital LEF", + /* 04 */ "Headphone Left", + /* 05 */ "Headphone Right", + /* 06 */ "Digital Rear Left", + /* 07 */ "Digital Rear Right", + /* 08 */ "Front Left", + /* 09 */ "Front Right", + /* 10 */ "Center", + /* 11 */ "LFE", + /* 12 */ "???", + /* 13 */ "???", + /* 14 */ "Rear Left", + /* 15 */ "Rear Right", + /* 16 */ "AC97 Front Left", + /* 17 */ "AC97 Front Right", + /* 18 */ "ADC Caputre Left", + /* 19 */ "ADC Capture Right", + /* 20 */ "???", + /* 21 */ "???", + /* 22 */ "???", + /* 23 */ "???", + /* 24 */ "???", + /* 25 */ "???", + /* 26 */ "???", + /* 27 */ "???", + /* 28 */ "???", + /* 29 */ "???", + /* 30 */ "???", + /* 31 */ "???", + /* 32 */ "???", + /* 33 */ "???", + /* 34 */ "???", + /* 35 */ "???", + /* 36 */ "???", + /* 37 */ "???", + /* 38 */ "???", + /* 39 */ "???", + /* 40 */ "???", + /* 41 */ "???", + /* 42 */ "???", + /* 43 */ "???", + /* 44 */ "???", + /* 45 */ "???", + /* 46 */ "???", + /* 47 */ "???", + /* 48 */ "???", + /* 49 */ "???", + /* 50 */ "???", + /* 51 */ "???", + /* 52 */ "???", + /* 53 */ "???", + /* 54 */ "???", + /* 55 */ "???", + /* 56 */ "???", + /* 57 */ "???", + /* 58 */ "???", + /* 59 */ "???", + /* 60 */ "???", + /* 61 */ "???", + /* 62 */ "???", + /* 33 */ "???" + }; + + emu10k1_t *emu = entry->private_data; + unsigned int val, val1; int nefx = emu->audigy ? 64 : 32; + char **outputs = emu->audigy ? audigy_outs : creative_outs; int idx; snd_iprintf(buffer, "EMU10K1\n\n"); - val = emu->audigy ? - snd_emu10k1_ptr_read(emu, A_FXRT1, 0) : - snd_emu10k1_ptr_read(emu, FXRT, 0); snd_iprintf(buffer, "Card : %s\n", emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative")); snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); - snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", emu->fx8010.etram_pages.bytes); + snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes); snd_iprintf(buffer, "\n"); - if (emu->audigy) { - snd_iprintf(buffer, "Effect Send Routing : A=%i, B=%i, C=%i, D=%i\n", - val & 0x3f, - (val >> 8) & 0x3f, - (val >> 16) & 0x3f, - (val >> 24) & 0x3f); - } else { - snd_iprintf(buffer, "Effect Send Routing : A=%i, B=%i, C=%i, D=%i\n", - (val >> 16) & 0x0f, - (val >> 20) & 0x0f, - (val >> 24) & 0x0f, - (val >> 28) & 0x0f); + snd_iprintf(buffer, "Effect Send Routing :\n"); + for (idx = 0; idx < NUM_G; idx++) { + val = emu->audigy ? + snd_emu10k1_ptr_read(emu, A_FXRT1, idx) : + snd_emu10k1_ptr_read(emu, FXRT, idx); + val1 = emu->audigy ? + snd_emu10k1_ptr_read(emu, A_FXRT2, idx) : + 0; + if (emu->audigy) { + snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i, ", + idx, + val & 0x3f, + (val >> 8) & 0x3f, + (val >> 16) & 0x3f, + (val >> 24) & 0x3f); + snd_iprintf(buffer, "E=%i, F=%i, G=%i, H=%i\n", + val1 & 0x3f, + (val1 >> 8) & 0x3f, + (val1 >> 16) & 0x3f, + (val1 >> 24) & 0x3f); + } else { + snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i\n", + idx, + (val >> 16) & 0x0f, + (val >> 20) & 0x0f, + (val >> 24) & 0x0f, + (val >> 28) & 0x0f); + } } snd_iprintf(buffer, "\nCaptured FX Outputs :\n"); for (idx = 0; idx < nefx; idx++) { if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) - snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx%32]); + snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); } snd_iprintf(buffer, "\nAll FX Outputs :\n"); for (idx = 0; idx < 32; idx++) @@ -155,11 +238,11 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { u32 pc; - emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return); + emu10k1_t *emu = entry->private_data; snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name); snd_iprintf(buffer, " Code dump :\n"); - for (pc = 0; pc < 512; pc++) { + for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) { u32 low, high; low = snd_emu10k1_efx_read(emu, pc * 2); @@ -186,22 +269,27 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, } #define TOTAL_SIZE_GPR (0x100*4) +#define A_TOTAL_SIZE_GPR (0x200*4) #define TOTAL_SIZE_TANKMEM_DATA (0xa0*4) #define TOTAL_SIZE_TANKMEM_ADDR (0xa0*4) +#define A_TOTAL_SIZE_TANKMEM_DATA (0x100*4) +#define A_TOTAL_SIZE_TANKMEM_ADDR (0x100*4) #define TOTAL_SIZE_CODE (0x200*8) +#define A_TOTAL_SIZE_CODE (0x400*8) static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_data, - struct file *file, char *buf, long count) + struct file *file, char __user *buf, + unsigned long count, unsigned long pos) { long size; - emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO); + emu10k1_t *emu = entry->private_data; unsigned int offset; + int tram_addr = 0; if (!strcmp(entry->name, "fx8010_tram_addr")) { - if (emu->audigy) return -EINVAL; offset = TANKMEMADDRREGBASE; + tram_addr = 1; } else if (!strcmp(entry->name, "fx8010_tram_data")) { - if (emu->audigy) return -EINVAL; offset = TANKMEMDATAREGBASE; } else if (!strcmp(entry->name, "fx8010_code")) { offset = emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; @@ -209,21 +297,24 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_ offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; } size = count; - if (file->f_pos + size > entry->size) - size = (long)entry->size - file->f_pos; + if (pos + size > entry->size) + size = (long)entry->size - pos; if (size > 0) { unsigned int *tmp; long res; unsigned int idx; if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL) return -ENOMEM; - for (idx = 0; idx < ((file->f_pos & 3) + size + 3) >> 2; idx++) - tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (file->f_pos >> 2), 0); - if (copy_to_user(buf, ((char *)tmp) + (file->f_pos & 3), size)) + for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++) + if (tram_addr && emu->audigy) { + tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11; + tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; + } else + tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); + if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size)) res = -EFAULT; else { res = size; - file->f_pos += size; } kfree(tmp); return res; @@ -231,6 +322,152 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_ return 0; } +#ifdef CONFIG_SND_DEBUG +static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + emu10k1_t *emu = entry->private_data; + unsigned long value; + unsigned long flags; + int i; + snd_iprintf(buffer, "IO Registers:\n\n"); + for(i = 0; i < 0x40; i+=4) { + spin_lock_irqsave(&emu->emu_lock, flags); + value = inl(emu->port + i); + spin_unlock_irqrestore(&emu->emu_lock, flags); + snd_iprintf(buffer, "%02X: %08lX\n", i, value); + } +} + +static void snd_emu_proc_io_reg_write(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + emu10k1_t *emu = entry->private_data; + unsigned long flags; + char line[64]; + u32 reg, val; + while (!snd_info_get_line(buffer, line, sizeof(line))) { + if (sscanf(line, "%x %x", ®, &val) != 2) + continue; + if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) { + spin_lock_irqsave(&emu->emu_lock, flags); + outl(val, emu->port + (reg & 0xfffffffc)); + spin_unlock_irqrestore(&emu->emu_lock, flags); + } + } +} + +static unsigned int snd_ptr_read(emu10k1_t * emu, + unsigned int iobase, + unsigned int reg, + unsigned int chn) +{ + unsigned long flags; + unsigned int regptr, val; + + regptr = (reg << 16) | chn; + + spin_lock_irqsave(&emu->emu_lock, flags); + outl(regptr, emu->port + iobase + PTR); + val = inl(emu->port + iobase + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); + return val; +} + +static void snd_ptr_write(emu10k1_t *emu, + unsigned int iobase, + unsigned int reg, + unsigned int chn, + unsigned int data) +{ + unsigned int regptr; + unsigned long flags; + + regptr = (reg << 16) | chn; + + spin_lock_irqsave(&emu->emu_lock, flags); + outl(regptr, emu->port + iobase + PTR); + outl(data, emu->port + iobase + DATA); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + + +static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry, + snd_info_buffer_t * buffer, int iobase, int offset, int length) +{ + emu10k1_t *emu = entry->private_data; + unsigned long value; + int i,j; + if (offset+length > 0x80) { + snd_iprintf(buffer, "Input values out of range\n"); + return; + } + snd_iprintf(buffer, "Registers 0x%x\n", iobase); + for(i = offset; i < offset+length; i++) { + snd_iprintf(buffer, "%02X: ",i); + for (j = 0; j < 4; j++) { + if(iobase == 0) + value = snd_ptr_read(emu, 0, i, j); + else + value = snd_ptr_read(emu, 0x20, i, j); + snd_iprintf(buffer, "%08lX ", value); + } + snd_iprintf(buffer, "\n"); + } +} + +static void snd_emu_proc_ptr_reg_write(snd_info_entry_t *entry, + snd_info_buffer_t * buffer, int iobase) +{ + emu10k1_t *emu = entry->private_data; + char line[64]; + unsigned int reg, channel_id , val; + while (!snd_info_get_line(buffer, line, sizeof(line))) { + if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) + continue; + if ((reg < 0x80) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) ) + snd_ptr_write(emu, iobase, reg, channel_id, val); + } +} + +static void snd_emu_proc_ptr_reg_write00(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_write(entry, buffer, 0); +} + +static void snd_emu_proc_ptr_reg_write20(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_write(entry, buffer, 0x20); +} + + +static void snd_emu_proc_ptr_reg_read00a(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40); +} + +static void snd_emu_proc_ptr_reg_read00b(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40); +} + +static void snd_emu_proc_ptr_reg_read20a(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40); +} + +static void snd_emu_proc_ptr_reg_read20b(snd_info_entry_t *entry, + snd_info_buffer_t * buffer) +{ + snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40); +} +#endif + static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { .read = snd_emu10k1_fx8010_read, }; @@ -238,43 +475,70 @@ static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { int __devinit snd_emu10k1_proc_init(emu10k1_t * emu) { snd_info_entry_t *entry; +#ifdef CONFIG_SND_DEBUG + if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_io_reg_write; + } + if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00a); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write00; + } + if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00b); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write00; + } + if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20a); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write20; + } + if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { + snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20b); + entry->c.text.write_size = 64; + entry->c.text.write = snd_emu_proc_ptr_reg_write20; + } +#endif if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) - snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1_proc_read); + snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = TOTAL_SIZE_GPR; + entry->size = emu->audigy ? A_TOTAL_SIZE_GPR : TOTAL_SIZE_GPR; entry->c.ops = &snd_emu10k1_proc_ops_fx8010; } - if (!emu->audigy && ! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) { + if (! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = TOTAL_SIZE_TANKMEM_DATA; + entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_DATA : TOTAL_SIZE_TANKMEM_DATA ; entry->c.ops = &snd_emu10k1_proc_ops_fx8010; } - if (!emu->audigy && ! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) { + if (! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = TOTAL_SIZE_TANKMEM_ADDR; + entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_ADDR : TOTAL_SIZE_TANKMEM_ADDR ; entry->c.ops = &snd_emu10k1_proc_ops_fx8010; } if (! snd_card_proc_new(emu->card, "fx8010_code", &entry)) { entry->content = SNDRV_INFO_CONTENT_DATA; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = TOTAL_SIZE_CODE; + entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE; entry->c.ops = &snd_emu10k1_proc_ops_fx8010; } if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = emu; entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->c.text.read_size = 64*1024; + entry->c.text.read_size = 128*1024; entry->c.text.read = snd_emu10k1_proc_acode_read; } return 0;