Android14音頻子系統-Linux音頻子系統ASoC-ALSA

文章目錄

    • 1、術語
    • 2、概述
      • 1)資料快車
    • 3、預備工作
      • 1)codec - UDA1340 - 硬件規格
      • 2)ASOC-ALSA代碼重點目錄介紹
      • 3)ASOC-ALSA層級介紹
      • 4)了解基本的軟硬件架構
    • 4、數據結構
    • 5、代碼分析
      • 1)Machine
        • 1、總體流程介紹
        • 2、Machine代碼流程圖
          • 重點介紹
      • 2)Platform_driver
      • 3)codec

1、術語

1、asoc : alsa on chip  //嵌入式平臺下的alsa,對ALSA進一步的封裝
2、runtime : 記錄substream的一些重要軟件和硬件運行的環境和參數
3、DAI : Digital Audio Interface
4、component :組件(可以理解為 面向對象 中的對象)
5、SAI : ALSA Soc Digital Audio Interface(SAI)
6、topology : 拓撲
7、dpcm : dynamic pcm
8、BE :Blackend 后端9、mixer的含義? 在不同層級有不同含義?
1)在tinyalsa下 代表設置寄存器control
2)在硬件上和驅動層,代表mixer混合器(codec中的一個部件)10、component : 組件,可以理解為一個音頻處理單元(可以是物理設備也可以是虛擬設備)-面向對象中的對象,每個處理單元都有獨立的功能和控制接口,比如一個音頻解碼器、音頻放大器、音頻均衡器、DMA都是一個組件,組件化可以提高系統代碼的模塊化程度和可維護性;component是音頻系統中的邏輯單元;

2、概述

1)資料快車

1、linux ALSA ASoc架構: https://blog.csdn.net/weixin_45437140/article/details/128637521

2、alsa框架介紹:https://blog.51cto.com/u_93011/8854396 原文(付費):https://blog.csdn.net/RadianceBlau/article/details/79432661

3、官方網站:https://www.alsa-project.org/main/index.php/ASoC

3、預備工作

1、首先要對硬件盡可能熟悉(專業名詞、與主控的數據通信方式、芯片內部的部件作用);

2、深入代碼前應該先掌握這套架構的設計對象和設計思想,那樣我們才能更高的效率去看代碼!

1)codec - UDA1340 - 硬件規格

1)功能框圖
在這里插入圖片描述

2)引腳介紹
在這里插入圖片描述

重點介紹:

1、DSP:codec負責音效處理的單元2、codec中的音頻路徑是指?有哪些?
不同codec不盡相同,比如UDA1340
1)播放路徑:CPU -> DATA(I2S) -> DSP -> INTERPOLATION FILTER -> NOISE SHAPER -> DAC -> VOUTL/VOUTR(DAC output left/right)
2)錄音路徑:VINL/VINR(ADC input left/right) -> ADC -> DC-CANCELATION FILTER -> DATA(I2S) -> CPU

2)ASOC-ALSA代碼重點目錄介紹

