static void audio_buffdone(void *data)
{
	struct snd_pcm_substream *substream = data;
	struct runtime_data *prtd;

	pr_debug("Entered %s\n", __func__);

	if (!substream)
		return;

	prtd = substream->runtime->private_data;

	if (prtd->state & ST_RUNNING) {
		snd_pcm_period_elapsed(substream);

		if (!samsung_dma_has_circular()) {
			spin_lock(&prtd->lock);

			prtd->dma_loaded--;
			if (!samsung_dma_has_infiniteloop())
				dma_enqueue(substream);

			spin_unlock(&prtd->lock);
		}
	}
}
Exemple #2
0
static int dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	unsigned long totbytes = params_buffer_bytes(params);
	struct s3c_dma_params *dma =
		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
	struct samsung_dma_req req;
	struct samsung_dma_config config;

	pr_debug("Entered %s\n", __func__);

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params -HW */
	if (prtd->params == NULL) {
		/* prepare DMA */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		prtd->params->ops = samsung_dma_get_ops();

		req.cap = (samsung_dma_has_circular() ?
			DMA_CYCLIC : DMA_SLAVE);
		req.client = prtd->params->client;
		config.direction =
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
			? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
		config.width = prtd->params->dma_size;
		config.maxburst = 1;
		config.fifo = prtd->params->dma_addr;
		prtd->params->ch = prtd->params->ops->request(
				prtd->params->channel, &req);
		prtd->params->ops->config(prtd->params->ch, &config);
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	runtime->dma_bytes = totbytes;

	spin_lock_irq(&prtd->lock);
	prtd->dma_loaded = 0;
	prtd->dma_period = params_period_bytes(params);
	prtd->dma_start = runtime->dma_addr;
	prtd->dma_pos = prtd->dma_start;
	prtd->dma_end = prtd->dma_start + totbytes;
	spin_unlock_irq(&prtd->lock);

	return 0;
}
static int dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	unsigned long totbytes = params_buffer_bytes(params);
	struct s3c_dma_params *dma =
		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
	struct samsung_dma_info dma_info;

	pr_debug("Entered %s\n", __func__);

	/*                                             
                                                 */
	if (!dma)
		return 0;

	/*                                                   
                              */
	if (prtd->params == NULL) {
		/*             */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		prtd->params->ops = samsung_dma_get_ops();

		dma_info.cap = (samsung_dma_has_circular() ?
			DMA_CYCLIC : DMA_SLAVE);
		dma_info.client = prtd->params->client;
		dma_info.direction =
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
			? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
		dma_info.width = prtd->params->dma_size;
		dma_info.fifo = prtd->params->dma_addr;
		prtd->params->ch = prtd->params->ops->request(
				prtd->params->channel, &dma_info);
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	runtime->dma_bytes = totbytes;

	spin_lock_irq(&prtd->lock);
	prtd->dma_loaded = 0;
	prtd->dma_period = params_period_bytes(params);
	prtd->dma_start = runtime->dma_addr;
	prtd->dma_pos = prtd->dma_start;
	prtd->dma_end = prtd->dma_start + totbytes;
	spin_unlock_irq(&prtd->lock);

	return 0;
}
/* dma_enqueue
 *
 * place a dma buffer onto the queue for the dma system
 * to handle.
 */
