2006-10-12 16:26:55 +04:00
/*
* linux / sound / arm / pxa2xx - pcm . c - - ALSA PCM interface for the Intel PXA2xx chip
*
* Author : Nicolas Pitre
* Created : Nov 30 , 2004
* Copyright : ( C ) 2004 MontaVista Software , Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/dma-mapping.h>
# include <sound/core.h>
# include <sound/soc.h>
2008-09-10 05:01:20 +04:00
# include <sound/pxa2xx-lib.h>
2006-10-12 16:26:55 +04:00
# include "pxa2xx-pcm.h"
2008-09-10 05:01:20 +04:00
# include "../../arm/pxa2xx-pcm.h"
2006-10-12 16:26:55 +04:00
static int pxa2xx_pcm_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct pxa2xx_runtime_data * prtd = runtime - > private_data ;
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
2007-02-02 19:21:50 +03:00
struct pxa2xx_pcm_dma_params * dma = rtd - > dai - > cpu_dai - > dma_data ;
2006-10-12 16:26:55 +04:00
int ret ;
2007-02-02 19:21:50 +03:00
/* return if this is a bufferless transfer e.g.
* codec < - - > BT codec or GSM modem - - lg FIXME */
2008-04-23 17:14:18 +04:00
if ( ! dma )
return 0 ;
2007-02-02 19:21:50 +03:00
2006-10-12 16:26:55 +04:00
/* this may get called several times by oss emulation
* with different params */
if ( prtd - > params = = NULL ) {
prtd - > params = dma ;
ret = pxa_request_dma ( prtd - > params - > name , DMA_PRIO_LOW ,
pxa2xx_pcm_dma_irq , substream ) ;
if ( ret < 0 )
return ret ;
prtd - > dma_ch = ret ;
} else if ( prtd - > params ! = dma ) {
pxa_free_dma ( prtd - > dma_ch ) ;
prtd - > params = dma ;
ret = pxa_request_dma ( prtd - > params - > name , DMA_PRIO_LOW ,
pxa2xx_pcm_dma_irq , substream ) ;
if ( ret < 0 )
return ret ;
prtd - > dma_ch = ret ;
}
2008-09-10 05:01:20 +04:00
return __pxa2xx_pcm_hw_params ( substream , params ) ;
2006-10-12 16:26:55 +04:00
}
static int pxa2xx_pcm_hw_free ( struct snd_pcm_substream * substream )
{
struct pxa2xx_runtime_data * prtd = substream - > runtime - > private_data ;
2008-09-10 05:01:20 +04:00
__pxa2xx_pcm_hw_free ( substream ) ;
2006-10-12 16:26:55 +04:00
2009-01-01 01:39:23 +03:00
if ( prtd - > dma_ch > = 0 ) {
2006-10-12 16:26:55 +04:00
pxa_free_dma ( prtd - > dma_ch ) ;
2009-01-01 01:39:23 +03:00
prtd - > dma_ch = - 1 ;
2006-10-12 16:26:55 +04:00
}
return 0 ;
}
2008-11-21 17:05:48 +03:00
static struct snd_pcm_ops pxa2xx_pcm_ops = {
2008-09-10 05:01:20 +04:00
. open = __pxa2xx_pcm_open ,
. close = __pxa2xx_pcm_close ,
2006-10-12 16:26:55 +04:00
. ioctl = snd_pcm_lib_ioctl ,
. hw_params = pxa2xx_pcm_hw_params ,
. hw_free = pxa2xx_pcm_hw_free ,
2008-09-10 05:01:20 +04:00
. prepare = __pxa2xx_pcm_prepare ,
2006-10-12 16:26:55 +04:00
. trigger = pxa2xx_pcm_trigger ,
. pointer = pxa2xx_pcm_pointer ,
. mmap = pxa2xx_pcm_mmap ,
} ;
static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK ;
2008-07-29 14:42:24 +04:00
static int pxa2xx_soc_pcm_new ( struct snd_card * card , struct snd_soc_dai * dai ,
2006-10-12 16:26:55 +04:00
struct snd_pcm * pcm )
{
int ret = 0 ;
if ( ! card - > dev - > dma_mask )
card - > dev - > dma_mask = & pxa2xx_pcm_dmamask ;
if ( ! card - > dev - > coherent_dma_mask )
card - > dev - > coherent_dma_mask = DMA_32BIT_MASK ;
if ( dai - > playback . channels_min ) {
ret = pxa2xx_pcm_preallocate_dma_buffer ( pcm ,
SNDRV_PCM_STREAM_PLAYBACK ) ;
if ( ret )
goto out ;
}
if ( dai - > capture . channels_min ) {
ret = pxa2xx_pcm_preallocate_dma_buffer ( pcm ,
SNDRV_PCM_STREAM_CAPTURE ) ;
if ( ret )
goto out ;
}
out :
return ret ;
}
struct snd_soc_platform pxa2xx_soc_platform = {
. name = " pxa2xx-audio " ,
. pcm_ops = & pxa2xx_pcm_ops ,
2008-07-29 14:42:24 +04:00
. pcm_new = pxa2xx_soc_pcm_new ,
2006-10-12 16:26:55 +04:00
. pcm_free = pxa2xx_pcm_free_dma_buffers ,
} ;
EXPORT_SYMBOL_GPL ( pxa2xx_soc_platform ) ;
2008-12-10 09:47:22 +03:00
static int __init pxa2xx_soc_platform_init ( void )
2008-12-03 22:58:17 +03:00
{
return snd_soc_register_platform ( & pxa2xx_soc_platform ) ;
}
module_init ( pxa2xx_soc_platform_init ) ;
static void __exit pxa2xx_soc_platform_exit ( void )
{
snd_soc_unregister_platform ( & pxa2xx_soc_platform ) ;
}
module_exit ( pxa2xx_soc_platform_exit ) ;
2006-10-12 16:26:55 +04:00
MODULE_AUTHOR ( " Nicolas Pitre " ) ;
MODULE_DESCRIPTION ( " Intel PXA2xx PCM DMA module " ) ;
MODULE_LICENSE ( " GPL " ) ;