2. 注册platform

news2024/12/25 14:04:39

这里先分析platform

对应的dts内容如下

    i2s0_8ch: i2s@ff800000 {
        compatible = "rockchip,rv1126-i2s-tdm";
        reg = <0xff800000 0x1000>;
        interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cru MCLK_I2S0_TX>, <&cru MCLK_I2S0_RX>, <&cru HCLK_I2S0>;
        clock-names = "mclk_tx", "mclk_rx", "hclk";
        dmas = <&dmac 20>, <&dmac 19>;
        dma-names = "tx", "rx";
        resets = <&cru SRST_I2S0_TX_M>, <&cru SRST_I2S0_RX_M>;
        reset-names = "tx-m", "rx-m";
        rockchip,cru = <&cru>;
        rockchip,grf = <&grf>;
        pinctrl-names = "default";
        pinctrl-0 = <&i2s0m0_sclk_tx
                 &i2s0m0_sclk_rx
                 &i2s0m0_lrck_tx
                 &i2s0m0_lrck_rx
                 &i2s0m0_sdi0
                 &i2s0m0_sdo0
                 &i2s0m0_sdo1_sdi3
                 &i2s0m0_sdo2_sdi2
                 &i2s0m0_sdo3_sdi1>;
        status = "disabled";
    }; 
    
    &i2s0_8ch {
        status = "okay";
        #sound-dai-cells = <0>;
        rockchip,clk-trcm = <0>;
        rockchip,i2s-rx-route = <0 1 2 3>;
        pinctrl-names = "default";
        pinctrl-0 = <&i2s0m0_lrck_rx
                &i2s0m0_sclk_rx
                &i2s0m0_sdi0>;
        rockchip,capture-only;
    }; 

对应的驱动代码位置

kernel/sound/soc/rockchip/rockchip_i2s_tdm.c

这里只关注alsa相关的代码

static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
{
    ...

    ret = devm_snd_soc_register_component(&pdev->dev,
                          &rockchip_i2s_tdm_component,
                          soc_dai, 1);

    ...

    ret = rockchip_pcm_platform_register(&pdev->dev);
    if (ret) {
        dev_err(&pdev->dev, "Could not register PCM\n");
        return ret;
    }

    ...
}

rockchip_i2s_tdm_probe()->devm_snd_soc_register_component()

 

int devm_snd_soc_register_component(struct device *dev,
             const struct snd_soc_component_driver *cmpnt_drv,
             struct snd_soc_dai_driver *dai_drv, int num_dai)
{
    struct device **ptr;
    int ret;

    ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
    if (!ptr)
        return -ENOMEM;

    ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
    if (ret == 0) {
        *ptr = dev;
        devres_add(dev, ptr);
    } else {
        devres_free(ptr);
    }   

    return ret;
}

int snd_soc_register_component(struct device *dev,
            const struct snd_soc_component_driver *component_driver,
            struct snd_soc_dai_driver *dai_drv,
            int num_dai)
{
    struct snd_soc_component *component;

    component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
    if (!component)
        return -ENOMEM;

    return snd_soc_add_component(dev, component, component_driver,
                     dai_drv, num_dai);
}

int snd_soc_add_component(struct device *dev,
            struct snd_soc_component *component,
            const struct snd_soc_component_driver *component_driver,
            struct snd_soc_dai_driver *dai_drv,
            int num_dai)
{
    int ret;
    int i;

    /* 初始化componment 
     * 关联dev和component_driver
     */
    ret = snd_soc_component_initialize(component, component_driver, dev);
    if (ret)
        goto err_free;

    if (component_driver->endianness) {
        for (i = 0; i < num_dai; i++) {
            convert_endianness_formats(&dai_drv[i].playback);
            convert_endianness_formats(&dai_drv[i].capture);
        }
    }

    /* 1. 创建dai
     * 2. 关联component dev dai_drv
     * 3. 将dai通过list挂载到component的dai_list
     * 4. 更新component->num_dai
     */
    ret = snd_soc_register_dais(component, dai_drv, num_dai);
    if (ret < 0) {
        dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
        goto err_cleanup;
    }

    /* 将component通过list挂载到 component_list (全局) 上*/
    snd_soc_component_add(component);

    return 0;

err_cleanup:
    snd_soc_component_cleanup(component);
err_free:
    return ret;
}

 rockchip_i2s_tdm_probe()->rockchip_pcm_platform_register()

int rockchip_pcm_platform_register(struct device *dev)
{
    return devm_snd_dmaengine_pcm_register(dev, &rk_dmaengine_pcm_config,
        SND_DMAENGINE_PCM_FLAG_COMPAT);
}

