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

📄 akt50-sound_c.txt

📁 2410uda1341的测试代码
💻 TXT
字号:
//#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_lock

static 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 + -