4. 注册machine

news2024/12/22 20:55:21

数字mic系列,注册machine

 dts配置如下

    digital_mic: digital-mic {
         status = "okay";
         compatible = "simple-audio-card";
         simple-audio-card,format = "i2s";
         simple-audio-card,mclk-fs = <256>;
         simple-audio-card,name = "digital-mic";
         simple-audio-card,cpu {
             sound-dai = <&i2s0_8ch>;
         };

         simple-audio-card,codec {
             sound-dai = <&dummy_codec>;
         };
    };

驱动代码位置 sound/soc/generic/simple-card.c

static int asoc_simple_card_probe(struct platform_device *pdev)
{
    struct simple_card_data *priv;
    struct snd_soc_dai_link *dai_link;
    struct simple_dai_props *dai_props;
    struct device *dev = &pdev->dev;
    struct device_node *np = dev->of_node;
    struct snd_soc_card *card;
    int num, ret;

    /* Get the number of DAI links */
    if (np && of_get_child_by_name(np, PREFIX "dai-link"))
        num = of_get_child_count(np);
    else
        /* 对于dai-link*/
        num = 1;

    /* Allocate the private data and the DAI link array */
    priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    if (!priv)
        return -ENOMEM;

    dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
    dai_link  = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
    if (!dai_props || !dai_link)
        return -ENOMEM;

    priv->dai_props         = dai_props;
    priv->dai_link          = dai_link;

    /* Init snd_soc_card */
    card = simple_priv_to_card(priv);
    card->owner     = THIS_MODULE;
    card->dev       = dev;
    card->dai_link      = priv->dai_link;
    card->num_links     = num;
    card->probe     = asoc_simple_soc_card_probe;

    if (np && of_device_is_available(np)) {

        ret = asoc_simple_card_parse_of(priv);
        if (ret < 0) {
            if (ret != -EPROBE_DEFER)
                dev_err(dev, "parse error %d\n", ret);
            goto err;
        }

    } else {
        ...
    }
    snd_soc_card_set_drvdata(card, priv);

asoc_simple_card_probe() -> asoc_simple_is_available()

static int asoc_simple_card_parse_of(struct simple_card_data *priv)
{
    struct device *dev = simple_priv_to_dev(priv);
    struct snd_soc_card *card = simple_priv_to_card(priv);
    struct device_node *dai_link;
    struct device_node *node = dev->of_node;
    int ret;

    if (!node)
        return -EINVAL;

    /* 这里会匹配 simple-audio-card,dai-link 子节点 */
    dai_link = of_get_child_by_name(node, PREFIX "dai-link");

    /* 解析 simple-audio-card,widgets 属性 */
    ret = asoc_simple_card_of_parse_widgets(card, PREFIX);
    if (ret < 0)
        goto card_parse_end;
    /* 解析 simple-audio-card,routing 属性 */
    ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1);
    if (ret < 0)
        goto card_parse_end;

    /* Factor to mclk, used in hw_params() */
    /* 解析 simple-audio-card,mclk-fs 属性 */
    of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);

    /* Single/Muti DAI link(s) & New style of DT node */
    /* 不支持 跳过 */
    if (dai_link) {
        struct device_node *np = NULL;
        int i = 0;

        for_each_child_of_node(node, np) {
            dev_dbg(dev, "\tlink %d:\n", i);
            ret = asoc_simple_card_dai_link_of(np, priv,
                               i, false);
            if (ret < 0) {
                of_node_put(np);
                goto card_parse_end;
            }
            i++;
        }
    } else {
        /* For single DAI link & old style of DT node */
        ret = asoc_simple_card_dai_link_of(node, priv, 0, true);
        if (ret < 0)
            goto card_parse_end;
    }

    /* label属性没有 
     * card->dai_link->name
     */
    ret = asoc_simple_card_parse_card_name(card, PREFIX);
    if (ret < 0)
        goto card_parse_end;

    /* 没有aux-devs */
    ret = asoc_simple_card_parse_aux_devs(node, priv);

card_parse_end:
    of_node_put(dai_link);

    return ret;
}

asoc_simple_card_probe() -> asoc_simple_is_available() -> asoc_simple_card_dai_link_of()

