Linux内核驱动初探(二) TI声卡

news2024/11/27 8:45:37

目录

0. 前言

1. menuconfig

2. 超时问题

3. 稳定性问题


0. 前言

通过查询该设备原理图可知,该声卡的Codec芯片型号为德州仪器 TLV320DAC3101。


1. menuconfig

我们在 linux-menuconfig 里面如下设置:进入 Device Drivers ---> Sound card support ---> Advanced Linux Sound Architecture ---> ALSA for SoC audio support

 进入 SoC Audio for Freescale CPUs:

注意,不必选择Eukrea TLV320.

返回上一层,进入 CODEC drivers:

这里就遇到了第一个问题,选项中并没有正正好好的TLV320DAC3101

外设开发商一般很难做到,将自己历史上所有设备的驱动都做成独立条目,加入Linux内核。所以,在没有完全对应的选项时,首先把最接近的条目给选中。上图的选项是笔者几次尝试后的选择,亲测可用。

保存选项,退出menuconfig,编译一次通过,无报错。把zImage放入设备启动,结果在内核启动的时候报错了。


2. 超时问题

内核启动时上报的跟CODEC有关的错误有若干个,其中比较典型的当属这个:

[   55.618137] tlv320aic31xx-codec 0-0018: aic31xx_wait_bits: Failed! 0x25 was 0x82f3a0a8 expected 0x1 (0, 0x1, 500000 us)

......

[   64.214435] tlv320aic31xx-codec 0-0018: aic31xx_wait_bits: Failed! 0x25 was 0x82f3a0a8 expected 0x10 (0, 0x10, 500000 us)

内核报上面这个问题的时候,出现了明显的卡顿(尽管不影响最后的rootfs引导)。我们使用命令“grep -rl” 可以找到报错的来源:./sound/soc/codecs/tlv320aic31xx.c

static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
			     unsigned int mask, unsigned int wbits, int sleep,
			     int count)
{
	unsigned int bits;
	int counter = count;   
	int ret = regmap_read(aic31xx->regmap, reg, &bits);

	while ((bits & mask) != wbits && counter && !ret) // wait for counter times
    {
		usleep_range(sleep, sleep * 2);
		ret = regmap_read(aic31xx->regmap, reg, &bits);
		counter--;
	}

	if ((bits & mask) != wbits) 
    {
		dev_err(aic31xx->dev,
			"%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n",
			__func__, reg, bits, wbits, ret, mask,
			(count - counter) * sleep);
		ret = -1;
	}
	return ret;
}

字面上讲,就是内核在等待 CODEC芯片 的 0x25 寄存器变成 0x01 或者 0x10,但该寄存器一直是其他乱七八糟的值。理论上,内核会等待最多counter次 ret == 0 的情况。

我们看看 TLV320DAC3101 的器件手册:

 0x10 或者 0x01 分别是为了等到左通道或者右通道 class-D driver 启动,可见接力棒在CODEC芯片那边,它不递过来也就没办法。

笔者采取的补救措施:

......
	unsigned int bits;
	int counter = count * 3;   
	int ret = regmap_read(aic31xx->regmap, reg, &bits);

	while ((bits & mask) != wbits && counter && !ret) 
    {
		usleep_range(sleep, sleep * 2);
		ret = regmap_read(aic31xx->regmap, reg, &bits);
		counter--;
	}
......

让 counter 增加2倍,regmap_read(...)读寄存器的失败重复次数更多。

其他报错也主要是类似的原因,笔者也采用类似的方法:

如在 ./sound/soc/soc-dapm.c 中

......
		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
			w->name, ev_name);
		soc_dapm_async_complete(w->dapm);
		trace_snd_soc_dapm_widget_event_start(w, event);

        ret = w->event(w, NULL, event);
		trace_snd_soc_dapm_widget_event_done(w, event);
		if (ret < 0)
			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",ev_name, w->name, ret);
......

也要等到 ret 返回1 为止,通过while循环读取 event 5次。

......
		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
			w->name, ev_name);
		soc_dapm_async_complete(w->dapm);
		trace_snd_soc_dapm_widget_event_start(w, event);

		int i = 5;
		while( ret = w->event(w, NULL, event) && i-- )
		trace_snd_soc_dapm_widget_event_done(w, event);
		if (ret < 0)
			dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",ev_name, w->name, ret);
