Plattformreferenz: Hersteller V2.0.0, RK3399, RK3326/PX30, RK3288, RK312x/PX3SE, RK180x; Linux 4.4. Die vollständigen Kapitel behandeln Kameratreiber, Sensoranbindung, Erfassung und Fehlersuche. Konkrete ArmSoM-Board/BSP/SDK/Kernel-Kombinationen sind nicht validiert; Schaltplan, Schnittstellen, Versorgung/Takte, Treiber und IQ-Dateien prüfen. Beispiele/Messwerte stammen vom Hersteller, nicht von ArmSoM; keine Hardwarebefehle ausgeführt. ZH nutzt chinesische Originalbilder, EN/RU/DE englische.
Technisches Vorwort: ISP/CIF-Struktur, Sensorentwicklung/-portierung, übergeordnete Fehlersuche, Anwendungs-APIs und 3A. Treiber orientieren sich an V4L2 und bieten Portierungs-/Anwendungsschnittstellen; Kenntnisse der V4L2-Werkzeuge und Konzepte werden vorausgesetzt.
| SoC | Kernel | ISP | CIF |
|---|---|---|---|
| RK3399 | 4.4 | 2 | — |
| RK3326/PX30 | 4.4 | 1 | 1 |
| RK3288 | 4.4 | 1 | 1 |
| RK312x/PX3SE | 4.4 | — | 1 |
| RK180x | 4.4 | 1 | 1 |
1. Versionen und Begriffe
1.1 Begriffe
3A: Autofokus AF, automatische Belichtung AE und Weißabgleich AWB beziehungsweise algorithms.so.
Async Sub Device: asynchrones V4L2-Untergerät im Media Controller, etwa Sensor/MIPI DPHY. Bayer Raw/Raw Bayer: RGGB-, BGGR-, GBRG-, GRBG-Frames von Sensor/ISP. Buildroot: darauf basierende Rockchip-Linux-SDKs. Camera: Gesamtsystem aus VIP/ISP, Sensor und Treibern. CIF: VIP-Modul zum Empfang in den Speicher, ohne ISP-Verarbeitung. DVP: paralleler Digital Video Port. Entity: Media-Controller-Knoten. FCC/FourCC: vier Zeichen zur Formatbeschreibung im Kernel, siehe FourCC-Abschnitt. HSYNC: DVP-Zeilensynchronisation. ISP: Image Signal Processing, Bildempfang/-verarbeitung einschließlich Hardware und Treiber. IOMMU: Input-Output Memory Management Unit; bildet verstreute physische Speicherseiten auf zusammenhängende CIF-/ISP-Adressen ab, einschließlich Hardware/Treiber. Englisch schreibt hier iohmu. IQ: Image Quality, abgestimmte Bayer-Raw-XML für 3A. Media Controller: Kernel-Medienframework zur Topologieverwaltung. MIPI: MIPI-Protokoll. MIPI-DPHY: D-PHY-Protokoll oder entsprechender Rockchip-Controller. MP: Main Path, ISP-Ausgang voller Auflösung für Fotos und RAW. PCLK: Sensor-Pixeltakt. Pipeline: Kette verbundener Entities. RKCIF: CIF-Treibername. RKISP1: ISP-Treibername.
SP: Self Path, ISP-Ausgang bis 1080p. Userspace: Linux-Benutzerraum gegenüber Kernelraum. V4L2: Video4Linux2, Kernel-Videosystem. VIP: Video Input Processor, früher auch Bezeichnung für CIF. VSYNC: DVP-Bildsynchronisation.
1.2 Historische ISP-/CIF-Treiber
RKISP1/RKCIF basieren auf Media Controller, V4L2 Framework und VB2; Sensoren werden asynchron als Sub Devices registriert. Code unter drivers/media/platform/rockchip/isp1/ und drivers/media/platform/rockchip/cif/, Sensoren unter drivers/media/i2c. Ältere Versionen werden nicht mehr regelmäßig aktualisiert oder unterstützt:
| Treiber | Typ | Kernel | Im Artikel behandelt | Codepfad |
|---|---|---|---|---|
| RKISP1 | ISP | 4.4 | Ja | drivers/media/platform/rockchip/isp1 |
| RKCIF | CIF | 4.4 | Ja | drivers/media/platform/rockchip/cif |
| RK-ISP10 | ISP | 4.4 | Nein | drivers/media/platform/rk-isp10/ |
| RK- CAMSYS |
CIF | 4.4 | Nein | drivers/media/video |
1.3 FAQ-Dokument
Zur Sensorfehlersuche Rockchip_Trouble_Shooting_Linux4.4_Camera_CN heranziehen, normalerweise im selben Verzeichnis.
2. Sensortreiber entwickeln und portieren
Treiber liegen in drivers/media/i2c. Gemeint sind Media-Controller-Treiber, nicht drivers/media/i2c/soc_camera. Sensor und RKCIF/RKISP1 sind weitgehend unabhängig, werden asynchron registriert und über remote-endpoint im DTS verbunden. Der beschriebene Treiber passt zu beiden.
Der Sensor ist ein Sub Device, per Pad an Rkcif/Rkisp1/Mipi Dphy gebunden. Behandelt werden Code, DTS und Debugging. Fünf Aufgaben: vdd/reset/powerdown/clk-Sequenz nach Datasheet; Register für Format/Auflösung; struct v4l2_subdev_ops mit set_fmt/get_fmt/s_stream/s_power; V4L2 controls für fps/exposure/gain/test pattern; probe() mit Media-Control-/Sub-Device-Initialisierung. Dokumentation nach Documentation/devicetree/bindings/media/i2c/ ergänzen. Im Board-DTS clk/iomux, regulator/gpio nach Schaltplan und port-Unterknoten zur CIF-/ISP-Verbindung setzen. Beispiele: ov5695/ov2685.
2.1 Einschaltsequenz
Anforderungen unterscheiden sich. Viele OV-Sensoren benötigen nur korrekte mclk/vdd/reset/powerdown-Zustände ohne strikte Reihenfolge, OV2685 dagegen eine genaue Sequenz. Datasheet-Diagramm befolgen. Gekürztes Beispiel __ov5695_power_on() aus drivers/media/i2c/ov5695.c:
static int __ov5695_power_on(struct ov5695 *ov5695)
{
int ret;
u32 delay_us;
struct device *dev = &ov5695->client->dev;
ret = clk_set_rate(ov5695->xvclk, OV5695_XVCLK_FREQ);
if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
ret = clk_prepare_enable(ov5695->xvclk);
if (!IS_ERR(ov5695->reset_gpio))
gpiod_set_value_cansleep(ov5695->reset_gpio, 1);
ret = regulator_bulk_enable(OV5695_NUM_SUPPLIES, ov5695->supplies);
if (!IS_ERR(ov5695->reset_gpio))
gpiod_set_value_cansleep(ov5695->reset_gpio, 0);
if (!IS_ERR(ov5695->pwdn_gpio))
gpiod_set_value_cansleep(ov5695->pwdn_gpio, 1);
/* 8192 cycles prior to first SCCB transaction */
delay_us = ov5695_cal_delay(8192);
usleep_range(delay_us, delay_us * 2);
return 0;
}
OV5695: zuerst xvclk/mclk, dann Reset, anschließend vdd-Versorgungen. regulator_bulk genügt, weil vdd/vodd/avdd keine feste Reihenfolge verlangen; andernfalls separat wie OV2685 steuern. Reset/powerdown gemäß Gehäuse und Schaltplan aktiv setzen; eventuell ist nur einer nötig. Abschließend 8192 Taktzyklen warten. Auch wenn ein Sensor anders funktioniert, ist die Herstellersequenz zuverlässiger. Ebenso die Abschaltsequenz implementieren.
2.1.1 Einschalten prüfen
In .probe() wird die Chip-ID gelesen, etwa durch ov5695_check_sensor_id(). Eine korrekte ID bestätigt normalerweise die Einschaltsequenz und I2C-Kommunikation.
2.2 Initialisierungsregister
struct ov5695_mode/struct ov2685_mode beschreiben Modi mit Auflösung, Mbus Code, fps und Registerliste. Herstellerwerte übernehmen. REG_NULL beendet die Liste und darf nicht mit einer Registeradresse kollidieren.
2.3 v4l2_subdev_ops-Callbacks
Kern der Sensorsteuerung; vollständiger Umfang in include/media/v4l2-subdev.h. Empfohlen: .open() beim Öffnen von /dev/v4l-subdev? aus Userspace, nötig für separate Controls; .s_power() ein/aus; .s_stream() Stream ein/aus mit Registerkonfiguration; .enum_mbus_code() Formate; .enum_frame_size() Größen; .get_fmt() aktuelles Format/Größe, sonst fehlt diese Angabe in media-ctl; .set_fmt() Einstellung. OV5695 nutzt pm_runtime für Versorgung und v4l2_ctrl_handler_setup() in .s_stream(), um möglicherweise im ausgeschalteten Zustand geänderte Controls tatsächlich in Register zu schreiben.
2.4 V4L2 controls
Für dynamische Belichtung, Gain und Blanking, besonders RAW Bayer, Controls implementieren. ov5695_initialize_controls() legt unterstützte Controls und Grenzen fest; struct v4l2_ctrl_ops benennt ov5695_set_ctrl() zur Werteinstellung durch Anwendungen.
2.5 Probe, Media Entity und v4l2 subdev
probe liest regulator/gpio/clk aus DTS für die Versorgung und registriert Media Entity, Subdev und Controls. Subdev-Registrierung ist asynchron. v4l2_i2c_subdev_init() setzt Subdev/Callbacks; ov5695_initialize_controls() die Controls; media_entity_init() die Entity, bei OV5695 mit einem Source Pad; v4l2_async_register_subdev() ist wegen asynchroner RKISP1-/RKCIF-Registrierung erforderlich.
2.6 DTS-Beispiel: MIPI-Sensor
pinctrl/iomux, clk, gpio und Remote-Port nach Hardware konfigurieren. OV5695-Beispiel aus rk3326-evb-lp3-v10-linux.dts:
ov5695: ov5695@36 {
compatible = "ovti,ov5695";
reg = <0x36>;
clocks = <&cru SCLK_CIF_OUT>;
clock-names = "xvclk";
avdd-supply = <&vcc2v8_dvp>;
dovdd-supply = <&vcc1v8_dvp>;
dvdd-supply = <&vdd1v5_dvp>;
/*reset-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>;*/
pwdn-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "TongJu";
rockchip,camera-module-lens-name = "CHT842-MD";
port {
ucam_out: endpoint {
remote-endpoint = <&mipi_in_ucam>;
data-lanes = <1 2>;
};
};
};
pinctrl setzt Reset und clk-iomux. Der Treiber erwartet den Taktnamen xvclk mit 24M. OV5695 benötigt drei Versorgungen. port/endpoint verbindet mipi_in_wcam; MIPI DPHY verweist zurück auf wcam_out. data-lanes gibt zwei Lanes an und muss in wcam_out dazu passen.
2.7 DTS-Beispiel: DVP-Sensor
Anders als MIPI benötigt DVP keine data-lanes; endpoint verbindet CIF. Beispiel gc2155 in arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts: remote-endpoint zeigt auf cif_in; restliche Angaben entsprechen MIPI.
2.8 Sensor debuggen
Nach dem Portieren die Funktion prüfen; bei Problemen zuerst die FAQ nutzen.
2.8.1 Registrierung erfolgreich?
Zunächst I2C und Chip-ID prüfen; eine richtige ID bestätigt normalerweise die Einschaltsequenz. Treiberlogs sind sensorspezifisch. Anschließend muss der Sensor als Entity in media-ctl erscheinen; dann ist er registriert.
2.8.2 Aufnahme liefert Bilder?
Mit v4l2-ctl, GStreamer oder Kamera-App erfassen.
2.8.3 Controls wirksam?
Gain/Exposure/Blanking mit v4l2-ctl einstellen und Bilder prüfen: höhere Helligkeit bei Gain/Exposure, niedrigere Bildrate bei mehr Blanking.
3. Debugwerkzeuge und Befehle
Lange Befehle sind mit Backslash \ fortgesetzt. So können sie kopiert werden; beim Zusammenziehen auf eine Zeile die Fortsetzungszeichen entfernen.
3.1 v4l-utils
In Rockchip-SDKs standardmäßig integriert; über Buildroot ein-/ausschaltbar:
# grep -rn LIBV4L_UTILS - buildroot/configs/rockchip/camera.config
BR2_PACKAGE_LIBV4L_UTILS=y
Quellcode auf www.linuxtv.org; unter Ubuntu per apt installierbar:
# sudo apt-get install v4l-utils
3.2 Topologie mit media-ctl
media-ctl gehört zu v4l-utils und prüft/konfiguriert Format, Crop und Linkstatus jeder Entity. Für übliche Anwendungen genügen die Vorgaben; das Werkzeug ermöglicht flexiblere Nutzung.
3.2.1 Topologie anzeigen
Der Befehl zeigt die Topologie. Bei CIF+ISP, mehreren ISPs oder USB-Kamera gibt es möglicherweise /dev/media0, /dev/media1 und /dev/media2.
# media-ctl -p -d /dev/media0
Entscheidend ist die Sensor-Entity. Fehlt sie, Registrierung gemäß FAQ prüfen. Gekürztes OV5695-Beispiel auf RK3326:
# media-ctl -p -d /dev/media1
- entity 9: m00_b_ov5695 2-0036 (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev2
pad0: Source
[fmt:SBGGR10_1X10/2592x1944@10000/300000 field:none]
-> "rockchip-mipi-dphy-rx":0 [ENABLED,DYNAMIC]
m00_b_ov5695 2-0036 ist ein V4L2-Subdev-Sensor mit /dev/v4l-subdev2 für Anwendungen/v4l2-ctl. Ein Source-Ausgang pad0; Format [fmt:SBGGR10_1X10/2592x1944@10000/300000 field:none]. SBGGR10_1X10 ist mbus-code. Source pad0 ist mit pad0 von “rockchip-mipi-dphy-rx” verbunden und ENABLED. DYNAMIC erlaubt DISABLED. Sind zwei Sensoren an einem ISP/CIF angeschlossen, ist nur einer aktiv. Beispiel:
[root@rk3326_64:/]# media-ctl -p -d /dev/media1
-entity 9: irs16x5c 1-003d (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev2
pad0: Source
[fmt:SBGGR12_1X12/224x1557@10000/300000 field:none]
-> "rockchip-mipi-dphy-rx":0 [ENABLED,DYNAMIC]
-entity 10: irs16x5c 2-003d (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[fmt:SBGGR12_1X12/224x1557@10000/300000 field:none]
-> "rockchip-mipi-dphy-rx":0 [DYNAMIC]
Im Beispiel:
Beide irs16x5c sind mit “rockchip-mipi-dphy-rx”:0 verbunden, aber nur Entity 9 ist ENABLED. Sensorwechsel nur bei gestoppter Pipeline; während der Aufnahme keine Entity-Konfiguration ändern.
3.2.2 Sensor wechseln
Mehrere Sensoren lassen sich mit folgenden Befehlen umschalten:
# media-ctl -d /dev/media0 \
-l '"ov5695 7-0036":0->"rockchip-sy-mipi-dphy":0[0]'
# media-ctl -d /dev/media0 \
-l '"ov2685 7-003c":0->"rockchip-sy-mipi-dphy":0[1]'
Format: media-ctl -l’“entity name”:pad->“entity name”:pad[Status]’. Den Link wegen > [ ] in einfache, Entity-Namen wegen Leerzeichen in doppelte Anführungszeichen setzen. Status 0/1 schaltet aus/ein; konkreten Wert mit Beispiel und media-ctl prüfen.
3.2.3 Entity-Format und Größe
Beispiel 1: OV5695 von standardmäßig 2592x1944 auf 1920x1080 ändern.
# media-ctl -d /dev/media1 \
--set-v4l2 '"m00_b_ov5695 2-0036":0[fmt:SBGGR10_1X10/1920x1080]'
Danach rkisp1-isp-subdev und Video-Crop anpassen: Nachfolgende Stufen dürfen nicht größer als vorherige sein.
# media-ctl -d /dev/media1 \
--set-v4l2 '"rkisp1-isp-subdev":0[fmt:SBGGR10_1X10/1920x1080]'
# media-ctl -d /dev/media1 \
--set-v4l2 '"rkisp1-isp-subdev":0[crop:(0,0)/1920x1080]'
# media-ctl -d /dev/media1 \
--set-v4l2 '"rkisp1-isp-subdev":2[crop:(0,0)/1920x1080]'
# v4l2-ctl -d /dev/video1 \
--set-selection=target=crop,top=0,left=0,width=1920,height=1080
Beispiel 2: Bayer RAW wird standardmäßig als YUV ausgegeben. fmt von rkisp1-isp-subdev an den Sensor anpassen, um RAW über MP auszugeben.
# media-ctl -d /dev/media1 \
--set-v4l2 '"rkisp1-isp-subdev":2[fmt:SBGGR10/2592x1944]'
Zu beachten:
Sonderzeichen korrekt in einfache/doppelte Anführungszeichen setzen; Leerzeichen darin nicht ändern. Details: media-ctl –help.
3.2.4 Übliche mbus-code-Formate
Media Bus Pixel Codes beschreiben den Transport auf physischer Busverbindung, etwa Sensor→ISP über MIPI DPHY oder zwischen ISP-Modulen. FourCC dagegen beschreibt Speicherformate. Definitionen: include/uapi/linux/media-bus-format.h. Verwendete Codes:
| Kernel-Makro | Mbus-code-Kurzform | Typ | Bpp | Busbreite | Samples |
|---|---|---|---|---|---|
| MEDIA_BUS_FMT_SBGGR8_1X8 | SBGGR8_1X8 | Bayer Raw |
8 | 8 | 1 |
| MEDIA_BUS_FMT_SRGGB8_1X8 | SRGGB8_1X8 | Bayer Raw |
8 | 8 | 1 |
| MEDIA_BUS_FMT_SBGGR10_1X10 | SBGGR10_1X10 | Bayer Raw |
10 | 10 | 1 |
| MEDIA_BUS_FMT_SRGGB10_1X10 | SRGGB10_1X10 | Bayer Raw |
10 | 10 | 1 |
| MEDIA_BUS_FMT_SBGGR12_1X12 | SBGGR12_1X12 | Bayer Raw |
12 | 12 | 1 |
| MEDIA_BUS_FMT_SRGGB12_1X12 | SRGGB12_1X12 | Bayer Raw |
12 | 12 | 1 |
| MEDIA_BUS_FMT_YUYV8_2X8 | YVYU8_2X8 | YUV 422 |
16 | 8 | 2 |
| MEDIA_BUS_FMT_UYUV8_2X8 | UYUV8_2X8 | YUV 422 |
16 | 8 | 2 |
| MEDIA_BUS_FMT_Y8_1X8 | Y8_1X8 | YUV GREY |
8 | 8 | 1 |
| MEDIA_BUS_FMT_RGB888_1X24 | RGB888_1X24 | RGB 888 |
24 | 24 | 1 |
Unterstützte mbus-codes auflisten:
# media-ctl --known-mbus-fmts
3.2.5 Videogeräte finden
Sub Devices entsprechen /dev/v4l-subdev, Video Devices /dev/video. Bei mehreren Geräten den bildliefernden Knoten bestimmen.
# media-ctl -d /dev/media1 -e "rkisp1_selfpath"
/dev/video2
# media-ctl -d /dev/media1 -e "rkisp1_mainpath"
/dev/video1
Die beiden Befehle zeigen SP-/MP-Pfade in /dev/media1. RKISP1 besitzt zwei Bildausgänge. Für RKCIF entsprechend:
# media-ctl -d /dev/media0 -e "stream_cif"
/dev/video0
Der Befehl zeigt RKCIF in /dev/media0. RKCIF besitzt einen Videoausgang.
# v4l2-ctl -d /dev/video1 --all
Der Befehl zeigt /dev/video1-Parameter wie crop, fmt und Controls.
3.3 Aufnahme mit v4l2-ctl
media-ctl verwaltet über /dev/media0 Format/Größe/Links der Topologie; Englisch schreibt /dev/medio0. v4l2-ctl arbeitet auf /dev/video0/1 mit set_fmt/reqbuf/qbuf/dqbuf/stream_on/stream_off. Hier dient es zur Aufnahme und Exposure-/Gain-/VTS-Einstellung. Zuerst Hilfe lesen, insbesondere streaming und vidcap. Kurzfassung:
# v4l2-ctl --help
Vollständige Hilfe:
# v4l2-ctl --help-all
Streaming-Parameter:
# v4l2-ctl --help-streaming
Vidcap-Parameter, insbesondere get-fmt/set-fmt:
# v4l2-ctl --help-vidcap
3.3.1 Frames mit v4l2-ctl erfassen
Beispiel 1: Ein NV12-Frame 640x480 von RKCIF nach /tmp/nv12.bin. Die ersten drei Frames werden an Userspace geliefert, aber nicht gespeichert.
# v4l2-ctl -d /dev/video0 \
--set-fmt-video=width=640,height=480,pixelformat=NV12 \
--stream-mmap=3 \
--stream-skip=3 \
--stream-to=/tmp/nv12.bin \
--stream-count=1 \
--stream-poll
Beispiel 2: Zehn NV12-Frames 1920x1080 von RKISP nach /tmp/nv12.bin.
# v4l2-ctl -d /dev/video1 \
--set-selection=target=crop,top=0,left=0,width=1920,height=1080
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 \
--stream-to=/tmp/nv12.bin \
--stream-count=10 \
--stream-poll
Parameter: -d wählt /dev/video0. –set-selection setzt Crop, nicht größer als die vorherige RKISP1-Stufe; RKCIF nutzt –set-crop. –set-fmt-video bestimmt Breite/Höhe und FourCC-Pixelformat, hier NV12. –stream-mmap wählt einen vom Kernel physisch zusammenhängend oder per IOMMU angelegten Puffer. –stream-skip verwirft die ersten drei Frames. –stream-to setzt die Datei. –stream-count zählt gespeicherte Frames ohne verworfene. –stream-poll nutzt asynchrones IO/select vor dqbuf, sodass dqbuf nicht blockiert; ohne Option wartet dqbuf auf den Frame.
3.3.2 Exposure, Gain und weitere Controls
Implementiert der Sensortreiber Controls, lassen sich Exposure/Gain vor der Aufnahme setzen. RKCIF/RKISP erben Subdevice-Controls, sichtbar etwa über /dev/video3. OV5695 auf RK3326 mit Exposure/Gain/Blanking/Testpattern:
# v4l2-ctl -d /dev/video1 -l
User Controls
exposure 0x00980911 (int) : min=4 max=2228 step=1 default=1104 value=1104
gain 0x00980913 (int) : min=0 max=16383 step=1 default=1024 value=1024
Image Source Controls
vertical_blanking 0x009e0901 (int) : min=1152 max=31687 step=1 default=1152 value=1152
analogue_gain 0x009e0903 (int) : min=16 max=248 step=1 default=248 value=248
Image Processing Controls
test_pattern 0x009f0903 (menu): min=0 max=4 default=0 value=0
Exposure und analogue_gain ändern:
# v4l2-ctl -d /dev/video3 --set-ctrl'exposure=1216,analogue_gain=10'
3.3.3 RAW erfassen
MP von RKISP1 erfasst RAW im ISP-Bypass ohne Bildabstimmung. Beispiel OV5695: SBGGR10_1X10, 2592x1944.
# media-ctl -d /dev/media0 \
--set-v4l2 '"ov5695 7-0036":0[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":0[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":0[crop:(0,0)/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":2[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":2[crop:(0,0)/2592x1944]'
# v4l2-ctl -d /dev/video4 \
--set-ctrl 'exposure=1216,analogue_gain=10' \
--set-selection=target=crop,top=0,left=0,width=2592,height=1944 \
--set-fmt-video=width=2592,height=1944,pixelformat=BG10 \
--stream-mmap=3 \
--stream-to=/tmp/mp.raw.out \
--stream-count=1 \
--stream-poll
Zeile 4 gleicht isp-subdev-Format an den Sensor an. Zeilen 3/5 setzen Crop gleich Sensorgröße, ohne Beschneiden. In Zeile 6 können Exposure/Gain bei dunklem Bild erhöht werden, sofern Controls implementiert sind. Zeilen 7/8 setzen Selection ohne Crop und FourCC BG10. 10-/12-Bit-RAW wird trotz Bypass unten mit Nullen auf 16 Bit aufgefüllt. Ein dreizeiliger PGM-Header macht RAW unter Ubuntu direkt sichtbar. Beispiel:
# cat > /tmp/raw.pgm << EOF
P5
2592 1944
65535
EOF
# cat /tmp/mp.raw.out >> /tmp/raw.pgm
Zeile 2: feste Kennung P5. Zeile 3: Breite/Höhe durch Leerzeichen getrennt. Zeile 4: Tiefe 65535 für 16 Bit beziehungsweise 255 für 8 Bit. Zeile 7 hängt RAW an. Der Header hat genau drei Zeilen, keine zusätzlichen Leerzeilen.
3.3.4 FourCC-Formate
Four Character Codes benennt ein Format mit vier Zeichen, also 32 Bit. Linux-Makro:
#define v4l2_fourcc(a,b,c,d) \
(((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
FourCC beschreibt Bild-/Videospeicherung im Speicher, nicht den Bus wie mbus-code. Gebräuchliche Formate unten; vollständig in videodev2.h.
| Kernel-Makro | FourCC |
|---|---|
| V4L2_PIX_FMT_NV12 | NV12 |
| V4L2_PIX_FMT_NV21 | NV21 |
| V4L2_PIX_FMT_NV16 | NV16 |
| V4L2_PIX_FMT_NV61 | NV61 |
| V4L2_PIX_FMT_NV12M | NM12 |
| V4L2_PIX_FMT_YUYV | YUYV |
| V4L2_PIX_FMT_YUV420 | YU12 |
| V4L2_PIX_FMT_SBGGR10 | BG10 |
| V4L2_PIX_FMT_SGBRG10 | GB10 |
| V4L2_PIX_FMT_SGRBG10 | BA10 |
| V4L2_PIX_FMT_SRGGB10 | RG10 |
| V4L2_PIX_FMT_GREY | GREY |
3.4 YUV mit mplayer unter Ubuntu anzeigen
Gespeicherte Frames können mit mplayer betrachtet werden. Installation per apt:
# sudo apt-get install mplayer
NV12 640x480:
# W=640; H=480; mplayer /tmp/nv12.bin -loop 0 -demuxer rawvideo -fps 30 \
-rawvideo w=${W}:h=${H}:size=$((${W}*${H}*3/2)):format=NV12
YUYV 640x480:
# W=640; H=480; mplayer /tmp/yuyv.bin -loop 0 -demuxer rawvideo -fps 30 \
-rawvideo w=${W}:h=${H}:size=$((${W}*${H}*2)):format=YUY2
W/H sind Breiten-/Höhenvariablen für spätere Referenz.
fps bestimmt die Wiedergaberate, 1 entspricht einem Frame pro Sekunde. size ist die Framegröße, format das Format; mplayer -rawvideo format=help listet Varianten. Unter Windows beispielsweise 7yuv verwenden.
3.5 GStreamer
Im SDK ermöglicht GStreamer Vorschau und Kodierung. v4l2src liest Videogeräte; rkisp_3A_server sorgt standardmäßig für richtige Helligkeit/Farbe.
3.5.1 GStreamer-Anzeige
Folgender Befehl zeigt die Kamera:
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/gstreamer-1.0
# export XDG_RUNTIME_DIR=/tmp/.xdg
# gst-launch-1.0 v4l2src device=/dev/video1 ! \
video/x-raw,format=NV12,width=2592,height=1944,framerate=30/1 ! kmssink
3.5.2 Video-/Bildkodierung
Das SDK unterstützt Hardwarekodierung. Die Befehle kodieren und speichern den Kamerastrom:
# gst-launch-1.0 v4l2src device=/dev/video1 num-buffers=100 ! \
video/x-raw,format=NV12,width=1920,height=1088,framerate=30/1 ! \
videoconvert ! mpph264enc ! h264parse ! mp4mux ! \
filesink location=/tmp/h264.mp4
# gst-launch-1.0 -v v4l2src device=/dev/video1 num-buffers=10 ! \
video/x-raw,format=NV12,width=1920,height=1080 ! mppjpegenc ! \
multifilesink location=/tmp/test%05d.jpg
mppjpegenc/mpph264enc sind Hardwareencoder aus rockchipmpp. MPP verlangt 16er-Höhenausrichtung; Kernelpatch fea937b015e7 media: rockchip: isp1/cif: set height alignment to 16 in queue_setup erforderlich.
3.6 Boards ohne Bildschirm debuggen
librkuvc.so macht das Board zur UVC-Kamera am PC über USB OTG. Beispielcode im Anwendungskapitel.
3.7 Debugausgabe aktivieren
RKISP1/RKCIF enthalten v4l2_dbg()-Ausgaben. Aktivierung:
# echo 1 > /sys/module/video_rkcif/parameters/debug
Oder:
# echo 1 > /sys/module/video_rkisp1/parameters/debug
VB2/V4L2 haben ebenfalls Schalter. VB2-Log:
# echo 7 > /sys/module/videobuf2_core/parameters/debug
VB2 protokolliert reqbuf/qbuf/dqbuf und Pufferzustände. Der Schalter ist global und aktiviert auch andere VB2-Nutzer wie VPU/ISP. Danach vollständige V4L2-Ausgabe, etwa ioctl:
# echo 0x1f > /sys/class/video4linux/video0/dev_debug
Auch einzelne Meldungsgruppen lassen sich über Bits aus include/media/v4l2-ioctl.h aktivieren:
/* Just log the ioctl name + error code */
#define V4L2_DEV_DEBUG_IOCTL 0x01
/* Log the ioctl name arguments + error code */
#define V4L2_DEV_DEBUG_IOCTL_ARG 0x02
/* Log the file operations open, release, mmap and get_unmapped_area */
#define V4L2_DEV_DEBUG_FOP 0x04
/* Log the read and write file operations and the VIDIOC_(D)QBUF ioctls */
#define V4L2_DEV_DEBUG_STREAMING 0x08
/* Log poll() */
#define V4L2_DEV_DEBUG_POLL 0x10
4. 3A integrieren
Gilt nur für RKISP1; RKCIF besitzt keine ISP-Funktion und benötigt kein 3A. Frühere Lösungen banden librkisp.so ein oder nutzten rkisp/rkv4l2src-Plug-ins, erschwerten aber Anwendungen und VLC/Chrome-Kompatibilität. Ab RKISP1 v0.1.5 und camera_engine_rkisp v2.2.0 übernimmt rkisp_3A_server die Abstimmung automatisch. Anwendungen behandeln nur Datenströme, ohne librkisp.so; normales v4l2src/VLC liefert korrekte Bilder.
4.1 rkisp_3A_server
Besteht aus RKISP1-Kerneltreiber, camera_engine_rkisp und Startskripten. Im entsprechenden SDK standardmäßig integriert: RKISP1 v0.1.5+ (kernel/drivers/media/platform/rockchip/isp1/version.h); camera_engine_rkisp v2.2.0+ unter external/camera_engine_rkisp; Build-/Autostartskripte unter buildroot/package/rockchip/camera_engine_rkisp. Erzeugte Dateien:
/usr/bin/rkisp_3A_server
/usr/lib/librkisp.so
/usr/lib/librkisp_api.so
/usr/lib/rkisp/
├── ae
│ └── librkisp_aec.so
├── af
│ └── librkisp_af.so
└── awb
└── librkisp_awb.so
/etc/iqfiles/
/etc/init.d/S40rkisp_3A
Hinweise:
rkisp_3A_server überwacht und startet 3A nach Bedarf. librkisp.so stellt Haupt-APIs bereit und ruft nichtoffene aec-/af-/awb-Bibliotheken auf. iqfiles enthält Sensor-IQ-XML. S40rkisp_3A startet den Server beim Booten. Rockchip-Debian verwendet dieselbe Logik mit anderem Startmechanismus.
4.2 rkisp_3A_server-Log
Per Umgebungsvariable aktivieren, Beispiel AEC:
# export persist_camera_engine_log=0x40
Zeile in /etc/init.d/S40rkisp_3A ergänzen; Ausgabe landet in /var/log/messages. Bei Rotation messages.0/messages.1 mit sichern:
# tar zcvf /tmp/camera-log.tar.gz /var/log/messages*
Modulbezogene Logauswahl:
bits: 31-28 27-24 23-20 19-16 15-12 11-8 7-4 3-0
module: [u] [u] [xcore] [ISP] [AF] [AWB] [AEC] [NO]
*[u] means unused now.
each module log has following ascending levels:
0: error
1: warning
2: info
3: verbose
4: debug
5: low1
6-7: unused, now the same as debug
Bei manuellem Serverstart Logs in eine Datei umleiten: Die Menge ist für langsame serielle Anschlüsse oder normale Shellausgabe zu groß.
# /etc/init.d/S40rkisp_3A stop
# export persist_camera_engine_log=0x40
# /usr/bin/rkisp_3A_server --mmedia=/dev/media0 > /tmp/log 2>&1
Zuerst Service stoppen, Umgebung setzen und Server manuell mit Ausgabe nach /tmp/log starten.

4.3 XML-Laden beschleunigen
Für schnellen Bildstart kann XML-Ladebeschleunigung aktiviert werden:
# make menuconfig
│ │ --- Rockchip BSP packages │ │
│ │ [*] Rockchip Camera Engine for linux │ │
│ │ [*] Rockchip Camera Engine 3A service run in booting │ │
│ │ Specify a directory to store xml speed up bin (disabled) ---> │ │
│ │ () Rockchip Camera Engine IQ xml file │ │
Specify a directory to store xml speed up bin je nach Schreibbarkeit der rootfs wählen.
│ │ (X) disabled │ │
│ │ ( ) /etc/iqfiles-db │ │
│ │ ( ) /userdata/iqfiles-db │ │
Bei read-only rootfs /userdata/iqfiles-db wählen. Das XML-Bin-Verzeichnis muss auf einem beschreibbaren Dateisystem liegen.
4.4 Ablauf von rkisp_3A_server
Sequenzdiagramm:
Teilnehmer: userspace_app, kernel_rkisp1_driver, rkisp_3A_server, 3A_Tunning_Thread. Aufnahme starten.
Sequenz: Aufnahme → RAW benötigt 3A → Tuning-Thread starten → Start erfolgreich → Nachricht/Timeout setzt Aufnahme fort; kontinuierliche Bilder und Tuning; Aufnahmeende → bereit zum Beenden → Thread beenden → Tuning beendet → Nachricht/Timeout beendet Aufnahme.
Beenden vorbereiten; Tuning-Thread beenden; Tuning beendet; nach Threadmeldung oder Timeout Aufnahme abschließen.
Teilnehmer: userspace_app, kernel_rkisp1_driver, rkisp_3A_server, 3A_Tunning_Thread.
5. Anwendungsentwicklung
Neben v4l2-ctl/GStreamer/VLC können eigene V4L2-Anwendungen erfassen und verarbeiten. Mit librkisp.so erhalten sie manuelle Exposure-/Gain-Steuerung, regionale Gewichte/Spotmessung, Helligkeitsstatistik und Histogramm sowie Begrenzung von fps/Gain. Dafür zuerst rkisp_3A_server stoppen; die Anwendung initialisiert und startet 3A selbst.
# /etc/init.d/S40rkisp_3A stop
Alternativ S40rkisp_3A direkt entfernen.
# rm /etc/init.d/S40rkisp_3A
5.1 librkisp_api.so verwenden
camera_engine_rkisp bietet rkisp_api in librkisp_api.so zur direkten Verwendung oder als Vorlage. Deklarationen in rkisp_api.h. Beispiel 1: 1920x1080 öffnen und erfassen.
int test_capture_mmap_quick()
{
const struct rkisp_api_ctx *ctx;
const struct rkisp_api_buf *buf;
int count = 10;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
rkisp_set_fmt(ctx, 1920, 1080, ctx->fcc);
if (rkisp_start_capture(ctx))
return -1;
do {
buf = rkisp_get_frame(ctx, 0);
/* Deal with the buffer */
rkisp_put_frame(ctx, buf);
} while (count--);
rkisp_stop_capture(ctx);
rkisp_close_device(ctx);
return 0;
}
Hier übernimmt weiterhin rkisp_3A_server das 3A. Für zusätzliche Statistik den Öffnungsparameter ändern:
ctx = rkisp_open_device("/dev/video1", 1);
buf enthält anschließend weitere Statistik. Beispiel 2: OV5695-Ausgabe auf 1920x1080 ändern.
const struct rkisp_api_ctx *ctx;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
rkisp_set_sensor_fmt(ctx, 1920, 1080, MEDIA_BUS_FMT_SBGGR10_1X10);
5.2 DMA Buffer gemeinsam nutzen
Gemeinsame Puffer reduzieren Kopien zwischen Camera/RGA/DRM/MPP. rkisp_api allokiert standardmäßig per mmap Kernelpuffer und kann sie als DMA Buffer exportieren. Umgekehrt nimmt es fremde Puffer entgegen und schreibt Frames direkt hinein. Beispiel 1: MMAP-Puffer exportieren.
const struct rkisp_api_ctx *ctx;
const struct rkisp_api_buf *buf;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL || rkisp_start_capture(ctx))
return -1;
rkisp_get_frame(ctx, 0);
printf("size: %d, dmabuf fd: %d\n", buf->size, buf->fd);
buf->fd ist der DMA-Buffer-Deskriptor für andere Module. Solange diese ihn nutzen, rkisp_put_frame() nicht aufrufen; danach den Aufruf nicht vergessen. Beispiel 2: Kameradaten direkt in fremden Puffer schreiben.
int test_capture_ext_dmabuf()
{
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
for (i = 0, ret = 0; i < buf_count; i++) {
if (drmGetBuffer(dev.drm_fd, width, height, FORMAT, &buf[i]))
goto out;
dmabuf_fd[i] = buf[i].dmabuf_fd;
}
rkisp_set_fmt(ctx, width, height, ctx->fcc);
rkisp_set_buf(ctx, buf_count, dmabuf_fd, buf[0].size);
if (rkisp_start_capture(ctx))
goto out;
buf = rkisp_get_frame(ctx, 0);
printf("The ext buf fd is: %d\n", buf->fd);
rkisp_put_frame(ctx, buf);
rkisp_stop_capture(ctx);
out:
while (--i >= 0)
drmPutBuffer(dev.drm_fd, &buf[i]);
rkisp_close_device(ctx);
}
rkisp_set_buf() übergibt einen von DRM allokierten DMA Buffer an die Kamera. Gezeigt wird rkisp_api; drmGetBuffer()/drmPutBuffer() sind im Original nicht näher ausgeführt.
5.3 Regionale Belichtungsgewichte
Globale Belichtung ist nicht immer optimal. Höhere Gewichtung einer wichtigen Region verbessert dort die Helligkeit, kann andere Bereiche über-/unterbelichten. Beispiel Gesichtserkennung bei Gegenlicht ohne HDR: erkannte Gesichtsregion höher gewichten.
Beispiel Saugroboter: Gegenstände am Boden betreffen vor allem den unteren Bildteil; unterschiedliche Reflexion verursacht Helligkeitsunterschiede. Unteren Bereich stärker gewichten. API-Aufruf:
unsigned char weights[] = {
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
1, 1, 5, 9, 15, 31, 15, 5, 1,
};
rkisp_set_expo_weights(ctx, weights, 81);
Das 9×9-Array beschreibt 81 Regionen. Jeder Wert liegt in [1, 31]; größer bedeutet höheres Gewicht.
5.4 UVC-Kamera mit librkuvc.so
SDK enthält librkuvc.so unter external/uvc_app. Kamerabilder lassen sich komprimieren und an den PC übertragen. Beispiel:
#include "uvc_control.h"
#include "uvc_video.h"
int test_uvc_mmap()
{
const struct rkisp_api_ctx *ctx;
const struct rkisp_api_buf *buf;
uint32_t flags = 0;
int extra_cnt = 0;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
if (rkisp_set_fmt(ctx, 640, 480, V4L2_PIX_FMT_NV12))
return -1;
if (rkisp_start_capture(ctx))
return -1;
flags = UVC_CONTROL_LOOP_ONCE;
uvc_control_run(flags);
do {
buf = rkisp_get_frame(ctx, 0);
extra_cnt++;
uvc_read_camera_buffer(buf->buf, buf->fd, buf->size, &extra_cnt, sizeof(extra_cnt));
rkisp_put_frame(ctx, buf);
} while (1);
uvc_control_join(flags);
rkisp_stop_capture(ctx);
rkisp_close_device(ctx);
return 0;
}
Der Kameratreiber allokiert den Speicher und übergibt DMA Buffer an die UVC-Kodierung.
# GCC=buildroot/output/rockchip_rk3326_64/host/bin/aarch64-buildroot-linux-gnu-gcc
# SYSROOT=buildroot/output/rockchip_rk3326_64/staging
# ENGINE=external/camera_engine_rkisp
# $GCC --sysroot=$SYSROOT camera_uvc.c \
-L$ENGINE/build/lib/ -lrkisp -lrkisp_api \
-L $SYSROOT/usr/lib/ -lrkuvc \
-I $SYSROOT/usr/include/uvc/ \
-I./ \
-o camera_uvc
camera_uvc bauen, nach /usr/bin kopieren und auf dem Board starten:
# /usr/bin/uvc_MJPEG.sh
# /usr/bin/camera_uvc
uvc_MJPEG.sh einmal pro Boot initialisieren. Auflösungen 640x480, 1280x720, 1920x1080, 2560x1440; aktuellen Stand in /usr/bin/uvc_MJPEG.sh prüfen. MPP benötigt eine durch 16 teilbare Pufferhöhe, sonst drohen Speichergrenzüberschreitungen.
6. RKISP1-Treiber
Code unter drivers/media/platform/rockchip/isp1. Auf V4L2/Media Framework basierend werden Hardware, Interrupts, Pufferwechsel und Versorgung von MIPI-DPHY-/Sensor-Subdevices gesteuert. Dateien:
# tree drivers/media/platform/rockchip/isp1/
drivers/media/platform/rockchip/isp1/
├── capture.c #Contains the configuration of mp/sp and vb2, frame interrupt processing
├── dev.c #Include probe, sensor registration, clock, pipeline, iommu
├── isp_params.c #3A Related parameter settings
├── isp_stats.c #3A related statistics
├── regs.c #register related read and write operations
├── rkisp1.c #corresponding to rkisp-isp-sd entity, including receiving data from mipi/dvp and crop
function
MIPI DPHY unter drivers/phy/rockchip/phy-rockchip-mipi-rx.c ist ebenfalls V4L2-Subdevice. Das Diagramm zeigt Sensor bis ISP-Ausgabe.

Userspace-Anwendung.
MP: Main-Path-Videogerät; SP: Self-Path-Videogerät; jeweils Speicherschnittstelle.
Skalierung MpOutResize / SpOutResize.
Main-Path-/Self-Path-Eingangscrop.
Isp Sub Device und ISP Out Crop.
ISP In Crop.
DVP-Sensor und MIPI DPHY.
MIPI-Sensor A / MIPI-Sensor B.
RKISP1 unterstützt DVP/MIPI; MIPI benötigt DPHY. Mehrere Sensoren sind anschließbar, nur einer ist aktiv. Ein Bild wird auf MP/SP aufgeteilt und unabhängig gleichzeitig ausgegeben. MP unterstützt bis 4416x3312, YUV oder RAW; RAW nur über MP.
SP unterstützt bis 1920x1080, YUV/RGB, kein RAW. Crop/Resize beider Pfade sind unabhängig. Vergleich:
| Ausgabegerät | Max. Auflösung | Formate | Crop/Resize |
|---|---|---|---|
| SP | 1920x1080 | YUV, RGB | Unterstützt |
| MP | 4416x3312 | YUV, RAW | Unterstützt |
rkisp1-input-params und rkisp1-statistics dienen 3A. rkisp1_rawpath/rkisp1_dmapath sind Sonderfälle und für normale Anwendungen meist irrelevant.
6.1 RKISP1-Board-DTS
Im SDK sind ISP-Knoten bereits definiert: rkisp1 in rk3288-rkisp1.dtsi sowie rkisp1_0/rkisp1_1 in rk3399.dtsi. Tabelle:
| Chip | DTS-Knoten | MIPI DPHY | IOMMU |
|---|---|---|---|
| RK3399 | rkisp1_0 | mipi_dphy_rx0 | isp0_mmu |
| RK3399 | rkisp1_1 | mipi_dphy_tx1rx1 | isp1_mmu |
| RK3288 | rkisp1 | mipi_phy_rx0 or mipi_phy_tx1rx1 | isp_mmu |
| PX30/RK3326 | rkisp1 | mipi_dphy_rx0 | isp_mmu |
| RK1808 | rkisp1 | mipi_dphy_rx | isp_mmu |
RK3399 hat zwei ISPs mit getrenntem DPHY/MMU. RK3288 hat einen ISP und wählbar rx0/tx1rx1. Boardseitig passende Knoten aktivieren und remote-endpoint verbinden. Beispiel arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts: sensor, mipi_dphy_rx0, rkisp1, isp_mmu. data-lane von Sensor und mipi_dphy_rx0 muss bei MIPI korrekt und identisch sein.
7. RKCIF-Treiber
TODO — dieser Abschnitt ist im Original nicht ausgearbeitet.
Unterschiede des Quellcodes
Der Haupttext folgt der jeweiligen Sprachquelle, RU/DE dem EN-Original. Abweichende Fragmente der anderen Quelle einschließlich Kommentar-/Layoutabweichungen bleiben unten erhalten. Unabhängige Beispiele, kein zusammenhängendes Skript; Quellparameter wurden nicht stillschweigend überschrieben.
CN PDF p.6 · 13
static int __ov5695_power_on(struct ov5695 *ov5695)
{
int ret;
u32 delay_us;
struct device *dev = &ov5695->client->dev;
ret = clk_set_rate(ov5695->xvclk, OV5695_XVCLK_FREQ);
if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
ret = clk_prepare_enable(ov5695->xvclk);
if (!IS_ERR(ov5695->reset_gpio))
gpiod_set_value_cansleep(ov5695->reset_gpio, 1);
ret = regulator_bulk_enable(OV5695_NUM_SUPPLIES, ov5695->supplies);
if (!IS_ERR(ov5695->reset_gpio))
gpiod_set_value_cansleep(ov5695->reset_gpio, 0);
if (!IS_ERR(ov5695->pwdn_gpio))
gpiod_set_value_cansleep(ov5695->pwdn_gpio, 1);
/* 8192 cycles prior to first SCCB transaction */
delay_us = ov5695_cal_delay(8192);
usleep_range(delay_us, delay_us * 2);
return 0;
}
CN PDF p.8 · 28
ov5695: ov5695@36 {
compatible = "ovti,ov5695";
reg = <0x36>;
clocks = <&cru SCLK_CIF_OUT>;
clock-names = "xvclk";
avdd-supply = <&vcc2v8_dvp>;
dovdd-supply = <&vcc1v8_dvp>;
dvdd-supply = <&vdd1v5_dvp>;
/*reset-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>;*/
pwdn-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "TongJu";
rockchip,camera-module-lens-name = "CHT842-MD";
port {
ucam_out: endpoint {
remote-endpoint = <&mipi_in_ucam>;
CN PDF p.9 · 29
data-lanes = <1 2>;
};
};
};
CN PDF p.10 · 45
# grep -rn LIBV4L_UTILS -- buildroot/configs/rockchip/camera.config
BR2_PACKAGE_LIBV4L_UTILS=y
CN PDF p.11 · 56
[root@rk3326_64:/]# media-ctl -p -d /dev/media1
- entity 9: irs16x5c 1-003d (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev2
pad0: Source
[fmt:SBGGR12_1X12/224x1557@10000/300000 field:none]
-> "rockchip-mipi-dphy-rx":0 [ENABLED,DYNAMIC]
- entity 10: irs16x5c 2-003d (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[fmt:SBGGR12_1X12/224x1557@10000/300000 field:none]
-> "rockchip-mipi-dphy-rx":0 [DYNAMIC]
CN PDF p.16 · 103
# v4l2-ctl -d /dev/video3 --set-ctrl 'exposure=1216,analogue_gain=10'
CN PDF p.16 · 106
# media-ctl -d /dev/media0 \
--set-v4l2 '"ov5695 7-0036":0[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":0[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":0[crop:(0,0)/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":2[fmt:SBGGR10_1X10/2592x1944]'
# media-ctl -d /dev/media0 \
--set-v4l2 '"rkisp1-isp-subdev":2[crop:(0,0)/2592x1944]'
# v4l2-ctl -d /dev/video4 \
--set-ctrl 'exposure=1216,analogue_gain=10' \
--set-selection=target=crop,top=0,left=0,width=2592,height=1944 \
--set-fmt-video=width=2592,height=1944,pixelformat=BG10 \
--stream-mmap=3 \
--stream-to=/tmp/mp.raw.out \
--stream-count=1 \
--stream-poll
CN PDF p.24 · 182
int test_capture_mmap_quick()
{
const struct rkisp_api_ctx *ctx;
const struct rkisp_api_buf *buf;
int count = 10;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
rkisp_set_fmt(ctx, 1920, 1080, ctx->fcc);
if (rkisp_start_capture(ctx))
return -1;
do {
buf = rkisp_get_frame(ctx, 0);
/* Deal with the buffer */
rkisp_put_frame(ctx, buf);
} while (count--);
rkisp_stop_capture(ctx);
rkisp_close_device(ctx);
return 0;
}
CN PDF p.25 · 191
int test_capture_ext_dmabuf()
{
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
for (i = 0, ret = 0; i < buf_count; i++) {
if (drmGetBuffer(dev.drm_fd, width, height, FORMAT, &buf[i]))
goto out;
dmabuf_fd[i] = buf[i].dmabuf_fd;
}
rkisp_set_fmt(ctx, width, height, ctx->fcc);
rkisp_set_buf(ctx, buf_count, dmabuf_fd, buf[0].size);
if (rkisp_start_capture(ctx))
goto out;
buf = rkisp_get_frame(ctx, 0);
printf("The ext buf fd is: %d\n", buf->fd);
rkisp_put_frame(ctx, buf);
rkisp_stop_capture(ctx);
out:
while (--i >= 0)
drmPutBuffer(dev.drm_fd, &buf[i]);
CN PDF p.26 · 192
rkisp_close_device(ctx);
}
CN PDF p.26 · 200
#include "uvc_control.h"
#include "uvc_video.h"
int test_uvc_mmap()
{
const struct rkisp_api_ctx *ctx;
const struct rkisp_api_buf *buf;
CN PDF p.27 · 201
uint32_t flags = 0;
int extra_cnt = 0;
ctx = rkisp_open_device("/dev/video1", 0);
if (ctx == NULL)
return -1;
if (rkisp_set_fmt(ctx, 640, 480, V4L2_PIX_FMT_NV12))
return -1;
if (rkisp_start_capture(ctx))
return -1;
flags = UVC_CONTROL_LOOP_ONCE;
uvc_control_run(flags);
do {
buf = rkisp_get_frame(ctx, 0);
extra_cnt++;
uvc_read_camera_buffer(buf->buf, buf->fd, buf->size, &extra_cnt, sizeof(extra_cnt));
rkisp_put_frame(ctx, buf);
} while (1);
uvc_control_join(flags);
rkisp_stop_capture(ctx);
rkisp_close_device(ctx);
return 0;
}
CN PDF p.28 · 210
# tree drivers/media/platform/rockchip/isp1/
drivers/media/platform/rockchip/isp1/
├── capture.c #包含 mp/sp 的配置及 vb2,帧中断处理
├── dev.c #包含 probe、Sensor注册、clock、pipeline、iommu
├── isp_params.c #3A 相关参数设置
├── isp_stats.c #3A 相关统计
├── regs.c #寄存器相关的读写操作
├── rkisp1.c #对应 rkisp-isp-sd entity,包含从mipi/dvp接收数据及crop功能
