Kernel-Modules

ALSA/ASoC:如何正確載入設備/驅動程序?

  • January 30, 2013

我正在使用 Buildroot 為 NXP LPC3250 微控制器建構嵌入式 Linux (2.6.39.2) 系統。

現在,我正在嘗試啟動並執行 ALSA/ASoC,但在讓模組協同工作方面遇到了一些問題。(我認為!)

一些重要的背景:

我正在測試的開發板是Embedded Artists 3250 V2 開發板。V2 與 V1 的不同之處在於它沒有 LCD 螢幕,但包含I2S 音頻編解碼器:NXP UDA1380。對 EA3250 V1的板級支持包含在核心的LPCLinux版本中。還有一個不同的開發板,稱為Phytec 3250,它包含相同的 UDA1380 編解碼器晶片。LPCLinux 發行版還支持 Phytec 板以及音頻編解碼器晶片。據我所知,Phytec 3250 板在 I2C 地址0x18上有 UDA1380 編解碼器。在我的 EA3250 V2 板上,音頻編解碼器位於 I2C 地址0x1a(我已驗證晶片已通電,並且可以使用 I2C-tools 包與其通信。它響應 i2cdetect,我可以使用 i2cget 從晶片中正確讀取寄存器。)

修改源碼:

我需要編輯 Phytec 3250 驅動程序文件來更改編解碼器晶片的地址。我編輯了lpc3xxx-uda1380.c的這一部分:

static struct snd_soc_dai_link phy3250_uda1380_dai[] = {
      {
                 .name           = "uda1380",
                 .stream_name    = "UDA1380 Duplex",
 #if defined(CONFIG_SND_LPC32XX_USEI2S1)
                 .cpu_dai_name   = "lpc3xxx-i2s1",
 #else
                 .cpu_dai_name   = "lpc3xxx-i2s0",
 #endif
                 .codec_dai_name = "uda1380-hifi",
                 .init           = phy3250_uda1380_init,
                 .platform_name  = "lpc3xxx-audio.0",
        //EDIT// .codec_name     = "uda1380-codec.0-0018",  //EDIT//
                 .codec_name     = "uda1380-codec.0-001a",
                 .ops            = &phy3250_uda1380_ops,
         },
 };

進行此更改後,我繼續重新建構系統,一切編譯正常。啟動到系統後,我有以下模組(除了標準核心模組)/lib/modules/2.6.39.2/kernel/sound

./soc/codecs: snd-soc-uda1380.ko          <-- ASoC codec driver
./soc/lpc3xxx: snd-soc-lpc3xxx-i2s.ko      <-- ASoC DAI
              snd-soc-lpc3xxx-uda1380.ko  <-- ASoC machine driver
              snd-soc-lpc3xxx.ko          <-- ASoC platform driver

現在,我如何真正將所有這些東西綁定在一起?

僅插入模組modprobe實際上並不會將設備提供給 ALSA/ASoC。我無法檢測到音效卡。這是否意味著我現在必須uda1380-codec在地址0x1a處創建一個新設備並將其綁定到驅動程序?我嘗試執行以下操作:

echo uda1380-codec 0x01a > /sys/bus/i2c/devices/i2c-0/new_device

並收到:

i2c i2c-0: new_device: Instantiated device uda1380-codec at 0x1a

然後我嘗試將驅動程序綁定到設備:

echo 0x1a > /sys/bus/i2c/drivers/uda1380-codec/bind

並收到:

sh: write error: No such device

我嘗試的所有操作都收到此錯誤!我感覺我沒有正確創建設備,然後我不確定如何將它綁定到正確的驅動程序。

請注意:

昨晚我在玩這個,不知何故能夠讓 ASoC 醒來並至少探測卡。我猜我在玩不同的綁定。記住我的步驟已經很晚了,但我至少能夠以某種方式得到以下錯誤:

uda1380-codec 0-001a: asoc: failed to probe CODEC uda1380-codec.0-001a: -22
asoc: failed to instantiate card LPC32XX: -22

我一直無法重現此錯誤!

編輯:

我已經確認我的修改程式碼正在編譯,所以驅動程序現在應該與正確的地址通信。手動載入模組後,輸出lsmod為:

