Linux Audio (4) ASOC代码分析-基于kernel3.4.2

news2024/11/17 5:33:37

ASOC代码分析-基于kernel3.4.2

  • Overview
  • Platform
    • CPU DAI
    • CPU DMA
  • Codec
  • Mechine

Linux kernel版本:3.4.2

Overview

linux ASoC音频设备驱动
ASoC是ALSA在SoC方面的发展和演变,它的本质仍然属于ALSA,但是在ALSA架构基础上对CPU相关的代码和Codec相关的代码进行了分离,其原因是采用传统ALSA架构情况下,同一型号的Codec工作于不同的CPU时,需要不同的驱动,这是不符合代码重用的要求的。

ASoC主要由3部分组成:
(1)Codec驱动,这一部分只关系Codec本身,与CPU相关的特性不由此部分操作
(2)平台驱动,这一部分只关心CPU本身,不关系Codec,它主要处理了两个问题:DMA引擎和SoC解除的PCM、IIS或AC’97数字接口控制。
(3)板驱动,这一部分将平台驱动和Codec驱动绑定在一起,描述了板一级的硬件特征

以上3部分中,1和2基本都可以仍然是通用的驱动了,即Codec驱动认为自己可以连接任意CPU,而CPU的IIS、PCM、或AC’97接口对应的平台驱动则认为自己可以连接
符号其接口类型的Codec,只有3是不通用的,由特定的电路板上具体的CPU和Codec确定,因此它很像一个插座,上面插着Codec和平台这两个插头。ASoC的用户空间编程方法与ALSA完全一致。

下面以实例来分析函数的调用过程:

machine: sound\soc\samsung\s3c24xx_uda134x.c
platform: sound\soc\samsung\s3c24xx-i2s.c
codec:   sound\soc\codecs\uda134x.c

抓住小尾巴dai_link:

static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
	.name = "UDA134X",
	.stream_name = "UDA134X",
	.codec_name = "uda134x-codec",
	.codec_dai_name = "uda134x-hifi",
	.cpu_dai_name = "s3c24xx-iis",
	.ops = &s3c24xx_uda134x_ops,
	.platform_name	= "samsung-audio",
};

Platform

Platform分为两部分:Platform(DMA)和cpu dai(iis);
platform: sound\soc\samsung\s3c24xx-i2s.c

CPU DAI

.cpu_dai_name = "s3c24xx-iis",    // 2440(CPU)的哪个DAI接口

下面是搜到的"s3c24xx-iis"信息,有platform_driver和platform_device,匹配后会执行driver的probe函数:
.probe = s3c24xx_iis_dev_probe,在注册时会把DMA的file_operation操作函数集注册到soc-core中。

linux-3.4.2\sound\soc\samsung\s3c24xx-i2s.c

s3c24xx_iis_dev_probe(struct platform_device *pdev)
	snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);//Register a DAI with the ASoC core
		list_add(&dai->list, &dai_list); //把cpu dai添加到dai_list中,在snd_soc_instantiate_cards中会去遍历dai_list

CPU DMA

.platform_name= "samsung-audio",  // 2440(CPU)的哪个DMA驱动程序

下面是搜到的"samsung-audio"信息,有platform_driver和platform_device,匹配后会执行driver的probe函数:
.probe = samsung_asoc_platform_probe,在注册时会把DMA的file_operation操作函数集注册到soc-core中。

linux-3.4.2\sound\soc\samsung\dma.c

samsung_asoc_platform_probe(struct platform_device *pdev)
	snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);
		list_add(&platform->list, &platform_list);

套路和cpu dai是一样的,在snd_soc_register_platform()函数中把platform->list加到platform_list中,然后在snd_soc_instantiate_cards()中遍历platform_list注册设备。

总结: 通过machine中的snd_soc_dai_link中的platform_name和cpu_dai_name分别查找平台的dma设备驱动和cpu侧的dai驱动。最终会将这dai保存到component->dai_list中,platform保存到platform_list当中。然后将component放入到component_list链表中。这些数据会在Machine代码的开始过程中进行匹配操作。

Codec

codec: sound\soc\codecs\uda134x.c

sound\soc\codecs\uda134x.c
uda134x_codec_probe(struct platform_device *pdev)
	snd_soc_register_codec(&pdev->dev,&soc_codec_dev_uda134x, &uda134x_dai, 1); -->snd_soc_instantiate_cards()
		list_add(&codec->list, &codec_list);
		snd_soc_register_dais(dev, dai_drv, num_dai);
			list_add(&dai->list, &dai_list);

Mechine

mechine担负着定义dai_link结构体,注册逻辑设备的神圣使命。在Asoc结构中,声卡的注册过程如下:
devm_snd_soc_register_card --> snd_soc_register_card --> ①soc_init_dai_link ②snd_soc_instantiate_card-->③snd_card_register();

当codec、dai、platform的device name和driver name匹配时,就会执行对应Driver的probe()函数。
machine: sound\soc\samsung\s3c24xx_uda134x.c中,mechine的platform_driver和platform_device名字匹配后就会执行Driver的probe()函数。

Mechine中向Linux平台设备总线注册名为“soc-audio” 的设备