分為兩部分
1、根據芯片廠商或平臺進行分類,每個文件夾放置相應硬件平臺的音頻驅動代碼
├─adi //Anolog Devices, Inc
├─amd //Advanced Mircro Devices, Inc
├─atmel //愛特梅爾
├─au1x //AMD下的au1x系統處理器
├─bcm //Broadcom
├─cirrus //Cirrus Logic, Inc
├─davinci //TI下的davinci系列處理器
├─dwc //ST Microelectronics下的dwc
├─fsl //飛思卡爾-Freescale,現為NXP
├─hisilicon //海思
├─img //Imagination Technologies Ltd.
├─intel //英特爾
├─jz4740 //杰睦(Ingenic)JZ4740系列處理器
├─kirkwood
├─mediatek //聯發科
├─meson //Amlogic Meson系統
├─mxs //Freescale i.MX系列處理器
├─nuc900 //Nuvoton Nuclias系列處理器
├─omap //德州儀器(TI)OMAP系列處理器
├─pxa //Marvell PXA系列處理器
├─qcom //Qualcomm 高通
├─rockchip //瑞芯微
├─samsung //三星
├─sh //renesas(瑞薩 -日本)SH系列處理器
├─sirf //聯發科(MediaTek)旗下的聯發科數字(Sirf)音頻驅動
├─spear //ST下的SPEAr 系列ARM處理器
├─sti //意法半導體(STMicroelectronics)
├─stm //意法半導體
├─sunxi //全志科技(Allwinner)
├─tegra //英偉達(NVIDIA)Tegra系列處理器
├─txx9  //Renesas(瑞薩 -日本) Txx9系列處理器
├─uniphier //富士通(Fujitsu)
├─ux500 //德州儀器(TI)UX500系列處理器
├─xtensa //Tensilica(現為Cadence)
└─zte //中興
1) 眾多的硬件平臺,由此可見soc推出必要性,大大降低重復代碼和復用
2) 認識以上廠商或芯片是有必要的,在linux代碼中不同廠商和架構隨處可見
3)Soc相關的驅動無非就是 I2S/PCM/AC97/I2C/SPDIF 通信接口的驅動代碼2、通用類和框架類代碼
├─generic //audio-graph-card和simple-card驅動代碼,不針對特定硬件平臺
├─codecs //通用的codecs驅動代碼,不針對特定硬件平臺
soc-* //asoc框架核心代碼實現

3)ASOC-ALSA層級介紹

在這里插入圖片描述

1、ASOC-ALSA是根據嵌入式設備特點,在ALSA基礎上再封裝一層而來,有了ALSA學習基礎,這里就更容易學習AOSC-ALSA;

1)ALSA目前主要應用在個人電腦上的聲卡,而ASOC針對嵌入式設備(一般為I2S接口設備的功放);

2)可以理解ALSA為通用的音頻框架,ASOC-ALSA為專用于嵌入式設備的音頻框架,根據需求來選擇基于哪個架構來進行開發;

2、ASOC-ALSA解決什么問題?

1)codec驅動與soc cpu的代碼過于緊密,導致不同平臺有不同的codec驅動,而在嵌入式紛繁復雜的產品中,各種搭配導致代碼冗余 ->

解決方法:將這codec和soc獨立為單獨的驅動;

2)一旦播放和錄音時,驅動使能整個codec(有些codec有多路輸入和輸出),所有部件處于上電狀態,但實際上有些部件是沒有用到,對于移動設備來說,會十分浪費不必要的電量 -> 解決方法:設計DAPM解決,將各個寄存器按照 場景來劃分 組合;

3)音頻事件沒有標準的方法來通知用戶 -> 解決方法:

3、如何寫ASOC? >> 開發時寫codec端即可,使用ASOC封裝好的API構造聲卡設備

4)了解基本的軟硬件架構

1)一般平臺的音頻系統硬件架構(高度抽象)
在這里插入圖片描述

2)來看一個嵌入式領域的一個具體例子的硬件模型(基本都長這樣),接下來以這個例子來進行學習
在這里插入圖片描述

1)以pci - als300為例,上述的i2s/i2c/dma/timer驅動都放在android\kernel\fusion\4.19\sound\pci\als300.c 實現,那么如果換個平臺,als300.c就需要重寫;

2)如何改進?ASOC-ALSA結合硬件框架模型(滿足市面上絕大多數的codec)來設計軟件架構,讓其通用且可復用;ASOC的做法將其組件化(類似面向對象),然后不同平臺自行組裝,相同的特性 單獨抽離出來統一設計,硬件專有的實現 留接口給廠商自行掛接;那么組件(component) 對象可以分為:

1、platform - cpu的DMA

2、platform -cpu的I2S

3、Codec的I2S

4、Codec的I2C

以上均需要單獨實現;

3)有面向對象編程的人不難看出linux音頻驅動的結構與類圖很像,將變化的東西封裝了起來,層次清晰,方便理解和調試:

》內核代碼是一直在變化,越高版本的Linux內核,逐漸往面向對象的方向發展;

4)設計對象說明 - 概念介紹