Module                      Size  Used by    Not tainted
snd_soc_lpc3xxx_uda1380     2087  0 
snd_soc_lpc3xxx             3089  0 
snd_soc_lpc3xxx_i2s         4089  1 
snd_soc_uda1380            10865  0 
snd_soc_core               51549  4 snd_soc_lpc3xxx_uda1380,snd_soc_lpc3xxx,snd_soc_lpc3xxx_i2s,snd_soc_uda1380
snd_pcm                    52098  2 snd_soc_lpc3xxx,snd_soc_core
snd_timer                  15590  1 snd_pcm
snd_page_alloc              3021  1 snd_pcm
snd                        37286  3 snd_soc_core,snd_pcm,snd_timer

這看起來對嗎?

還有我的設備表:

# Audio stuff
/dev/audio      c       666     0       29      14      4       -       -       -
#/dev/audio1    c       666     0       29      14      20      -       -       -
/dev/dsp        c       666     0       29      14      3       -       -       -
#/dev/dsp1      c       666     0       29      14      19      -       -       -
#/dev/sndstat   c       666     0       29      14      6       -       -       -
/dev/mixer      c       666     0       29      14      0       -       -       -
/dev/snd        d       755     0       29      -       -       -       -       -
/dev/snd/controlC0      c       666     0       29      116     0       -       -       -
/dev/snd/pcmC0D0c       c       666     0       29      116     24      -       -       -
/dev/snd/pcmC0D0p       c       666     0       29      116     16      -       -       -
/dev/snd/seq    c       666     0       29      116     1       -       -       -
/dev/snd/timer  c       666     0       29      116     33      -       -       -

需要編輯定義平台設備的電路板文件。我需要修改arch/arm/mach-lpc32xx/ea3250.c

添加這個:

/*
* Platform Data for UDA1380 Audiocodec.
* As there are no GPIOs for codec power & reset pins,
* dummy GPIO numbers are used.
*/
static struct uda1380_platform_data uda1380_info = {
   .gpio_power = LPC32XX_GPIO(LPC32XX_GPO_P3_GRP,10),
   .gpio_reset = LPC32XX_GPIO(LPC32XX_GPO_P3_GRP,2),
   .dac_clk    = UDA1380_DAC_CLK_WSPLL,
};

編輯它以包含編解碼器:

static struct i2c_board_info __initdata ea3250_i2c_board_info [] = {
       {   I2C_BOARD_INFO("uda1380", 0x1a),
           .platform_data = &uda1380_info,
       }, 
#if defined (CONFIG_LEDS_PCA9532)
       {
           I2C_BOARD_INFO("pca9532", I2C_PCA9532_ADDR),
           .platform_data = &ea3250_leds,
       },
#endif
#if defined (CONFIG_FB_ARMCLCD)
       {
           /* 8Kb Configuration EEPROM on display board */
           I2C_BOARD_INFO("ea_i2c_disp_cfg", LCDB_CONFIG_EEPROM_I2C_ADDR),
       },
       {
           I2C_BOARD_INFO("ea_i2c_video", LCDB_PCA9532_I2C_ADDR),
       },
#endif
#if defined (CONFIG_EEPROM_AT24)
       {
           I2C_BOARD_INFO("24c256", I2C_24LC256_ADDR),
       },
#endif
   };
#endif

現在我擁有了所有設備:

# cat cards
0 [LPC32XX        ]:  - LPC32XX
                     LPC32XX
# cat devices
 2: [ 0- 0]: digital audio playback
 3: [ 0- 0]: digital audio capture
 4: [ 0]   : control
33:        : timer

# cat pcm
00-00: UDA1380 Duplex uda1380-hifi-0 :  : playback 1 : capture 1

雖然我還無法aplay檢測到任何東西,但也許這是一個不同的問題。

編輯:是的,這是一個不同的問題。顯示的設備前面的編號cat devices應與 /dev/snd 設備條目中的次要設備編號匹配。現在 ALSA 端的一切似乎都很好,但我沒有來自 LPC3250 的 I2S 數據……

EDIT2:已解決已解決。如果沒有 I2S 數據/時鐘,請確保正確配置輸出多路復用器寄存器以將輸出引腳連接到 I2S 外設!!!

引用自:https://unix.stackexchange.com/questions/59497