源码位于kernel\sound\soc\codecs\Wcd9335.c

1. 模块初始化入口代码放在了module_platform_driver()这个函数中,关于这个函数的解析,请看博客链接如下,

http://blog.csdn.net/jgw2008/article/details/52690602

module_platform_driver(tasha_codec_driver);

tasha_codec_driver结构体如下,模块加载入口从"tasha_probe"开始

static struct platform_driver tasha_codec_driver = {.probe = tasha_probe,.remove = tasha_remove,.shutdown = tasha_powershutdown,.driver = {.name = "tasha_codec",.owner = THIS_MODULE,
#ifdef CONFIG_PM.pm = &tasha_pm_ops,
#endif},
};

2. 下面分析函数"tasha_probe"

2.1 为tasha private data(私有数据)申请空间,并保存起来,

关于platform_set_drvdata的分析,请参见博文http://blog.csdn.net/jgw2008/article/details/52692616

 tasha = devm_kzalloc(&pdev->dev, sizeof(struct tasha_priv),GFP_KERNEL);if (!tasha) {dev_err(&pdev->dev, "%s: cannot create memory for wcd9335\n",__func__);return -ENOMEM;}platform_set_drvdata(pdev, tasha);

2.2 下面是tasha结构体初始化
注意:

a. 初始了2了工作队列,一个是跟power有关;一个是跟control有关。

b. 初始了6个mutex。

关于队列的分析介绍,请参见博文http://blog.csdn.net/jgw2008/article/details/52693268

关于devm_kzalloc的使用,参加博文http://blog.csdn.net/jgw2008/article/details/52691568

 tasha->wcd9xxx = dev_get_drvdata(pdev->dev.parent);tasha->dev = &pdev->dev;INIT_DELAYED_WORK(&tasha->power_gate_work, tasha_codec_power_gate_work);mutex_init(&tasha->power_lock);mutex_init(&tasha->sido_lock);INIT_WORK(&tasha->swr_add_devices_work, wcd_swr_ctrl_add_devices);BLOCKING_INIT_NOTIFIER_HEAD(&tasha->notifier);mutex_init(&tasha->micb_lock);mutex_init(&tasha->swr_read_lock);mutex_init(&tasha->swr_write_lock);mutex_init(&tasha->swr_clk_lock);cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),GFP_KERNEL);if (!cdc_pwr) {ret = -ENOMEM;goto cdc_pwr_fail;}tasha->wcd9xxx->wcd9xxx_pwr[WCD9XXX_DIG_CORE_REGION_1] = cdc_pwr;cdc_pwr->pwr_collapse_reg_min = TASHA_DIG_CORE_REG_MIN;cdc_pwr->pwr_collapse_reg_max = TASHA_DIG_CORE_REG_MAX;wcd9xxx_set_power_state(tasha->wcd9xxx,WCD_REGION_POWER_COLLAPSE_REMOVE,WCD9XXX_DIG_CORE_REGION_1);

2.3 向系统注册codec

关于codec注册的分析,可以参阅博文http://blog.csdn.net/jgw2008/article/details/52799186

 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tasha,tasha_dai, ARRAY_SIZE(tasha_dai));if (ret) {dev_err(&pdev->dev, "%s: Codec registration failed\n",__func__);goto cdc_reg_fail;}}

注意,snd_soc_register_codec的第二个参数"soc_codec_dev_tasha"的定义如下,其结构体成员将会赋值给结构体”snd_soc_codec“。

这个结构体里还有一个codec probe函数"tasha_codec_probe"不知道什么时候被呼叫,但无论如何,codec probe一定会被呼叫,而且是十分重要的函数。

关于codec probe函数"tasha_codec_probe"的分析,请参考博文http://blog.csdn.net/jgw2008/article/details/52818081

static struct snd_soc_codec_driver soc_codec_dev_tasha = {.probe = tasha_codec_probe,.remove = tasha_codec_remove,.suspend = tasha_codec_suspend,.resume = tasha_codec_resume,.controls = tasha_snd_controls,.num_controls = ARRAY_SIZE(tasha_snd_controls),.dapm_widgets = tasha_dapm_widgets,.num_dapm_widgets = ARRAY_SIZE(tasha_dapm_widgets),.dapm_routes = audio_map,.num_dapm_routes = ARRAY_SIZE(audio_map),
};

2.4 初始化资源管理器

 /** Init resource manager so that if child nodes such as SoundWire* requests for clock, resource manager can honor the request*/resmgr = wcd_resmgr_init(&tasha->wcd9xxx->core_res, NULL);if (IS_ERR(resmgr)) {ret = PTR_ERR(resmgr);dev_err(&pdev->dev, "%s: Failed to initialize wcd resmgr\n",__func__);goto unregister_codec;}tasha->resmgr = resmgr;