该函数里的Platform 指的是Linux设备总线模型中的概念呦!
static int s3c24xx_uda134x_probe(struct platform_device *pdev)
{
	// 为snd soc card申请一个名为"soc-audio"的platform_device结构体
	s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
	// 把snd_soc_card结构体作为私有数据填充到platform_device结构体中;
	platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x);
	// 把snd soc card "soc-audio"注册到platform设备总线上。
	ret = platform_device_add(s3c24xx_uda134x_snd_device);
}

对应的"soc-audio" platform_driver在soc-core.c (sound\soc)z中定义:

/* ASoC platform driver */
static struct platform_driver soc_driver = {
	.driver		= {
		.name		= "soc-audio",
		.owner		= THIS_MODULE,
		.pm		= &snd_soc_pm_ops,
	},
	.probe		= soc_probe,
	.remove		= soc_remove,
};
// 在其入口函数中将结构体注册进platform_driver中
static int __init snd_soc_init(void)
{
	return platform_driver_register(&soc_driver);
}
module_init(snd_soc_init);

当“soc-audio”的Driver和Device匹配后,会执行sound\soc\soc-core.c-->struct soc_driver.probe = soc_probe()函数。

/* probes a new socdev */
static int soc_probe(struct platform_device *pdev)
{
	// 在machine: sound\soc\samsung\s3c24xx_uda134x.c中在s3c24xx_uda134x_probe()中
	// 已经在把snd_soc_card结构体填充到了device的私有数据中,这里再取出来用来向内核注册Driver
	struct snd_soc_card *card = platform_get_drvdata(pdev); 
	/* Bodge while we unpick instantiation */
	card->dev = &pdev->dev;
	// 向Asoc core注册声卡设备
	ret = snd_soc_register_card(card); --->>> snd_soc_instantiate_card()
}

下面看下函数调用

snd_soc_register_card(struct snd_soc_card *card) 
	snd_soc_instantiate_cards(void)	
		soc_bind_dai_link(card, i);//从dai_list中遍历cpu dai,codec dai
		snd_card_create(...., card->owner, 0, &card->snd_card);
	/* 下面开始执行一些probe函数,比如codec, dai, platform(dma)等file_operation中的结构体 */	
		card->probe(card);
		soc_probe_dai_link(card, i, order);
		snd_card_register(card->snd_card);

在ALSA时,我们分析过这个函数,这样就完美的和ALSA接轨了。在snd_card_register()向内核注册逻辑设备。

/**
 *  snd_card_register - register the soundcard
 *  @card: soundcard structure
 *
 *  This function registers all the devices assigned to the soundcard.
 *  Until calling this, the ALSA control interface is blocked from the
 *  external accesses.  Thus, you should call this function at the end
 *  of the initialization of the card.
 *
 *  Returns zero otherwise a negative error code if the registration failed.
 */
int snd_card_register(struct snd_card *card)

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

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

相关文章

【python之django1.11框架一】django环境搭建及基本操作

1. 环境准备 开发环境:windows 11先安装好miniconda3。镜像地址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 选择windows 64位下载。 下载地址: https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-lates…

JIRA的数据备份与恢复教程

目录 一、简介 二、数据备份(默认系统会自动备份,不需要手动) 1、使用管理员账号登录JIRA。 2、点击左上角的设置按钮,选择“系统”选项。 3、选择“备份系统”选项 4、开始手动备份 5、查看备份进度 三、数据恢复 1、使用…

MyBatisPlus入门案例

文章目录 1 入门案例步骤1:创建数据库及表步骤2:创建SpringBoot工程步骤3:勾选配置使用技术步骤4:pom.xml补全依赖步骤5:添加MP的相关配置信息步骤6:根据数据库表创建实体类步骤7:创建Dao接口步骤8:编写引导类步骤9:编写测试类 2 MybatisPlus简介 MyBatisPlus主要是对MyBatis的…

SQL注入 - Part 1

前置知识:sql前置的软件环境:预装了phpstudy_prodvwa,花了好长时间……时间主要浪费在听从chatgpt的建议装xampp上,卸载了mysql,重置了密码。其实使用xampp搭建环境也成功了,但是由于phpstudy教程比较多&am…

了解物理层下的传输媒体

1.了解物理层下的传输媒体 声明:该学习笔记来自湖科大教书匠,笔记仅做学习参考 笔记来源: 湖科大教书匠:物理层的基本概念 湖科大教书匠:物理层下面的传输媒体 1.1 物理层的基本概念 物理层考虑在连接各计算机的传输…

JQuery原理剖析——自己手写简易版JQuery

目录 为什么需要JQuery 在此之前回顾JavaScript对象知识: 自己手写的简易JQuery: 为什么需要JQuery 在我们之前写的JS代码中经常会遇见document.getElementById等等获取元素的对象,当大量的元素对象需要被获取时,就会有很多相似…

linux系统升级/更新OpenSSL版本操作流程记录

问题描述:有时 OpenSSL 版本过老升级,或者需要更新 OpenSSL 版本 1. 登录 linux 系统后输入 openssl version 查看现在使用的版本 我的输入后版本信息为:OpenSSL 1.1.1g FIPS 21 Apr 2020 ,可以看到是一年前更新版本,…

