2005-06-30 20:54:04 +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 .
*/
2011-07-15 20:38:28 +04:00
# include <linux/module.h>
2013-06-27 15:53:37 +04:00
# include <linux/dma-mapping.h>
2013-08-12 12:42:39 +04:00
# include <linux/dmaengine.h>
2014-05-04 07:25:21 +04:00
# include <mach/dma.h>
2005-06-30 20:54:04 +04:00
# include <sound/core.h>
2008-09-10 05:01:20 +04:00
# include <sound/pxa2xx-lib.h>
2013-08-12 12:42:39 +04:00
# include <sound/dmaengine_pcm.h>
2005-06-30 20:54:04 +04:00
# include "pxa2xx-pcm.h"
2005-11-17 17:10:38 +03:00
static int pxa2xx_pcm_prepare ( struct snd_pcm_substream * substream )
2005-06-30 20:54:04 +04:00
{
2005-11-17 17:10:38 +03:00
struct pxa2xx_pcm_client * client = substream - > private_data ;
2005-06-30 20:54:04 +04:00
2008-09-10 05:01:20 +04:00
__pxa2xx_pcm_prepare ( substream ) ;
2005-06-30 20:54:04 +04:00
return client - > prepare ( substream ) ;
}
2005-11-17 17:10:38 +03:00
static int pxa2xx_pcm_open ( struct snd_pcm_substream * substream )
2005-06-30 20:54:04 +04:00
{
2005-11-17 17:10:38 +03:00
struct pxa2xx_pcm_client * client = substream - > private_data ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
2005-06-30 20:54:04 +04:00
struct pxa2xx_runtime_data * rtd ;
int ret ;
2008-09-10 05:01:20 +04:00
ret = __pxa2xx_pcm_open ( substream ) ;
2005-06-30 20:54:04 +04:00
if ( ret )
goto out ;
2008-09-10 05:01:20 +04:00
rtd = runtime - > private_data ;
2005-06-30 20:54:04 +04:00
rtd - > params = ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK ) ?
client - > playback_params : client - > capture_params ;
2013-08-12 12:42:39 +04:00
ret = pxa_request_dma ( " dma " , DMA_PRIO_LOW ,
2005-06-30 20:54:04 +04:00
pxa2xx_pcm_dma_irq , substream ) ;
if ( ret < 0 )
goto err2 ;
rtd - > dma_ch = ret ;
ret = client - > startup ( substream ) ;
if ( ! ret )
goto out ;
pxa_free_dma ( rtd - > dma_ch ) ;
err2 :
2008-09-10 05:01:20 +04:00
__pxa2xx_pcm_close ( substream ) ;
2005-06-30 20:54:04 +04:00
out :
return ret ;
}
2005-11-17 17:10:38 +03:00
static int pxa2xx_pcm_close ( struct snd_pcm_substream * substream )
2005-06-30 20:54:04 +04:00
{
2005-11-17 17:10:38 +03:00
struct pxa2xx_pcm_client * client = substream - > private_data ;
2005-06-30 20:54:04 +04:00
struct pxa2xx_runtime_data * rtd = substream - > runtime - > private_data ;
pxa_free_dma ( rtd - > dma_ch ) ;
client - > shutdown ( substream ) ;
2008-09-10 05:01:20 +04:00
return __pxa2xx_pcm_close ( substream ) ;
2005-06-30 20:54:04 +04:00
}
2005-11-17 17:10:38 +03:00
static struct snd_pcm_ops pxa2xx_pcm_ops = {
2005-06-30 20:54:04 +04:00
. open = pxa2xx_pcm_open ,
. close = pxa2xx_pcm_close ,
. ioctl = snd_pcm_lib_ioctl ,
2008-09-10 05:01:20 +04:00
. hw_params = __pxa2xx_pcm_hw_params ,
. hw_free = __pxa2xx_pcm_hw_free ,
2005-06-30 20:54:04 +04:00
. prepare = pxa2xx_pcm_prepare ,
. trigger = pxa2xx_pcm_trigger ,
. pointer = pxa2xx_pcm_pointer ,
. mmap = pxa2xx_pcm_mmap ,
} ;
2005-11-17 17:10:38 +03:00
int pxa2xx_pcm_new ( struct snd_card * card , struct pxa2xx_pcm_client * client ,
struct snd_pcm * * rpcm )
2005-06-30 20:54:04 +04:00
{
2005-11-17 17:10:38 +03:00
struct snd_pcm * pcm ;
2005-06-30 20:54:04 +04:00
int play = client - > playback_params ? 1 : 0 ;
int capt = client - > capture_params ? 1 : 0 ;
int ret ;
ret = snd_pcm_new ( card , " PXA2xx-PCM " , 0 , play , capt , & pcm ) ;
if ( ret )
goto out ;
pcm - > private_data = client ;
pcm - > private_free = pxa2xx_pcm_free_dma_buffers ;
2013-06-27 15:53:37 +04:00
ret = dma_coerce_mask_and_coherent ( card - > dev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret )
goto out ;
2005-06-30 20:54:04 +04:00
if ( play ) {
int stream = SNDRV_PCM_STREAM_PLAYBACK ;
snd_pcm_set_ops ( pcm , stream , & pxa2xx_pcm_ops ) ;
ret = pxa2xx_pcm_preallocate_dma_buffer ( pcm , stream ) ;
if ( ret )
goto out ;
}
if ( capt ) {
int stream = SNDRV_PCM_STREAM_CAPTURE ;
snd_pcm_set_ops ( pcm , stream , & pxa2xx_pcm_ops ) ;
ret = pxa2xx_pcm_preallocate_dma_buffer ( pcm , stream ) ;
if ( ret )
goto out ;
}
if ( rpcm )
* rpcm = pcm ;
ret = 0 ;
out :
return ret ;
}
EXPORT_SYMBOL ( pxa2xx_pcm_new ) ;
MODULE_AUTHOR ( " Nicolas Pitre " ) ;
MODULE_DESCRIPTION ( " Intel PXA2xx PCM DMA module " ) ;
MODULE_LICENSE ( " GPL " ) ;