1、Machine
是指某一款機器,可以是某款設備,某款開發板,又或者是某款智能手機,由此可以看出每個Machine上的硬件實現可能都不一樣,CPU不一樣,Codec不一樣,音頻的輸入、輸出設備也不一樣,Machine為CPU、Codec、輸入輸出設備提供了一個載體。Machine驅動 Machine驅動負責處理機器特有的一些控件和音頻事件(例如,當播放音頻時,需要先行打開一個放大器);單獨的PlatformCodec驅動是不能工作的,它必須由Machine驅動把它們結合在一起才能完成整個設備的音頻處理工作。2、Platform
一般是指某一個SoC平臺,即CPU,比如pxaxxx,s3cxxxx,omapxxx等等,與音頻相關的通常包含該SoC中的時鐘、DMA、I2S、PCM等等,只要指定了SoC,那么我們可以認為它會有一個對應的Platform,它只與SoC相關,與Machine無關,這樣我們就可以把Platform抽象出來,使得同一款SoC不用做任何的改動,就可以用在不同的Machine中。實際上,把Platform認為是某個SoC更好理解。Platform驅動包含了該SoC平臺的音頻DMA和音頻接口的配置和控制(I2S,PCM,AC97等等);它也不能包含任何與板子或機器相關的代碼。3、Codec
字面上的意思就是編解碼器,Codec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常包含多種輸入(Mic、Line-in、I2S、PCM)和多個輸出(耳機、喇叭、聽筒,Line-out),Codec和Platform一樣,是可重用的部件,同一個Codec可以被不同的Machine使用。嵌入式Codec通常通過I2C對內部的寄存器進行控制。Codec驅動在ASoC中的一個重要設計原則就是要求Codec驅動是平臺無關的,它包含了一些音頻的控件(Controls),音頻接口,DAMP(動態音頻電源管理)的定義和某些Codec IO功能。為了保證平臺無關性,任何特定于平臺和機器的代碼都要盡量移到Platform,所有的Codec驅動都要提供以下特性:
Codec DAI 和 PCM的配置信息;
Codec的IO控制方式(I2C,SPI等);
Mixer和其他的音頻控件;
Codec的ALSA音頻操作接口;必要時,也可以提供以下功能:
DAPM描述信息;
DAPM事件處理程序;
DAC數字靜音控制

4、數據結構

整個ASoc是由一系列的數據結構組成(C語言實現的架構大多數如此),理清里面的數據結構就等同掌握ASoc的工作機理

在linux4.19上數據結構如下:
在這里插入圖片描述

1、從ASOC-ALSA架構來看,1/2/3區域分別對應如下

在這里插入圖片描述

2、linux4.9上使用component概念來代表cpu或codec,根據之前對于組件的分類:

1)4區域對應:platform - cpu的DMA、Codec的I2C (共用同一個結構體)

2)5區域對應:platform -cpu的I2S、Codec的I2S (共用同一個結構體)

3、所有的數據結構通過snd_soc_card作為總源頭,把握這個主線索,串聯其它的數據結構,其次在初始化時,根據開發者構造的snd_soc_card,找到選定的cpu和codec信息,將driver/ops放在snd_soc_pcm_runtime里(這部分在Machine里面再展開體現)

4、結構體(作用類似對象)對應一個實際的例子(wm8960) 如下
在這里插入圖片描述

重點介紹:

1、machine會根據名字去匹配component (即cpu和codec) 對應的driver/dai,并放進snd_soc_pcm_runtime里面2. machine如何指定cpu和codec?
使用snd_soc_dai_link指定當前平臺使用的 cpu 和 codec
struct snd_soc_dai_link *dai_link;  /* predefined links only */3、在舊版驅動中ASoC定義了三個全局的鏈表頭變量:codec_list、dai_list、platform_list;linux 4.19在哪里?
均在snd_soc_pcm_runtime上體現
struct snd_soc_pcm_runtime {struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai;  //一個平臺一般只有一個cpu struct snd_soc_dai **codec_dais; //掛接多個codec dai,一個平臺或有多個codec,對應dai_listunsigned int num_codecs;struct list_head component_list; //匹配platform_name,對應platform_list 
}4、總體而言,ASoC軟件框架分為3部分:
a. platform (用來描述芯片的DAI接口、負責數據傳輸):DAI: snd_soc_dai_driver, 用來表示支持哪些格式數據, 提供設置格式的函數, 啟動數據傳輸數據傳輸: snd_soc_component_driverb. codec (用來描述音頻編解碼芯片, 含有2部分: DAI接口、控制接口):DAI: snd_soc_dai_driver, 用來表示支持哪些格式數據, 提供設置格式的函數, 控制接口: snd_soc_component_driver讀寫芯片的寄存器c. machine (snd_soc_card, snd_soc_dai_link,用來確定使用哪一個platform, 哪一個codec芯片)最能調用ALSA接口進行分配/設置/注冊 snd_card