openGauss数据库Package原理分析FAQ

FAQ的形式分析OpenGauss中package实现基础关键逻辑。 下面四个问题基本将市面上基于postgresql实现package的方法分成了几类。 例如问题一: openGauss使用包所在的namespace作为包函数的namespace。IvorySQL使用包本身的oid作为包函数的namespace。还有db创建一个…

微信小程序vue+nodejs校园快递物流取件及上门服务系统uniapp

系统分为用户和管理员两个角色 用户的主要功能有: 1.用户注册和登陆系统 2.用户查看系统的公告信息 3.用户在线快递下单,支付订单,在线订购快递取件 4.用户在线预约快递,填写快递预约信息 5.用户个人中心在线充值 6.用户个人中心修…

c++学习——概述、命名空间注意事项

C语言在c语言的基础上添加了面向对象编程和泛型编程的支持。 第一个helloworld #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;//标准命名空间int main() {//cout是标准的输出流对象&#xff0c;打印字符串//endl是刷新缓冲区&#xff0c;…

软件详细设计总复习(一)【太原理工大学】

实验内容重点看&#xff0c;无需死记&#xff0c;它更是一种设计思想。要理解一种设计模式出现的意义是什么&#xff0c;它又是如何方便我们使用的&#xff1f;目的无非就是解耦、易扩充。题目问到优缺点&#xff0c;你只要知道该模式的设计思想就完全可以用自己的话概述&#…

chatgpt赋能Python-python3绘制图形

Python3绘制图形 – 让数据更加生动 作为一种可视化数据的工具&#xff0c;图形在数据分析和展示中扮演着重要的角色。Python3作为一种高效的编程语言&#xff0c;在图形方面也有自己的实现方式&#xff0c;让我们一起来了解Python3的图形绘制。 什么是Python3图形绘制&#…

chatgpt赋能Python-python3_取余

Python3 取余 在Python3中&#xff0c;取余运算是使用%符号进行实现的。它可以用于整数和浮点数&#xff0c;并返回一个余数。Python3是一种开放源码、高级编程语言。它是一种解释型语言&#xff0c;由于其简洁的语法和易于阅读的特性而受到广泛的欢迎。 取余基础 取余运算就…

ContOS7单机安装Hadoop

安装Hadoop 1&#xff0c;准备环节 因为Hadoop是由java编写的&#xff0c;所以需要Java的环境支持&#xff0c;作为开发者我们需要安装jdk。 安装jdk的教程http://t.csdn.cn/6qJKg 下载Hadoop的安装包 Hadoop官网&#xff1a;http://hadoop.apache.org/ Hadoop版本下载地…

【连续介质力学】张量的偏微分、球张量和偏张量

张量的偏微分 张量的一阶微分&#xff0c;定义&#xff1a; ∂ A ∂ A A , A ∂ A i j ∂ A k l ( e ^ i ⨂ e ^ j ⨂ e ^ k ⨂ e ^ l ) δ i k δ j l ( e ^ i ⨂ e ^ j ⨂ e ^ k ⨂ e ^ l ) I \frac{\partial A}{\partial A} A_{,A}\frac{\partial A_{ij}}{\partial A…

C++ map用法总结(整理)

1&#xff0c;map简介 map是STL的一个关联容器&#xff0c;它提供一对一的hash。 第一个可以称为关键字(key)&#xff0c;每个关键字只能在map中出现一次&#xff1b;第二个可能称为该关键字的值(value)&#xff1b; map以模板(泛型)方式实现&#xff0c;可以存储任意类型的…

算法26:暴力递归

目录 题目1&#xff1a;给你一个字符串&#xff0c;要求打印打印出这个字符串的全部子序列&#xff08;子序列不能重复&#xff09; 题目2&#xff1a;打印一个字符串的全部排列。 题目3&#xff1a;针对题目2&#xff0c;要求去除重复元素 题目4&#xff1a;给定一个字符串…

【靶机】vulnhub靶机billu

靶机下载地址&#xff1a;https://download.vulnhub.com/billu/Billu_b0x.zip 一、环境搭建 1.1 实验环境设计 使用vmware导入靶机&#xff0c;模式为nat模式即可&#xff0c;同时开启kali作为攻击机&#xff0c;对靶机进行渗透&#xff0c;要确定两台主机在同一网段。 Kali…

[Python从零到壹] 六十六.图像识别及经典案例篇之基于机器学习的图像分类

五月太忙&#xff0c;还是写一篇吧&#xff01; 欢迎大家来到“Python从零到壹”&#xff0c;在这里我将分享约200篇Python系列文章&#xff0c;带大家一起去学习和玩耍&#xff0c;看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解&#xff0c;真心想把…

opencv_c++学习(十五)

一、图像的模板匹配 顾名思义&#xff0c;模板匹配是在一幅图像中寻找一个相同或相似的对象&#xff0c;如上图所示。 matchTemplate(lnputArray image, lnputArray templ,OutputArray result, int method, lnputArray mask noArray())image:待模板匹配的原图像&#xff0c;图…