int devm_snd_dmaengine_pcm_register(struct device *dev,
    const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
    struct device **ptr;
    int ret;

    ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
    if (!ptr)
        return -ENOMEM;

    ret = snd_dmaengine_pcm_register(dev, config, flags);
    if (ret == 0) {
        *ptr = dev;
        devres_add(dev, ptr);
    } else {
        devres_free(ptr);
    }   

    return ret;
}

int snd_dmaengine_pcm_register(struct device *dev,
    const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
    struct dmaengine_pcm *pcm;
    int ret;

    pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
    if (!pcm)
        return -ENOMEM;

#ifdef CONFIG_DEBUG_FS
    pcm->component.debugfs_prefix = "dma";
#endif
    pcm->config = config;
    pcm->flags = flags;

    /* dma相关
     * 这里会关联到dma 获取dts中rx tx channel
     * channel存放在pcm->chan[]数组
     */
    ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
    if (ret)
        goto err_free_dma;

    if (config && config->process)
        ret = snd_soc_add_component(dev, &pcm->component,
                        &dmaengine_pcm_component_process,
                        NULL, 0); 
    else
        /* 增加一个新的component 主要用于dma相关
         * 同样component通过list挂载到 component_list (全局) 上
         */
        ret = snd_soc_add_component(dev, &pcm->component,
                        &dmaengine_pcm_component, NULL, 0); 
    if (ret)
        goto err_free_dma;

    return 0;

err_free_dma:
    dmaengine_pcm_release_chan(pcm);
    kfree(pcm);
    return ret;
}

 

 以上代码可以得到这样一张链接关系图,都只是挂载到链表,并没有实际的注册动作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/714728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA开发( 腾讯云消息队列 RocketMQ使用总结 )

一、问题背景 之所以需要不停的总结是因为在java开发过程中使用到中间件实在太多了&#xff0c;久久不用就会慢慢变得生疏&#xff0c;有时候一个中间很久没使用&#xff0c;可能经过了很多版本的迭代&#xff0c;使用起来又有区别。所以还是得不断总结更新。最近博主就是在使用…

睿铂相机同步性控制技术解析

极客睿铂 前几期睿铂给大家分享了一些倾斜相机背后的技术&#xff0c;主要都是的关于镜头光学方面的。但实际上倾斜摄影相机还有很多其他关键性技术有待突破&#xff0c;任何技术的发展都不能一蹴而就&#xff0c;需要根据客户的问题反馈&#xff0c;发现新的问题并解决问题&a…

自定义MVC架构【下】

目录 一、前言 二、导出自定义MVC架包 三、使用自定义MVC架包 四、优化增删改查Dao层及Servlet 1.优化增删改查Dao层 2.优化增删改查Servlet代码 五、案例实操 1.将PageTag自定义标签进行配置 2.jsp页面环境搭建 3.案例演示 一、前言 在上篇中&#xff0c;我们已经优化…

ARM架构(寄存器点灯)

文章目录 前言一、LED原理图二、使用寄存器点灯的步骤三、如何操作寄存器四、实际操作1.使能GPIO端口2.将引脚设置为输出模式3.设置输出状态 五、全部代码总结 前言 本篇文章我们来讲解一下如何使用寄存器点亮一个LED灯&#xff0c;一般对于新人来说都是使用HAL库或者标准库来…

SpringBoot3【④ 基础特性】

1. SpringApplication 1.1. 自定义 banner 类路径添加banner.txt或设置spring.banner.location就可以定制 banner推荐网站&#xff1a;Spring Boot banner 在线生成工具&#xff0c;制作下载英文 banner.txt&#xff0c;修改替换 banner.txt 文字实现自定义&#xff0c;个性化…

操作系统面试知识点

1、进程、线程和协程的区别和联系 1、进程是资源调度的基本单位&#xff0c;运行一个可执行程序会创建一个或多个进程&#xff0c;进程就是运行起来的可执行程序 2、线程是程序执行的基本单位&#xff0c;是轻量级的进程。每个进程中都有唯一的主线程&#xff0c;且只能有一个…

机器学习第三课(sklearn接口)

一、sklearn基本知识 中文官网 英文官网 注意&#xff1a;sklearn第三方模块的安装 要用pip install scikit-learn from sklearn.neighbors import KNeighborsClassifier # 1 准备数据 # 训练集的特征数据 2维 x [[-2],[-1],[2],[3],[4]] # 训练集的目标数据 1维 y [0,0,1,…

HTML培训心得体会五篇(合集)

HTML5培训心得一 关于html5培训心得总结? 一&#xff1a;了解HTML5前端开发技术? ?? HTML?指的是超文本标记语言?(Hyper?Text?Markup?Language)&#xff0c;标记语言是一套标记标签?(markup?tag)&#xff0c;HTML?使用标记标签来描述网页。HTML5区别于HTML的标…

