11 カーネルソースの編集
編集すべきは、以下の3つ。
(1) rpi-dac.c (snd_soc_rpi_dac)
(2) bcm2835-i2s.c (snd_soc_bcm2835_i2s)
(3) pcm1794a.c (snd_soc_pcm1794a)
(1),(2)は、
cd $bcm
dir
により、ディレクトリの一覧を見ることができる。
(3)は、
cd $codec
dir
により、ディレクトリの一覧を見ることができる。
(1)は、以下により編集可能。
nano $bcm/rpi-dac.c
「static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = {」のところ、以下のように修正。
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
//SND_SOC_DAIFMT_CBS_CFS,
SND_SOC_DAIFMT_CBM_CFS,
(「三日坊私が主ないつまでブログやれるか...( ̄~ ̄;) 」さんのラズベリーパイの分類の「Raspberry Pi i2s出力とPCM1716でノイズ対策」という記事のbcm2708-i2s.cという部分の修正を参考にした。)
これにより、外部クロックを使用できる。
(2)は、以下により編集可能。
nano $bcm/bcm2835-i2s.c
(3)は、以下により編集可能。
nano $codec/pcm1794a.c
もっとも、(3)は従前、以下を追加すべきであったが、すでに修正されている。
SNDRV_PCM_FMTBIT_S32_LE
編集すべき事項は、「ラズベリーパイDAC、I2S完全外部クロック、スレーブ入力のめどが立ちました!」の4(2)の①~④だが、③、④は最近のものはすでに反映されており、必要がない。
これらの修正により、ラズパイは32ビットのデータを受け付けるとともに、64倍fsのクロックが外部クロックからラズベリーパイへ供給されるモードとなる。LRクロック(LRの信号の伝送の開始タイミングを知らせる)がラズベリーパイから出力される。fsは、サンプリング周波数で、44.1kとか、96kとかである。pcmでは、44.1kの音声データを出力する際に、各サンプリングごとに音の大きさを定義しているから、その搬送の間に、左右(LR)32ビットずつ交互にDACへデータを送り付ける。そのタイミングは、LRクロックの立ち上がりの後、1クロック後に、32ビットのデータの送信を開始する。したがって、64倍のfsが必要になる。16ビット、24ビットの場合、32ビットに足りない分につき、後ろないし前を0で穴埋めすることになる(32ビットにフォーマット変更をする場合、16ビットの場合、32倍fsとなる)。
もっとも、外部からはどの周波数のどの系列(28.224、24.576)のクロックに乗せてよいかわからないので、ラズパイからgpioで、信号を送る。3ビット必要であり、1つは、2系列あるクロックの切り替え、1つは、周波数の切り替え。
周波数の切り替えでは、192k、96k、48kで、3通りあるとすれば、2ビット必要。
176.4k、88.2k、44.1kで、3通りあるとすれば、2ビット必要。
ここでも、「三日坊私が主ないつまでブログやれるか...( ̄~ ̄;) 」さんのラズベリーパイの分類の「Raspberry Pi i2s出力とPCM1716でノイズ対策」という記事のbcm2708-i2s.cという部分の修正が参考になる。
そこで、bcm2835-i2s.cを編集する。
nano $bcm/bcm2835-i2s.c
4行目に以下を追加。
(上記「三日坊私が主ないつまでブログやれるか...( ̄~ ̄;) 」さんの記事から引用。)
#include <linux/delay.h>
gpio.hは、カーネル領域で、gpioを操作するのに使う。
以下のファンクションを修正
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
bcm2708-i2s.cでは存在したsampling_rateは、bcm2835-i2s.cではなくなっているので、
374行を参考に、関数の2行目に、以下を追加。
そのうえで、サンプリング周波数に応じて、gpioを変える。
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);
}
if 以降がサンプリング周波数(ここでは、48k)に応じて、GPIO4を、0、1に変える処理ができるので、ほかの周波数でも定義すればよい。
GPIO13をクロック系列の切り替えに使うなら、以下の通り。
<2018.4.30 追記 ただし、以下の修正そのままでは、gpioが動作しない。。。 本記事連載のその8参照。>
if (myerr == 0) {
if (sampling_rate == 48000||sampling_rate == 96000||sampling_rate == 192000||sampling_rate == 384000) {
gpio_set_value(13, 0);
} else {
gpio_set_value(13, 1);
}
gpio_free(13);
<2018.4.22修正 検証の結果、上記をgpio4ではなく、gpio13を使うことにしたので、修正。>
GPIO5,GPIO6(GPIO6を上の桁とする)をクロック系列の切り替えに使うなら、以下の通り。
int myerr,myerr2;
myerr = gpio_request_one(13, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr == 0) {
if (sampling_rate == 48000||sampling_rate == 96000||sampling_rate == 192000||sampling_rate == 384000) {
gpio_set_value(13, 0);
}
gpio_free(13);
}
myerr = gpio_request_one(5, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr == 0) {
if (sampling_rate == 48000||sampling_rate == 44100) {
gpio_set_value(5, 1);
}
gpio_free(5);
}
myerr2 = gpio_request_one(6, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr2 == 0) {
if (sampling_rate == 48000||sampling_rate == 44100) {
gpio_set_value(6, 1);
}
gpio_free(6);
}
myerr = gpio_request_one(5, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr == 0) {
if (sampling_rate == 96000||sampling_rate == 88200) {
gpio_set_value(5, 0);
}
gpio_free(5);
}
myerr2 = gpio_request_one(6, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr2 == 0) {
if (sampling_rate == 96000||sampling_rate == 88200) {
gpio_set_value(6, 1);
}
gpio_free(6);
}
myerr = gpio_request_one(5, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr == 0) {
if (sampling_rate == 192000||sampling_rate == 176400) {
gpio_set_value(5, 1);
}
gpio_free(5);
}
myerr2 = gpio_request_one(6, GPIOF_OUT_INIT_LOW,”MyTest”);
if (myerr2 == 0) {
if (sampling_rate == 19200||sampling_rate == 176400) {
gpio_set_value(6, 0);
}
gpio_free(6);
}
myerr = gpio_request_one(5, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr == 0) {
if (sampling_rate == 384000||sampling_rate == 352800) {
gpio_set_value(5, 0);
}
gpio_free(5);
}
myerr2 = gpio_request_one(6, GPIOF_OUT_INIT_LOW, “MyTest”);
if (myerr2 == 0) {
if (sampling_rate == 384000||sampling_rate == 352800) {
gpio_set_value(6, 0);
}
gpio_free(6);
}
….
<2018.4.22 追加> ”|sampling_rate == 352800″を追加しました。
<2018.4.28 myerror2==0のところmyerror==0となっていたので、修正。>