......

如此这般修改以后,再编译,再启动内核。声卡确实好用了。可以 aplay 播放wav文件了。


3. 稳定性问题

就在笔者认为声卡驱动大功告成的时候,以下问题再次出现:

[   55.618137] tlv320aic31xx-codec 0-0018: aic31xx_wait_bits: Failed! 0x25 was 0x82f3a0a8 expected 0x1 (0, 0x1, 500000 us)

笔者做了稳定性测试,发现:

  • 平均把板子断电重启50次就会出现1次这样的错误
  • 一旦出现这样的错误,不断电重启是无法恢复的
  • 如果开机没出现这样的错误,则在接下来的使用过程中声卡都是OK的

截止编辑这个帖子的时候,这个稳定性问题依旧存在。希望接下来的工作中可以解决。

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

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

相关文章

准确率、精确率、召回率、F1-measure

文章目录准确率(Accuracy)精确率(precision)召回率(recall)F1-measure值学习理解网站-p’(Predicted)n’(Predicted)p(Actual)True PositiveFalse Negtiven(Actual)False PositiveTrue Negtive 准确率(Accuracy) ANo.Samples Predicted CorrectlyTotal No.of SamplesTPTNPN(1)A…

适配splashscreen步骤以及遇到的坑

Android 12 启动画面 从 Android 12 开始&#xff0c;在所有应用的冷启动和温启动期间&#xff0c;系统一律会应用 Android 系统的默认启动画面。默认情况下&#xff0c;此系统默认启动画面由应用的启动器图标元素和主题的 windowBackground&#xff08;如果是单色&#xff09…

虚函数的静态解析

目录 一.基类的constructor和destructor内 二.使用的是基类的对象而不是基类对象的pointer或reference 存在两种情况&#xff0c;虚函数机制不会出现预期行为&#xff1a; 即不根据虚函数的机制来调用类中对应的虚函数 示例中使用的基类和派生类&#xff1a; class base_cl…

vue事件车的原理与标准写法实现兄弟组件的传值

目录前言一&#xff0c;全局事件总线介绍1.1 原理介绍1.2 x需要满足的条件二&#xff0c;知识点的复习2.1 vc是什么2.2 vm管理vc如何体现2.3 原型2.4 上述知识的串联三&#xff0c;实现需求3.1 x的编写及讲解3.2 使用x四&#xff0c;标准写法4.1 写法改动4.2 销毁五 关键代码后…

有关BMP位图的分析

1、BMP是什么&#xff1f; BMP是 Bitmap&#xff08;位图&#xff09;的简称&#xff0c;是windows显示图片的基本格式。 在windows下&#xff0c;任何格式的图片文件&#xff08;包括视频播放&#xff09;都要转化为位图才能显示出来&#xff0c;各种各样格式的图片文件也都…

9.Java数组知识大全

文章目录前言一、数组介绍二、数组的定义域静态初始化三、数组元素访问数组地址中的小拓展:四、数组遍历1.获取数组里面的元素2.把数据存储到数组中3.遍历数组的最快方式4.遍历数组并求和5.统计个数6.变化数据五、数组动态初始化1.数组默认初始化值的规律2.数组动态初始化和静态…

单绞机控制算法模型(Simulink仿真)

线缆行业单绞机PLC控制算法详细解读可以参看下面的文章链接: 线缆行业单绞机控制算法(详细图解+代码)_RXXW_Dor的博客-CSDN博客在了解单绞机之前需要大家对收放卷以及排线控制有一定的了解,不清楚的可以参看下面几篇博客,这里不再赘述,受水平和能力所限,文中难免出现错…

【JavaEE】认识线程Thread类及常用方法线程状态

目录 一&#xff1a;认识线程&#xff1a; 二、线程的优点&#xff1a; 三、进程和线程的区别&#xff08;面试题&#xff09;&#xff1a; 四、第一个多线程程序&#xff1a; 五、创建线程的方式&#xff1a; 六、Thread类及常用方法 Thread类常见构造方法&#xff1…

整理介绍字符函数和字符串函数+内存函数

本篇重点介绍处理字符和字符串的库函数的使用和注意事项 本篇重点本篇重点介绍处理字符和字符串的库函数的使用和注意事项前言&#xff1a;求字符串长度strlen拷贝字符串函数strcpy&#xff08;追加&#xff09;连接字符串函数strcat比较两个字符串函数strcmp对上面改进字符串函…

