框架:

mt7688I2s做从机,codecRT5670做主机;mainclock由mt7688输出12MHz,测试音频为48K采样率。

设备树配置如下:

/dts-v1/;#include "mt7628an.dtsi"/ {compatible = "mediatek,mt7628an-eval-board", "mediatek,mt7628an-soc";model = "Mediatek MT7628AN evaluation board";chosen {bootargs = "console=ttyS0,115200";};memory@0 {device_type = "memory";reg = <0x0 0x2000000>;};sound {compatible = "simple-audio-card";simple-audio-card,name = "Audio-I2S";simple-audio-card,format = "i2s";simple-audio-card,bitclock-master = <&dailink0_master>;simple-audio-card,frame-master = <&dailink0_master>;simple-audio-card,widgets ="Headphone", "Headphones","Speaker", "Speakers","Microphone", "Microphones";simple-audio-card,routing ="Speakers", "LOUTL","Speakers", "LOUTR","Microphones", "MICBIAS2","IN2P", "Microphones";simple-audio-card,mclk-fs = <512>; //codec做主,主控供给编解码芯片用的时钟 512FS
simple-audio-card,cpu {sound-dai = <&i2s>;};dailink0_master: simple-audio-card,codec {sound-dai = <&codec>;};};
};&pinctrl {state_default: pinctrl0 {gpio {ralink,group = "gpio";ralink,function = "gpio";};};
};&gpio1 {status = "okay";
};&wmac {status = "okay";ralink,mtd-eeprom = <&factory 0x4>;
};&ethernet {mtd-mac-address = <&factory 0x28>;
};&gdma {status = "okay";
};
&i2c {status = "okay";codec: rt5670@1c {#sound-dai-cells = <0>;compatible = "ralink,rt5670";reg = <0x1c>;ralink,shared-lrclk;};    };&i2s {#sound-dai-cells = <0>;status = "okay";pinctrl-names = "default";pinctrl-0 = <&i2s_pins>, <&refclk_pins>;
};&spi0 {status = "okay";m25p80@0 {#address-cells = <1>;#size-cells = <1>;compatible = "jedec,spi-nor";reg = <0>;spi-max-frequency = <10000000>;m25p,chunked-io = <32>;partition@0 {label = "u-boot";reg = <0x0 0x30000>;read-only;};partition@30000 {label = "u-boot-env";reg = <0x30000 0x10000>;read-only;};factory: partition@40000 {label = "factory";reg = <0x40000 0x10000>;read-only;};partition@50000 {label = "firmware";reg = <0x50000 0x7b0000>;};};
};

audio平台使用 simple-audio-card,而非platform-machine-codec的架构自己重构个machine。

调试主要关注以下几个函数即可:

simple-card.c文件下的asoc_simple_card_hw_params

static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params)
{struct snd_soc_pcm_runtime *rtd = substream->private_data;struct snd_soc_dai *codec_dai = rtd->codec_dai;struct snd_soc_dai *cpu_dai = rtd->cpu_dai;struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);struct simple_dai_props *dai_props =simple_priv_to_props(priv, rtd->num);unsigned int mclk, mclk_fs = 0;int ret = 0;if (priv->mclk_fs)mclk_fs = priv->mclk_fs;else if (dai_props->mclk_fs)mclk_fs = dai_props->mclk_fs;if (mclk_fs) {mclk = params_rate(params) * mclk_fs;ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,SND_SOC_CLOCK_IN);if (ret && ret != -ENOTSUPP)goto err;ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,SND_SOC_CLOCK_OUT);if (ret && ret != -ENOTSUPP)goto err;}return 0;
err:return ret;
}

该函数在播放或者录音的时候会被调用,会分别设置codec的I2S时钟,CPU Dai的时钟,主要是设置时钟源(外部mainclock、PLL output clock、internel clock),比如设置codec的时钟,最终会调用如下函数:

static int rt5670_set_sysclk(struct snd_soc_codec *codec,int clk_id, int source, unsigned int freq, int dir)
{struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);unsigned int reg_val = 0;if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)return 0;switch (clk_id) {case RT5670_SCLK_S_MCLK:reg_val |= RT5670_SCLK_SRC_MCLK;break;case RT5670_SCLK_S_PLL1:reg_val |= RT5670_SCLK_SRC_PLL1;break;case RT5670_SCLK_S_RCCLK:reg_val |= RT5670_SCLK_SRC_RCCLK;break;default:dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);return -EINVAL;}snd_soc_update_bits(codec, RT5670_GLB_CLK,RT5670_SCLK_SRC_MASK, reg_val);rt5670->sysclk = freq;rt5670->sysclk_src = clk_id;dev_dbg(codec->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);return 0;}

