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

📄 akt50-sound.c

📁 基于linux kernel 2.6.20的UDA1341声音芯片的声卡驱动
💻 C
字号:
//#define DEBUG 1#include "debug.h"#include <linux/autoconf.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/device.h>#include <linux/pm.h>#include <linux/dma-mapping.h>#include <linux/platform_device.h>#include <sound/driver.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/initval.h>#include "algo-bit.h"#include <asm/system.h>#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/arch/regs-gpio.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/arch/regs-iis.h>#include "audio.h"#include "s3c24xx-iis.h"#include "uda1341.h"#ifdef DEBUG#undef pr_debug#define pr_debug(fmt,arg...) printk(fmt,##arg)#endif/* l3 operations */#define L3NAME "l3-bit-akt50-gpio"struct bit_data {	unsigned int	sda;	unsigned int	scl;	unsigned int	l3_mode;};static int getsda(void *data){	struct bit_data *bits = data;	return s3c2410_gpio_getpin(bits->sda);}static DECLARE_MUTEX(l3_lock);#define LOCK		&l3_lockstatic void l3_setscl(void *data, int state){	struct bit_data *bits = data;	unsigned long flags;//	pr_debug("--- %s\n", __FUNCTION__);	local_irq_save(flags);	if (state)		s3c2410_gpio_setpin(bits->scl,1);	else		s3c2410_gpio_setpin(bits->scl,0);	s3c2410_gpio_cfgpin(bits->scl, S3C2410_GPIO_OUTPUT);	local_irq_restore(flags);}static void l3_setsda(void *data, int state){	struct bit_data *bits = data;//	pr_debug("--- %s\n", __FUNCTION__);	if (state)		s3c2410_gpio_setpin(bits->sda,1);	else		s3c2410_gpio_setpin(bits->sda,0);}static void l3_setdir(void *data, int in){	struct bit_data *bits = data;	unsigned long flags;//	pr_debug("--- %s\n", __FUNCTION__);	local_irq_save(flags);	if (in) {		s3c2410_gpio_cfgpin(bits->sda, S3C2410_GPIO_INPUT);	}	else		s3c2410_gpio_cfgpin(bits->sda, S3C2410_GPIO_OUTPUT);	local_irq_restore(flags);}static void l3_setmode(void *data, int state){	struct bit_data *bits = data;//	pr_debug("--- %s\n", __FUNCTION__);	if (state)		s3c2410_gpio_setpin(bits->l3_mode,1);	else		s3c2410_gpio_setpin(bits->l3_mode,0);}static struct l3_algo_bit_data l3_bit_data = {	.data		= NULL,	.setdat		= l3_setsda,	.setclk		= l3_setscl,	.setmode	= l3_setmode,	.setdir		= l3_setdir,	.getdat		= getsda,	.data_hold	= 1,	.data_setup	= 1,	.clock_high	= 1,	.mode_hold	= 1,	.mode_setup	= 1,};static struct l3_adapter l3_adapter = {	.owner		= THIS_MODULE,	.name		= L3NAME,	.algo_data	= &l3_bit_data,	.lock		= LOCK,};static int __init l3_init(struct bit_data *bits){	l3_bit_data.data = bits;		pr_debug("--- %s\n", __FUNCTION__);	return l3_bit_add_bus(&l3_adapter);}static void __exit l3_exit(void){	pr_debug("--- %s\n", __FUNCTION__);	l3_bit_del_bus(&l3_adapter);}static struct bit_data bit_data;/* codec operations */struct akt50_sound_s {	struct s3c24xx_iis_ops		 ops;	s3c24xx_card_t			*card;	struct device			*dev;	struct uda1341                  *uda1341;} ;static struct uda1341 *ops_to_uda(struct s3c24xx_iis_ops *ops){	struct akt50_sound_s *akt50_sound;	pr_debug("--- %s\n", __FUNCTION__);	akt50_sound = container_of(ops, struct akt50_sound_s, ops);	return akt50_sound->uda1341;}static s3c24xx_card_t *ops_to_card(struct s3c24xx_iis_ops *ops){	struct akt50_sound_s *akt50_sound;	pr_debug("--- %s\n", __FUNCTION__);	akt50_sound = container_of(ops, struct akt50_sound_s, ops);	return akt50_sound->card;}static int akt50_sound_open(struct s3c24xx_iis_ops *ops,			    snd_pcm_substream_t *stream){	pr_debug("--- %s\n", __FUNCTION__);	return uda1341_open(ops_to_uda(ops));}static int akt50_sound_close(struct s3c24xx_iis_ops *ops,			     snd_pcm_substream_t *stream){	struct uda1341_cfg conf;	pr_debug("--- %s\n", __FUNCTION__);	if (stream->stream == SNDRV_PCM_STREAM_CAPTURE) {	  conf.record = 1;	  conf.play = 0;	}	else {	  conf.play = 1;	  conf.record = 0;	}	uda1341_close(ops_to_uda(ops), &conf);	return 0;}static int akt50_sound_prepare(struct s3c24xx_iis_ops *ops,				       snd_pcm_substream_t *stream,				       snd_pcm_runtime_t *run){	struct uda1341_cfg conf;	s3c24xx_card_t *card;	pr_debug("--- %s\n", __FUNCTION__);	card = ops_to_card(ops);	if (card->is_384)		conf.fs = 384; 	else 		conf.fs = 256;	conf.format = FMT_I2S;	if (stream->stream == SNDRV_PCM_STREAM_CAPTURE) {	  conf.record = 1;	  conf.play = 0;	}	else {	  conf.play = 1;	  conf.record = 0;	}	uda1341_configure(ops_to_uda(ops), &conf);	return 0;}static int akt50_sound_startup(struct s3c24xx_iis_ops *ops){	pr_debug("--- %s\n", __FUNCTION__);	/* nothing */	return 0;}/* sound card operations */struct s3c24xx_iis_ops akt50_sound_ops = {	.owner		= THIS_MODULE,	.startup	= akt50_sound_startup,	.open		= akt50_sound_open,	.close		= akt50_sound_close,	.prepare	= akt50_sound_prepare,};static void akt50_sound_free(struct akt50_sound_s * akt50_sound){	pr_debug("--- %s\n", __FUNCTION__);	kfree(akt50_sound);}static int akt50_sound_remove(struct device *dev){	pr_debug("--- %s\n", __FUNCTION__);	/* shouldn't happen */	return 0;}static struct device *audio_dev;static int akt50_sound_probe(struct device *dev){	pr_debug("--- %s\n", __FUNCTION__);	audio_dev = dev;	return 0;}static struct device_driver akt50_sound_driver = {	.name		= "akt50-sound",	.bus		= &platform_bus_type,	.probe		= akt50_sound_probe,	.remove		= akt50_sound_remove,};static int akt50_sound_codec_probe(struct device *dev) {	struct akt50_sound_s *akt50_sound;	int err;	pr_debug("--- %s\n", __FUNCTION__);      	if (audio_dev == NULL) {		printk("null audio dev!\n");		err = -EINVAL;		goto finish2;	}	dev_info(dev, "attached akt50-sound driver\n");	/* allocate sound device */	akt50_sound = kmalloc(sizeof(struct akt50_sound_s), GFP_KERNEL);	if (akt50_sound == NULL) {		err = -ENOMEM;		goto finish2;	}	memset(akt50_sound, 0, sizeof(struct akt50_sound_s));	akt50_sound->dev = dev;	akt50_sound->card = s3c24xx_iis_probe(audio_dev);	if (IS_ERR(akt50_sound->card)) {		printk("Cannot probe iis device!\n");		err = PTR_ERR(akt50_sound->card);		goto finish3;	}	akt50_sound->ops	= akt50_sound_ops;	akt50_sound->card->chip_ops  = &akt50_sound->ops;	akt50_sound->card->client	= akt50_sound;	strcpy(akt50_sound->card->card->driver,    "akt50-sound");	strcpy(akt50_sound->card->card->shortname, "akt50");	strcpy(akt50_sound->card->card->longname,  "S3C241X UDA1341");	snd_card_set_dev(akt50_sound->card->card, audio_dev);	akt50_sound->uda1341 = uda1341_create(akt50_sound->card->card, 				      L3NAME);	if (IS_ERR(akt50_sound->uda1341)) {		printk("Cannot creade UDA1341\n");		err = PTR_ERR(akt50_sound->uda1341);		goto finish4;	}	/* default configuration for IIS */	s3c24xx_iismod_cfg(akt50_sound->card, S3C2410_IISMOD_16BIT, 0x0);	s3c24xx_iismod_cfg(akt50_sound->card, S3C2410_IISMOD_32FS,  0x0);	s3c24xx_iismod_cfg(akt50_sound->card, S3C2410_IISMOD_384FS, 0x0);	err = s3c24xx_iis_cfgclksrc(akt50_sound->card, "cdclk");	if (err) {		printk("Cannot setpu iis clock!\n");		goto finish5;	}	err = snd_card_register(akt50_sound->card->card);	if (err) {		printk("Cannot register sound card!\n");		goto finish5;	}	return 0;        finish5:	/* uda should be automaticaly freed */ finish4:	akt50_sound_remove(dev);	 finish3:	akt50_sound_free(akt50_sound); finish2:	return err;}static int akt50_sound_codec_remove(struct device *dev){	s3c24xx_card_t *card;	struct akt50_sound_s *client;	pr_debug("--- %s\n", __FUNCTION__);	card = dev_get_drvdata(dev);	if (card != NULL) {		client = card->client;		s3c24xx_iis_remove(dev);		akt50_sound_free(client);	}	return 0;}struct device_driver akt50_sound_codecdrv = {	.name		= "uda1341",	.bus		= &platform_bus_type,	.probe		= akt50_sound_codec_probe,	.remove		= akt50_sound_codec_remove,};static int __init akt50_sound_init(void){	struct bit_data *bit = &bit_data;	unsigned long flags;	int ret;	pr_debug("--- %s\n", __FUNCTION__);#ifdef CONFIG_ARCH_ATK50	bit->sda     = S3C2410_GPB5;	bit->scl     = S3C2410_GPB6;	bit->l3_mode = S3C2410_GPB7;#elif  defined(CONFIG_ARCH_SMDK2410)	bit->scl     = S3C2410_GPB4;	bit->sda     = S3C2410_GPB3;	bit->l3_mode = S3C2410_GPB2;#endif	if (!bit->sda)		return -ENODEV;	/*	 * Default level for L3 mode is low.	 * We set SCL and SDA high (i2c idle state).	 */	local_irq_save(flags);	s3c2410_gpio_cfgpin(bit->scl, S3C2410_GPIO_OUTPUT);	s3c2410_gpio_cfgpin(bit->sda, S3C2410_GPIO_OUTPUT);	s3c2410_gpio_cfgpin(bit->l3_mode, S3C2410_GPIO_OUTPUT);	local_irq_restore(flags);	/* if needed  */	ret = l3_init(bit);	if (ret) {	  printk("Failed to init L3!\n");	  goto finish1;	}	/* register iis device and codec */	if (driver_register(&akt50_sound_driver)<0) {		printk("Registration of akt50 sound driver failed!\n");	}	if (driver_register(&akt50_sound_codecdrv)<0) {		printk("Registration of akt50 codec driver failed!\n");	}		return 0; finish1:	return ret;}static void __exit akt50_sound_exit(void){	pr_debug("--- %s\n", __FUNCTION__);	driver_unregister(&akt50_sound_codecdrv);	driver_unregister(&akt50_sound_driver);	l3_exit();}module_init(akt50_sound_init);module_exit(akt50_sound_exit);/* TODO: suspend and resume! */MODULE_LICENSE("GPL");MODULE_DESCRIPTION("S3C4XX / UDA1341 Audio driver");MODULE_AUTHOR("Christian Pellegrin <chri@evolware.com>");

⌨️ 快捷键说明

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