微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > s3c2410上iis接口的uda341驱动的学习

s3c2410上iis接口的uda341驱动的学习

时间:11-11 来源:互联网 点击:
to get memory region resouce\n");return -ENOENT;}//2410iis的虚拟地址,不知道什么时候ioremap过来的iis_base = (void *)S3C24XX_VA_IIS ;if (iis_base == 0) {printk(KERN_INFO PFX "failed to ioremap() region\n");return -EINVAL;}//clk相关的操作,见后文的分析iis_clock = clk_get(dev, "iis");if (iis_clock == NULL) {printk(KERN_INFO PFX "failed to find clock source\n");return -ENOENT;}/**************************modify by lfc*****************************///2.6.11内核有此函数,意思是增加一个引用计数,最新的内核已经没有了clk_use(iis_clock);//使能iis的时钟,因为2410启动时disable了该时钟的//对此处修改有疑问,因为后面的init_s3c2410_iis_bus中又disable了iis的时钟clk_enable(iis_clock);/*****************************end add********************************/local_irq_save(flags);//配置L3接口,i2s接口占用的GPIO引脚/* GPB 4: L3CLOCK, OUTPUT */s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);s3c2410_gpio_pullup(S3C2410_GPB4,1);... ...local_irq_restore(flags);//初始化2410的iis控制器init_s3c2410_iis_bus();//初始化uda1341init_uda1341();//初始化缓冲用的stream//输出用dma的channel2output_stream.dma_ch = DMA_CH2;if (audio_init_dma(&output_stream, "UDA1341 out")) {audio_clear_dma(&output_stream,&s3c2410iis_dma_out);printk( KERN_WARNING AUDIO_NAME_VERBOSE": unable to get DMA channels\n" );return -EBUSY;}//输入用dma的channel1input_stream.dma_ch = DMA_CH1;if (audio_init_dma(&input_stream, "UDA1341 in")) {audio_clear_dma(&input_stream,&s3c2410iis_dma_in);printk( KERN_WARNING AUDIO_NAME_VERBOSE": unable to get DMA channels\n" );return -EBUSY;}//audio_dev_dsp = register_sound_dsp(&smdk2410_audio_fops, -1);audio_dev_mixer = register_sound_mixer(&smdk2410_mixer_fops, -1);printk(AUDIO_NAME_VERBOSE " initialized\n");return 0;}//初始化2410的iis控制器static void init_s3c2410_iis_bus(void){writel(0, iis_base + S3C2410_IISPSR);writel(0, iis_base + S3C2410_IISCON);writel(0, iis_base + S3C2410_IISMOD);writel(0, iis_base + S3C2410_IISFCON);clk_disable(iis_clock);}

clk_get(dev, "iis")定义在plat-s3c24xx的clock.c里面,这个文件提供了所有s3c系列的cpu的时钟方面的管理接口.

struct clk *clk_get(struct device *dev, const char *id){struct clk *p;struct clk *clk = ERR_PTR(-ENOENT);int idno;if (dev == NULL || dev->bus != &platform_bus_type)idno = -1;elseidno = to_platform_device(dev)->id;mutex_lock(&clocks_mutex);//从维护的一个struct clk链表中找到名字等于输入参数的结点,这个链表中的元素是具体的cpu的初始时注册进去的,见后文描述list_for_each_entry(p, &clocks, list) {if (p->id == idno &&strcmp(id, p->name) == 0 &&try_module_get(p->owner)) {clk = p;break;}}... ...mutex_unlock(&clocks_mutex);return clk;}

在match-s3c2410/clock.c里面,定义了启动时要使能或不使能的时钟源

static struct clk init_clocks_disable[] = {{.name      = "nand",.id      = -1,.parent      = &clk_h,.enable      = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_NAND,}, {.name      = "iis",.id      = -1,.parent      = &clk_p,.enable      = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_IIS,},... ...};static struct clk init_clocks[] = {{.name      = "lcd",.id      = -1,.parent      = &clk_h,.enable      = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_LCDC,}, {.name      = "gpio",.id      = -1,.parent      = &clk_p,.enable      = s3c2410_clkcon_enable,.ctrlbit   = S3C2410_CLKCON_GPIO,}, ... ...};

系统初始化的时候会调用该文件的s3c2410_baseclk_add里面,调用了plat-s3c24xx提供的接口注册这些时钟源:

int __init s3c2410_baseclk_add(void){... ...clkp = init_clocks;for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {/* ensure that we note the clock state */clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;ret = s3c24xx_register_clock(clkp);if (ret < 0) {printk(KERN_ERR "Failed to register clock %s (%d)\n",clkp->name, ret);}}clkp = init_clocks_disable;for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {ret = s3c24xx_register_clock(clkp);if (ret < 0) {printk(KERN_ERR "Failed to register clock %s (%d)\n",clkp->name, ret);}s3c2410_clkcon_enable(clkp, 0);}... ...}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top