Raspberry Pi i2s出力とPCM1716でノイズ対策

raspbian だと標準で I2S 出力できるようになりましたが、
手元の PCM1716 を普通に繋いで MPD で再生すると
以下のケースでノイズが出てしまいます。

・再生開始時
・停止時
・シーク時
・音楽フォーマット変更時(16bit<=>24bit、44.1kHz <=> 48kHz など)

いくつか試した結果、外部クロックにしてドライバ内で設定が変わるたびに PCM1716 をミュートして0.1秒のウェイトを入れると、いい感じになりました。ヽ(´▽`)ノ
今まで出ていたポップノイズみたいなのが聞こえなくなってます。
以下、その改良内容です。

クロスコンパイルしたカーネルにRPi上でコンパイルしたドライバを組み込もうとすると、
ハングアップしちゃいます。
前はうまくいってたのになぁ~(;´д⊂)
しかたないのでRPi上でカーネル、ドライバをコンパイル!

https://github.com/raspberrypi/linux
から branch rpi-3.10.y を選択してダウンロード。

いざ、コンパイルしようとすると bc がないと言われちゃいます。
ので、
sudo apt-get install bc
でインストール。
でもってコンパイル!
5~6時間放置!!

コンパイルしたカーネル&ドライバでI2S出力できることを確認してから改良していきます。
赤文字が追加緑文字が更新です。

rpi-dac.c
53行目辺り
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
             //SND_SOC_DAIFMT_CBS_CFS,
             SND_SOC_DAIFMT_CBM_CFS,
これで外部クロックを使えるようになります。

bcm2708-i2s.c
41行目辺り
#include <linux/gpio.h>
#include <linux/delay.h>
を追加。

462行目辺り bcm2708_i2s_hw_params() 内
switch (params_channels(params)) {
case 2:
    format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format);
    format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos));
    format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos));
    break;
default:
    return -EINVAL;
}

int myerr = gpio_request_one(4, GPIOF_OUT_INIT_LOW, "MyTest");
if (myerr == 0) {
  if (sampling_rate == 48000) {
  gpio_set_value(4, 0);
  } else {
  gpio_set_value(4, 1);
  }
  gpio_free(4);
}

myerr = gpio_request_one(8, GPIOF_OUT_INIT_LOW, "MyTest");
if (myerr == 0) {
  if (data_length == 16) {
  gpio_set_value(8, 0);
  } else {
  gpio_set_value(8, 1);
  }
  gpio_free(8);
}
フォーマットに応じてPCM1716とPLL1707の設定を変更しています。
GPIO4はPLL1707のFS1 (PIN 5)、GPIO8はPCM1716のIW0 (PIN 23) に繋いでいます。
PCM1716のフォーマット選択はしなくても音鳴ってたけど、ついでなので制御するようにしました。

645行目辺り bcm2708_i2s_trigger() 内
int myerr;

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    myerr = gpio_request_one(7, GPIOF_OUT_INIT_LOW, "MyTest");
    if (myerr == 0) {
      gpio_set_value(7, 1);
      gpio_free(7);
      mdelay(100);
    }

    bcm2708_i2s_start_clock(dev);

    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
        mask = BCM2708_I2S_RXON;
    else
        mask = BCM2708_I2S_TXON;

    regmap_update_bits(dev->i2s_regmap,
            BCM2708_I2S_CS_A_REG, mask, mask);
    break;

case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    myerr = gpio_request_one(7, GPIOF_OUT_INIT_LOW, "MyTest");
    if (myerr == 0) {
      gpio_set_value(7, 0);
          gpio_free(7);
      mdelay(100);
    }

    bcm2708_i2s_stop(dev, substream, dai);
    break;
default:
    return -EINVAL;
}
停止や再開の時にPCM1716をミュートにして0.1秒ウェイトしています。
GPIO7をPCM1716のMUTE (PIN 25)に繋いでいます。

以上の修正をしたらドライバをコンパイルして組み込めばOK~

MPDクライアントでどんな操作してもポップノイズみたいなのが出なくなりました。ヽ(´▽`)ノ





0 件のコメント:

コメントを投稿