Raspberry pi I2S PCM1716でハイレゾ再生

moraでKalafinaのハイレゾ音源(24bit、96kHz)を購入したのでRPiのI2S出力で再生してみようと思います。

PCM1716を使用するにはシステムクロックが必要になるので
Raspberry Pi I2S 出力で外部クロック使用 その2
のようにPLL1707で外部クロックを生成するのですが、当時は16bit、48kHzまでしか想定していないのと768fsを使いたかったせいで、そのままでは使えませんでした。
そんなわけでシンプルにしてみました。


PLL1707は96kHzだと384fsまでしか出せないっぽいので、システムクロックにはPLL1707のSCKO3の384fsを。
RPiの入力に必要なビットクロック64fsはSCKO2の256fsを74AC163で4分周しました。


次にI2Sドライバー側です。過去の記事とほぼ一緒ですが...
以下、GPIOのピン番号はRPi B+用になってます。

sound/soc/bcm/bcm2708-i2s.c
53行目辺り
#include <linux/gpio.h>
#include <linux/delay.h>
539行目辺り
gpio_request_one(26, GPIOF_OUT_INIT_LOW, "MyTest");
if (sampling_rate == 48000 || sampling_rate == 96000) {
  gpio_set_value(26, 0);
} else {
  gpio_set_value(26, 1);
}
gpio_free(26);

gpio_request_one(13, GPIOF_OUT_INIT_LOW, "MyTest");
if (sampling_rate == 96000) {
  gpio_set_value(13, 1);
} else {
  gpio_set_value(13, 0);
}
gpio_free(13);

gpio_request_one(16, GPIOF_OUT_INIT_LOW, "MyTest");
if (data_length == 16) {
  gpio_set_value(16, 0);
} else {
  gpio_set_value(16, 1);
}
gpio_free(16);
GPIO26をPLL1707のFS1に繋いで44.1kHzか48kHzかを設定。
GPIO13をPLL1707のSRに繋いで上記周波数を2倍にするか否かを設定。
GPIO16をPCM1716のIWOに繋いで16bitか24bitかを設定しています。

694行目辺り
struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
uint32_t mask;
int myerr;

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  myerr = gpio_request_one(12, GPIOF_OUT_INIT_LOW, "MyTest");
  if (myerr == 0) {
    gpio_set_value(12, 1);
    gpio_free(12);
    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(12, GPIOF_OUT_INIT_LOW, "MyTest");
  if (myerr == 0) {
    gpio_set_value(12, 0);
    gpio_free(12);
    mdelay(100);
  }

  bcm2708_i2s_stop(dev, substream, dai);
  break;
GPIO12をPCM1716のMUTEに繋いでます。

791行目辺り
static struct snd_soc_dai_driver bcm2708_i2s_dai = {
        .name   = "bcm2708-i2s",
        .probe  = bcm2708_i2s_dai_probe,
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
                .rates =        SNDRV_PCM_RATE_8000_192000,
                .formats =      SNDRV_PCM_FMTBIT_S16_LE
                  // : disable for now, it causes white noise with xbmc
                                | SNDRV_PCM_FMTBIT_S24_LE
                                | SNDRV_PCM_FMTBIT_S32_LE
                },
        .capture = {
                .channels_min = 2,
                .channels_max = 2,
                .rates =        SNDRV_PCM_RATE_8000_192000,
                .formats =      SNDRV_PCM_FMTBIT_S16_LE
                                | SNDRV_PCM_FMTBIT_S24_LE
                                | SNDRV_PCM_FMTBIT_S32_LE
                },
        .ops = &bcm2708_i2s_dai_ops,
        .symmetric_rates = 1
};
24bitの所がコメントアウトされていたので外しました。しかし、最新のソースコードだと元々上記のようになってますね。

sound/soc/codecs/pcm1794a.c
24行目辺り
static struct snd_soc_dai_driver pcm1794a_dai = {
        .name = "pcm1794a-hifi",
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_8000_192000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE |
                           SNDRV_PCM_FMTBIT_S24_LE |
                           SNDRV_PCM_FMTBIT_S32_LE
        },
};
一応、SNDRV_PCM_FMTBIT_S32_LEを追加。

sound/soc/bcm/rpi-dac.c
45行目辺り
static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = {
{
        .name           = "HifiBerry Mini",
        .stream_name    = "HifiBerry Mini HiFi",
        .cpu_dai_name   = "bcm2708-i2s.0",
        .codec_dai_name = "pcm1794a-hifi",
        .platform_name  = "bcm2708-i2s.0",
        .codec_name     = "pcm1794a-codec",
        .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                                //SND_SOC_DAIFMT_CBS_CFS,
                                SND_SOC_DAIFMT_CBM_CFS,
        .ops            = &snd_rpi_rpi_dac_ops,
        .init           = snd_rpi_rpi_dac_init,
},
};
外部クロックを使うように設定しています。

あとはドライバーをコンパイルして適当な場所にコピーして組み込めばOK。
sudo insmod snd-soc-bcm2708-i2s.ko
sudo insmod snd-soc-pcm1794a.ko
sudo insmod snd-soc-rpi-dac.ko

MPDで再生してみるとみごと鳴ってくれました。ヽ(´▽`)ノ




0 件のコメント:

コメントを投稿