本文是基于mini2440开发板Linux版本号是linux-2.6.32.2的学习笔记

一. uda1341的硬件信息

CPU通过L3接口控制uda1341芯片,分别是:
L3DATA: 数据线
L3MODE: 模式控制线,置0时,地址模式;置1时,数据模式
L3CLOCK: 时钟线

  • 地址模式:
    data[7:2]:表示的是设备地址,UDA1341TS芯片的设备地址是 000101
    data[1:0]:表示的是传输类型

    00:地址寄存器,音量,低音增强,高音,峰值检测
    扩展寄存器地址,AGC控制,MIC灵敏度控制等
    01:读回峰值信息
    10: STATUS状态信息,复位、时钟、数据输入格式(数据位宽)等

STATUS控制,地址是:00010110 = 0x16




data0控制:地址是:00010100 = 0x14


data1控制,地址是:00010101 = 0x15

三. uda1341的写控制函数

写控制函数定义如下:

static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
  • 将value保存在cache[reg]中。
uda134x_write_reg_cache(codec, reg, value);
  • 根据传入的reg值,写地址。
  • UDA134X_EA000 ~ UDA134X_EA111属于扩展地址,也属于data[0:0]
    发送地址是:(5 << 2) | 0 ),发送地址时,L3MODE引脚拉低,地址模式。
    发送扩展地址,扩展地址最多有8个,但是扩展地址的最高两位为1,所以地址要与上0xc0
#define UDA134X_EXTADDR_PREFIX   0xC0
addr =  (reg | UDA134X_EXTADDR_PREFIX);
ret = l3_write(&pd->l3, UDA134X_DATA0_ADDR, &addr, 1);

发送扩展数据,扩展数据的高三位都是1,所以要在原来value上加0xe0

#define UDA134X_EXTDATA_PREFIX   0xE0
data = (value | UDA134X_EXTDATA_PREFIX);
ret = l3_write(&pd->l3, addr, &data, 1);

发送扩展地址和发送扩展数据,实际上都是发送数据,L3MODE引脚要拉高,选择数据模式。

  • UDA134X_STATUS0和UDA134X_STATUS1属于data[1:0]
    发送地址是:(5 << 2) | 2 )
    发送数据:
#define UDA134X_STATUS_ADDR  ((UDA134X_L3ADDR << 2) | 2)
addr = UDA134X_STATUS_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
  • UDA134X_DATA000,UDA134X_DATA001,UDA134X_DATA010属于data[0:0]
    发送地址是:(5 << 2) | 0 )
    发送数据:
#define UDA134X_L3ADDR   5
#define UDA134X_DATA0_ADDR  ((UDA134X_L3ADDR << 2) | 0)
addr = UDA134X_DATA0_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
  • UDA134X_DATA1属于data[0:1]
    发送地址是:(5 << 2) | 1 )
    发送数据:
#define UDA134X_L3ADDR   5
#define UDA134X_DATA1_ADDR  ((UDA134X_L3ADDR << 2) | 1)
addr = UDA134X_DATA1_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
四. uda1341的复位操作

发送地址:(5 << 2) | 2 )
发送数据:value | (1<<6)

五. uda1341的静音操作

发送地址:(5 << 2) | 0 )
发送数据:value | (1<<2)

六. uda1341的时钟设置

1.设置系统时钟
uda1341支持三种系统时钟, 512fs, 384fs,256fs
2.uda1341支持的采样率为:8000,11025,16000,22050,32000,44100,48000
3.则系统时钟的范围是:256 * 8000 <= freq <= 512 * 48000

2.设置时钟调用函数uda134x_set_dai_sysclk

static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir)
{struct snd_soc_codec *codec = codec_dai->codec;struct uda134x_priv *uda134x = codec->private_data;pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,clk_id, freq, dir);/* Anything between 256fs*8Khz and 512fs*48Khz should be acceptablebecause the codec is slave. Of course limitations of the clockmaster (the IIS controller) apply.We'll error out on set_hw_params if it's not OK */if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {uda134x->sysclk = freq;return 0;}printk(KERN_ERR "%s unsupported sysclk\n", __func__);return -EINVAL;
}

在这里系统时钟并没有真正的设置下去,而是保存到了uda134x->sysclk变量中,留在后面设置。

七. 设置支持数据格式

1.uda1341支持的格式如下:

(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
  1. 设置数据格式调用的函数是uda134x_set_dai_fmt
static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{struct snd_soc_codec *codec = codec_dai->codec;struct uda134x_priv *uda134x = codec->private_data;pr_debug("%s fmt: %08X\n", __func__, fmt);/* codec supports only full slave mode */if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {printk(KERN_ERR "%s unsupported slave mode\n", __func__);return -EINVAL;}/* no support for clock inversion */if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {printk(KERN_ERR "%s unsupported clock inversion\n", __func__);return -EINVAL;}/* We can't setup DAI format here as it depends on the word bit num *//* so let's just store the value for later */uda134x->dai_fmt = fmt;return 0;
}
八. uda1341设置bias(猜测是电源)等级

SND_SOC_BIAS_ON等级:
把ADC, DAC打开
发送地址:(5 << 2) | 2 )
发送数据:0x83

SND_SOC_BIAS_PREPARE等级:

pd->power(1);
for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)codec->write(codec, i, *cache++);

SND_SOC_BIAS_STANDBY等级:
发送地址:(5 << 2) | 2 )
发送数据:value & ~(0x03)

SND_SOC_BIAS_OFF等级:

pd->power(0);
九. 设置硬件参数

设置硬件参数调用的函数是uda134x_hw_params

  • 设置芯片的系统时钟的除数,512, 384,256
switch (uda134x->sysclk / params_rate(params))
{case 512:break;case 384:hw_params |= (1<<4);break;case 256:hw_params |= (1<<5);break;default:printk(KERN_ERR "%s unsupported fs\n", __func__);return -EINVAL;
}


发送数据:384fs(vaule | (1 << 4)) 256fs(value | 1 << 5)

  • 设置数据模式
switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK)
{case SND_SOC_DAIFMT_I2S:break;case SND_SOC_DAIFMT_RIGHT_J:switch (params_format(params)) {case SNDRV_PCM_FORMAT_S16_LE:hw_params |= (1<<1);break;case SNDRV_PCM_FORMAT_S18_3LE:hw_params |= (1<<2);break;case SNDRV_PCM_FORMAT_S20_3LE:hw_params |= ((1<<2) | (1<<1));break;default:printk(KERN_ERR "%s unsupported format (right)\n",__func__);return -EINVAL;}break;case SND_SOC_DAIFMT_LEFT_J:hw_params |= (1<<3);break;default:printk(KERN_ERR "%s unsupported format\n", __func__);return -EINVAL;
}

SND_SOC_DAIFMT_I2S:0
SND_SOC_DAIFMT_RIGHT_J和SND_SOC_DAIFMT_LEFT_J模式参考下图

十. Linux UDA1341芯片接口注册
static struct snd_soc_dai_ops uda134x_dai_ops = {.startup   = uda134x_startup,.shutdown    = uda134x_shutdown,.hw_params  = uda134x_hw_params,.digital_mute  = uda134x_mute,.set_sysclk = uda134x_set_dai_sysclk,.set_fmt  = uda134x_set_dai_fmt,
};
struct snd_soc_dai uda134x_dai = {.name = "UDA134X",/* playback capabilities */.playback = {.stream_name = "Playback",.channels_min = 1,.channels_max = 2,.rates = UDA134X_RATES,.formats = UDA134X_FORMATS,},/* capture capabilities */.capture = {.stream_name = "Capture",.channels_min = 1,.channels_max = 2,.rates = UDA134X_RATES,.formats = UDA134X_FORMATS,},/* pcm operations */.ops = &uda134x_dai_ops,
};
  • 注册时间:在启动内核是调用uda134x_init函数。在uda134x_init函数中注册UDA1341接口。
static int __init uda134x_init(void)
{return snd_soc_register_dai(&uda134x_dai);
}
module_init(uda134x_init);

跟I2S的接口注册一样,注册到一个dai_list的全局链表中,dai_list链表中是各种各样的dai接口。

十一. 总结
  • uda134x_dai接口在内核起来时注册。
  • uda134x_dai接口包含对UDA1341芯片的时钟,传输模式等硬件设置,一个硬件参数操作集uda134x_dai_ops。

参考博客:
https://blog.csdn.net/gqb_driver/article/details/8551551

