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

📄 h3600-uda1341.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
字号:
/* * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec. * * Copyright (c) 2000 Nicolas Pitre <nico@cam.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License. * * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support. * This driver makes use of the UDA1341 and the sa1100-audio modules. * * History: * * 2000-05-21	Nicolas Pitre	Initial UDA1341 driver release. * * 2000-07-??	George France	Bitsy support. * * 2000-12-13	Deborah Wallach Fixed power handling for iPAQ/h3600 * * 2001-06-03	Nicolas Pitre	Made this file a separate module, based on *				the former sa1100-uda1341.c driver. * * 2001-07-13	Nicolas Pitre	Fixes for all supported samplerates. * */#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/errno.h>#include <linux/sound.h>#include <linux/soundcard.h>#include <linux/l3/l3.h>#include <linux/l3/uda1341.h>#include <asm/semaphore.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/dma.h>//#include <asm/arch/h3600_hal.h>#include "sa1100-audio.h"#undef DEBUG#ifdef DEBUG#define DPRINTK( x... )  printk( ##x )#else#define DPRINTK( x... )#endif#define AUDIO_NAME		"Bitsy_UDA1341"#define AUDIO_RATE_DEFAULT	44100static struct l3_client uda1341;static intmixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg){	/*	 * We only accept mixer (type 'M') ioctls.	 */	if (_IOC_TYPE(cmd) != 'M')		return -EINVAL;	return l3_command(&uda1341, cmd, (void *)arg);}static struct file_operations h3600_mixer_fops = {	ioctl:		mixer_ioctl,	owner:		THIS_MODULE};/* * Audio interface */static long audio_samplerate = AUDIO_RATE_DEFAULT;/* * Stop-gap solution until rest of hh.org HAL stuff is merged. */#define GPIO_H3600_CLK_SET0		GPIO_GPIO (12)#define GPIO_H3600_CLK_SET1		GPIO_GPIO (13)static void h3600_set_audio_clock(long val){	switch (val) {	case 24000: case 32000: case 48000:	/* 00: 12.288 MHz */		GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;		break;	case 22050: case 29400: case 44100:	/* 01: 11.2896 MHz */		GPSR = GPIO_H3600_CLK_SET0;		GPCR = GPIO_H3600_CLK_SET1;		break;	case 8000: case 10666: case 16000:	/* 10: 4.096 MHz */		GPCR = GPIO_H3600_CLK_SET0;		GPSR = GPIO_H3600_CLK_SET1;		break;	case 10985: case 14647: case 21970:	/* 11: 5.6245 MHz */		GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;		break;	}}static void h3600_set_samplerate(long val){	struct uda1341_cfg cfg;	int clk_div = 0;	/* We don't want to mess with clocks when frames are in flight */	Ser4SSCR0 &= ~SSCR0_SSE;	/* wait for any frame to complete */	udelay(125);	/*	 * We have the following clock sources:	 * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz	 * Those can be divided either by 256, 384 or 512.	 * This makes up 12 combinations for the following samplerates...	 */	if (val >= 48000)		val = 48000;	else if (val >= 44100)		val = 44100;	else if (val >= 32000)		val = 32000;	else if (val >= 29400)		val = 29400;	else if (val >= 24000)		val = 24000;	else if (val >= 22050)		val = 22050;	else if (val >= 21970)		val = 21970;	else if (val >= 16000)		val = 16000;	else if (val >= 14647)		val = 14647;	else if (val >= 10985)		val = 10985;	else if (val >= 10666)		val = 10666;	else		val = 8000;	/* Set the external clock generator */	h3600_set_audio_clock(val);	/* Select the clock divisor */	switch (val) {	case 8000:	case 10985:	case 22050:	case 24000:		cfg.fs = 512;		clk_div = SSCR0_SerClkDiv(16);		break;	case 16000:	case 21970:	case 44100:	case 48000:		cfg.fs = 256;		clk_div = SSCR0_SerClkDiv(8);		break;	case 10666:	case 14647:	case 29400:	case 32000:		cfg.fs = 384;		clk_div = SSCR0_SerClkDiv(12);		break;	}	cfg.format = FMT_LSB16;	l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);	Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;	audio_samplerate = val;}static void h3600_audio_init(void *dummy){	unsigned long flags;	/* Setup the uarts */	local_irq_save(flags);	GAFR |= (GPIO_SSP_CLK);	GPDR &= ~(GPIO_SSP_CLK);	Ser4SSCR0 = 0;	Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);	Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;	Ser4SSCR0 |= SSCR0_SSE;	/* Enable the audio power */	clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);	set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);	set_h3600_egpio(IPAQ_EGPIO_QMUTE);	local_irq_restore(flags);	/* external clock configuration */	h3600_set_samplerate(audio_samplerate);	/* Wait for the UDA1341 to wake up */	set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);	mdelay(1);	/* make the left and right channels unswapped (flip the WS latch ) */	Ser4SSDR = 0;	/* Initialize the UDA1341 internal state */	l3_open(&uda1341);	clr_h3600_egpio(IPAQ_EGPIO_QMUTE);}static void h3600_audio_shutdown(void *dummy){	/* disable the audio power and all signals leading to the audio chip */	l3_close(&uda1341);	Ser4SSCR0 = 0;	clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);	clr_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);	clr_h3600_egpio(IPAQ_EGPIO_QMUTE);}static int h3600_audio_ioctl(struct inode *inode, struct file *file,			     uint cmd, ulong arg){	long val;	int ret = 0;	/*	 * These are platform dependent ioctls which are not handled by the	 * generic sa1100-audio module.	 */	switch (cmd) {	case SNDCTL_DSP_STEREO:		ret = get_user(val, (int *) arg);		if (ret)			return ret;		/* the UDA1341 is stereo only */		ret = (val == 0) ? -EINVAL : 1;		return put_user(ret, (int *) arg);	case SNDCTL_DSP_CHANNELS:	case SOUND_PCM_READ_CHANNELS:		/* the UDA1341 is stereo only */		return put_user(2, (long *) arg);	case SNDCTL_DSP_SPEED:		ret = get_user(val, (long *) arg);		if (ret) break;		h3600_set_samplerate(val);		/* fall through */	case SOUND_PCM_READ_RATE:		return put_user(audio_samplerate, (long *) arg);	case SNDCTL_DSP_SETFMT:	case SNDCTL_DSP_GETFMTS:		/* we can do 16-bit only */		return put_user(AFMT_S16_LE, (long *) arg);	default:		/* Maybe this is meant for the mixer (As per OSS Docs) */		return mixer_ioctl(inode, file, cmd, arg);	}	return ret;}static audio_stream_t output_stream, input_stream;static audio_state_t audio_state = {	output_stream:	&output_stream,	output_dma:	DMA_Ser4SSPWr,	output_id:	"UDA1341 out",	input_stream:	&input_stream,	input_dma:	DMA_Ser4SSPRd,	input_id:	"UDA1341 in",	need_tx_for_rx: 1,	hw_init:	h3600_audio_init,	hw_shutdown:	h3600_audio_shutdown,	client_ioctl:	h3600_audio_ioctl,	sem:		__MUTEX_INITIALIZER(audio_state.sem),};static int h3600_audio_open(struct inode *inode, struct file *file){	return sa1100_audio_attach(inode, file, &audio_state);}/* * Missing fields of this structure will be patched with the call * to sa1100_audio_attach(). */static struct file_operations h3600_audio_fops = {	open:		h3600_audio_open,	owner:		THIS_MODULE};static int audio_dev_id, mixer_dev_id;static int __init h3600_uda1341_init(void){	int ret;	if (!machine_is_h3xxx())		return -ENODEV;	ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");	if (ret)		goto out;	/* register devices */	audio_dev_id = register_sound_dsp(&h3600_audio_fops, -1);	mixer_dev_id = register_sound_mixer(&h3600_mixer_fops, -1);	printk( KERN_INFO "iPAQ audio support initialized\n" );	return 0;release_l3:	l3_detach_client(&uda1341);out:	return ret;}static void __exit h3600_uda1341_exit(void){	unregister_sound_dsp(audio_dev_id);	unregister_sound_mixer(mixer_dev_id);	l3_detach_client(&uda1341);}module_init(h3600_uda1341_init);module_exit(h3600_uda1341_exit);MODULE_AUTHOR("Nicolas Pitre, George France");MODULE_DESCRIPTION("Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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