static void dma_enqueue(struct snd_pcm_substream *substream)
{
	struct runtime_data *prtd = substream->runtime->private_data;
	dma_addr_t pos = prtd->dma_pos;
	unsigned int limit;
	struct samsung_dma_prep dma_info;

	pr_debug("Entered %s\n", __func__);

	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;

	pr_debug("%s: loaded %d, limit %d\n",
				__func__, prtd->dma_loaded, limit);

	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
	dma_info.direction =
		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
		? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
	dma_info.fp = audio_buffdone;
	dma_info.fp_param = substream;
	dma_info.period = prtd->dma_period;
	dma_info.len = prtd->dma_period*limit;

	if (dma_info.cap == DMA_CYCLIC) {
		dma_info.buf = pos;
		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
		prtd->dma_loaded += limit;
		return;
	}

	while (prtd->dma_loaded < limit) {
		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);

		if ((pos + dma_info.period) > prtd->dma_end) {
			dma_info.period  = prtd->dma_end - pos;
			pr_debug("%s: corrected dma len %ld\n",
					__func__, dma_info.period);
		}

		dma_info.buf = pos;
		prtd->params->ops->prepare(prtd->params->ch, &dma_info);

		prtd->dma_loaded++;
		pos += prtd->dma_period;
		if (pos >= prtd->dma_end)
			pos = prtd->dma_start;
	}

	prtd->dma_pos = pos;
}
Exemple #5
0
static void audio_buffdone(void *data)
{
	struct snd_pcm_substream *substream = data;
	struct runtime_data *prtd = substream->runtime->private_data;

	pr_debug("Entered %s\n", __func__);

	if (prtd->state & ST_RUNNING) {
		prtd->dma_pos += prtd->dma_period;
		if (prtd->dma_pos >= prtd->dma_end)
			prtd->dma_pos = prtd->dma_start;

		if (substream)
			snd_pcm_period_elapsed(substream);

		spin_lock(&prtd->lock);
		if (!samsung_dma_has_circular()) {
			prtd->dma_loaded--;
			dma_enqueue(substream);
		}
		spin_unlock(&prtd->lock);
	}
}
Exemple #6
0
//static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
//				void *dev_id, int size,
//				enum s3c2410_dma_buffresult result)
static void audio_buffdone(void *data)
{
	//struct snd_pcm_substream *substream = dev_id;
	//struct s3c24xx_runtime_data *prtd;
    struct snd_pcm_substream *substream = data;
	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;

	pr_debug("Entered %s\n", __func__);

	//if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
	//	return;
    //
	//prtd = substream->runtime->private_data;
	if (prtd->state & ST_RUNNING) {                                                                         
		prtd->dma_pos += prtd->dma_period;                                                                  
		if (prtd->dma_pos >= prtd->dma_end)                                                                 
			prtd->dma_pos = prtd->dma_start;                                                                

	//if (substream)
	//	snd_pcm_period_elapsed(substream);
		if (substream)                                                                                      
			snd_pcm_period_elapsed(substream);                                                              

	//spin_lock(&prtd->lock);
	//if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
	//	prtd->dma_loaded--;
	//	s3c_dma_enqueue(substream);
	//}
		spin_lock(&prtd->lock);                                                                             
		if (!samsung_dma_has_circular()) {                                                                  
			prtd->dma_loaded--;                                                                             
			s3c_dma_enqueue(substream);                                                                         
		}                                                                                                   
		spin_unlock(&prtd->lock);                                                                           
	}
	//spin_unlock(&prtd->lock);
}
Exemple #7
0
/* s3c_dma_enqueue
 *
 * place a dma buffer onto the queue for the dma system
 * to handle.
*/
static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
{
	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
	dma_addr_t pos = prtd->dma_pos;
	unsigned int limit;
	//int ret;
	struct samsung_dma_prep_info dma_info;

	pr_debug("Entered %s\n", __func__);

	//if (s3c_dma_has_circular())
	//	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
	//else
	//	limit = prtd->dma_limit;
	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;

	pr_debug("%s: loaded %d, limit %d\n",
				__func__, prtd->dma_loaded, limit);

	//while (prtd->dma_loaded < limit) {
	//	unsigned long len = prtd->dma_period;
	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);                                   
	dma_info.direction =                                                                                    
		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK                                                     
		? DMA_TO_DEVICE : DMA_FROM_DEVICE);                                                                 
	dma_info.fp = audio_buffdone;                                                                           
	dma_info.fp_param = substream;                                                                          
	dma_info.period = prtd->dma_period;                                                                     
	dma_info.len = prtd->dma_period*limit;                                                                  
                                                                                                           
	while (prtd->dma_loaded < limit) {                                                                      

		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);

		//if ((pos + len) > prtd->dma_end) {
		//	len  = prtd->dma_end - pos;
		//	pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n", 
		//		__func__, len);
		//}
		if ((pos + dma_info.period) > prtd->dma_end) {
			dma_info.period  = prtd->dma_end - pos;
			pr_debug("%s: corrected dma len %ld\n",
					__func__, dma_info.period);                                                             
		}

		//ret = s3c2410_dma_enqueue(prtd->params->channel,
		//	substream, pos, len);
		dma_info.buf = pos;
		prtd->params->ops->prepare(prtd->params->ch, &dma_info);

		//if (ret == 0) {
		//	prtd->dma_loaded++;
		//	pos += prtd->dma_period;
		//	if (pos >= prtd->dma_end)
		//		pos = prtd->dma_start;
		//} else
		//	break;
		prtd->dma_loaded++;                                                                                 
		pos += prtd->dma_period;                                                                            
		if (pos >= prtd->dma_end)                                                                           
			pos = prtd->dma_start;                                                                          
	}

	prtd->dma_pos = pos;
}
Exemple #8
0
static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct s3c24xx_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	unsigned long totbytes = params_buffer_bytes(params);
	struct s3c_dma_params *dma =
		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
	//int ret = 0;
	struct samsung_dma_info dma_info;


	pr_debug("Entered %s\n", __func__);

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params -HW */
	if (prtd->params == NULL) {
		/* prepare DMA */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		//ret = s3c2410_dma_request(prtd->params->channel,
		//			  prtd->params->client, NULL);
        //
		//if (ret < 0) {
		//	printk(KERN_ERR "failed to get dma channel\n");
		//	return ret;
		//}
        //
		///* use the circular buffering if we have it available. */
		//if (s3c_dma_has_circular())
		//	s3c2410_dma_setflags(prtd->params->channel,
		//			     S3C2410_DMAF_CIRCULAR);
		prtd->params->ops = samsung_dma_get_ops();                                                          
                                                                                                           
		dma_info.cap = (samsung_dma_has_circular() ?                                                        
			DMA_CYCLIC : DMA_SLAVE);                                                                        
		dma_info.client = prtd->params->client;                                                             
		dma_info.direction =                                                                                
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK                                                 
			? DMA_TO_DEVICE : DMA_FROM_DEVICE);                                                             
		dma_info.width = prtd->params->dma_size;                                                            
		dma_info.fifo = prtd->params->dma_addr;                                                             
		prtd->params->ch = prtd->params->ops->request(                                                      
				prtd->params->channel, &dma_info);                                                          
	}

	//s3c2410_dma_set_buffdone_fn(prtd->params->channel,
	//			    s3c24xx_audio_buffdone);
	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	runtime->dma_bytes = totbytes;

	spin_lock_irq(&prtd->lock);
	prtd->dma_loaded = 0;
	//prtd->dma_limit = runtime->hw.periods_min;
	prtd->dma_period = params_period_bytes(params);
	prtd->dma_start = runtime->dma_addr;
	prtd->dma_pos = prtd->dma_start;
	prtd->dma_end = prtd->dma_start + totbytes;
	spin_unlock_irq(&prtd->lock);
	return 0;
}