Mac应用程序无法打开或文件损坏的处理方法

很多用户在安装 盗版 Mac软件的时候&#xff0c;经常会遇到提示“xxx.app已损坏&#xff0c;打不开。您应该将它移到废纸篓“或”打不开的xxx.app&#xff0c;因为它来自身份不明的开发者”&#xff0c;等多种打不开盗版软件的各种提示&#xff0c;正版软件则不会出现。 错误截…

17种编程语言实现排序算法-基数排序

开源地址 https://gitee.com/lblbc/simple-works/tree/master/sort/ 覆盖语言&#xff1a;C、C、C#、Java、Kotlin、Dart、Go、JavaScript(JS)、TypeScript(TS)、ArkTS、swift、PHP。 覆盖平台&#xff1a;安卓(Java、Kotlin)、iOS(SwiftUI)、Flutter(Dart)、Window桌面(C#)、…

事件冒泡和时间捕获

事件冒泡和事件捕获 最近&#xff0c;在复习Vue的时候&#xff0c;发现自己对于事件冒泡和事件捕获的理解存在一定的错误。于是想写一份笔记来总结一下事件冒泡和事件捕获。✌✌✌ 一、事件 1、事件的三个阶段&#xff1a;事件捕获->事件目标->事件冒泡 捕获阶段&am…

MySQL 性能优化浅析及线上案例

作者&#xff1a;京东健康 孟飞 1、 数据库性能优化的意义 业务发展初期&#xff0c;数据库中量一般都不高&#xff0c;也不太容易出一些性能问题或者出的问题也不大&#xff0c;但是当数据库的量级达到一定规模之后&#xff0c;如果缺失有效的预警、监控、处理等手段则会对用户…

设计模式学习(十二):Decorator装饰器模式

一、什么是Decorator模式假如现在有一块蛋糕&#xff0c;如果只涂上奶油&#xff0c;其他什么都不加&#xff0c;就是奶油蛋糕。如果加上草莓&#xff0c;就是草莓奶油蛋糕。如果再加上一块黑色巧克力板&#xff0c;上面用白色巧克力写上姓名&#xff0c;然后插上代表年龄的蜡烛…

JavaEE5-Spring更简单的读取和存储对象

目录 1.存储Bean对象 1.1.前置工作&#xff1a;在配置文件中设置bean扫描的根路径&#xff08;重要&#xff09; 1.2.添加注解存储Bean对象到Spring中 1.2.1.类注解(添加到某个类上&#xff0c;将当前的类存储到Spring中)&#xff1a;Controller&#xff0c;Service&#x…

树,堆,二叉树的认识

1.树概念及结构 1.1树的概念 注意&#xff1a;树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 1.2 树的相关概念 1.3 树的表示 树结构相对线性表就比较复杂了&#xff0c;要存储表示起来就比较麻烦了&#xff0c;既然保存值域&#xff0c;也要保存…

Gateway服务网关

Gateway服务网关一、网关介绍二、gateway快速入门1.创建gateway服务&#xff0c;引入依赖2.编写启动类3.编写基础配置和路由规则4.重启测试5.网关路由的流程图三、断言工厂四、过滤器工厂1.路由过滤器的种类2.请求头过滤器3.默认过滤器4.总结五、全局过滤器1.全局过滤器作用2.自…

fpga实操训练(系统开发和硬件接口)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 相信很多学习fpga的同学都会有这样的一个感受,一开始fpga学习还比较简单,但是一旦涉及到呼吸灯、uart、spi、iic、ddr2后面就会越来越难。遇到这样的困难之后,学习的激情一下子少…

从零搭建一个组件库(一)项目环境搭建

文章目录前言monorepo架构1.monorepo架构的优势2.使用pnpm搭建monorepo架构&#xff08;1&#xff09;全局安装pnpm&#xff08;2&#xff09;初始化项目&#xff08;3&#xff09;新建workspace.yaml文件4.不同包之间的相互引用TypeScript支持1.安装TypeScript2.初始化TypeScr…

http三次握手四次挥手详解

1、 TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。 三次握手&#xff1a;为了对每次发送的数据量进行跟踪与协商&#xff0c;确保数据段的发送和接收同步&#xff0c;根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系&#xff0c;并建立虚连接。 四次挥…