北京大学2015计算机学科夏令营上机考试(未完)

A:整数的个数 #include<iostream> using namespace std; int main(){int k,a;cin>>k;int sum10,sum20,sum30;for(int i0;i<k;i){cin>>a;if(a1) sum1;if(a5) sum2;if(a10) sum3;}cout<<sum1<<endl<<sum2<<endl<<sum3;retur…

quiche编译

netty http3使用了rust语言的quiche&#xff0c;quiche使用了c语言的boringssl&#xff0c; 网上没有找到编译好的quiche&#xff0c;只能自己搭建rust环境编译 1、rust安装 见官网https://www.rust-lang.org/tools/install 我是用的是windows的ubuntu&#xff0c;所以直接使…

苹果市值再度突破3万亿美元

KlipC报道&#xff1a;当地时间周五&#xff0c;苹果市值再度突破3万亿美元&#xff0c;这是近43年来&#xff0c;苹果第二次市值达到3万亿。 KlipC的合伙人Andi Duan表示&#xff1a;“得益于苹果股价上涨&#xff0c;以及硅谷银行引发的金融市场动荡&#xff0c;再加上高端IP…

【嵌入式Qt开发入门】如何创建并连接信号与槽

创建信号 我们先新建一个项目&#xff0c;命名为 signal_slot_example&#xff0c;如果还不会新建项目&#xff0c;请回到 【嵌入式Qt开发入门】初识信号与槽查看项目如何建立的。取消勾选*ui 文件&#xff0c;其他步骤不变。 由于信号只需声明&#xff0c;无需定义。所以我们只…

Mac端显示服务器上show的内容

Mac端显示服务器上show的内容 1. 需求描述 在Mac端&#xff08;终端和PyCharm中&#xff09;编写代码&#xff0c;在服务器端运行程序。需要在Mac端显示服务器端运行的内容&#xff0c;比如&#xff0c;运行的视频等。 2. 常见报错 SSH 运行命令时报错示例。 (cv) czjing…

旋转链表:给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

解题思路&#xff1a; 1.找到原链表的最后一个节点 2.计算链表长度n 3.将原链表的尾节点指向链表的头节点&#xff0c;使链表形成环 4.新链表根据画图可知&#xff0c;会在环的&#xff08;n-k%n&#xff09;的地方断开&#xff0c;这个节点newtail是新链表的尾节点 5.将新…

Ubuntu 20.04 LTS x86_64 安装 stable-diffusion-webui

官网 Stable Diffusion官网 Stability AI 官方github GitHub - Stability-AI/stablediffusion: High-Resolution Image Synthesis with Latent Diffusion Models stable-diffusion-webui github https://github.com/AUTOMATIC1111/stable-diffusion-webui 安装 下载sta…

ruoyi页面切换查询条件保留

场景描述 业务遇到需求&#xff0c;管理平台的页面打开后输入的查询条件、已经点击的页码、已经查询的数据要求保留下来&#xff0c;在tab菜单切换时保留&#xff0c;在关闭菜单时重置清空。 解决方案 1.使用cookie、localStorage或者sessionStorage 这个方式能解决部分需求…

windows10或者Ubuntu20.04内启动USB外接摄像头并拍照

1. windows10系统内启动摄像头并拍照 1.1 把带摄像头的USB接口插到电脑的USB接口上。 1.2 左下角搜索“设备管理器”&#xff0c;并点击&#xff0c;主要是确保笔记本自带的摄像头被禁用&#xff0c;和usb连接的外部摄像头被起用。 1.3 左下角搜索“相机”&#xff0c;并点击拍…

读《effective modern c++》笔记总结

文章目录 一、类型推导与auto模板类型推导ParamType是一个指针或引用&#xff0c;但不是通用引用ParamType是一个通用引用ParamType即不是指针也不是引用数组实参函数实参 auto类型推导 二、decltype的理解三、优先考虑auto而非显示类型声明四、区别使用&#xff08;&#xff0…

大华 海康 宇视 摄像头 onvif协议 调整时间 开发过程 整理

1、onvif官网 查看SetSystemDateAndTime 方法。 2、下载 ONVIF Device Test Tool 工具&#xff0c;使用教程可以 在这查看。 3、根据Test Tool 工具生成的request进行 Send request 测试。 有了这个本质就是http请求了&#xff0c;我认为可以自己写http请求尝试&#xff0c;我…

大地200C

8芯网线 【24&#xff0c;M03&#xff0c;冷却&#xff0c; m35&#xff0c;m34&#xff0c;m33&#xff0c;m32&#xff0c;24】 冷却【m08开&#xff0c;m09关】 M10夹紧M11松开 M18润滑【m127开&#xff0c;m227关】 X轴&#xff1a;5000 3.0A Y轴&#xff1…