5、代碼分析

1)Machine

1、總體流程介紹
1、Machine代碼示例(命名規則一般為:平臺/芯片_codec)
1)android\kernel\fusion\4.19\sound\soc\samsung\rx1950_uda1380.c
//rx1950_uda1380.c命名解析:rx1950開發板_uda1380是codec音頻芯片
2)android\kernel\fusion\4.19\sound\soc\samsung\smdk_wm8994.c
3)android\kernel\fusion\4.19\sound\soc\samsung\s3c24xx_uda134x.c
//s3c24xx 三星CPU + uda134x Philips codec
采用s3c24xx_uda134x.c作為主要的介紹(例子應該盡可能簡單些,才更好地掌握框架內容,然后再由易及難,循序漸進)一、Machine
1.舊驅動寫法
1)platform driver
module_init(rx1950_init);
static int __init rx1950_init(void){1. platform_device_alloc會觸發soc-core.c里的同名platform_driver,最終調用snd_soc_register_card完成聲卡的創建注冊s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); 
}
2)對應的platform device
android\kernel\fusion\4.19\sound\soc\soc-core.c
/* ASoC platform driver */
static struct platform_driver soc_driver = {.driver		= {.name		= "soc-audio",.pm		= &snd_soc_pm_ops,},.probe		= soc_probe,.remove		= soc_remove,
};static int soc_probe(struct platform_deivce *pdev)
{snd_soc_register_card(card); //將Machine驅動的配置注冊到ASOC的核心,觸發Codec和platform driver的初始化
}2.較新的驅動里使用devm_snd_soc_register_card完成聲卡的創建注冊
static int s3c24xx_uda134x_probe(struct platform_device *pdev)
{struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x;struct s3c24xx_uda134x *priv;priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);card->dev = &pdev->dev;snd_soc_card_set_drvdata(card, priv);ret = devm_snd_soc_register_card(&pdev->dev, card);
}int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
{struct snd_soc_card **ptr;1.將release掛到card里面去devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);2.注冊soc cardsnd_soc_register_card(card);3.添加到dev res里統一管理devres_add(dev, ptr);
}
EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);使用devres_alloc() / devres_add()管理聲卡資源,在設備卸載時自動注銷聲卡,簡化驅動代碼,降低泄漏資源的風險3.指定platform和codec
1)snd_soc_card (Machine所對應的數據結構體)
static struct snd_soc_card snd_soc_s3c24xx_uda134x = {.name = "S3C24XX_UDA134X",.owner = THIS_MODULE,.dai_link = &s3c24xx_uda134x_dai_link,.num_links = 1,
};2)snd_soc_dai_link參數詳細說明
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {.name = "UDA134X",.stream_name = "UDA134X",.codec_name = "uda134x-codec", //1.對應platform_driver uda134x_codec_driver()- 控制接口(uda134×使用的是L3接口).codec_dai_name = "uda134x-hifi",  //2.對應snd_soc_dai_driver uda134x_dai() - 數據傳輸.cpu_dai_name = "s3c24xx-iis",   //3. 對應platform_driver s3c24xx_iis_driver() - soc端的I2S驅動.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |SND_SOC_DAIFMT_CBS_CFS,.ops = &s3c24xx_uda134x_ops,.platform_name	= "s3c24xx-iis", //4.對應platform_driver s3c24xx_iis_driver()- 使用soc的哪個部件來傳送音頻數據,這個是可選的,預留給需要更多部件操作的soc填充;這里其實是需要用到dma,s3c24xx-iis里面封裝了dma相關操作(如果還需要初始化更多soc部件,比如timer,也可以放這里去進行初始化),所以填s3c24xx-iis
};static const struct snd_soc_ops s3c24xx_uda134x_ops = {.startup = s3c24xx_uda134x_startup,.shutdown = s3c24xx_uda134x_shutdown,.hw_params = s3c24xx_uda134x_hw_params, //初始化platform端的硬件-這里主要是設置cpu端的I2S時鐘
};小結:
1)由于machine代碼涉及數據的匹配,C語言代碼實現起來是相當復雜的(用C語言實現面向對象),這塊需要好好啃下!
2)snd_soc_dai_link中填充platform、cpu dai、codec、codec_dai,稍后Machine驅動將會利用這些名字去匹配已經在系統中注冊的platform,codec,dai,這些注冊的部件都是在另外相應的Platform驅動和Codec驅動的代碼文件中定義的,這樣看來,Machine驅動的設備初始化代碼無非就是選擇Platform和Codec以及dai
2、Machine代碼流程圖

