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; ...@@ -38,6 +38,9 @@ typedef struct sndrv_xferv snd_xferv_t;
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct pci_dev; struct pci_dev;
#endif #endif
#ifdef CONFIG_SBUS
struct sbus_dev;
#endif
/* device allocation stuff */ /* device allocation stuff */
...@@ -256,6 +259,11 @@ void *snd_malloc_pci_pages(struct pci_dev *pci, unsigned long size, dma_addr_t * ...@@ -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_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); void snd_free_pci_pages(struct pci_dev *pci, unsigned long size, void *ptr, dma_addr_t dma_addr);
#endif #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_ISA
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
#define snd_malloc_isa_pages(size, dma_addr) snd_malloc_pci_pages(NULL, size, dma_addr) #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 { ...@@ -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_CONTINUOUS 0 /* continuous no-DMA memory */
#define SNDRV_PCM_DMA_TYPE_ISA 1 /* ISA continuous */ #define SNDRV_PCM_DMA_TYPE_ISA 1 /* ISA continuous */
#define SNDRV_PCM_DMA_TYPE_PCI 2 /* PCI 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 */ /* 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 */ #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, ...@@ -848,6 +849,15 @@ int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev *pci,
size_t size, size_t size,
size_t max); size_t max);
#endif #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) static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
{ {
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/info.h> #include <sound/info.h>
#ifdef CONFIG_SBUS
#include <asm/sbus.h>
#endif
/* /*
* memory allocation helpers and debug routines * memory allocation helpers and debug routines
...@@ -405,6 +408,72 @@ void snd_free_pci_pages(struct pci_dev *pci, ...@@ -405,6 +408,72 @@ void snd_free_pci_pages(struct pci_dev *pci,
#endif /* CONFIG_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 *snd_kcalloc(size_t size, int flags)
{ {
void *ptr; void *ptr;
......
...@@ -2379,3 +2379,7 @@ EXPORT_SYMBOL(snd_pcm_lib_preallocate_isa_pages_for_all); ...@@ -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);
EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages_for_all); EXPORT_SYMBOL(snd_pcm_lib_preallocate_pci_pages_for_all);
#endif #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) ...@@ -58,6 +58,11 @@ static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
case SNDRV_PCM_DMA_TYPE_PCI: 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); snd_free_pci_pages((struct pci_dev *)substream->dma_private, substream->dma_bytes, substream->dma_area, substream->dma_addr);
break; 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 #endif
} }
substream->dma_area = NULL; substream->dma_area = NULL;
...@@ -128,6 +133,11 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry, ...@@ -128,6 +133,11 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
case SNDRV_PCM_DMA_TYPE_PCI: case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr); dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
break; 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 #endif
default: default:
dma_area = NULL; dma_area = NULL;
...@@ -176,6 +186,11 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream, ...@@ -176,6 +186,11 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
case SNDRV_PCM_DMA_TYPE_PCI: case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages_fallback((struct pci_dev *)substream->dma_private, size, &dma_addr, &rsize); dma_area = snd_malloc_pci_pages_fallback((struct pci_dev *)substream->dma_private, size, &dma_addr, &rsize);
break; 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 #endif
default: default:
size = 0; size = 0;
...@@ -287,6 +302,11 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size) ...@@ -287,6 +302,11 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
case SNDRV_PCM_DMA_TYPE_PCI: case SNDRV_PCM_DMA_TYPE_PCI:
dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr); dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dma_addr);
break; 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 #endif
default: default:
return -ENXIO; return -ENXIO;
...@@ -320,6 +340,11 @@ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream) ...@@ -320,6 +340,11 @@ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream)
case SNDRV_PCM_DMA_TYPE_PCI: 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); snd_free_pci_pages((struct pci_dev *)substream->dma_private, runtime->dma_bytes, runtime->dma_area, runtime->dma_addr);
break; 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 #endif
} }
} }
...@@ -355,3 +380,30 @@ int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev *pci, ...@@ -355,3 +380,30 @@ int snd_pcm_lib_preallocate_pci_pages_for_all(struct pci_dev *pci,
} }
#endif /* CONFIG_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 ...@@ -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. * 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); memcpy(*bufptr, src, size);
*bufptr += size; *bufptr += size;
return 0; 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)) if (copy_to_user(*bufptr, src, size))
return -EFAULT; return -EFAULT;
...@@ -164,8 +164,8 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, ...@@ -164,8 +164,8 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
return newlen; return newlen;
} }
err = snd_seq_dump_var_event(event, err = snd_seq_dump_var_event(event,
in_kernel ? (snd_seq_dump_func_t)copy_in_kernel : in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel :
(snd_seq_dump_func_t)copy_in_user, (snd_seq_dump_func_t)seq_copy_in_user,
&buf); &buf);
return err < 0 ? err : newlen; return err < 0 ? err : newlen;
} }
......
...@@ -429,6 +429,11 @@ EXPORT_SYMBOL(snd_malloc_pci_pages); ...@@ -429,6 +429,11 @@ EXPORT_SYMBOL(snd_malloc_pci_pages);
EXPORT_SYMBOL(snd_malloc_pci_pages_fallback); EXPORT_SYMBOL(snd_malloc_pci_pages_fallback);
EXPORT_SYMBOL(snd_free_pci_pages); EXPORT_SYMBOL(snd_free_pci_pages);
#endif #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_to_user_fromio);
EXPORT_SYMBOL(copy_from_user_toio); EXPORT_SYMBOL(copy_from_user_toio);
/* init.c */ /* 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