static int asoc_simple_card_dai_link_of(struct device_node *node,
                    struct simple_card_data *priv,
                    int idx,
                    bool is_top_level_node)
{
    struct device *dev = simple_priv_to_dev(priv);
    struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
    struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
    struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
    struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
    struct device_node *cpu = NULL;
    struct device_node *plat = NULL;
    struct device_node *codec = NULL;
    char prop[128];
    char *prefix = ""; 
    int ret, single_cpu;

    /* For single DAI link & old style of DT node */
    if (is_top_level_node)
        prefix = PREFIX;

    snprintf(prop, sizeof(prop), "%scpu", prefix);
    /* simple-audio-card,cpu 节点 */
    cpu = of_get_child_by_name(node, prop);

    if (!cpu) {
        ret = -EINVAL;
        dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
        goto dai_link_of_err;
    }   

    snprintf(prop, sizeof(prop), "%splat", prefix);
    /* simple-audio-card,plat 节点 ,可以没有 */
    plat = of_get_child_by_name(node, prop);

    snprintf(prop, sizeof(prop), "%scodec", prefix);
    /* simple-audio-card,codec 节点 */
    codec = of_get_child_by_name(node, prop);

    if (!codec) {
        ret = -EINVAL;
        dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
        goto dai_link_of_err;
    }   
    /* 获取dai_fmt  主要通过machine和codec进行判断 
     * 对于当前dts配置来说, dai_fmt = SND_SOC_DAIFMT_I2S
     */
    ret = asoc_simple_card_parse_daifmt(dev, node, codec,
                        prefix, &dai_link->dai_fmt);
    if (ret < 0)
        goto dai_link_of_err;

    of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);

    /* 这里会找到platform
     * dai_link->cpu_of_node 会填充platform节点
     * 其中宏定义如下
     * #define DAI	"sound-dai"
     * #define CELL	"#sound-dai-cells"
     * #define PREFIX	"simple-audio-card,"
     * 注意这里查找dai_name的时候
     * 优先从dai->driver->name
     * 如果没有则使用节点的名字
     * 如果没有找到cpu的节点,则会返回-EPROBE_DEFER
     */
    ret = asoc_simple_card_parse_cpu(cpu, dai_link,
                     DAI, CELL, &single_cpu);
    if (ret < 0)
        goto dai_link_of_err;

    /* 同上 
     * dai_link->codec_of_node 会填充codec节点 
     */
    ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
    if (ret < 0)
        goto dai_link_of_err;

    /* 没有platform code */
    ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
    if (ret < 0)
        goto dai_link_of_err;

    /* 不支持 */
    ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai);
    if (ret < 0)
        goto dai_link_of_err;
    /* 不支持 */
    ret = asoc_simple_card_of_parse_tdm(codec, codec_dai);
    if (ret < 0)
        goto dai_link_of_err;
    /* platform clk节点 
     * 查找顺序
     * 1. platform (simple-audio-card,cpu)节点的 clock 
     * 2. platform (simple-audio-card,cpu)节点的 system-clock-frequency
     * 3. dai_link->cpu_of_node (i2s0_8ch) 节点的 clock
     *    这里是不是会到rcu ? 且只拿第一个时钟
     */
    ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
    if (ret < 0)
        goto dai_link_of_err;

    /* codec clk节点 
     * 查找顺序
     * 1. codec (simple-audio-card,codec)节点的 clock 
     * 2. codec (simple-audio-card,codec)节点的 system-clock-frequency
     * 3. dai_link->codec_of_node (dummy_codec) 节点的 clock
     */
    ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
    if (ret < 0)
        goto dai_link_of_err;

    /* 没有platform_of_node 
     * platform_of_node = cpu_of_node 
     */
    ret = asoc_simple_card_canonicalize_dailink(dai_link);
    if (ret < 0)
        goto dai_link_of_err;

    /* "ff800000.i2s-tdm-dummy_codec"
     * 名字保存在 dai_link->name 和 dai_link->stream_name    
     */
    ret = asoc_simple_card_set_dailink_name(dev, dai_link,
                        "%s-%s",
                        dai_link->cpu_dai_name,
                        dai_link->codec_dai_name);
    if (ret < 0)
        goto dai_link_of_err;
        
    dai_link->ops = &asoc_simple_card_ops;
    dai_link->init = asoc_simple_card_dai_init;

    /* dai_link->cpu_dai_name = NULL */
    asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);

