⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omap2-audio.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sound/arm/omap/omap2-audio.c * * Common ALSA audio handling for the OMAP processors * * Copyright (C) 2007 Texas Instruments. * * This file is licensed under the terms of the GNU General Public License  * version 2. This program is licensed "as is" without any warranty of any  * kind, whether express or implied. * * Based on omap linux open source community alsa driver  * sound/arm/omap/omap-alsa.c * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi> * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil  * Based on sa11xx-uda1341.c, * Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>  * */// #include <linux/config.h>#include <linux/autoconf.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/sched.h>#include <linux/poll.h>#include <linux/pm.h>#include <linux/errno.h>#include <linux/sysrq.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/dma-mapping.h>#include <sound/driver.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/initval.h>#include <sound/control.h>#include <linux/clk.h>#include <linux/platform_device.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/hardware.h>// #include <asm/arch/bus.h>#include <asm/arch/clock.h>#include "omap2-audio_if.h"/* * Buffer management for alsa and dma */struct omap_alsa_stream {	int stream_id;		/* numeric identification */	int active:1;		/* we are using this stream for transfer now */	int period;		/* current transfer period */	int periods;		/* current count of periods registerd in the DMA engine */	spinlock_t dma_lock;	/* for locking in DMA operations */	int offset;		/* store start position of the last period in the alsa buffer */	struct snd_pcm_substream *stream;	/* the pcm stream */};struct omap_alsa_state {	struct snd_card *card;	struct snd_pcm *pcm;	long samplerate;	struct omap_alsa_stream s[2];	/* playback & capture */	struct omap_alsa_codec *codec;};/***************************** MACROS ************************************//* Change to define if need be */#undef DEBUG#define DPRINTK( x... )#define FN_IN#define FN_OUT(x)#define OMAP_AUDIO_NAME		"omap-audio"#define DMA_NB_FRAGS	16#define DMA_FRAG_SIZE	(1024 * 8)static int audio_probe(struct platform_device *dev);static int audio_remove(struct platform_device *dev);static void audio_release(struct device *dev);static int audio_suspend(struct platform_device *dev, pm_message_t state);static int audio_resume(struct platform_device *dev);static struct platform_driver omap_audio_driver = {	.probe = audio_probe,	.remove = audio_remove,	.suspend = audio_suspend,	.resume = audio_resume,	.driver = {		.name = OMAP_AUDIO_NAME,	},};static struct platform_device omap_audio_device = {	.name = OMAP_AUDIO_NAME,	// .id = OMAP24xx_AUDIO_DEVID,	.id = 7,	.dev = {		/* we may add later */		.release = audio_release,	}};struct omap_alsa_state *omap_audio_state;// static int dpm_state;pm_message_t dpm_state;/**  * @brief audio_suspend - Function to handle suspend operations *  * @param dev  * @param state  *  * @return  */static int audio_suspend(struct platform_device *dev, pm_message_t state){	int ret = 0;	struct omap_alsa_state *chip;	struct snd_card *card = platform_get_drvdata(dev);	struct omap_alsa_codec *codec;	dpm_state = state;	chip = card->private_data;	codec = chip->codec;	if (card->power_state != SNDRV_CTL_POWER_D3) {		if (chip->card->power_state != SNDRV_CTL_POWER_D3) {			snd_power_change_state(chip->card,					SNDRV_CTL_POWER_D3);			snd_pcm_suspend_all(chip->pcm);			if (omap_audio_state->s[SNDRV_PCM_STREAM_PLAYBACK].active) {				ret = codec->codec_transfer_stop(SNDRV_PCM_STREAM_PLAYBACK);				codec->codec_shutdown();			}			if (omap_audio_state->s[SNDRV_PCM_STREAM_CAPTURE].active) {				ret = codec->codec_transfer_stop(SNDRV_PCM_STREAM_CAPTURE);				codec->codec_shutdown();			}		}	}	return ret;}/**  * @brief audio_resume - Function to handle resume operations *  * @param dev  *  * @return  */static int audio_resume(struct platform_device *dev){	int ret = 0;	struct omap_alsa_state *chip;	struct snd_card *card = platform_get_drvdata(dev);	struct omap_alsa_codec *codec; 	chip = card->private_data;	codec = chip->codec;	if (card->power_state != SNDRV_CTL_POWER_D0) {                          		if (chip->card->power_state != SNDRV_CTL_POWER_D0) {			if (omap_audio_state->s[SNDRV_PCM_STREAM_PLAYBACK].active) {				codec->codec_init();				ret = codec->codec_transfer_init(SNDRV_PCM_STREAM_PLAYBACK);			}			if (omap_audio_state->s[SNDRV_PCM_STREAM_CAPTURE].active) {				codec->codec_init();				ret = codec->codec_transfer_init(SNDRV_PCM_STREAM_CAPTURE);			}			snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);		}	}	return ret;        }// static u_int audio_get_dma_pos(struct omap_alsa_stream *s)static snd_pcm_uframes_t audio_get_dma_pos(struct omap_alsa_stream *s){	struct snd_pcm_substream *substream = s->stream;	struct snd_pcm_runtime *runtime = substream->runtime;	struct omap_alsa_state *state =	    snd_pcm_substream_chip(substream);	struct omap_alsa_codec *codec = state->codec;		// unsigned int offset;	snd_pcm_uframes_t offset;	unsigned long flags;	int ret = 0;	FN_IN;	if (unlikely(!s)) {		printk(KERN_ERR "Stream IS NULL!!\n");		return -EPERM;	}	/* we always ask only one frame to transmit/recieve,	 * variant is the element num 	 */	/* this must be called w/ interrupts locked as requested in dma.c */	spin_lock_irqsave(&s->dma_lock, flags);	ret = codec->codec_transfer_posn(s->stream_id); 	spin_unlock_irqrestore(&s->dma_lock, flags);	/* Now, the position related to the end of that period */	offset = bytes_to_frames(runtime, s->offset) - bytes_to_frames(runtime, ret);	if (offset >= runtime->buffer_size)		offset = 0;	if (ret < 0) {		printk(KERN_ERR		       "codec_transfer_posn: Unable to find index of "		       "transfer\n");	}	return offset;}/* *  Main dma routine, requests dma according where you are in main alsa buffer */static void audio_process_dma(struct omap_alsa_stream *s){	struct snd_pcm_substream *substream = s->stream;	struct snd_pcm_runtime *runtime;	struct omap_alsa_state *state =	    snd_pcm_substream_chip(substream);	struct omap_alsa_codec *codec = state->codec;		unsigned int dma_size;	unsigned int offset;	int ret;		FN_IN;	runtime = substream->runtime;	if (s->active) {		dma_size = frames_to_bytes(runtime, runtime->period_size);		offset = dma_size * s->period;		snd_assert(dma_size <= DMA_FRAG_SIZE,);		ret = codec->codec_transfer_start(s->stream_id,					(void *) (runtime->dma_addr) +					 offset, dma_size, s);		if (ret) {			printk(KERN_ERR			       "audio_process_dma: cannot queue DMA buffer (%i)\n",			       ret);			return;		}		s->period++;		s->period %= runtime->periods;		s->periods++;		s->offset = offset;	}}/*  *  This is called when dma IRQ occurs at the end of each transmited block */void audio_period_handler(void *arg){	struct omap_alsa_stream *s = arg;		FN_IN;	if (s->active)		snd_pcm_period_elapsed(s->stream);	spin_lock(&s->dma_lock);	if (s->periods > 0) 		s->periods--;		audio_process_dma(s);	spin_unlock(&s->dma_lock);}/*  * Alsa section * PCM settings and callbacks */static int snd_omap_alsa_trigger(struct snd_pcm_substream *substream, int cmd){	int stream_id = substream->pstr->stream;	struct omap_alsa_state *state =	    snd_pcm_substream_chip(substream);	struct omap_alsa_codec *codec = state->codec;		struct omap_alsa_stream *s = &state->s[stream_id];	int err = 0;	unsigned long flags;		FN_IN;	/* note local interrupts are already disabled in the midlevel code */	spin_lock(&s->dma_lock);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		/* requested stream startup */		s->active = 1;		audio_process_dma(s);		/* hnagalla -- 04/02/07 -- queue one more to get rid of poping noise */		audio_process_dma(s);		break;	case SNDRV_PCM_TRIGGER_STOP:		/* requested stream shutdown */		spin_lock_irqsave(&s->dma_lock, flags);		s->active = 0;		s->period = 0;		s->periods = 0;		/* TODO: need return ret code? */		codec->codec_transfer_stop(s->stream_id);		spin_unlock_irqrestore(&s->dma_lock, flags);		break;	default:		err = -EINVAL;		break;	}	spin_unlock(&s->dma_lock);		return err;}static int snd_omap_alsa_prepare(struct snd_pcm_substream * substream){	struct omap_alsa_state *state = snd_pcm_substream_chip(substream);	struct omap_alsa_codec *codec = state->codec; 	struct snd_pcm_runtime *runtime = substream->runtime;	struct omap_alsa_stream *s = &state->s[substream->pstr->stream];		FN_IN;	/* set requested samplerate */	codec->codec_set_samplerate(runtime->rate);	state->samplerate = runtime->rate;	if (runtime->channels == 1) {		/* Set Mono_mode, with DSP option */		codec->codec_set_stereomode(0x02, 0x01); 	}	else {		/* Set Stereo_mode, with DSP option */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -