前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ Linux驱动炼成记 ] 12 -音频驱动TAS5754添加EQ参数

[ Linux驱动炼成记 ] 12 -音频驱动TAS5754添加EQ参数

作者头像
程序手艺人
发布2019-02-20 17:20:27
1.3K0
发布2019-02-20 17:20:27
举报
文章被收录于专栏:程序手艺人程序手艺人

每一个带有音频播放的产品,设备初期的时候都会调试设备的EQ参数。EQ通过将声音中各频率的组成泛音等级加以修改,专为某一类音乐进行优化,增强人们的感觉。常见包括:正常、摇滚、流行、舞曲、古典、柔和、爵士、金属、重低音和自定义。1

调节音频芯片EQ参数一般是专业音响公司做的,必须有专业的设备和调音师完成,最终输出芯片配套的文件,供驱动写入。这里以TAS5754为例:

EQ参数

专业的音响设备调好EQ后给的文件,简要如下:

代码语言:javascript
复制
//可以发现都是芯片内部寄存器的一些值
reg_value base_main_Rate48_REG_xxx_program[] = {
    {0x00,0x00},
    {0x00,0x01},
//			# reg[1][3] = 0x4
    {0x03,0x04},
    {0x00,0x00},
//			# reg[0][0x3] = 0x11
    {0x03,0x11},
//			# reg[0][2] = 0x10
    {0x02,0x10},
    {0xFF,0x04},
    {0xFF,0x05},
    {0x00,0x00},
//			# reg[0][0x2b] = 0x1f
    {0x2B,0x1F},
    {0x00,0x2C},
....
};

tas5754音频芯片调完EQ参数后的值需要做简单的修改:

代码语言:javascript
复制
reg_value base_main_Rate48_REG_Section_program[] = {
    {0x00,0x00},
    {0x00,0x01},
//			# reg[1][3] = 0x4
    {0x03,0x04},
    {0x00,0x00},
//			# reg[0][0x3] = 0x11
    {0x03,0x11},
//			# reg[0][2] = 0x10
    {0x02,0x10},
    {0xFF,0x04},    // 1. 写ADC数据
    {0xFF,0x04},   //  2. 写DAC数据
    {0x00,0x00},

文件中提供了两个数组的数据,base_main_Rate48_REG_Section_program, tas5754_reg_values, 在第2处(写DAC数据),插入第二个数组的数据,同时把 {0xFF,0x04},  {0xFF,0x05}, 删掉,第二个数组就是DAC的EQ数据,因为TAS5754没有ADC,所以 {0xFF,0x04}的数据为空,不用写。
驱动写入EQ

EQ参数实际对应的都是芯片寄存器值,驱动中需要通过IIC写入到音频芯片中,由于音频芯片的EQ参数很多,需要单独在线程中写入,而不影响驱动的正常加载,这就需要内核中Workqueue机制2

  • tas5754的私有数据
代码语言:javascript
复制
// 私有数据
struct tas575x_private {
	struct snd_soc_codec *codec;
	... 
	struct workqueue_struct *workqueue;
	struct delayed_work      dwork;
	....
};
  • 创建工作队列
代码语言:javascript
复制
static int tas575x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
{
	struct tas575x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
	priv->codec = dai->codec;
	priv->format = format;
	//创建工作队列
	priv->workqueue = create_singlethread_workqueue("tas575x_workqueue");
	// 创建工作,调用函数是tas575x_task
	INIT_DELAYED_WORK(&priv->dwork,tas575x_task);
	//延时5s去执行
	queue_delayed_work(priv->workqueue,&priv->dwork,5);
	
	return 0;
}
  • 工作队列的处理函数 处理函数中巧妙之处是使用了container_of这个宏来从而避免了全局变量的使用,该宏的作用就是可以根据一个结构体变量中的一个成员变量的指针来获取指向整个结构体变量的指针。
代码语言:javascript
复制
static void tas575x_task(struct work_struct *work)
{
	int i = 0;
	struct tas575x_private *priv;
	struct delayed_work *dwork = to_delayed_work(work);
	int cnt = sizeof(tas5754_reg_values)/sizeof(tas5754_reg_values[0]);
	pr_info("%s, reg cnt:%d\n", __func__, cnt);
	priv = container_of(dwork, struct tas575x_private, dwork);
	for(i = 0; i<cnt; i++){
		snd_soc_write(priv->codec, tas5754_reg_values[i].reg,tas5754_reg_values[i].val);
	}
}

  1. EQ均衡器 ↩︎
  2. workqueue 机制 ↩︎
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • EQ参数
  • 驱动写入EQ
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档