[alsa-devel] Emu10k2 - support for 32 bit DMA mode
Hi,
Looks like audigy emu10k2 (probably emu10k1 - sb live too) support two modes for DMA. Second mode is useful for 64 bit os with more then 2 GB of ram (fixes problems with big soundfont loading)
1) 32MB from 2 GB address space using 8192 pages (used now as default) 2) 16MB from 4 GB address space using 4096 pages
Mode is set using HCFG_EXPANDED_MEM flag in HCFG register. Also format of emu10k2 page table is then different.
If someone wants to play with it, attached is patch to enable this mode for audigy. It is tested only on audigy rx (8 GB ram, 64 bit os).
Regards, Peter
At Sun, 26 Apr 2015 20:27:50 +0200, Peter Zubaj wrote:
Hi,
Looks like audigy emu10k2 (probably emu10k1 - sb live too) support two modes for DMA. Second mode is useful for 64 bit os with more then 2 GB of ram (fixes problems with big soundfont loading)
- 32MB from 2 GB address space using 8192 pages (used now as default)
- 16MB from 4 GB address space using 4096 pages
Mode is set using HCFG_EXPANDED_MEM flag in HCFG register. Also format of emu10k2 page table is then different.
If someone wants to play with it, attached is patch to enable this mode for audigy. It is tested only on audigy rx (8 GB ram, 64 bit os).
Great, thanks for spotting out this. I quickly tested an old board and confirmed to work.
The patch looks mostly OK for merge. Could you give your sign-off tag?
thanks,
Takashi
Regards, Peter diff -ur linux-4.0_orig/include/sound/emu10k1.h linux-4.0/include/sound/emu10k1.h --- linux-4.0_orig/include/sound/emu10k1.h 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/include/sound/emu10k1.h 2015-04-25 22:57:39.984002932 +0200 @@ -41,7 +41,8 @@
#define EMUPAGESIZE 4096 #define MAXREQVOICES 8 -#define MAXPAGES 8192 +#define MAXPAGES0 4096 /* 32 bit mode */ +#define MAXPAGES1 8192 /* 31 bit mode */ #define RESERVED 0 #define NUM_MIDI 16 #define NUM_G 64 /* use all channels */ @@ -50,8 +51,7 @@
/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ -#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */
/* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */
#define TMEMSIZE 256*1024 #define TMEMSIZEREG 4 @@ -466,8 +466,11 @@
#define MAPB 0x0d /* Cache map B */
-#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ -#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ +#define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK0 0x00000fff /* The 12 bit index to one of the 4096 PTE dwords */
+#define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
/* 0x0e, 0x0f: Not used */
@@ -1704,6 +1707,7 @@ unsigned short model; /* subsystem id */ unsigned int card_type; /* EMU10K1_CARD_* */ unsigned int ecard_ctrl; /* ecard control bits */
- unsigned int address_mode; /* address mode */ unsigned long dma_mask; /* PCI DMA mask */ unsigned int delay_pcm_irq; /* in samples */ int max_cache_pages; /* max memory size / PAGE_SIZE */
diff -ur linux-4.0_orig/sound/pci/emu10k1/emu10k1_callback.c linux-4.0/sound/pci/emu10k1/emu10k1_callback.c --- linux-4.0_orig/sound/pci/emu10k1/emu10k1_callback.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emu10k1_callback.c 2015-04-25 22:12:20.301949674 +0200 @@ -415,7 +415,7 @@ snd_emu10k1_ptr_write(hw, Z2, ch, 0);
/* invalidate maps */
- temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
- temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); snd_emu10k1_ptr_write(hw, MAPA, ch, temp); snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
#if 0 @@ -436,7 +436,7 @@ snd_emu10k1_ptr_write(hw, CDF, ch, sample);
/* invalidate maps */
temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
snd_emu10k1_ptr_write(hw, MAPA, ch, temp); snd_emu10k1_ptr_write(hw, MAPB, ch, temp);temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
diff -ur linux-4.0_orig/sound/pci/emu10k1/emu10k1_main.c linux-4.0/sound/pci/emu10k1/emu10k1_main.c --- linux-4.0_orig/sound/pci/emu10k1/emu10k1_main.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emu10k1_main.c 2015-04-25 23:25:48.695837022 +0200 @@ -160,7 +160,7 @@ unsigned int silent_page; int ch; u32 tmp;
- /* disable audio and lock cache */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
@@ -282,7 +282,7 @@ snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
- silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
- silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); for (ch = 0; ch < NUM_G; ch++) { snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); }
- if (emu->address_mode == 0) {
/* use 16M in 4G */
outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
- }
- return 0;
}
@@ -1877,8 +1882,10 @@
is_audigy = emu->audigy = c->emu10k2_chip;
- /* set addressing mode */
- emu->address_mode = is_audigy ? 0 : 1; /* set the DMA transfer mask */
- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
- emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { dev_err(card->dev,
@@ -1903,7 +1910,7 @@
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
32 * 1024, &emu->ptb_pages) < 0) {
err = -ENOMEM; goto error; }(emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
@@ -2002,8 +2009,8 @@
/* Clear silent pages and set up pointers */ memset(emu->silent_page.area, 0, PAGE_SIZE);
- silent_page = emu->silent_page.addr << 1;
- for (idx = 0; idx < MAXPAGES; idx++)
silent_page = emu->silent_page.addr << emu->address_mode;
for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
/* set up voice indices */
diff -ur linux-4.0_orig/sound/pci/emu10k1/emupcm.c linux-4.0/sound/pci/emu10k1/emupcm.c --- linux-4.0_orig/sound/pci/emu10k1/emupcm.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emupcm.c 2015-04-25 22:48:39.794353213 +0200 @@ -380,7 +380,7 @@ snd_emu10k1_ptr_write(emu, Z1, voice, 0); snd_emu10k1_ptr_write(emu, Z2, voice, 0); /* invalidate maps */
- silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
- silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); /* modulation envelope */
diff -ur linux-4.0_orig/sound/pci/emu10k1/memory.c linux-4.0/sound/pci/emu10k1/memory.c --- linux-4.0_orig/sound/pci/emu10k1/memory.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/memory.c 2015-04-25 22:55:56.865308462 +0200 @@ -34,10 +34,11 @@
- aligned pages in others
*/ #define __set_ptb_entry(emu,page,addr) \
- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
#define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) -#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) +#define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) +#define MAX_ALIGN_PAGES1 (MAXPAGES1 / UNIT_PAGES) /* get aligned page from offset address */ #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) /* get offset address from aligned page */ @@ -124,7 +125,7 @@ } page = blk->mapped_page + blk->pages; }
- size = MAX_ALIGN_PAGES - page;
- size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page; if (size >= max_size) { *nextp = pos; return page;
@@ -181,7 +182,7 @@ q = get_emu10k1_memblk(p, mapped_link); end_page = q->mapped_page; } else
end_page = MAX_ALIGN_PAGES;
end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
/* remove links */ list_del(&blk->mapped_link);
@@ -307,7 +308,7 @@ if (snd_BUG_ON(!emu)) return NULL; if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
return NULL; hdr = emu->memhdr; if (snd_BUG_ON(!hdr))runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Hi,
I am not sure, if this is what you want.
Regards, Peter
On Mon, 2015-04-27 at 14:34 +0200, Takashi Iwai wrote:
At Sun, 26 Apr 2015 20:27:50 +0200, Peter Zubaj wrote:
Hi,
Looks like audigy emu10k2 (probably emu10k1 - sb live too) support two modes for DMA. Second mode is useful for 64 bit os with more then 2 GB of ram (fixes problems with big soundfont loading)
- 32MB from 2 GB address space using 8192 pages (used now as default)
- 16MB from 4 GB address space using 4096 pages
Mode is set using HCFG_EXPANDED_MEM flag in HCFG register. Also format of emu10k2 page table is then different.
If someone wants to play with it, attached is patch to enable this mode for audigy. It is tested only on audigy rx (8 GB ram, 64 bit os).
Great, thanks for spotting out this. I quickly tested an old board and confirmed to work.
The patch looks mostly OK for merge. Could you give your sign-off tag?
thanks,
Takashi
Regards, Peter diff -ur linux-4.0_orig/include/sound/emu10k1.h linux-4.0/include/sound/emu10k1.h --- linux-4.0_orig/include/sound/emu10k1.h 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/include/sound/emu10k1.h 2015-04-25 22:57:39.984002932 +0200 @@ -41,7 +41,8 @@
#define EMUPAGESIZE 4096 #define MAXREQVOICES 8 -#define MAXPAGES 8192 +#define MAXPAGES0 4096 /* 32 bit mode */ +#define MAXPAGES1 8192 /* 31 bit mode */ #define RESERVED 0 #define NUM_MIDI 16 #define NUM_G 64 /* use all channels */ @@ -50,8 +51,7 @@
/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ -#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */
/* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */
#define TMEMSIZE 256*1024 #define TMEMSIZEREG 4 @@ -466,8 +466,11 @@
#define MAPB 0x0d /* Cache map B */
-#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ -#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ +#define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK0 0x00000fff /* The 12 bit index to one of the 4096 PTE dwords */
+#define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +#define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
/* 0x0e, 0x0f: Not used */
@@ -1704,6 +1707,7 @@ unsigned short model; /* subsystem id */ unsigned int card_type; /* EMU10K1_CARD_* */ unsigned int ecard_ctrl; /* ecard control bits */
- unsigned int address_mode; /* address mode */ unsigned long dma_mask; /* PCI DMA mask */ unsigned int delay_pcm_irq; /* in samples */ int max_cache_pages; /* max memory size / PAGE_SIZE */
diff -ur linux-4.0_orig/sound/pci/emu10k1/emu10k1_callback.c linux-4.0/sound/pci/emu10k1/emu10k1_callback.c --- linux-4.0_orig/sound/pci/emu10k1/emu10k1_callback.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emu10k1_callback.c 2015-04-25 22:12:20.301949674 +0200 @@ -415,7 +415,7 @@ snd_emu10k1_ptr_write(hw, Z2, ch, 0);
/* invalidate maps */
- temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
- temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); snd_emu10k1_ptr_write(hw, MAPA, ch, temp); snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
#if 0 @@ -436,7 +436,7 @@ snd_emu10k1_ptr_write(hw, CDF, ch, sample);
/* invalidate maps */
temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
snd_emu10k1_ptr_write(hw, MAPA, ch, temp); snd_emu10k1_ptr_write(hw, MAPB, ch, temp);temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
diff -ur linux-4.0_orig/sound/pci/emu10k1/emu10k1_main.c linux-4.0/sound/pci/emu10k1/emu10k1_main.c --- linux-4.0_orig/sound/pci/emu10k1/emu10k1_main.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emu10k1_main.c 2015-04-25 23:25:48.695837022 +0200 @@ -160,7 +160,7 @@ unsigned int silent_page; int ch; u32 tmp;
- /* disable audio and lock cache */ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
@@ -282,7 +282,7 @@ snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
- silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
- silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); for (ch = 0; ch < NUM_G; ch++) { snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); }
- if (emu->address_mode == 0) {
/* use 16M in 4G */
outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
- }
- return 0;
}
@@ -1877,8 +1882,10 @@
is_audigy = emu->audigy = c->emu10k2_chip;
- /* set addressing mode */
- emu->address_mode = is_audigy ? 0 : 1; /* set the DMA transfer mask */
- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
- emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { dev_err(card->dev,
@@ -1903,7 +1910,7 @@
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
32 * 1024, &emu->ptb_pages) < 0) {
err = -ENOMEM; goto error; }(emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
@@ -2002,8 +2009,8 @@
/* Clear silent pages and set up pointers */ memset(emu->silent_page.area, 0, PAGE_SIZE);
- silent_page = emu->silent_page.addr << 1;
- for (idx = 0; idx < MAXPAGES; idx++)
silent_page = emu->silent_page.addr << emu->address_mode;
for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
/* set up voice indices */
diff -ur linux-4.0_orig/sound/pci/emu10k1/emupcm.c linux-4.0/sound/pci/emu10k1/emupcm.c --- linux-4.0_orig/sound/pci/emu10k1/emupcm.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/emupcm.c 2015-04-25 22:48:39.794353213 +0200 @@ -380,7 +380,7 @@ snd_emu10k1_ptr_write(emu, Z1, voice, 0); snd_emu10k1_ptr_write(emu, Z2, voice, 0); /* invalidate maps */
- silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
- silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); /* modulation envelope */
diff -ur linux-4.0_orig/sound/pci/emu10k1/memory.c linux-4.0/sound/pci/emu10k1/memory.c --- linux-4.0_orig/sound/pci/emu10k1/memory.c 2015-04-13 00:12:50.000000000 +0200 +++ linux-4.0/sound/pci/emu10k1/memory.c 2015-04-25 22:55:56.865308462 +0200 @@ -34,10 +34,11 @@
- aligned pages in others
*/ #define __set_ptb_entry(emu,page,addr) \
- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
#define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) -#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) +#define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) +#define MAX_ALIGN_PAGES1 (MAXPAGES1 / UNIT_PAGES) /* get aligned page from offset address */ #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) /* get offset address from aligned page */ @@ -124,7 +125,7 @@ } page = blk->mapped_page + blk->pages; }
- size = MAX_ALIGN_PAGES - page;
- size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page; if (size >= max_size) { *nextp = pos; return page;
@@ -181,7 +182,7 @@ q = get_emu10k1_memblk(p, mapped_link); end_page = q->mapped_page; } else
end_page = MAX_ALIGN_PAGES;
end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
/* remove links */ list_del(&blk->mapped_link);
@@ -307,7 +308,7 @@ if (snd_BUG_ON(!emu)) return NULL; if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
return NULL; hdr = emu->memhdr; if (snd_BUG_ON(!hdr))runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
Peter Zubaj
-
Takashi Iwai