设为首页 加入收藏

TOP

Alsa音频子系统Codec---al5623.c内核代码框架分析(一)
2017-06-22 10:24:00 】 浏览:509
Tags:Alsa 音频 子系统 Codec---al5623.c 内核 代码 框架 分析

驱动代码位于: sound/soc/codec/alc5623.c


随便找个Linux内核都会有。


1、首先进行i2c总线驱动加载在:


static int __init alc5623_modinit(void)
在该函数中:
i2c_add_driver(&alc5623_i2c_driver);
alc5623_i2c_driver是一个结构体变量,并且已经被初始化,我们来看看它做了什么?


static struct i2c_driver alc5623_i2c_driver = {
 .driver = {
  .name = "alc562x-codec",  //这是要注册的驱动的名字
  .owner = THIS_MODULE,    //该驱动属于哪个模块
 },
 .probe = alc5623_i2c_probe,      //驱动执行的probe函数,也就是说,驱动从这个函数开始加载相关的操作,类似第一个步骤里的__init
 .remove =  __devexit_p(alc5623_i2c_remove), //驱动模块删除函数
 .id_table = alc5623_i2c_table,    //对应的id_table--->其实就是该驱动支持的芯片类型。
};


2、i2c_driver结构体.
//这就是将该设备相关的平台注册到i2c总线上,该结构体变量已经做了初始化的操作.因为音频子系统alsa codec是与平台无关的,故可以这么来实现。


(1)id_table
我们先来看看id_table:
这是一个结构体数组,分别支持的音频芯片是alc5621,alc5622,alc5623---->对应的芯片ID就是0x21、0x22、0x23


static const struct i2c_device_id alc5623_i2c_table[] = {
 {"alc5621", 0x21},
 {"alc5622", 0x22},
 {"alc5623", 0x23},
 {}
};


(2)alc5623_i2c_remove
接下来看看该结构体中__devexit_p(alc5623_i2c_remove)的alc5623_i2c_remove函数:
这里实现很简单:


static int alc5623_i2c_remove(struct i2c_client *client)

 //通过客户端传回来的结构体指针变量--->获取i2c客户端的数据,因为这个驱动是i2c驱动。
 struct alc5623_priv *alc5623 = i2c_get_clientdata(client);
 //注销codec平台相关的设备
 snd_soc_unregister_codec(&client->dev);
 //释放内存
 kfree(alc5623);
 return 0;
}


(3)alc5623_i2c_probe
来看看我们驱动在probe函数的实现。
以下就是probe函数,作为一个支持i2c协议的芯片平台


static int alc5623_i2c_probe(struct i2c_client *client,
    const struct i2c_device_id *id)
{
 //定义一个获取芯片数据的指针
 struct alc5623_platform_data *pdata;
 //
 struct alc5623_priv *alc5623;
 int ret, vid1, vid2;
 //通过i2c总线获取芯片供应商的第一个ID--->下面就是这个宏的相关定义
 //#define ALC5623_VENDOR_ID1   0x7C
 vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1);
 //出错处理
 if (vid1 < 0) {
  dev_err(&client->dev, "failed to read I2C\n");
  return -EIO;
 }
 //将ID的高低八位互换再组合
 vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
 //通过i2c总线获取芯片供应商的第二个ID--->下面就是这个宏的相关定义---->通过芯片手册查阅到
 //#define ALC5623_VENDOR_ID2   0x7E
 vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2);
 if (vid2 < 0) {
  dev_err(&client->dev, "failed to read I2C\n");
  return -EIO;
 }
 //出错处理
 if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
  dev_err(&client->dev, "unknown or wrong codec\n");
  dev_err(&client->dev, "Expected %x:%lx, got %x:%x\n",
    0x10ec, id->driver_data,
    vid1, vid2);
  return -ENODEV;
 }
 //通过以上的操作组合我们可以得知我们需要操作的芯片是alc56xxx
 dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
 //开始对这个设备分配内核空间,根据GFP_KERNEL来分配
 alc5623 = kzalloc(sizeof(struct alc5623_priv), GFP_KERNEL);
 //如果分配为空,返回错误码
 if (alc5623 == NULL)
  return -ENOMEM;
 //获取数据
 pdata = client->dev.platform_data;
 if (pdata) {
  alc5623->add_ctrl = pdata->add_ctrl;
  alc5623->jack_det_ctrl = pd

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android系统shell中的df命令实现 下一篇Android系统shell中的clear命令实..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目