Linux音频驱动之五:UDA1341芯片操作接口相关推荐

  1. Linux音频驱动之二:Control接口的调用

    本文是基于mini2440开发板Linux版本号是linux-2.6.32.2的学习笔记 一. control接口说明 Control接口主要让用户空间的应用程序(alsa-lib)可以访问和控制音频 ...

  2. Linux 音频驱动(五) ALSA音频驱动之PCM逻辑设备

    目录 1. 前言 2. PCM逻辑设备 2.1. 创建 PCM逻辑设备: 2.2. PCM逻辑设备文件操作函数集:snd_pcm_f_ops[] 2.3. Open PCM逻辑设备 2.4. Writ ...

  3. STM32MP157驱动开发——Linux 音频驱动

    STM32MP157驱动开发--Linux 音频驱动 一.简介 1.CS42L51 简介 2.I2S总线 3.STM32MP1 SAI 总线接口 二.驱动开发 1.音频驱动 1)修改设备树 i2c 接 ...

  4. 转载:Linux音频驱动-OSS和ALSA声音系统简介及其比较

    Linux音频驱动-OSS和ALSA声音系统简介及其比较 概述 昨天想在Ubuntu上用一下HTK工具包来绘制语音信号的频谱图和提取MFCC的结果,但由于前段时间把Ubuntu升级到13.04,系统的 ...

  5. Linux 音频驱动(二) ASoC音频驱动之Platform驱动

    目录 1. 简介 2. 源码分析 2.1. CPU DAI 2.1.1. 数据结构struct snd_soc_dai_driver 2.1.2. 注册CPU DAI:snd_soc_register ...

  6. Linux 音频驱动(四) ASoC音频驱动之Machine驱动

    目录 1. 基本介绍 2. 源码分析 2.1. Machine数据结构 struct snd_soc_dai_link 3. 声卡 3.1. 数据结构struct snd_soc_card 3.2. ...

  7. linux 音频架构绕过,linux音频驱动架构

    1.linux音频驱动架构分为3部分组成:硬件无关层(核心层ALSA).板级音频数字接口层驱动(McASP.McBSP等).外部codes驱动 sound/soc/davinci/ti81xx-etv ...

  8. Linux 音频驱动

    Linux 音频驱动 硬件介绍 WM8960与IMX6ULL之间有两个通信接口:I2C和I2S 其中I2C用于配置WM8960 I2S用于音频数据传输 修改设备树文件 编写I2C子节点设备树 code ...

  9. linux 音频驱动的流程,Intel平台下Linux音频驱动流程分析

    [软件框架] 在对要做的事情一无所知的时候,从全局看看系统的拓扑图对我们认识新事物有很大的帮助.Audio 部分的驱动程序框架如下图所示: 这幅图明显地分为 3 级. 上方蓝色系的 ALSA Kern ...

最新文章

  1. 1.IocDI和Spring
  2. 动物统计加强版(贪心,字典序)
  3. 第四章 进程(3)进程的命令行环境变量
  4. mysql锁机制总结
  5. 【Python位运算】——左移操作(<<)右移操作>>
  6. .Net Core开发日志——Peachpie
  7. 工作294:for[item.key]使用
  8. mysql对测试如何_我如何对MySQL进行基准测试?
  9. 设计模式--观察者模式--Java实现
  10. 170504、MongoDB和MySQL对比(译)
  11. OSPF外部实验详解
  12. [CSS学习] line-height属性讲解
  13. 软件环境整理(pro、sit、test、pre、dev)
  14. 支持向量回归(多核函数)
  15. 51单片机流水灯方法大全
  16. 一键清除失效/删除微博转发微博收藏爬虫
  17. 《太极张三丰》原声音乐 320/mp3打包下载
  18. python 将中文数字转换为阿拉伯数字
  19. python不合法的布尔表达式,python笔试题22-41
  20. 同步上下文(SynchronizationContext)

热门文章

  1. 开源增强型zigbee协议栈
  2. 共享单车项目、mongodb集群
  3. 二叉树的遍历(二叉树与递归算法)
  4. SAP-MM知识精解-批次管理(03-02)-批次主数据之视图介绍
  5. el-table设置封装
  6. 设置微信PC端代理使用burp抓取微信小程序的数据包
  7. Hudson插件开发入门体验
  8. LeetCode 69.X的平方根
  9. 【NOIP 2018 提高组】赛道修建
  10. linux基础测试题