RK 3288+ADAU 1977接続


既存のワークピース(RK 3399のマザーボードを使用)のオーディオチップセットが正常に動作しないようで、デバッグプロセスが必要で、テストボードを作成する必要があります.
ニードルマップと互換性のあるボードがあり、よくテストできると思っていたので、Tinkerボードを使用しました.

ほとんどのチップセットは、データテーブルの名前にかかわらず、回路図を提供しています.
回路は大体以下の通りです.

用意する。


Tinkerボード回路の点検


接続リンク DownloadプロジェクトのScheticsをダウンロードすればよい.
ボード上の40ピンのヘッダーからメインAPにアクセスできます.

ADAU 1977は、I 2 Cによって制御可能なADCである.
制御はI 2 C、データはI 2 Sです.
PIN名を覚えてデータテーブルを見ればいいです

RK 3288データテーブルの検証




I 2 Sシーケンスクロック(SCLK)LRクロック(RCK RX/TX)シーケンスデータ(SDI/O)などが確認できます.

やるべきこと


RK 3288は、ADAU 1977からデータを取得する必要があることを示す.
  • ADAU 1977のSDATAUTは、RK 3288のi2s_sdiに接続する必要があります.
  • ADAU 1977のBCL K線は、RK 3288のi2s_sclkに接続されている必要があります.
  • RK 3288受信データは、Masterとして動作する必要があります.
    ADAU 1977のLLRCL K線は、RK 3288のi2s_lrclkrxに接続されている.
    DirectionはOutputのはずです.
  • AD11 - i2s_sclk - I2S_SCLK_GPIO6_A0
  • AG11 - i2s_lrckrx - I2S_LRCK_RX/GPIO6_A1
  • AE11 - i2s_sdi - I2S_SDI/GPIO6_A3
  • I 2 Cは、制御のためにSDA、SCLを接続する

    せつぞく

  • I 2 S SCLK GPIO 6 A 0はGP 6 A 0 PCM CLK Rで、マザーボードの12番ピンに接続されています.
  • I 2 S LLCK RX/GPIO 6 A 1はGP 6 A 1 PCM FSであり、マザーボードの37番ピンに接続されている.
  • I 2 S SDI/GPIO 6 A 3 PCM SD、マザーボードの38番ピンに接続します.
  • SDA/SCLはI 2 C 1に接続されている.
  • カーネル設定の変更


    デバイスを追加する操作なので、デバイスツリーを変更する必要があります.
    作業中、Rockchip linux kernelにはadau 1977の関連ソースコードがありません.
    そこで、Raspberry piのカーネルソースコードを持ってきました.
    リンクのadau 1977-adc.cをsound/soc/rockchipにコピーします.

    構築準備


    Kconfigの変更

    config SND_SOC_ADAU1977_ADC  
         tristate "Support for ADAU1977 ADC"  
         depends on SND_SOC_ROCKCHIP_I2S  
         select SND_SOC_ADAU1977_I2S  
         help  
             Say Y or M if you want to add support for ADAU1977 ADC.

    Makefileの変更

    snd-soc-adau1977-adc-objs := adau1977-adc.o
     obj-$(CONFIG_SND_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o

    デバイスドライバの準備


    リンクのadau 1977-adc-overlay.dtsをarch/arm/boot/dts/overlaysにコピーします.

    dtsの変更

    // Definitions for ADAU1977 ADC  
    /dts-v1/;  
    /plugin/;  
    / {   
        compatible = "brcm,bcm2708";   
     
        fragment@0 {
              target = <&i2c1>;
     
            __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;
            status = "okay";
            
                adau1977: codec@11 {
                    compatible = "adi,adau1977";
                    reg = <0x11>;
                    reset-gpios = <&gpio 5 0>;
                    AVDD-supply = <&vdd_3v3_reg>;
                };
            };
        };
     
        fragment@1 {
            target = <&i2s>;
            __overlay__ {
                status = "okay";
            };
        };
        
        fragment@2 {
            target = <&sound>;
            __overlay__ {
                compatible = "adi,adau1977-adc";
                i2s-controller = <&i2s>;
                status = "okay";
            };
        };
    };
    Overlayが登録して使用する場合、デバイスをキャプチャできないという問題があります.
    rk3288-miniarm.クリップをdtsに直接追加することをお勧めします.(操作確認)
    次にdefconfigを適用しmake menuconfigを実行してADAU 1977を有効にします


    config設定が完了すると、構築後のカーネルインストールパスでイメージ、モジュール、およびデバイスに関連するファイルを上書きできます.

    デバイス接続の検証



    回路基板が起動すると、ドライバがオンラインになると、デバイスがキャプチャされているのが見えます.
    ただし、初期化操作は行われていません.ドライバコードを変更する必要があります.

    ドライバコードの変更


    アナログデバイスが提供するリソースを参照して改訂した.linux/sound/soc/bcm/adau1977-adc.cファイルを修正すると、linux/sound/soc/rockchipディレクトリに入れなければなりません.
    static int eval_adau1977_init(struct snd_soc_pcm_runtime *rtd)
    {
        int ret;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        
        // I2S
        // ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 0);
        
        // TDM
        ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0x0f, 8, 16);
     
        if (ret < 0)
            return ret;
     
        // I2S
        // return snd_soc_codec_set_sysclk(rtd->codec, ADAU1977_SYSCLK,
        //        ADAU1977_SYSCLK_SRC_LRCLK, 1228000, SND_SOC_CLOCK_IN);
     
        // TDM
        return snd_soc_codec_set_sysclk(rtd->codec, ADAU1977_SYSCLK,
                ADAU1977_SYSCLK_SRC_LRCLK, 1228000, SND_SOC_CLOCK_IN);
    }
    以上のように変更して使用できます.

    後で必要とされるのを恐れて記録した部分。


    選択モード(I 2 S/TDM)


    I 2 S/TDMモードにより、渡すパラメータが異なります
    int snd_soc_dai_set_tdm_slot(
    	struct snd_soc_dai * dai**,
    	unsigned int** tx_mask**,
    	unsigned int** rx_mask**,
    	int** slots**,
    	int** slot_width**
    );
    
    リンクを参照すると、TDMモードは以下のようになる.
    ret = snd_soc_dai_set_tdm_slot(
    	snd_soc_dai = codec_dai,
    	tx_mask = 0x00, // 0000 0000 중 선택된 비트에 순서대로 채널을 할당한다.
    	rx_mask = 0x0f, // 0000 0000 중 선택된 비트에 순서대로 채널을 할당한다.
      slots = 4, // 슬롯 수이며 채널을 얼만큼 전송할 것인지 의미한다.
      slot_width = 32 // 슬롯당 데이터 길이를 의미한다.
    );
    上記の例は[0,1,2,3]スロット割り当て[1,2,3,4]チャネルである.
    つまり、各スロットのデータ長を32ビットに設定します.
    static struct snd_soc_dai_link snd_rpi_adau1977_dai[] = {
        {
        .name = "adau1977",
        .stream_name = "ADAU1977", 
        .cpu_dai_name = "bcm2708-i2s.0", 
        .codec_dai_name = "adau1977-hifi",
        .platform_name = "bcm2708-i2s.0",
        .codec_name = "adau1977.1-0011",
        .init = eval_adau1977_init,
     
        /* I2S
        .dai_fmt = SND_SOC_DAIFMT_I2S |
            SND_SOC_DAIFMT_NB_NF |
            SND_SOC_DAIFMT_CBM_CFM,
        },
        */
        
        // TDM
        .dai_fmt = SND_SOC_DAIFMT_DSP_B |
            SND_SOC_DAIFMT_NB_NF |
            SND_SOC_DAIFMT_CBS_CFS,
        },
    };
    ここで変更した部分は上記の部分と関係があります.
    設定はI 2 SかTDMかによります.dai_fmtは、ADAU 1977のデジタルオーディオインタフェースフォーマットをどのように設定および使用するかを変更するデジタルオーディオインタフェースフォーマットを表す.
    必要な定数を設定するには、次の手順に従います.
    定義はadau1979.cにあり、ADAU 1977の基本的な動作原理を体現している.

    定数関連コンテンツ

  • SND_SOC_DAIFMT_I2S
  • SND_SOC_DAIFMT_NB_NF
  • SND_SOC_DAIFMT_CBM_CFM
  • 上記の3つの定数を使用
    static int adau1977_set_dai_fmt(
    	struct snd_soc_dai *dai,
    	unsigned int fmt
    )
    上記の関数の動作原理を検証できます.

    SND_SOC_DAIFMT_I2S

    switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
            ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
            break;
        case SND_SOC_DAIFMT_LEFT_J:
            ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
            invert_lrclk = !invert_lrclk;
            break;
        case SND_SOC_DAIFMT_RIGHT_J:
            ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT;
            adau1977->right_j = true;
            invert_lrclk = !invert_lrclk;
            break;
        case SND_SOC_DAIFMT_DSP_A:
            ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
            ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S;
            invert_lrclk = false;
            break;
        case SND_SOC_DAIFMT_DSP_B:
            ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE;
            ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ;
            invert_lrclk = false;
            break;
        default:
            return -EINVAL;
    }
  • I2S
  • LEFT_J
  • RIGHT_J
  • DSP_A
  • DSP_B
  • SND_SOC_DAIFMT_NB_NF

    switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    case SND_SOC_DAIFMT_NB_NF:
        invert_lrclk = false;
        break;
    case SND_SOC_DAIFMT_IB_NF:
        block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
        invert_lrclk = false;
        break;
    case SND_SOC_DAIFMT_NB_IF:
        invert_lrclk = true;
        break;
    case SND_SOC_DAIFMT_IB_IF:
        block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE;
        invert_lrclk = true;
        break;
    default:
        return -EINVAL;
    }
  • NB_NF
  • IB_NF
  • NB_IF
  • IB_IF
  • ここで注意すべき部分は#define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6).
    IBの場合はblock Powerの6位を設定します.

    これは、インバータlrclkとblockパワーを設定する部分のようです.
    Bit/LR ClockのPolarityを変更した部分ですが、特に理由はないので変更する必要はありません.

    SND_SOC_DAIFMT_CBM_CFM

    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
            adau1977->master = false;
            break;
        case SND_SOC_DAIFMT_CBM_CFM:
            ctrl1 |= ADAU1977_SAI_CTRL1_MASTER;
            adau1977->master = true;
            break;
        default:
            return -EINVAL;
    }
    これまでadau1977-adc.cで動作主体がMasterかSlaveかの設定部分であることが確認されていた.
    (slaveと仮定し、使用状況が異なるため)
    CBS CFS、CBM CFMの2種類が利用可能です.
    アクションボディがslaveの場合、ファイルフォーマットもslaveに一致する必要があります.
    従ってslaveとしてSND SOC DAIFMT CBS CFSを用いる.
    同様に、データテーブルにも対応する内容があります.