その他
Fairphone 6の広角カメラの実験的なLinuxサポート
Fairphone 6 wide camera experimental Linux support (nondescriptpointer.com)
要約
Fairphone 6の超広角カメラがGNOME Snapshotで動作するようになったことが報告されています。これは、メインラインLinuxおよびpostmarketOSコミュニティにとって重要な進展であり、Fairphone 6の比較的新しいハードウェアと、開発を推進するFairphone社のサポートが、この成果に貢献しています。今後は、オーディオと他のカメラサポートが課題となります。
全文翻訳
Fairphone 6の超広角カメラがGNOME Snapshotで動作するようになった。
背景
Fairphone 6は、メインラインLinuxおよびpostmarketOSにとって、いくつかの理由から興味深いターゲットとなっている。
- 他の多くのpostmarketOSサポートデバイスと比較して、比較的新しいハードウェアを搭載している。
- FairphoneはメインラインLinuxサポートに投資しており、Luca Weiss氏が開発の多くを主導している。これらの取り組みは、すでにハードウェアに対する有望な初期サポートを提供している。
- Fairphoneは意図的に代替オペレーティングシステムの利用を許可している。
- Fairphoneはデバイスの長期サポートを目指しており、将来の作業のための安定した基盤を提供できる可能性がある。
デバイスを一般的に使用可能にするための主なブロッカーは、オンボードオーディオとカメラサポートの2つである。私はQRコードスキャンを必要とするプロジェクトに取り組んでおり、少なくとも1つのカメラを動作させることができるかを確認する機会としてそれを利用した。
免責事項:この作業を成功させるために、私はLLM(大規模言語モデル)の支援に大きく依存した。
Fairphone 6のカメラ
Fairphone 6には3つのカメラが搭載されている。
- リア:Sony IMX896
- フロント:Samsung S5KKD1
- ワイド:OmniVision OV13B10
SonyとSamsungのセンサーにはメインラインLinuxドライバーが存在しないが、OmniVision OV13B10にはメインラインドライバーが存在する。超広角カメラはQRコードスキャンに十分である。
電話のカメラは単一のデバイスではない。Qualcomm SoCでは、キャプチャパスはチェーンを形成する。
画像センサー → CSI-2 D-PHY → CSIPHY → CSID → ISP (VFE/TFE) → メモリ (I2C) (MIPIレーン) (デコード) (デマルチプレクサ) (ライトエンジン) (DMA)
カメラクロックコントローラー(camcc)、CCI(Qualcomm専用カメラI2Cコントローラー)、電源レール、オートフォーカス用のVCM(ボイスコイルモーター)など、いくつかのサポートコンポーネントも存在する。
下流のベンダーAndroidカーネルは、Qualcommの広範でプロプライエタリなCAMX/cam-kernelスタックを使用して、これらすべてを駆動している。メインラインでは、同等のものはより小規模なqcom-camssドライバーであり、libcameraがユーザー空間統合と画像処理を提供している。
OmniVisionカメラを動作させるためには、qcom-camssにSoC固有のブロックについて教え、デバイスツリーでハードウェアを記述し、センサードライバーを有効にし、アプリケーションが使用できる画像に生のBayerフレームを変換するようにlibcameraを設定する必要があった。
初期調査
実装を開始する前に、作業のどれだけが新規で、メインラインがすでにサポートしているハードウェアから移植できるものがどれだけあるかを把握したかった。これにより、メーカーのサポートなしでプロジェクトが実現可能かどうかを示せるはずだ。
初期調査は有望だった。
- FP6のSoCはQualcomm milos (SM7635) である。
- 下流のボードはコードネーム「volcano」であり、postmarketOSはすでにメインラインベースのカーネルフォークでこれを起動している。
- カメラハードウェアブロックはTFE665(薄型フロントエンドISP)、CSID665、およびCSIPHY v2.2.1である。
- camccクロックコントローラーとCCIはすでにカーネルフォークに存在する。
- 3つのカメラは以下の通りである。
- メイン:Sony IMX896、メインラインドライバーなし。
- 超広角:OmniVision OV13B10、ACPI/x86のみをサポートするメインラインドライバーが存在する。
- フロント:Samsung S5KKD1、メインラインドライバーなし。
これにより、ターゲットは明らかになった。OV13B10超広角カメラである。これは13MPセンサーで、既存のメインラインドライバーがあり、その広視野角はQRコードスキャンに適している。
下流のレジスタヘッダー(cam_tfe665.h、cam_csiphy_2_2_1_hwreg.h、およびcam_tfe_bus.c)をメインラインqcom-camssと比較したところ、TFE665は基本的にTFE530と同じIPであることが判明した。TFE530はメインラインですでにサポートされている。レジスタレイアウトは同一である。内部ブロックのベースオフセットのみが異なる。これは、ライトバスが異なるアドレスに存在するためである。同様に、CSID665 RDIレジスタはサポートされているCSIDと一致し、CSIPHY v2.2.1は同じ3相PHYファミリーに属する。
これは、すべてをゼロから書くのではなく、既存のドライバーを移植できることを意味した。
ステップ1:キャプチャサブシステムをカーネルに移植する
qcom-camssはまだmilosで利用可能ではなかったため、既存のコンポーネントを接続する必要があった。
TFE665 ISPドライバー
メインラインのTFE530ドライバー(camss-vfe-340.c)に直接基づいて、新しいcamss-vfe-665.cを追加した。レジスタの内容は同一であるため、ドライバーロジックは同じである。主な違いは、milosがISP制御ブロックとライトバスブロックを異なるオフセットに配置していることである。バスレジスタのベースが0xa00から0x1800に移動し、そのオフセットシフトをカプセル化することが作業の大部分を占めた。
CSID665およびCSIPHY v2.2.1
CSID665は、そのRDIレジスタオフセットが同一であったため、既存のgen-2 CSID操作を再利用した。CSIPHY v2.2.1は、このリビジョン用に新しいレーン構成テーブルとD-PHYチューニング値が必要だった。下流のcam_csiphy_2_2_1_hwreg.hからレーンレジスタシーケンスと約1.1 Gbps/レーン(「500 Msps」)のデータレートおよびAFE設定を転記した。PHYのレジスタウィンドウはオフセット0x1000にあった。
リソース、互換性、およびデバイスツリー
camss.cで、milosのキャプチャコンプレックスを記述した。4つのCSIPHY、3つのCSID、3つのTFE、それらのクロック、相互接続、および電源ドメインである。また、新しいqcom,milos-camss互換性を登録した。
デバイスツリーでは、camss@ac13000ノードにレジスタ、IRQ、クロック、相互接続、IOMMU、GDSC、およびCSI入力ポートを追加した。MCLKとリセットのピンコンフィギュレーション状態も設定した。
欠落していたレジスタバスクロック
この時点で問題に遭遇した。ドライバーはバインドされたが、TFEハードウェアバージョンレジスタの読み取りは0x0を返し、ブロックに電源が入っていないかのようにリセットがタイムアウトした。修正は、ISPクロックとして明白ではなかったクロック、CAM_CC_SOC_AHB_CLKであった。これは、カメラコンプレックス全体(CCIを含む)が使用するAHBレジスタバスをゲートしていた。これがなければ、レジスタアクセスはサイレントにゼロを返していた。
このクロックとCAMNOC AXIクロックを追加し、CAMNOCデータパスクロックレートを設定した。ISPはhw_version = 0x30000000で起動した。これは、Qualcommハードウェアでは、ゼロと読み取られるブロックが、そのアクセスパス上のクロックまたは電源ドメインを欠いている可能性があることを示唆している。
ステップ2:OV13B10センサーの起動
メインラインのov13b10ドライバーは存在するが、x86/ACPIラップトップ用に書かれており、ACPI経由でのみ一致する。2つの箇所を変更した。
ドライバーをARMおよびデバイスツリーで利用可能にする
ドライバーがデバイスツリーからプローブできるように、OpenFirmware互換性テーブル(ovti,ov13b10)を追加した。milos-fairphone-fp6.dtsでセンサーを記述した。それはCCI I2Cバス上のアドレス0x36にあり、MCLK1(19.2 MHz)、リセットGPIO、および電源レールを必要とする。この実験的な起動のために、レギュレーターを完全にシーケンスする代わりに、単純にオンにした。
2つの小さな詳細
レーン番号付け。
下流のデバイスツリーはdata-lanes = <1 2 3 4>を使用していたが、メインラインの規約はゼロベースの<0 1 2 3>である。誤った番号付けにより、CSIPHYはレーン0が欠落したレーンマスクをプログラムし、PHYは決してロックしなかった。
どのCSIPHYか?
FP6の配線は、超広角カメラをCSIPHY1にルーティングしていた。これを推測するのではなく、下流のデバイスツリーから取得したことで、多くの試行錯誤が節約された。
この時点で、センサーは正常にプローブされ、チップIDはI2C経由で正しく読み取られ、CSIPHYはレーンアクティビティを報告し、ISPは完全に黒いフレームを生成した。
ステップ3:すべてのピクセルがゼロのフレームの謎
これが主なバグだった。フレームは適切なレートとサイズで到着し、buf_doneは発火したが、すべてのピクセルがゼロだった。これは、センサーの内部カラーバーテストパターンを有効にした場合でも同様だった。このパターンはセンサー内部で生成されるはずであり、シーンに関係なく表示されるべきだった。データパスはフレームタイミングを配信したが、ピクセルデータは配信しなかった。
カーネルログが手がかりを提供した。「VFE0: Bad config violation」。ISPのライトエンジンは、ライトマスターの設定が入ってくるデータと一致しなかったため、フレームごとにコンシューマー/コンフィギュレーション違反を報告した。
下流のcam_tfe_bus.cを詳しく調べると、違いが明らかになった。RDIライトマスターのパッカーフォーマットは、ISPバス幅に依存する。
- TFE530(メインラインドライバーのターゲットであるqcm2290)は64ビットRDIバスを持つため、パッカー0xaを使用する。
- TFE665(milos)は128ビットRDIバスを持つため、パッカー0x0が必要である。
メインラインドライバーは64ビット値をハードコードしていた。milosではそれは間違っており、ライトエンジンはピクセルを書き込むことを拒否した。レジスタ値をPLAIN64 (0xa) から 0x0に変更したことで、すべてのピクセルがゼロのフレームが、再...