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

📄 harmony.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	return IRQ_HANDLED;}/*  * proc entry * this proc file will give some debugging info */static void snd_harmony_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer){	snd_card_harmony_t *harmony = (snd_card_harmony_t *)entry->private_data;	snd_iprintf(buffer, "LASI Harmony driver\nLaurent Canet <canetl@esiee.fr>\n\n");	snd_iprintf(buffer, "IRQ %d, hpa %lx, id %d rev %d\n",			harmony->irq, harmony->hpa,			harmony->id, harmony->rev);	snd_iprintf(buffer, "Current gain %lx\n", (unsigned long) harmony->current_gain);	snd_iprintf(buffer, "\tsample rate=%d\n", harmony->sample_rate);	snd_iprintf(buffer, "\tstereo select=%d\n", harmony->stereo_select);	snd_iprintf(buffer, "\tbitperchan=%d\n\n", harmony->data_format);		snd_iprintf(buffer, "Play status:\n");	snd_iprintf(buffer, "\tstopped %d\n", harmony->ply_stopped);	snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->ply_buffer, harmony->ply_count);	snd_iprintf(buffer, "\tbuf %d size %d\n\n", harmony->ply_buf, harmony->ply_size);		snd_iprintf(buffer, "Capture status:\n");	snd_iprintf(buffer, "\tstopped %d\n", harmony->cap_stopped);	snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->cap_buffer, harmony->cap_count);	snd_iprintf(buffer, "\tbuf %d, size %d\n\n", harmony->cap_buf, harmony->cap_size);	snd_iprintf(buffer, "Funny stats: total played=%d, recorded=%d\n\n", harmony->ply_total, harmony->cap_total);			snd_iprintf(buffer, "Register:\n");	snd_iprintf(buffer, "\tgainctl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_GAINCTL));	snd_iprintf(buffer, "\tcntl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_CNTL));	snd_iprintf(buffer, "\tid: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_ID));	snd_iprintf(buffer, "\tpcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PCURADD));	snd_iprintf(buffer, "\trcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RCURADD));	snd_iprintf(buffer, "\tpnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PNXTADD));	snd_iprintf(buffer, "\trnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RNXTADD));	snd_iprintf(buffer, "\tdstatus: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_DSTATUS));	snd_iprintf(buffer, "\tov: %lx\n\n", (unsigned long) gsc_readl(harmony->hpa+REG_OV));	}static void __devinit snd_harmony_proc_init(snd_card_harmony_t *harmony){	snd_info_entry_t *entry;		if (! snd_card_proc_new(harmony->card, "harmony", &entry))		snd_info_set_text_ops(entry, harmony, 2048, snd_harmony_proc_read);}/*  * PCM Stuff */static int snd_card_harmony_playback_ioctl(snd_pcm_substream_t * substream,				         unsigned int cmd,				         void *arg){	return snd_pcm_lib_ioctl(substream, cmd, arg);}static int snd_card_harmony_capture_ioctl(snd_pcm_substream_t * substream,					unsigned int cmd,					void *arg){	return snd_pcm_lib_ioctl(substream, cmd, arg);}static int snd_card_harmony_playback_trigger(snd_pcm_substream_t * substream,					   int cmd){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);		switch (cmd) {		case SNDRV_PCM_TRIGGER_STOP:			if (harmony->ply_stopped) 				return -EBUSY;			harmony->ply_stopped = 1;			snd_harmony_disable_interrupts(harmony);			break;		case SNDRV_PCM_TRIGGER_START:			if (!harmony->ply_stopped)				return -EBUSY;			harmony->ply_stopped = 0;			/* write the location of the first buffer to play */			gsc_writel(harmony->ply_buffer, harmony->hpa+REG_PNXTADD);			snd_harmony_enable_interrupts(harmony);			break;		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		case SNDRV_PCM_TRIGGER_SUSPEND:			DPRINTK(KERN_INFO PFX "received unimplemented trigger: %d\n", cmd);		default:			return -EINVAL;	}	return 0;}static int snd_card_harmony_capture_trigger(snd_pcm_substream_t * substream,					  int cmd){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);		switch (cmd) {		case SNDRV_PCM_TRIGGER_STOP:			if (harmony->cap_stopped) 				return -EBUSY;			harmony->cap_stopped = 1;			snd_harmony_disable_interrupts(harmony);			break;		case SNDRV_PCM_TRIGGER_START:			if (!harmony->cap_stopped)				return -EBUSY;			harmony->cap_stopped = 0;			snd_harmony_enable_interrupts(harmony);			break;		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		case SNDRV_PCM_TRIGGER_SUSPEND:			DPRINTK(KERN_INFO PFX "Received unimplemented trigger: %d\n", cmd);		default:			return -EINVAL;	}	return 0;}/* set data format */static int snd_harmony_set_data_format(snd_card_harmony_t *harmony, int pcm_format){	int old_format = harmony->data_format;	int new_format = old_format;	switch (pcm_format) {	case SNDRV_PCM_FORMAT_S16_BE:		new_format = HARMONY_DF_16BIT_LINEAR;		break;	case SNDRV_PCM_FORMAT_A_LAW:		new_format = HARMONY_DF_8BIT_ALAW;		break;	case SNDRV_PCM_FORMAT_MU_LAW:		new_format = HARMONY_DF_8BIT_ULAW;		break;	}	/* re-initialize silence buffer if needed */	if (old_format != new_format)		snd_pcm_format_set_silence(pcm_format, harmony->silence_dma.area,					   (HARMONY_BUF_SIZE * SILENCE_BUFS * 8) / snd_pcm_format_width(pcm_format));	return new_format;}static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;		harmony->ply_size 			= snd_pcm_lib_buffer_bytes(substream);	harmony->ply_count 			= snd_pcm_lib_period_bytes(substream);	harmony->ply_buf			= 0;	harmony->ply_stopped		= 1;		/* initialize given sample rate */	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);	/* data format */	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);	/* number of channels */	if (runtime->channels == 2)		harmony->stereo_select = HARMONY_SS_STEREO;	else		harmony->stereo_select = HARMONY_SS_MONO;		DPRINTK(KERN_INFO PFX "Playback_prepare, sr=%d(%x), df=%x, ss=%x hpa=%lx\n", runtime->rate,				harmony->sample_rate, harmony->data_format, harmony->stereo_select, harmony->hpa);	snd_harmony_update_control(harmony);	harmony->format_initialized = 1;	harmony->ply_buffer = runtime->dma_addr;		return 0;}static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);		harmony->cap_size 			= snd_pcm_lib_buffer_bytes(substream);	harmony->cap_count 			= snd_pcm_lib_period_bytes(substream);	harmony->cap_count			= 0;	harmony->cap_stopped		= 1;	/* initialize given sample rate */	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);		/* data format */	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);		/* number of channels */	if (runtime->channels == 1)		harmony->stereo_select = HARMONY_SS_MONO;	else if (runtime->channels == 2)		harmony->stereo_select = HARMONY_SS_STEREO;			snd_harmony_update_control(harmony);	harmony->format_initialized = 1;		harmony->cap_buffer = runtime->dma_addr;	return 0;}static snd_pcm_uframes_t snd_card_harmony_capture_pointer(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);	unsigned long rcuradd;	int recorded;		if (harmony->cap_stopped) return 0;	if (harmony->capture_substream == NULL) return 0;	rcuradd = gsc_readl(harmony->hpa+REG_RCURADD);	recorded = (rcuradd - harmony->cap_buffer);	recorded %= harmony->cap_size;			return bytes_to_frames(runtime, recorded);}/* */static snd_pcm_uframes_t snd_card_harmony_playback_pointer(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);	int played;	long int pcuradd = gsc_readl(harmony->hpa+REG_PCURADD);		if ((harmony->ply_stopped) || (harmony->playback_substream == NULL)) return 0;	if ((harmony->ply_buffer == 0) || (harmony->ply_size == 0)) return 0;		played = (pcuradd - harmony->ply_buffer);		printk(KERN_DEBUG PFX "Pointer is %lx-%lx = %d\n", pcuradd, harmony->ply_buffer, played);		if (pcuradd > harmony->ply_buffer + harmony->ply_size) return 0;		return bytes_to_frames(runtime, played);}static snd_pcm_hardware_t snd_card_harmony_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 					SNDRV_PCM_INFO_JOINT_DUPLEX | 					SNDRV_PCM_INFO_MMAP_VALID |					SNDRV_PCM_INFO_BLOCK_TRANSFER),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | 					SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5500,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	MAX_BUFFER_SIZE,	.period_bytes_min =	HARMONY_BUF_SIZE,	.period_bytes_max =	HARMONY_BUF_SIZE,	.periods_min =		1,	.periods_max =		MAX_BUFS,	.fifo_size =		0,};static snd_pcm_hardware_t snd_card_harmony_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 					SNDRV_PCM_INFO_JOINT_DUPLEX | 					SNDRV_PCM_INFO_MMAP_VALID |					SNDRV_PCM_INFO_BLOCK_TRANSFER),	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | 					SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5500,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	MAX_BUFFER_SIZE,	.period_bytes_min =	HARMONY_BUF_SIZE,	.period_bytes_max =	HARMONY_BUF_SIZE,	.periods_min =		1,	.periods_max =		MAX_BUFS,	.fifo_size =		0,};static int snd_card_harmony_playback_open(snd_pcm_substream_t * substream){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;		harmony->playback_substream = substream;	runtime->hw = snd_card_harmony_playback;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);		if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)		return err;		return 0;}static int snd_card_harmony_capture_open(snd_pcm_substream_t * substream){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;		harmony->capture_substream = substream;	runtime->hw = snd_card_harmony_capture;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)		return err;	return 0;}static int snd_card_harmony_playback_close(snd_pcm_substream_t * substream){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);		harmony->playback_substream = NULL;	harmony->ply_size 			= 0;	harmony->ply_buf			= 0;	harmony->ply_buffer			= 0;	harmony->ply_count			= 0;	harmony->ply_stopped		= 1;	harmony->format_initialized = 0;		return 0;}static int snd_card_harmony_capture_close(snd_pcm_substream_t * substream){	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);		harmony->capture_substream = NULL;	harmony->cap_size 			= 0;	harmony->cap_buf			= 0;	harmony->cap_buffer			= 0;	harmony->cap_count			= 0;	harmony->cap_stopped		= 1;	harmony->format_initialized = 0;		return 0;}static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream, 	                   snd_pcm_hw_params_t * hw_params){	int err;		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));	if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS)		substream->runtime->dma_addr = __pa(substream->runtime->dma_area);	DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,			(unsigned long)substream->runtime->dma_addr);	return err;}static int snd_card_harmony_hw_free(snd_pcm_substream_t *substream) {	snd_pcm_lib_free_pages(substream);			return 0;}static snd_pcm_ops_t snd_card_harmony_playback_ops = {	.open =			snd_card_harmony_playback_open,	.close =		snd_card_harmony_playback_close,	.ioctl =		snd_card_harmony_playback_ioctl,	.hw_params = 	snd_card_harmony_hw_params,

⌨️ 快捷键说明

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