dai_link_of_err:
    of_node_put(cpu);
    of_node_put(codec);

    return ret;
}

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

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

相关文章

你知道2个KT6368A的蓝牙芯片模块如何配对_以及数据传输吗

目录 一、简介你知道2个KT6368A的蓝牙芯片模块如何配对_以及数据传输吗&#xff1f;KT6368A的蓝牙模块之间是可以建立连接&#xff0c;并且全双工数据透传的但是有几点注意事项&#xff0c;一定要选择KT6368A的主机版本&#xff0c;和从机版本&#xff0c;如下图&#xff1a; …

Spring Boot 中的分布式锁

Spring Boot 中的分布式锁 在分布式系统中&#xff0c;多个应用程序可能需要同时对同一个资源进行修改。为了避免数据的不一致性和冲突等问题&#xff0c;我们需要对这些资源进行加锁操作。在本文中&#xff0c;我们将介绍 Spring Boot 中的分布式锁是什么&#xff0c;原理是什…

OpenCV键盘监听函数 cv2::waitKey( delay )

1、函数原型&#xff1a;cv::waitKey( delay ) delay&#xff1a;等待时间(毫秒) 作用&#xff1a;通过 waitKey() 可以获取键盘输入2、示例&#xff1a; 实现键盘输入1&#xff0c;将图像转为灰度图输出&#xff1b; 键盘输入2&#xff0c;将图像转为HSV图输出&#xff1b; …

element ui - el-button 重新渲染后disabled属性失效

element ui - el-button重新渲染后disabled属性失效 场景解决方法 场景 有两组不同的按钮&#xff1a; 不在灰度发布状态下的 disabled 的灰色按钮&#xff1b;灰度发布状态下的 可点击按钮&#xff1b; 发现当再次渲染 灰色按钮 时&#xff0c;disabled 属性失效。 解决方…

7.6 【Linux】文件系统的特殊观察与操作

7.6.1 磁盘空间之浪费问题 从上面的特殊字体部分&#xff0c;那就是每个文件所使用掉 block 的容量&#xff01;举例来说&#xff0c;那个 crontab 虽然仅有 451Bytes &#xff0c; 不过他却占用了整个 block &#xff08;每个 block 为 4K&#xff09;&#xff0c;所以将所有的…

电子企业MES管理系统如何加强生产现场管控

随着数字化时代的到来&#xff0c;中小型电子企业面临着提升生产现场管控的挑战。为了应对这一挑战&#xff0c;许多企业开始采用MES生产管理系统。本文将探讨MES生产管理系统如何帮助电子企业加强生产现场管控&#xff0c;提高生产效率和质量。 在电子企业的生产现场&#xf…

MCU是否会从ADAS域控制器消失

摘要&#xff1a; ADAS架构及MCU功能概览、未来ADAS架构的两种方案、MCU是否从ADAS域消失的一点思考 ADAS的装机量和渗透率再提升&#xff0c;尤其L2及L2级&#xff1b;那么随着ADAS域控制器主控芯片的增强&#xff0c;未来&#xff0c;MCU是否还会存在&#xff1f; 转自佐思汽…

SSM之MyBatis

MyBatis学习笔记 一、入门二、XML配置1、configuration&#xff08;配置&#xff09;2、properties&#xff08;属性&#xff09;3、settings&#xff08;设置&#xff09;4、typeAliases&#xff08;类型别名&#xff09;5、typeHandlers&#xff08;类型处理器&#xff09;6、…

CSS的学习3

什么是CSS CSS是层叠样式表的简称&#xff0c;又称为CSS样式表或级联样式表。CSS是一种标记语言。 主要用于设置HTML页面中的文本内容&#xff08;字体、大小、对齐方式等&#xff09;、图片的外形&#xff08;宽高、边框样式、边距等&#xff09;、版面的布局和外观显示样式…

【算法】树形DP ② 打家劫舍Ⅲ(树上最大独立集)