以上这个函数就是设置rt5670的i2ssysclk的时钟源,simple audio card默认的是设置外部mainclock为I2Ssysclk的时钟源,关于RT5670的i2s_sysclk时钟源的路径可以参考下图:

理论上只要CLK_sys可以分频出256FS的频率,codec就可以正常录音播放,但是调试的时候却发现几个问题:

1.如果采用如下路径配置CLK_sys时钟,codec不能正常录音播放

推断可能是时钟不符合256FS,所以不能正常播放;

2.采用PLL分频出CLK_sys,设备树里面设置 simple-audio-card,mclk-fs = <256>; 按如下路径设置CLK_sys

12M 经过PLL后输出12.288M,MX73[14:12]不分频,输出刚好符合256FS,但是播放录音均不正常

3. 采用PLL分频出CLK_sys,设备树里面设置 simple-audio-card,mclk-fs = <512>; 按如下路径设置CLK_sys

12M 经过PLL后输出24.576M,MX73[14:12]2分频,输出为12.288M刚好符合256FS,播放录音正常;

以上3中配置情况测量lrclk Bclk mainclk 均为 48K  3M  12M左右;

经过以上3个系统时钟的配置测试,得出rt5670时钟的奇葩路径配置:

先由simple audio card端设置codec的sysclk时钟源为外部mainclok(即上面的 asoc_simple_card_hw_params 函数),然后调用codec的 rt5670_hw_params 将 pll的时钟源设置为mainclock,然后再倍频至24.576M,然后再通过MX73[14:12]分频至12.288M:

static int rt5670_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{struct snd_soc_codec *codec = dai->codec;struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);unsigned int val_len = 0, val_clk, mask_clk;int pre_div, bclk_ms, frame_size;if (RT5670_AIF2 == dai->id) {snd_soc_update_bits(codec, RT5670_GPIO_CTRL1,RT5670_I2S2_PIN_MASK, RT5670_I2S2_PIN_I2S);}rt5670->lrck[dai->id] = params_rate(params);pre_div = rl6231_get_clk_info(rt5670->sysclk, rt5670->lrck[dai->id]);if (pre_div < 0) {dev_err(codec->dev, "Unsupported clock setting\n");return -EINVAL;}frame_size = snd_soc_params_to_frame_size(params);if (frame_size < 0) {dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);return -EINVAL;}bclk_ms = frame_size > 32;rt5670->bclk[dai->id] = rt5670->lrck[dai->id] * (32 << bclk_ms);dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",rt5670->bclk[dai->id], rt5670->lrck[dai->id]);dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",bclk_ms, pre_div, dai->id);switch (params_width(params)) {case 16:break;case 20:val_len |= RT5670_I2S_DL_20;break;case 24:val_len |= RT5670_I2S_DL_24;break;case 8:val_len |= RT5670_I2S_DL_8;break;default:return -EINVAL;}switch (dai->id) {case RT5670_AIF1:mask_clk = RT5670_I2S_BCLK_MS1_MASK | RT5670_I2S_PD1_MASK;val_clk = bclk_ms << RT5670_I2S_BCLK_MS1_SFT |pre_div << RT5670_I2S_PD1_SFT;snd_soc_update_bits(codec, RT5670_I2S1_SDP,RT5670_I2S_DL_MASK, val_len);snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk);  // 分频,确保i2s sysclk为 256FSbreak;case RT5670_AIF2:mask_clk = RT5670_I2S_BCLK_MS2_MASK | RT5670_I2S_PD2_MASK;val_clk = bclk_ms << RT5670_I2S_BCLK_MS2_SFT |pre_div << RT5670_I2S_PD2_SFT;snd_soc_update_bits(codec, RT5670_I2S2_SDP,RT5670_I2S_DL_MASK, val_len);snd_soc_update_bits(codec, RT5670_ADDA_CLK1, mask_clk, val_clk);break;}struct snd_soc_pcm_runtime *p = (struct snd_soc_pcm_runtime *)substream->private_data;struct snd_soc_dai *cpu_dai = p->cpu_dai;
snd_soc_dai_set_pll(dai, dai->id,RT5670_PLL1_S_MCLK, 12000000, params_rate(params)*512);        // set pll source use outside mainclock and set pll output 24.576Msnd_soc_dai_set_sysclk(dai, RT5670_SCLK_S_PLL1, params_rate(params)*512, SND_SOC_CLOCK_IN);     // set sysclk source use pll output, if(cpu_dai){printk("CPU DAI\r\n");snd_soc_dai_set_sysclk(cpu_dai, RT5670_SCLK_S_MCLK, 12000000, SND_SOC_CLOCK_OUT);}        return 0;
}

转载于:https://www.cnblogs.com/weishengzhong/p/11103935.html

