Commit 51da4bc3 authored by David S. Miller's avatar David S. Miller

[ALSA]: Add SBUS dma support.

parent 77ac98e8
......@@ -38,6 +38,9 @@ typedef struct sndrv_xferv snd_xferv_t;
#ifdef CONFIG_PCI
struct pci_dev;
#endif
#ifdef CONFIG_SBUS
struct sbus_dev;
#endif
/* device allocation stuff */
......@@ -256,6 +259,11 @@ void *snd_malloc_pci_pages(struct pci_dev *pci, unsigned long size, dma_addr_t *
void *snd_malloc_pci_pages_fallback(struct pci_dev *pci, unsigned long size, dma_addr_t *dma_addr, unsigned long *res_size);
void snd_free_pci_pages(struct pci_dev *pci, unsigned long size, void *ptr, dma_addr_t dma_addr);
#endif
#ifdef CONFIG_SBUS
void *snd_malloc_sbus_pages(struct sbus_dev *sdev, unsigned long size, dma_addr_t *dma_addr);
void *snd_malloc_sbus_pages_fallback(struct sbus_dev *sdev, unsigned long size, dma_addr_t *dma_addr, unsigned long *res_size);
void snd_free_sbus_pages(struct sbus_dev *sdev, unsigned long size, void *ptr, dma_addr_t dma_addr);
#endif
#ifdef CONFIG_ISA
#ifdef CONFIG_PCI
#define snd_malloc_isa_pages(size, dma_addr) snd_malloc_pci_pages(NULL, size, dma_addr)
......
......@@ -121,6 +121,7 @@ typedef struct _snd_pcm_ops {
#define SNDRV_PCM_DMA_TYPE_CONTINUOUS 0 /* continuous no-DMA memory */
#define SNDRV_PCM_DMA_TYPE_ISA 1 /* ISA continuous */
#define SNDRV_PCM_DMA_TYPE_PCI 2 /* PCI continuous */
#define SNDRV_PCM_DMA_TYPE_SBUS 3 /* SBUS continuous */
/* If you change this don't forget to changed snd_pcm_rates table in pcm_lib.c */
#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */
......@@ -848,6 +849,15 @@ int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev *pci,
size_t size,
size_t max);
#endif
#ifdef CONFIG_SBUS
int snd_pcm_lib_preallocate_sbus_pages(struct sbus_dev *sdev,
snd_pcm_substream_t *substream,
size_t size, size_t max);
int snd_pcm_lib_preallocate_sbus_pages_for_all(struct sbus_dev *sdev,
snd_pcm_t *pcm,
size_t size,
size_t max);
#endif
static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
{
......
......@@ -29,6 +29,9 @@
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/info.h>
#ifdef CONFIG_SBUS
#include <asm/sbus.h>
#endif
/*
* memory allocation helpers and debug routines
......@@ -405,6 +408,72 @@ void snd_free_pci_pages(struct pci_dev *pci,
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
void *snd_malloc_sbus_pages(struct sbus_dev *sdev,
unsigned long size,
dma_addr_t *dma_addr)
{
int pg;
void *res;
snd_assert(size > 0, return NULL);
snd_assert(dma_addr != NULL, return NULL);
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
if (res != NULL) {
struct page *page = virt_to_page(res);
struct page *last_page = page + (1 << pg);
while (page < last_page)
SetPageReserved(page++);
#ifdef CONFIG_SND_DEBUG_MEMORY
snd_alloc_pages += 1 << pg;
#endif
}
return res;
}
void *snd_malloc_sbus_pages_fallback(struct sbus_dev *sdev,
unsigned long size,
dma_addr_t *dma_addr,
unsigned long *res_size)
{
void *res;
snd_assert(res_size != NULL, return NULL);
do {
if ((res = snd_malloc_sbus_pages(sdev, size, dma_addr)) != NULL) {
*res_size = size;
return res;
}
size >>= 1;
} while (size >= PAGE_SIZE);
return NULL;
}
void snd_free_sbus_pages(struct sbus_dev *sdev,
unsigned long size,
void *ptr,
dma_addr_t dma_addr)
{
int pg;
struct page *page, *last_page;
if (ptr == NULL)
return;
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
page = virt_to_page(ptr);
last_page = page + (1 << pg);
while (page < last_page)
ClearPageReserved(page++);
sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr);
#ifdef CONFIG_SND_DEBUG_MEMORY
snd_alloc_pages -= 1 << pg;
#endif
}
#endif /* CONFIG_SBUS */
void *snd_kcalloc(size_t size, int flags)
{
void *ptr;
......
......@@ -2379,3 +2379,7 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_isa_pages_for_all);
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages);
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages_for_all);
#endif
#ifdef CONFIG_SBUS
EXPORT_SYMBOL(snd_pcm_lib_preallocate_sbus_pages);
EXPORT_SYMBOL(snd_pcm_lib_preallocate_sbus_pages_for_all);
#endif
......@@ -58,6 +58,11 @@ static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
case SNDRV_PCM_DMA_TYPE_PCI:
snd_free_pci_pages((struct pci_dev *)substream->dma_private, substream->dma_bytes, substream->dma_area, substream->dma_addr);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_PCM_DMA_TYPE_SBUS:
snd_free_sbus_pages((struct sbus_dev *)substream->dma_private, substream->dma_bytes, substream->dma_area, substream->dma_addr);
break;
#endif
}
substream->dma_area = NULL;
......@@ -128,6 +133,11 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_PCM_DMA_TYPE_SBUS:
dma_area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, &dma_addr);
break;
#endif
default:
dma_area = NULL;
......@@ -176,6 +186,11 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages_fallback((struct pci_dev *)substream->dma_private, size, &dma_addr, &rsize);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_PCM_DMA_TYPE_SBUS:
dma_area = snd_malloc_sbus_pages_fallback((struct sbus_dev *)substream->dma_private, size, &dma_addr, &rsize);
break;
#endif
default:
size = 0;
......@@ -287,6 +302,11 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_PCM_DMA_TYPE_SBUS:
dma_area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, &dma_addr);
break;
#endif
default:
return -ENXIO;
......@@ -320,6 +340,11 @@ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream)
case SNDRV_PCM_DMA_TYPE_PCI:
snd_free_pci_pages((struct pci_dev *)substream->dma_private, runtime->dma_bytes, runtime->dma_area, runtime->dma_addr);
break;
#endif
#ifdef CONFIG_SBUS
case SNDRV_PCM_DMA_TYPE_SBUS:
snd_free_sbus_pages((struct sbus_dev *)substream->dma_private, runtime->dma_bytes, runtime->dma_area, runtime->dma_addr);
break;
#endif
}
}
......@@ -355,3 +380,30 @@ int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev *pci,
}
#endif /* CONFIG_PCI */
#ifdef CONFIG_SBUS
int snd_pcm_lib_preallocate_sbus_pages(struct sbus_dev *sdev,
snd_pcm_substream_t *substream,
size_t size, size_t max)
{
substream->dma_type = SNDRV_PCM_DMA_TYPE_SBUS;
substream->dma_private = sdev;
return snd_pcm_lib_preallocate_pages1(substream, size, max);
}
int snd_pcm_lib_preallocate_sbus_pages_for_all(struct sbus_dev *sdev,
snd_pcm_t *pcm,
size_t size, size_t max)
{
snd_pcm_substream_t *substream;
int stream, err;
for (stream = 0; stream < 2; stream++)
for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
if ((err = snd_pcm_lib_preallocate_sbus_pages(sdev, substream, size, max)) < 0)
return err;
return 0;
}
#endif /* CONFIG_SBUS */
......@@ -128,14 +128,14 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
* expand the variable length event to linear buffer space.
*/
static int copy_in_kernel(char **bufptr, const void *src, int size)
static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
{
memcpy(*bufptr, src, size);
*bufptr += size;
return 0;
}
static int copy_in_user(char **bufptr, const void *src, int size)
static int seq_copy_in_user(char **bufptr, const void *src, int size)
{
if (copy_to_user(*bufptr, src, size))
return -EFAULT;
......@@ -164,8 +164,8 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
return newlen;
}
err = snd_seq_dump_var_event(event,
in_kernel ? (snd_seq_dump_func_t)copy_in_kernel :
(snd_seq_dump_func_t)copy_in_user,
in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel :
(snd_seq_dump_func_t)seq_copy_in_user,
&buf);
return err < 0 ? err : newlen;
}
......
......@@ -429,6 +429,11 @@ EXPORT_SYMBOL(snd_malloc_pci_pages);
EXPORT_SYMBOL(snd_malloc_pci_pages_fallback);
EXPORT_SYMBOL(snd_free_pci_pages);
#endif
#ifdef CONFIG_SBUS
EXPORT_SYMBOL(snd_malloc_sbus_pages);
EXPORT_SYMBOL(snd_malloc_sbus_pages_fallback);
EXPORT_SYMBOL(snd_free_sbus_pages);
#endif
EXPORT_SYMBOL(copy_to_user_fromio);
EXPORT_SYMBOL(copy_from_user_toio);
/* init.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment