Armadilloフォーラム

CEUとV4L2について

kes-konishi

2016年11月25日 13時34分

KES)小西です。

ソース及び動作から追いかけ切れない部分があったので、質問させていただきます。

800系(R-MobileA1)では映像の入力はCEUで実施していると思いますが、
810等の拡張ボードの場合はSOCカメラ(OV7725)が動作し、
この場合、
V4L2
├──────────────────┐
SOC_CAMERA         sh_mobile_ceu_camera
OV7725

の構成で動作すると思います。
ここで疑問なのは
soc_camera.cのsoc_camera_readが標準のものから処理が消されています。
このため、v4l2-dev.cのv4l2_readからfops経由でコールされた場合
エラーになると思いますが、810では動作していると思います。
これはreadのオペレーションがshのDMA転送によって行われているとすると、
V4L2に対して何か申告を行っているのかな?と思いますが、
board-armadillo840.cやboard-armadillo810.cでも特に実装されているようには見えませんでした。

CEUドライバ(sh_mobile_ceu_camera.c)内でV4L2に対して申告している部分も
なさそうでした。

本題ですが、
CEUドライバを使用してv4L2とリンクする場合、V4L2へのREAD登録等はどこを参考にすればよいでしょうか?

コメント

kes-konishi

2016年11月25日 16時02分

KES)小西です。

追記で質問です。
sh_mobile_ceu_camera.c
はconfig上での
SOC_CAMERAとの接続のみで、
VIDEO_CAPTUREは対応していない仕様であっていますでしょうか?
例.
 container_ofでsoc_camera_deviceを検索とかしてますので。。。

at_kojiro.yamada

2016年11月25日 18時44分

> ここで疑問なのは
> soc_camera.cのsoc_camera_readが標準のものから処理が消されています。
> このため、v4l2-dev.cのv4l2_readからfops経由でコールされた場合
> エラーになると思いますが、810では動作していると思います。
> これはreadのオペレーションがshのDMA転送によって行われているとすると、
> V4L2に対して何か申告を行っているのかな?と思いますが、
> board-armadillo840.cやboard-armadillo810.cでも特に実装されているようには見えませんでした。

V4L2では、IOCTLを使って画像の読み書きをするので、
見るべきは .read ではなく、
.unlocked_ioctl です。

soc_camera.cの static struct v4l2_file_operations soc_camera_fopsを見ると

    .unlocked_ioctl    = video_ioctl2,

となっており、video_ioctl2() 関数は v4l2-ioctl.c で実装されています。

video_ioctl2() -> __video_do_ioctl()
とコールされ、そこからは例えば、VIDIOC_S_FMTの場合は、
v4l2_ioctl_ops を経由で soc_camera.c の soc_camera_ioctl_ops.vidioc_s_fmt_vid_cap() がコールされ・・・
という流れになります。

以上、参考になれば幸いです。

kes-konishi

2016年11月28日 8時42分

KES)小西です。

ご回答ありがとうございます。

> soc_camera.cの static struct v4l2_file_operations soc_camera_fopsを見ると
>

>     .unlocked_ioctl    = video_ioctl2,
> 

> となっており、video_ioctl2() 関数は v4l2-ioctl.c で実装されています。
>
> video_ioctl2() -> __video_do_ioctl()
> とコールされ、そこからは例えば、VIDIOC_S_FMTの場合は、
> v4l2_ioctl_ops を経由で soc_camera.c の soc_camera_ioctl_ops.vidioc_s_fmt_vid_cap() がコールされ・・・
> という流れになります。
ありがとうございます。
理解しました。

/dev/video0等を直接CATした場合はエラーになる点も論拠が通りました。
つまり、SOCビデオを入力として使用する場合はgstreamer経由または、
自前でv4l2経由のioctlで読み込みですね。

キャプチャドライバをSOC_CAMERA化しないといけませんが。。。

kes-konishi

2016年11月28日 14時13分

KES)小西です。

補足ありがとうございます。

ターゲットはキャプチャチップなので、
V4L2はread/write対応していますが、soc_camera.cのsoc_camera_readが標準からアットマークディストでは削除されていますので、
このルートを戻すと、こんどはDMA転送系が不一致おきます。
このため、V4L2→SOC_CAMERA間ではread/writeのルートを使用しないのが得策で、
キャプチャドライバをSOCカメラ化するのが、最短かと考えました。

at_yashi

2016年11月28日 14時29分

> ターゲットはキャプチャチップなので、
> V4L2はread/write対応していますが、soc_camera.cのsoc_camera_readが標準からアットマークディストでは削除されていますので、
> このルートを戻すと、こんどはDMA転送系が不一致おきます。

削除されているとは、どういう意味でしょう?
soc_came.cの 626行目に関数はありますよ?

ただ、この関数を使っても EINVALになるので自前で同じシグネチャの関数を作成する必要があります。

> このため、V4L2→SOC_CAMERA間ではread/writeのルートを使用しないのが得策で、
> キャプチャドライバをSOCカメラ化するのが、最短かと考えました。

結論的には、SoCカメラのフレームワークを使った方がコード量は減ると思います。
CEUのドライバーも SoCカメラフレームワークを使うように作られていますし。

私が、「DMA転送系の不一致」を理解できていないのかも?

CEUは、あるクロックでデーターラインをラッチして、指定されたメモリに書き込みます。

CPU側(というか、v4l2側というか、カーネル側というか...)は、書き込まれたデータを
ioctl()経由か read()経由で、アプリに渡すだけです。この時 CEUは CPUの都合を
知らないので、データーを書き込む為の十分なバッファーを与える必要があります。

kes-konishi

2016年11月28日 14時50分

KES)小西です。

> > ターゲットはキャプチャチップなので、
> > V4L2はread/write対応していますが、soc_camera.cのsoc_camera_readが標準からアットマークディストでは削除されていますので、
> > このルートを戻すと、こんどはDMA転送系が不一致おきます。
>
> ?
>
> 削除されているとは、どういう意味でしょう?
> soc_came.cの 626行目に関数はありますよ?
>
> ただ、この関数を使っても EINVALになるので自前で同じシグネチャの関数を作成する必要があります。
はぃ、あっています。
関数はあり、ステーブルでは処理があります。
この中に元のカーネルソースのドライバでは

    if (ici->ops->init_videobuf2 && icd->vb2_vidq.io_modes & VB2_READ)
        return vb2_read(&icd->vb2_vidq, buf, count, ppos,
                                    file->f_flags & O_NONBLOCK);

があり、この場合VB2_readが呼ばれてしまうかと思った次第です。

この場合VideoBuffer2のvb2_readがCEUのDMA転送結果の取得ができていないようでした。
下記の「DMA転送系の不一致」はこの部分を指していました。
ハードウェア的なDMA転送は動作しているため、ioctlで画像読み込みが出来ていると思います。

> > このため、V4L2→SOC_CAMERA間ではread/writeのルートを使用しないのが得策で、
> > キャプチャドライバをSOCカメラ化するのが、最短かと考えました。
>
> 結論的には、SoCカメラのフレームワークを使った方がコード量は減ると思います。
> CEUのドライバーも SoCカメラフレームワークを使うように作られていますし。
>
> 私が、「DMA転送系の不一致」を理解できていないのかも?
>
> CEUは、あるクロックでデーターラインをラッチして、指定されたメモリに書き込みます。
>
> CPU側(というか、v4l2側というか、カーネル側というか...)は、書き込まれたデータを
> ioctl()経由か read()経由で、アプリに渡すだけです。この時 CEUは CPUの都合を
> 知らないので、データーを書き込む為の十分なバッファーを与える必要があります。

追伸.
 と書いている間に vb2_readが直前の分岐で弾かれて呼ばれていないことがわかりました。。。すみません。

 キャプチャチップからgstreamer経由で動画は取れました。
 まだバスサイズが合っていないため、画像が横に伸びちゃいましたが。。。