在這里插入圖片描述

重點介紹
總入口函數devm_snd_soc_register_card,基本所有核心操作均在此函數實現1、
int snd_soc_register_card(struct snd_soc_card *card){1.檢查link是否都設置了soc_init_dai_link(card, link); 2.初始化card里面的鏈表widgets/paths/dapm_list/aux_comp_list/component_dev_listsnd_soc_initialize_card_lists(card);INIT_LIST_HEAD(&card->dai_link_list); //dai_link listINIT_LIST_HEAD(&card->rtd_list); //rtd(runtime) list3.實例化card,將里面的設置的platform/codec等,根據name去其它驅動里面找出合適的驅動或實例,掛到card結構體里面snd_soc_instantiate_card(card);
}2、
snd_soc_instantiate_card()
{1. 找到cpu/codec的component -> pcm_runtime -> cardsoc_bind_dai_link(card, &card->dai_link[i]);soc_new_pcm_runtime(card, dai_link); //構造runtimesnd_soc_rtdcom_add(rtd, rtd->cpu_dai->component); //將cpu_dai component掛到rtd中去snd_soc_rtdcom_add(rtd, codec_dais[i]->component); //將codec_dais component掛到rtd中去snd_soc_rtdcom_add(rtd, component);/ /將platform component掛到rtd中去soc_add_pcm_runtime(card, rtd); //然后掛到card->rtd_list上2. 使用構造好的card,調用ALSA接口創建alsa cardsnd_card_new()3.執行各個snd_soc_component_driver的probesoc_probe_link_components(card, rtd, order);--soc_probe_component(card, component);----component->driver->probe(component); //調用各個snd_soc_component_driver *driver的probe4.執行各個snd_soc_dai的probesoc_probe_link_dais(card, rtd, order);--soc_probe_dai(cpu_dai, order); //cpu dai probe--soc_probe_dai(rtd->codec_dais[i], order); //codec dai probe5.調用ALSA接口注冊聲卡snd_card_register(card->snd_card);
}

2)Platform_driver

