S3C2440 UDA1341声卡驱动分析(oos)

发布时间:2024-06-13  

1,驱动架构:
驱动分两个层次,上层是平台设备驱动,底层是audio驱动与mixer驱动。

(1)标准的平台设备驱动结构,probe与remove两个函数。
probe:
获得平台资源->申请内存区域-io内存重映射->获得并使能时钟->设置gpio口->初始化iis总线-> 初始化uda1341->audio dma初始化->注册dsp和mixer->释放内存区域。
代码及注释:

static int s3c2410iis_probe(struct platform_device *pdev) {

struct resource *res;
unsigned long flags;
int ret;

DPRINTK("s3c2410iis_proben");

//获得平台设备资源

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
printk(KERN_INFO PFX "failed to get memory region resoucen");
return -ENOENT;
}

//申请可用内存

res = request_mem_region(res->start, RESSIZE(res), pdev->name);
if(res == 0){
printk(KERN_INFO PFX "failed to request io memory region.n");
return -ENOENT;
}

//io内存重映射

iis_base = ioremap(res->start, RESSIZE(res));
if(iis_base == 0){
printk(KERN_INFO PFX "failed to ioremap() io memory region.n"); ret = -EINVAL;
goto free_mem_region;
}

//获得时钟资源

iis_clock = clk_get(&pdev->dev, "iis");
if (iis_clock == NULL) {
printk(KERN_INFO PFX "failed to find clock sourcen");
return -ENOENT;
}
/**************************modify by lfc*****************************/
clk_enable(iis_clock);//使能时钟

/*****************************end add********************************/
//禁用本地中断,gpio口设置,恢复中断

local_irq_save(flags);

/* GPB 4: L3CLOCK, OUTPUT */
s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
s3c2410_gpio_pullup(S3C2410_GPB4,1);
/* GPB 3: L3DATA, OUTPUT */
s3c2410_gpio_cfgpin(S3C2410_GPB3,S3C2410_GPB3_OUTP);
/* GPB 2: L3MODE, OUTPUT */
s3c2410_gpio_cfgpin(S3C2410_GPB2,S3C2410_GPB2_OUTP);
s3c2410_gpio_pullup(S3C2410_GPB2,1);
/* GPE 3: I2SSDI */
s3c2410_gpio_cfgpin(S3C2410_GPE3,S3C2410_GPE3_I2SSDI);
s3c2410_gpio_pullup(S3C2410_GPE3,1);
/* GPE 0: I2SLRCK */
s3c2410_gpio_cfgpin(S3C2410_GPE0,S3C2410_GPE0_I2SLRCK);
s3c2410_gpio_pullup(S3C2410_GPE0,1);
/* GPE 1: I2SSCLK */
s3c2410_gpio_cfgpin(S3C2410_GPE1,S3C2410_GPE1_I2SSCLK);
s3c2410_gpio_pullup(S3C2410_GPE1,1);
/* GPE 2: CDCLK */
s3c2410_gpio_cfgpin(S3C2410_GPE2,S3C2410_GPE2_CDCLK);
s3c2410_gpio_pullup(S3C2410_GPE2,1);
/* GPE 4: I2SSDO */
s3c2410_gpio_cfgpin(S3C2410_GPE4,S3C2410_GPE4_I2SSDO);
s3c2410_gpio_pullup(S3C2410_GPE4,1);

local_irq_restore(flags);

init_s3c2410_iis_bus();//初始化iis


init_uda1341();//初始化uda1341


//初始化dma ch1 ch2

output_stream.dma_ch = DMA_CH2;

if (!audio_init_dma(&output_stream, "UDA1341 out") & DMACH_LOW_LEVEL) {
audio_clear_dma(&output_stream,&s3c2410iis_dma_out);
printk( KERN_WARNING AUDIO_NAME_VERBOSE
": unable to get DMA channelsn" );
return -EBUSY;
}

input_stream.dma_ch = DMA_CH1;

if (!audio_init_dma(&input_stream, "UDA1341 in") & DMACH_LOW_LEVEL) {
audio_clear_dma(&input_stream,&s3c2410iis_dma_in);
printk( KERN_WARNING AUDIO_NAME_VERBOSE
": unable to get DMA channelsn" );
return -EBUSY;
}

//注册dsp及mixer

audio_dev_dsp = register_sound_dsp(&smdk2410_audio_fops, -1);
audio_dev_mixer = register_sound_mixer(&smdk2410_mixer_fops, -1);

printk(AUDIO_NAME_VERBOSE " initializedn");

//释放内存区域

free_mem_region:
release_mem_region(res->start, RESSIZE(res));

return 0;
}

remove:
禁用时钟->取消dsp mixer注册->清除dma

static int s3c2410iis_remove(struct platform_device *dev) {
DPRINTK("s3c2410iis_removen");

if (iis_clock != NULL){
clk_disable(iis_clock);
clk_put(iis_clock);
iis_clock = NULL;
}

unregister_sound_dsp(audio_dev_dsp);
unregister_sound_mixer(audio_dev_mixer);
audio_clear_dma(&output_stream,&s3c2410iis_dma_out);
audio_clear_dma(&input_stream,&s3c2410iis_dma_in); /* input */
printk(AUDIO_NAME_VERBOSE " unloadedn");

return 0;
}

uda1341的初始化:
设置gpio口->uda1341复位->uda1341设置

static void init_uda1341(void)
{

/* GPB 4: L3CLOCK */
/* GPB 3: L3DATA */
/* GPB 2: L3MODE */

unsigned long flags;

DPRINTK("init_uda1341n");

uda1341_volume = 62 - ((DEF_VOLUME * 61) / 100);
uda1341_boost = 0;
// uda_sampling = DATA2_DEEMP_NONE;

// uda_sampling &= ~(DATA2_MUTE);



local_irq_save(flags);

s3c2410_gpio_setpin(S3C2410_GPB2,1);//L3MODE=1

s3c2410_gpio_setpin(S3C2410_GPB4,1);//L3CLOCK=1

local_irq_restore(flags);

uda1341_l3_address(UDA1341_REG_STATUS);
uda1341_l3_data(0x40 | STAT0_SC_384FS | STAT0_IF_MSB|STAT0_DC_FILTER); // reset uda1341

uda1341_l3_data(STAT1 | STAT1_ADC_ON | STAT1_DAC_ON);

uda1341_l3_address(UDA1341_REG_DATA0);
// uda1341_l3_data(DATA0 |DATA0_VOLUME(0x0)); // maximum volume

uda1341_l3_data(DATA0 | DATA0_VOLUME(uda1341_volume));//lfc

uda1341_l3_data(DATA1 |DATA1_BASS(uda1341_boost)| DATA1_TREBLE(0));
uda1341_l3_data((DATA2 |DATA2_DEEMP_NONE) &~(DATA2_MUTE));
uda1341_l3_data(EXTADDR(EXT2));
uda1341_l3_data(EXTDATA(EXT2_MIC_GAIN(0x6)) | EXT2_MIXMODE_CH1);//input channel 1 select(input channel 2 off)


}


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>