2.5 初始化 读/写/中断等的回调函数,十分重要

 tasha->swr_plat_data.handle = (void *) tasha;tasha->swr_plat_data.read = tasha_swrm_read;tasha->swr_plat_data.write = tasha_swrm_write;tasha->swr_plat_data.bulk_write = tasha_swrm_bulk_write;tasha->swr_plat_data.clk = tasha_swrm_clock;tasha->swr_plat_data.handle_irq = tasha_swrm_handle_irq;

2.6 注册clock

 /* Register for Clock */wcd_ext_clk = clk_get(tasha->wcd9xxx->dev, "wcd_clk");if (IS_ERR(wcd_ext_clk)) {dev_err(tasha->wcd9xxx->dev, "%s: clk get %s failed\n",__func__, "wcd_ext_clk");goto resmgr_remove;}tasha->wcd_ext_clk = wcd_ext_clk;

2.7 tasha其他设置,如电压等

 tasha->sido_voltage = SIDO_VOLTAGE_NOMINAL_MV;set_bit(AUDIO_NOMINAL, &tasha->status_mask);tasha->sido_ccl_cnt = 0;

2.8 更新code默认值

 /* Update codec register default values */tasha_update_reg_defaults(tasha);

2.9 添加设备(为什么要使用队列呢?)

关于添加设备到device list, 请见博文http://blog.csdn.net/jgw2008/article/details/52815271

 schedule_work(&tasha->swr_add_devices_work);

2.10 获取codec版本

 tasha_get_codec_ver(tasha);

至此,codec和DAIs(Digital Audio Interface)已经成功注册,probe函数跑完!

另外,研究一个驱动或者函数,其中涉及的结构体最为重要,在函数tasha_probe()中,主要涉及的结构体是"tasha_priv", 函数完成了对这个结构体的填充和初始化。

下面是结构体的定义

struct tasha_priv {struct device *dev;struct wcd9xxx *wcd9xxx;struct snd_soc_codec *codec;u32 adc_count;u32 rx_bias_count;s32 dmic_0_1_clk_cnt;s32 dmic_2_3_clk_cnt;s32 dmic_4_5_clk_cnt;s32 ldo_h_users;s32 micb_ref[TASHA_MAX_MICBIAS];s32 pullup_ref[TASHA_MAX_MICBIAS];u32 anc_slot;bool anc_func;/* Vbat module */struct wcd_vbat vbat;/* cal info for codec */struct fw_info *fw_data;/*track tasha interface type*/u8 intf_type;/* num of slim ports required */struct wcd9xxx_codec_dai_data  dai[NUM_CODEC_DAIS];/* SoundWire data structure */struct tasha_swr_ctrl_data *swr_ctrl_data;int nr;/*compander*/int comp_enabled[COMPANDER_MAX];/* Maintain the status of AUX PGA */int aux_pga_cnt;u8 aux_l_gain;u8 aux_r_gain;bool spkr_pa_widget_on;struct regulator *spkdrv_reg;struct regulator *spkdrv2_reg;bool mbhc_started;/* class h specific data */struct wcd_clsh_cdc_data clsh_d;struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;/** list used to save/restore registers at start and* end of impedance measurement*/struct list_head reg_save_restore;/* handle to cpe core */struct wcd_cpe_core *cpe_core;u32 current_cpe_clk_freq;enum tasha_sido_voltage sido_voltage;int sido_ccl_cnt;u32 ana_rx_supplies;/* Multiplication factor used for impedance detection */int zdet_gain_mul_fact;/* to track the status */unsigned long status_mask;struct work_struct swr_add_devices_work;struct wcd_swr_ctrl_platform_data swr_plat_data;/* Port values for Rx and Tx codec_dai */unsigned int rx_port_value;unsigned int tx_port_value;unsigned int vi_feed_value;/* Tasha Interpolator Mode Select for EAR, HPH_L and HPH_R */u32 hph_mode;u16 prim_int_users[TASHA_NUM_INTERPOLATORS];int spl_src_users[SPLINE_SRC_MAX];struct wcd9xxx_resmgr_v2 *resmgr;struct delayed_work power_gate_work;struct mutex power_lock;struct mutex sido_lock;/* mbhc module */struct wcd_mbhc mbhc;struct blocking_notifier_head notifier;struct mutex micb_lock;struct clk *wcd_ext_clk;struct mutex swr_read_lock;struct mutex swr_write_lock;struct mutex swr_clk_lock;int swr_clk_users;int power_active_ref;int (*zdet_gpio_cb)(struct snd_soc_codec *codec, bool high);struct on_demand_supply on_demand_list[ON_DEMAND_SUPPLIES_MAX];int (*machine_codec_event_cb)(struct snd_soc_codec *codec,enum wcd9335_codec_event);struct snd_info_entry *entry;struct snd_info_entry *version_entry;int spkr_gain_offset;int spkr_mode;struct hpf_work tx_hpf_work[TASHA_NUM_DECIMATORS];struct tx_mute_work tx_mute_dwork[TASHA_NUM_DECIMATORS];int hph_l_gain;int hph_r_gain;int rx_7_count;int rx_8_count;
};