1、s3c24xx_uda134x.c對應的Platform代碼位置
android\kernel\fusion\4.19\sound\soc\samsung\s3c24xx-i2s.c2、Platform要實現以下:
1)實現數據傳輸 - I2S(傳數據給codec);
2)platform數據處理 - 一般是將用戶空間傳下來的數據保存在DMA,然后啟動I2S,取出DMA數據發送給codec;3、代碼介紹
static struct platform_driver s3c24xx_iis_driver = {.probe  = s3c24xx_iis_dev_probe,.driver = {.name = "s3c24xx-iis",},
};
module_platform_driver(s3c24xx_iis_driver);static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
{1. ioremaps3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res);2. dmasamsung_asoc_dma_platform_register(&pdev->dev, NULL, NULL, NULL);3.注冊 snd_soc_component_driver(s3c24xx_i2s_component - 一般是dma) 和 snd_soc_dai_driver (s3c24xx_i2s_dai - i2s),掛接到snd_soc_component中去devm_snd_soc_register_component(&pdev->dev,&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
}2、兩類driver的實現
1)platform數據處理 -dma
static const struct snd_soc_component_driver s3c24xx_i2s_component = {.name		= "s3c24xx-i2s", //這里是空的實現,因為新版本驅動把dma挪到i2s下
};2)數據傳輸dai -I2S
static struct snd_soc_dai_driver s3c24xx_i2s_dai = {.probe = s3c24xx_i2s_probe,.suspend = s3c24xx_i2s_suspend,.resume = s3c24xx_i2s_resume,.playback = {  //描述playback的能力.channels_min = 2,.channels_max = 2,.rates = S3C24XX_I2S_RATES,.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},.capture = {  //描述capture的能力.channels_min = 2,.channels_max = 2,.rates = S3C24XX_I2S_RATES,.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},.ops = &s3c24xx_i2s_dai_ops, //capture和playback對應的ops
};static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {.trigger	= s3c24xx_i2s_trigger, //啟動數據傳輸.hw_params	= s3c24xx_i2s_hw_params, //設置硬件參數.set_fmt	= s3c24xx_i2s_set_fmt,.set_clkdiv	= s3c24xx_i2s_set_clkdiv,.set_sysclk	= s3c24xx_i2s_set_sysclk,
};2、s3c24xx_i2s_hw_params設置硬件參數
static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params,struct snd_soc_dai *dai)
{struct snd_dmaengine_dai_dma_data *dma_data;dma_data = snd_soc_dai_get_dma_data(dai, substream);writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
}

3)codec