Openwrt开发之声卡RT5670挂载相关推荐

  1. openwrt开发环境搭建

    OpenWrt 可以被描述为一个嵌入式的 Linux 发行版.现在叫lede,全名Linux嵌入式开发环境项目(Linux Embedded Development Environment) open ...

  2. 智能路由器OpenWrt 开发环境 及 编译分析(一)

    OpenWrt 开发环境及编译分析 OpenWrt的版本:Chaos Calmer 15.05 软件源:软件源就是一个应用程序安装库,很多很多的应用软件都在这个库里面.只要设定好软件源,就能很方便的安 ...

  3. 集多功能为一体的智能WiFi模块Linux多线程处理器openwrt开发板工业4G路由器网口有线转无线WiFi

    集多功能为一体的智能WiFi模块Linux多线程处理器openwrt开发板工业路由器网口有线转无线WiFi双路RS485/RS232串口透传 RMS7688A集多功能为一体的智能WiFi模块,能跑Li ...

  4. Ubuntu 16.04下配置openWRT开发环境

    Ubuntu 16.04下配置openWRT开发环境 1.配置openwrt开发环境,本实验室在ubuntu16.04系统下测试 在编译之前我们先要搭建环境,ubuntu下OpenWrt编译环境需要安 ...

  5. openwrt开发教程之下载配置编译openwrt(MT7621A)

    什么是openwrt? openwrt可以被描述为一个嵌入式Linux发行版,openwrt的包管理器提供了一个完全可写的文件系统. openwrt是使用框架来构建应用程序的,对于用户来说,这意味着其 ...

  6. 构建openwrt开发环境与系统(ARM)

    首先我们首选的OpenWrt编译环境是Ubuntu,并且应尽量选择更高版本的.这里我们使用Ubuntu11.04作为编译平台,此平台必须要能稳定地接入网络.我们推荐您使用以下或更高的硬件配置: CPU ...

  7. OpenWrt开发指南博文导航

    自博主更新该专栏也很久了,今天博主就给出关于OpenWrt开发的一个导航,为的是读者朋友能更好找到自己所感兴趣的那一块,当然博主以后对OpenWrt有新的发现和想法也会在第一时间发表在CSDN上,在此 ...

  8. openwrt开发--ILI9341屏幕显示开发

    前些天在学习linux下的驱动编写,找到了一块之前淘到的液晶屏,主控芯片是ili9341,分辨率为240*320的屏幕,接口方式是SPI的,心血来潮想搞一下.不过奈何驱动水平不到家,只是开发出了一种杂 ...

  9. 开发板通过NTS挂载在PC机中的文件夹

    文章目录 1 安装NFS服务 2 开发板通过NFS挂在PC中的文件 2.1 设置开发板的IP地址网段和Ubuntu一致 2.2 开发板挂在PC中的文件 1 安装NFS服务 NFS 即网络文件系统,允许 ...

最新文章

  1. 计算机网络分为两大阶段,【多选题】计算机网络的发展分为哪些阶段?() A. 远程终端联机阶段 B. 计算机网络阶段 C. 计算机网络互联阶段 D. 信息高速公路阶段...
  2. 新款华为手机,免费带回家
  3. sql server 2005 在 windows7 报 IIS Feature Requirement 错误。解决办法。
  4. mysqld_multi stop 不能停掉mysql
  5. SpringBoot 如何统一后端返回格式?老鸟们都是这样玩的!
  6. 详解rel=”nofollow”的用法与意义
  7. ubuntu 安装搜狗输入法(解决部分ubuntu安装完没有键盘选择栏)
  8. 详解 MySQL 基准测试和 sysbench 工具
  9. SQL分类,DDL,DML,DCL
  10. 随机过程通过线性系统matlab,随机信号分析实验:随机过程通过线性系统的分析.doc...
  11. 多线段几何图形—— 简单几何图形(布尔运算)
  12. 原来CSS可以添加多个阴影
  13. 分布式系统——MapReduce:Simplified Data Processing on Large Clusters论文
  14. (边学边练)JAVA基础学习第三天
  15. 脚本防止电脑自动锁屏
  16. Python爬虫:使用线程池快速下载视频
  17. 塔勒布四部曲之《非对称风险》
  18. Anaconda的升级与卸载
  19. Commvault发布横向扩展一体机 矛头对准Rubrik和Cohesity
  20. 关于软件中“业务逻辑”的详解

热门文章

  1. Sitecore 开篇
  2. 《语音信号处理》整理
  3. 中国国家授时中心的时间服务器IP地址及时间同步方法
  4. HTTP请求报文的结构组成及URL的结构组成
  5. Axure的布尔运算/发布与设置
  6. centos DNS问题(只能ping通IP域名白费)
  7. Synchronous SRAMs 同步静态随机存储器
  8. 使用VCG检查服务器与ESXi兼容性 V2.0
  9. 麒麟V10系统-如何获取软件商店下载的安装包
  10. leader说:查一查为什么系统性能这么差