WCD9335 audio driver Probe函数分析相关推荐

  1. [Linux Audio Driver] Android 10 machine driver probe函数分析

    0. 背景 平台:Qualcomm 5G SM6350.android10.kernel version: msm-4.19. 本文重点分析machine driver里面的msm_asoc_mach ...

  2. 3.1 mxc_v4l2_capture.c分析---probe函数分析

    mxc_v4l2_capture.c函数提供了应用程序中的一些接口函数,所以从分析它开始: (一)看一个驱动程序从它的入口函数开始: module_init(camera_init);static _ ...

  3. 4.1 ipu_common.c分析---入口函数及probe函数分析

    这个ipu_common.c函数提供ipu底层函数调用的一些关系和函数. (一)分析这个文件从init函数入口,发现有这个subsys_initcall,说明ipu是作为一个子系统注册到内核中的: i ...

  4. framebuffer驱动详解4——framebuffer驱动分析2(probe函数讲解)

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 主要在填充fbdev这个结构体. 二.framebuffer驱动分析2 1.probe函数分析 (1)struct s ...

  5. platform_device和platform_driver的注册过程,及probe函数何时调用的分析

    转载于http://blog.chinaunix.net/uid-7828352-id-3833188.html 参考资料:http://blog.csdn.net/xiafeng1113/artic ...

  6. 音频audio/sound声卡驱动分析

    音频可以播放(可以听到声音), 说明音频解码和输出部分基本是正常的, 整个通道已经打通了. 感觉播放速度太快了(或太慢了)说明audio输出部分的频率不对, 太高了或者太低了.audio/sound音 ...

  7. [Linux Audio Driver] 高通平台内部MIC_BIAS简介

    #更新 2020.05.10 我觉得我这个标题取的不是很妥当,为了表达对技术的敬畏之心,我将原标题 <一文搞懂内部MIC_BIAS>修改为<高通平台内部MIC_BIAS简介> ...

  8. 【整理】Linux驱动中,probe函数何时被调用

    声明:以下主要内容参考自: 关于struct device_driver结构中的probe探测函数的调用 http://blog.chinaunix.net/u2/71164/showart.php? ...

  9. Linux驱动中,probe函数何时被调用

    最近看到linux的设备驱动模型,关于Kobject.Kset等还不是很清淅.看到了struct device_driver这个结构时,想到一个问题:它的初始化函数到底在哪里调用呢?以前搞PCI驱动时 ...

最新文章

  1. 将JSON数据转换成JAVA的实体类
  2. php7 一句话木马,PHP一句话木马研究
  3. 传智播客 C/C++学习笔记 数组和指针的关系, 字符串学习
  4. 【Sencha Toucha】Sencha Touch ExtJs 给 Button 添加图片
  5. 绘图工具 Gliffy 使用简介
  6. 商业模式丶商业模式画布丶商业模式画布个人版
  7. 计算机通信的应用,计算机技术在通信中的应用
  8. matlab 读取.pgm,【数字图像处理】pbm/pgm/ppm图片的读写(Matlab)
  9. Xiph opus音频编码器试用
  10. 网络安全——防火墙详解
  11. 转:程序员应该怎样去学习和掌握计算机英语呢?
  12. python 爬取懂车帝详情页“全部车型模块信息”
  13. Qt5.13.0虚拟键盘 使用文档说明及函数说明 (一)构建 build
  14. oracle 字段别名
  15. Uos统信系统 本地APT源配置
  16. 深入理解grpc(二):grpc原理
  17. 从前车马很慢,书信很远,一生只够爱一个人
  18. 嵌入式Linux驱动学习【8】—— Nand Flash
  19. 自制app(游戏)Please Go之上传头像篇----萌新成长之路
  20. activiti之UserTask用户任务的到期日期(dueDate)属性作用

热门文章

  1. 华为[ENSP]删除配置错误端口trunk口
  2. Eftp - Mac 系统下免费开源的 FTP/SFTP 远程文件上传工具
  3. 终于看到Scroll Lock键的用途了
  4. 新锦福 苹果iPhone8概念机曝光:这外观,华为三星拍马难及
  5. DaSiamRPN测试程序分析
  6. 高中生活--第4篇--两座不可逾越的大山
  7. 负载、集群功能Beetle Agent简介
  8. HDU 4539 郑厂长系列故事――排兵布阵
  9. 考研必备 | 快速下载百度网盘的视频
  10. PS 滤镜算法原理——曝光过度