1、s3c24xx_uda134x.c對應的codec代碼位置:
android\kernel\fusion\4.19\sound\soc\codecs\uda134x.c2、codec要實現什么功能?
1)DAI接口的操作;- I2S (傳錄音數據給CPU) 誰來控制?
2)控制接口的操作;- I2C/L33、代碼介紹
codec的probe
static int uda134x_codec_probe(struct platform_device *pdev)
{1. 使用regmap來read/write寄存器,linux3.1引進的操作寄存器接口struct uda134x_priv *uda134x;uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd, &uda134x_regmap_config);2.注冊snd_soc_component_driver(soc_component_dev_uda134x - L3) 和 snd_soc_dai_driver(uda134x_dai - I2S),,掛接到snd_soc_component中去return devm_snd_soc_register_component(&pdev->dev,&soc_component_dev_uda134x, &uda134x_dai, 1);
}static const struct regmap_config uda134x_regmap_config = {.reg_bits = 8,.val_bits = 8,.max_register = UDA134X_DATA1,.reg_defaults = uda134x_reg_defaults,.num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults),.cache_type = REGCACHE_RBTREE,.reg_write = uda134x_regmap_write, //寄存器的讀寫
};2、兩類driver的實現
1)一個是dai (I2S)-數據
static struct snd_soc_dai_driver uda134x_dai = {.name = "uda134x-hifi",/* 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,
};static const 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,
};2)一個是codec(L3)-控制
為啥是放在codec里面實現?L3跟codec走,不是跟platform-CPU走,理論上應該與codec一起走
static const struct snd_soc_component_driver soc_component_dev_uda134x = {.probe			= uda134x_soc_probe,.set_bias_level		= uda134x_set_bias_level,.dapm_widgets		= uda134x_dapm_widgets,.num_dapm_widgets	= ARRAY_SIZE(uda134x_dapm_widgets),.dapm_routes		= uda134x_dapm_routes,.num_dapm_routes	= ARRAY_SIZE(uda134x_dapm_routes),.suspend_bias_off	= 1,.idle_bias_on		= 1,.use_pmdown_time	= 1,.endianness		= 1,.non_legacy_dai_naming	= 1,
};
使用DAPM/widgets/routes/kcontrol這套框架來進行控制,DAPM相關后續單獨介紹

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/911791.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/911791.shtml
英文地址,請注明出處:http://en.pswp.cn/news/911791.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

零基礎入門Java+大模型(持續更新)

0.初始一些常見的概念 AI:人工智能 大模型劃分:(本章了解一下這個就行)NLP模型-->自然語言模型(AI現在爆火的原因,就是自然語言模型這一塊取得了很大的成就)。 LLM:大語言模型…

數據庫系統總結

數據庫系統概述 數據庫系統(Database System, DBS)是用于高效管理、存儲和檢索數據的軟件系統。 數據庫系統的組成包括:數據庫、硬件、軟件、人員。 三級模式-兩級映像 內模式:管理如何存儲物理的數據,對數據的存儲…

2026-軟件工程-《軟件質量測試與保證》-期末復習—習題匯總

題量: 20 滿分: 100 作答時間:06-04 17:30至06-22 23:59 智能分析 80分 一. 單選題(共10題,50分) (單選題)白盒測試設計測試用例的依據是( )。 A. 代碼邏輯結構 B. 代碼注釋說明 C. 需求規格說明書 D. 用戶使用場景 我的答案:A:代碼邏輯結構…

量化面試綠皮書:35. 蒙蒂霍爾問題

文中內容僅限技術學習與代碼實踐參考,市場存在不確定性,技術分析需謹慎驗證,不構成任何投資建議。 35. 蒙蒂霍爾問題 蒙提霍爾問題是一個基于美國老電視節目《讓我們做個交易》的概率謎題,該問題以該節目的主持人命名。假設你現在…

如何防范 SQL 注入攻擊以及SQL 注入防范技巧

在互聯網高度發展的時代,網絡安全問題日益突出,SQL 注入攻擊成為眾多網站和應用程序面臨的嚴重威脅之一。本文將詳細介紹如何防范 SQL 注入攻擊,通過多個關鍵方面的詳細闡述,幫助開發者和網站管理者構建更安全的網絡環境&#xff…

k8s從入門到放棄之數據存儲

k8s從入門到放棄之數據存儲 在Kubernetes中,數據存儲主要通過持久卷(Persistent Volumes, PVs)和持久卷聲明(Persistent Volume Claims, PVCs)機制來實現。這種設計允許存儲與計算分離,使得容器可以根據需…

用戶體驗驅動的3D設計:從功能實現到情感共鳴的設計升級

你有沒有想過: 為什么有些產品看起來“平平無奇”,卻能贏得用戶喜愛?同樣是3D建模,為什么有些人做的模型總讓人覺得“有溫度”?設計師只是關注功能和結構就夠了嗎?還是應該讓作品“打動人心”?…

【圖床配置記錄】——pigo+gitee+typroa

記錄一下安裝的過程 基本上blog1可以解決 blog1 但是如果pigo上面沒有gitee 或者下載gitee沒啥反應 手動安裝,在c:/用戶/用戶名/AppData/Roaming/picgo這個目錄下,以管理員身份打開powershell(或cmd; 文件——以管理員打開ps——輸入npm in…

Python問題匯總(發個庫存)

常見問題: 文章目錄 IDE與1.如何注釋2.python運行代碼后沒有輸出,但無報錯,有exit code 0標志3.導入txt文件,但是出現錯誤:UnicodeDecodeError: gbk codec cant decode byte 0x80 in position 205: illegal multibyte…

Java課后習題(編程題)

第一題&#xff1a; import java.util.Scanner;class Test {public static void main(String args[]) {Scanner scnew Scanner(System.in);System.out.println("請輸入一個x值&#xff1a;");int xsc.nextInt();int y0;if(x>0){y3*x-1;}else if(x<0){y2*x-1;}e…

Spring--spring事務在什么情況下會失效,以及對應的解決方案

前言 一般失效是使用了Transaction注解的情況下&#xff0c;這篇博客就帶你詳解一下&#xff0c;哪些情況下注解會失效&#xff0c;在開發過程中要避免這些問題和可以及時發現這些問題&#xff0c;并且知道如何去規避和解決 一、Spring事務的基本原理 在深入了解事務失效的場…

在智慧教育行業中,OPS插拔式電腦啟到什么作用

在全球數字化浪潮的推動下&#xff0c;教育行業正經歷前所未有的深刻變革。目前&#xff0c;智慧校園已不再是簡單的信息化升級&#xff0c;而是涵蓋AI、云計算、大數據、物聯網等技術的系統性創新。而作為智慧教育發展的助手之一——國產OPS插拔式電腦&#xff0c;能助力傳統教…

Windows 配置 Qt 環境變量全指南

Windows 配置 Qt 環境變量全指南 適用于 Qt 5.x / 6.x, MSVC / MinGW, Qt Creator / CLion / CMake GUI 等環境 一. 為什么需要配置 Qt 環境變量 Qt 是一個跨平臺 C 開發框架&#xff0c;包含 GUI、網絡、SQL、多媒體等模塊&#xff0c;安裝后自帶豐富工具鏈&#xff0c;如&am…

SpringBoot項目快速開發框架JeecgBoot——項目簡介及系統架構!

項目簡介及系統架構 Jeecg Boot是一款基于Spring Boot的開發平臺&#xff0c;它采用前后端分離架構&#xff0c;集成的框架有Spring Boot 2.x、Spring Cloud、Ant Design of Vue、Mybatis-plus、Shiro和JWT&#xff0c;而且它支持微服務開發。Jeecg Boot還有強大的代碼生成功能…

工業設計軟件的范式革命:對象模型與五維市場驅動的未來

工業設計軟件的技術洗牌本質 破局關鍵:萬物對象模型的應用 工業設計的對象化重構 class IndustrialDesignObject:def __init__(self, obj_type, attributes):self.metadata = {"type": obj_type,"version": "1.0","entropy_rating"…

VMware 安裝Windows 虛擬機,Windows 虛擬機可 ping 通本地電腦,但本地電腦無法 ping 通虛擬機 IP 的解決思路和操作步驟

VMware 安裝Windows 虛擬機&#xff0c;Windows 虛擬機可 ping 通本地電腦&#xff0c;但本地電腦無法 ping 通虛擬機 IP 的問題如下圖所示&#xff1a; 解決辦法&#xff1a; 一、網絡連接模式與網段一致性 確認虛擬機網絡模式 若用 VMware 等軟件&#xff0c;常見模式有 NA…

高精度RTK定位導航模塊軟硬件協同設計

高精度RTK定位導航模塊軟硬件協同設計 下載鏈接:摘要1.1 RTK技術背景與發展現狀1.1.1 RTK技術原理與背景1.1.2 技術發展里程碑1.1.3 當前技術挑戰與突破1.1.4 應用場景擴展1.1.5 標準化進展1.2.1 高精度定位的計算瓶頸1.2.2 功耗優化需求1.2.3 系統可靠性與實時性保障1.2.4 典型…

【軟考高級系統架構論文】論多源數據集成及應用

論文真題 在如今信息爆炸的時代,企業、組織和個人面臨著大量的數據。這些數據來自不同的渠道和資源,包括傳感器、社交媒體、銷售記錄等,它們各自具有不同的數據格式、分布和存儲方式。因此如何收集、整理和清洗數據,以建立一個一致、完整的數據集尤為重要。多源數據集成可…

如何將這些 SQL 插入語句批量執行?

要批量執行這些SQL插入語句&#xff0c;可根據使用的數據庫管理系統(DBMS)選擇不同的方法。以下是幾種常見的批量執行方式&#xff1a; 1. 使用數據庫客戶端工具 MySQL / MariaDB 命令行&#xff1a;將所有SQL語句保存到文件(如cities.sql)&#xff0c;然后執行&#xff1a; 登…

RedisVL EmbeddingsCache深度實踐與最佳指南

一、為什么需要 EmbeddingsCache 減少重復計算 對同一段文本&#xff0c;向量化模型會每次返回相同的嵌入。借助緩存&#xff0c;首次計算后無論后續何時再請求&#xff0c;都能直接復用上次結果。 降低業務延遲 嵌入模型推理耗時&#xff08;數十毫秒到百毫秒不等&#xff09…