文章目录 前期知识例题337. 打家劫舍 III 相关练习题目没有上司的舞会 https://www.luogu.com.cn/problem/P13521377. T 秒后青蛙的位置 https://leetcode.cn/problems/frog-position-after-t-seconds/⭐⭐⭐解法1&#xff1a;BFS优化代码 解法2——自顶向下dfs解法3——自底向…

Buildroot 系统设置开机密码登录-迅为RK3588开发板

首先对开发板进行上电&#xff0c;开发板正常启动后&#xff0c;使用命令“vi /etc/inittab”对文件进行修改&#xff0c;如 下图所示&#xff1a; 设置为密码登陆时配置如下图&#xff08;注意将 ttyS0 修改为 ttyFIQ0&#xff09;&#xff1a; 修改完&#xff0c;保存退出&a…

GLM: General Language Model Pretrainingwith Autoregressive Blank Infilling翻译理解

GPT&#xff08;autoregressive&#xff09;模型是一个自回归模型&#xff0c;利用left-to-right语言模型&#xff0c;由于不是双向attention 机制&#xff0c;因此不能再NLU任务中&#xff0c;获取充分的上下文信息&#xff0c;BERT类似自编码&#xff08;autoencoding&#x…

SQL 优化(四):合理使用 join

在工作的时候经常听到的一句话就是&#xff0c;“这条 SQL 因为 join 了很多表&#xff0c;导致查询速度比较慢”&#xff0c;可以从侧面反映出&#xff0c;join语句对性能的影响是比较大的&#xff0c;而且大部分人不知道如何进行优化。这篇文章我们来讲讲join的执行过程&…

PC C++ SDK 全局函数、防录制功能、下载器、播放器

本文档提供了使用 CSDK 的操作步骤及代码示例&#xff0c;通过本文您可以快速了解如何使用 SDK 提供的功能。您也可以通过 Demo 中的示例进行了解和自有业务开发。 SDK 名词含义及功能说明 参见 plv-player-def.h SDK 全局函数 设置日志&#xff0c;日志过滤项。设置观众信息…

ENVI遥感影像处理—水体提取

2 .水体提取 &#xff08;1&#xff09;导入经过大气校正后的影像FLAASH_result.dat。 &#xff08;2&#xff09;选择工具箱中ToolBox——Band Ratio——Band Math&#xff0c;输入(float(b1)-float(b2))/(float(b1)float(b2))&#xff0c;点击Add to List&#xff0c;选中公…

R3LIVE环境搭建

一、安装ros、livox sdk、livox_ros_driver 安装方法[参考] 二、CGAL和pcl_viewer sudo apt-get install libcgal-dev pcl-tools 三、opencv&#xff08;≥3.3&#xff09; 3.1 命令检查 OpenCV 版本&#xff0c;如果 openCV 版本低于 OpenCV-3.3, 更新openCV版本为3.3.1、3…

Kubernetes 多集群管理工具 - Kuboard

Kuboard 是Kubernetes 多集群管理工具&#xff0c;是一个界面化的web网站&#xff0c;使用起来非常方便。在Kuboard中可以导入集群&#xff0c;在kuboard上可以完成很多的运维工作&#xff0c;比如创建命名空间、创建标签、运行服务、修改pod数量等等。 一&#xff1a;kuboard…

【JavaEE初阶】CSS

摄影分享~ 文章目录 一.CSS基本规范1. CSS基本语法规范2.CSS选择器 二.CSS常用属性1. 字体属性2.文本属性3.背景属性4.圆角矩形5.元素的显示模式块级元素行内元素 6.盒子模型边框内边距外边距 7.弹性布局 一.CSS基本规范 层叠样式表。(Cascading Style Sheets) CSS 能够对网页…

【零基础入门学习Python---Python中Web开发基础之快速入门实践】

&#x1f680; 零基础入门学习Python&#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜…

springboot医院自助服务系统-计算机毕设 附源码74853

springboot医院自助服务系统 目 录 摘要 1 绪论 1.1研究意义 1.2研究背景 1.3springboot框架介绍 1.3论文结构与章节安排 2 医院自助服务系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 …