Rockchip · AI & Linux Hub

Kameras und Video

Rockchip-VI-Treiber: ISP, VICAP, Sensoren und Kameradiagnose

Vollständige Plattformreferenz V1.0.7 für Linux-4.19-Kamerapipelines, CIS-/VCM-/Blitz-/Objektivtreiber, Speicher- und Latenzoptimierung, Diagnose und sämtliche fünf Anhänge.

· ArmSoM-Redaktion · Rockchip-Quelldokumentation · 119 Min. Lesezeit

ArmSoM-Anwendbarkeit und Quellenumfang

Dies ist eine Rockchip-Plattformreferenz und kein Bericht über eine Hardwarevalidierung auf ArmSoM. Sie beschreibt das RKISP-Modul, den gesamten Kameraablauf und zugehörige APIs zur Kameratreiberdiagnose. Die bereitgestellte Quelle ist Rockchip_Driver_Guide_VI_EN_v1.0.7.pdf, V1.0.7, mit 133 Seiten. Ein entsprechendes chinesisches PDF wurde nicht bereitgestellt. Chinesisch, Russisch und Deutsch sind vollständige Übersetzungen dieser englischen Quelle; alle Fassungen verwenden deren englische Originalabbildungen.

Die Produkttabelle auf dem Titelblatt nennt RV1126/RV1109 mit Linux 4.19; die nachfolgende Anwendbarkeitstabelle enthält zusätzlich RK3566/RK3568. Beide bleiben unten erhalten. Daraus folgt keine Kompatibilität mit jedem ArmSoM-Board oder BSP. Prüfen Sie vor der Anpassung den genauen SoC, das Linux-4.19-Hersteller-SDK/BSP, die ISP-/ISPP-/VICAP-Topologie, Kameraanschluss, Lane-Führung, Stromversorgung und Takte von Sensor/VCM/Blitz sowie DTS- und IQ-/AIQ-Version. Es wurden keine boardspezifischen Hardwaretests durchgeführt. Sämtliche Messungen, Protokolle und Befehle unten stammen aus der Quelle und sind keine ArmSoM-Testergebnisse.

Widersprüche der Quelle werden nicht stillschweigend korrigiert: Die Funktionstabellen auf PDF-Seiten 6 und 13 nennen unterschiedliche maximale RK356x-Auflösungen. Mehrere Absätze nennen RV1106, während der Produktumfang RV1109 angibt. Schreibweisen wie hsync-acitve, pclk-ative, hieght und /dev/medio0 sind gegen das Ziel-BSP zu prüfen. Beachten Sie vor Anwendung der Beispiele die Prüfnotizen. Das Deaktivieren der IOMMU und Erhöhen von Takten im Latenzabschnitt sind Optimierungsbeispiele der Quelle, keine pauschalen Empfehlungen für den Produktionseinsatz.

Redaktionelle Prüfnotizen · Offizielle ArmSoM-Dokumentation · Linux-Media-Userspace-API

Ursprünglicher Produktumfang (PDF-Seite 1)

Chipname Kernelversion
RV1126/RV1109 Linux 4.19

Ursprüngliche Anwendbarkeitsmatrix (PDF-Seite 2)

Plattform Linux-Kernel 4.19
RV1126 Y
RV1109 Y
RK3566 Y
RK3568 Y

Unterschiede der VI-Funktionen zwischen den Chips

SoC VI-IP VI-Schnittstelle Maximale Bayer-CIS-
Auflösung
Merkmal
RV1109 ISP20 ( ISP +
ISPP): 1
VICAP Full: 1
VICAP Lite: 1
MIPI DPHY:
2 x 4Lanes 2.5Gbps/Lane
LVDS:
2 x 4Lanes 1.0Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
3072x2048 HDR mit bis zu
3 Bildern
RK3566 ISP21 Lite: 1
VICAP Full: 1
MIPI DPHY:
2 x 2Lanes oder 1 x 4Lanes
2.5Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4096x2304 Kein HDR
RK3568 ISP21:1
VICAP Full: 1
MIPI DPHY:
2 x 2Lanes oder 1 x 4Lanes
2.5Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4096x2304 HDR mit bis zu
2 Bildern
RV1126 ISP20 ( ISP +
ISPP): 1
VICAP Full: 1
VICAP Lite: 1
MIPI DPHY:
2 x 4Lanes 2.5Gbps/Lane
LVDS:
2 x 4Lanes 1.0Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4416x3312 HDR mit bis zu
3 Bildern

Verzeichnisübersicht der Kameratreibersoftware

Linux-Kernel 4.19

  • arch/arm/boot/dts — DTS-Konfigurationsdatei

  • drivers/phy/rockchip

  • drivers/phy/rockchip/phy-rockchip-mipi-rx.c — MIPI-DPHY-Treiber

  • drivers/phy/rockchip/phy-rockchip-csi2-dphy-common.h

  • drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c

  • drivers/phy/rockchip/phy-rockchip-csi2-dphy.c

  • drivers/media

  • drivers/media/platform/rockchip/cif

  • drivers/media/platform/rockchip/isp

  • drivers/media/platform/rockchip/isp/dev — Geräteerkennung, asynchrone Registrierung, Takt, Pipeline, IOMMU und Media-/V4L2-Framework

  • drivers/media/platform/rockchip/isp/capture — mp-/sp-/rawwr-Konfiguration, vb2 und Bildinterruptverarbeitung

  • drivers/media/platform/rockchip/isp/dmarx — rawrd-Konfiguration, vb2 und Bildinterruptverarbeitung

  • drivers/media/platform/rockchip/isp/isp_params — 3A-Parametereinstellungen

  • drivers/media/platform/rockchip/isp/isp_stats — 3A-Statistiken

  • drivers/media/platform/rockchip/isp/isp_mipi_luma — Helligkeitsstatistiken der MIPI-Daten

  • drivers/media/platform/rockchip/isp/regs — Register-Lese- und Schreibzugriffe

  • drivers/media/platform/rockchip/isp/rkisp — Registrierung von ISP-Subdevice und Entity

  • drivers/media/platform/rockchip/isp/csi — CSI-Subdevice und MIPI-Konfiguration

  • drivers/media/platform/rockchip/isp/bridge — Bridge-Subdevice zur Verbindung von ISP und ISPP

  • drivers/media/platform/rockchip/ispp

  • drivers/media/platform/rockchip/ispp/dev — Geräteerkennung, asynchrone Registrierung, Takt, Pipeline, IOMMU und Media-/V4L2-Framework

  • drivers/media/platform/rockchip/ispp/stream — Konfiguration von 4 Videoausgängen, vb2 und Bildinterruptverarbeitung

  • drivers/media/platform/rockchip/ispp/rkispp — Registrierung von ISPP-Subdevice und Entity

  • drivers/media/platform/rockchip/ispp/params — TNR-/NR-/SHP-/FEC-/ORB-Parametereinstellung

  • drivers/media/platform/rockchip/ispp/stats — ORB-Statistiken

  • drivers/media/i2c

  • drivers/media/i2c/os04a10.c — CIS-Treiber (CMOS-Bildsensor)

Verknüpfung zwischen ISP und VICAP

Auf RV1126/RV1109 und RK356X sind VICAP und ISP unabhängige Bildverarbeitungs-IP-Blöcke. Sollen von VICAP erfasste Bilder im ISP verarbeitet werden, muss der Treiber ein V4L2-Subdevice für die entsprechende VICAP-Schnittstelle erzeugen und mit dem zugehörigen ISP-Knoten verknüpfen. Es stellt dem ISP-Treiber die benötigten Parameter bereit. Siehe die Abschnitte zu RKISP- und RKVICAP-Treibern. Das folgende Blockdiagramm zeigt die Verknüpfung der einzelnen VICAP-Schnittstellen mit dem ISP:

Englische Originalabbildung 1, PDF-Seite 7

Englische Originalabbildung 1, PDF-Seite 7

RKISP-Treiber

Kurze Frameworkbeschreibung

Der RKISP-Treiber basiert hauptsächlich auf dem V4L2-/Media-Framework. Er übernimmt Hardwarekonfiguration, Interruptverarbeitung, Pufferwechsel und das Ein-/Ausschalten von Subdevices wie MIPI DPHY und Sensor.

Das folgende Blockdiagramm beschreibt die Topologie des RKISP-Treibers:

Englische Originalabbildung 2, PDF-Seite 8

Englische Originalabbildung 2, PDF-Seite 8

Name Typ Beschreibung
rkisp_mainpath v4l2_vdevcapture Formate: YUV, RAW Bayer; unterstützt Bildbeschnitt
rkisp_selfpath v4l2_vdevcapture Formate: YUV, RGB; unterstützt Bildbeschnitt
rkisp-isp-subdev v4l2_subdev Interne ISP-Blöcke; unterstützen Beschnitt an Source-/Sink-Pads.
Format und Größe am Sink-Pad entsprechen der Sensoreingabe.
Bei RAW-Bayer-Ausgabe muss das Source-Pad-Format dem Vdev-Ausgabeformat entsprechen,
andernfalls YUYV2X8. Die Größe darf die Sink-Pad-Größe nicht überschreiten.
rkisp-mipi-luma v42_vdevcapture Liefert die Helligkeit des RAW-Bildes
rkisp-statistics v4l2_vdevcapture Liefert Farbstatistiken des Bildes
rkisp-input-params v4l2_vdevoutput Empfängt Parameter für Bildverbesserungsblöcke wie AWB, BLC usw.
rkisp_rawrd0_m v4l2_vdevoutput Liest RAW-Bilder aus DDR in den ISP, üblicherweise das mittlere HDR-Bild
rkisp_rawrd1_l v4l2_vdevoutput Liest RAW-Bilder aus DDR in den ISP, üblicherweise das lange HDR-Bild
rkisp_rawrd2_s v4l2_vdevoutput Liest RAW-Bilder aus DDR in den ISP, üblicherweise das kurze HDR-Bild
rkisp-csi-subdev v4l2_subdev MIPI-CSI-Konfiguration
rkisp_rawwr0 v4l2_vdevcapture Schreibt Sensor-RAW-Bilder in DDR, üblicherweise das mittlere HDR-Bild
rkisp_rawwr1 v4l2_vdevcapture Schreibt Sensor-RAW-Bilder in DDR, üblicherweise das lange HDR-Bild
rkisp_rawwr2 v4l2_vdevcapture Schreibt Sensor-RAW-Bilder in DDR, üblicherweise das kurze HDR-Bild
rkisp_rawwr3 v4l2_vdevcapture Schreibt Sensor-RAW-Bilder in DDR
rockchip-mipi-
dphy-rx
v4l2_subdev MIPI-DPHY-Konfiguration
rkisp-bridge-ispp v4l2_subdev Überträgt YUV-Bilder vom ISP an ISPP
rkispp_input_image v4l2_vdevoutput Liest YUV-Bilder aus DDR in ISPP
rkisp-isp-subdev v4l2_subdev Format und Größe am Sink-Pad entsprechen der ISP-Ausgabe.
Maximale Größe: 4416x3312; minimale Größe: 66x258.
rkispp_m_bypass v4l2_vdev
capture
Volle Auflösung und YUV-Format
rkispp_scale0 v4l2_vdev
capture
Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis: [1 8].
Maximale Breite: 3264 für yuv422, 2080 für yuv420.
rkispp_scale1 v4l2_vdev
capture
Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis: [2 8]; maximale Breite: 1280.
rkispp_scale2 v4l2_vdev
capture
Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis: [2 8]; maximale Breite: 1280.

ISP-HDR-Modus

RKISP2 unterstützt MIPI-Sensoren mit HDR-Ausgabe aus 3 oder 2 Bildern. Die Hardware erfasst die Daten über 3 beziehungsweise 2 dmatx in DDR und liest sie anschließend über 3 beziehungsweise 2 dmarx in den ISP. Dort werden die Bilder zusammengeführt. Treiberpipeline:

Englische Originalabbildung 3, PDF-Seite 10

Englische Originalabbildung 3, PDF-Seite 10

Englische Originalabbildung 4, PDF-Seite 10

Englische Originalabbildung 4, PDF-Seite 10

Das CSI-Subdevice ermittelt über get_fmt die Ausgabeinformationen des Sensortreibers in mehreren Pad-Formaten, die den Source-Pads von CSI entsprechen.

Zur konkreten Konfiguration des MIPI-Sensortreibers siehe die Schritte zur Treiberportierung.

Name Name Beschreibung
rkisp-isp-
subdev
Sensor
pad0
ISP erfasst Breite, Höhe und Format der Sensorausgabe auf vc0 (Standard),
üblicherweise für den linearen Modus.
rkisp_rawwr0 Sensor
pad1
Rawwr0 erfasst Breite, Höhe und Format der Sensorausgabe auf vcX
rkisp_rawwr1 Sensor
pad2
Rawwr1 erfasst Breite, Höhe und Format der Sensorausgabe auf vcX
rkisp_rawwr2 Sensor
pad3
Rawwr2 erfasst Breite, Höhe und Format der Sensorausgabe auf vcX
rkisp_rawwr3 Sensor
pad4
Rawwr3 erfasst Breite, Höhe und Format der Sensorausgabe auf vcX

RKVICAP-Treiber

Frameworkbeschreibung

Der RKVICAP-Treiber basiert hauptsächlich auf dem V4L2-/Media-Framework. Er übernimmt Hardwarekonfiguration, Interruptverarbeitung, Pufferwechsel und das Ein-/Ausschalten von Subdevices wie MIPI DPHY und Sensor.

Bei RV1126/RV1109 besitzt VICAP zwei IP-Kerne: VICAP FULL und VICAP LITE. VICAP FULL verfügt über dvp/mipi/lvds. DVP kann gleichzeitig mit MIPI oder LVDS arbeiten, MIPI und LVDS jedoch nicht gleichzeitig. VICAP LITE besitzt nur eine LVDS-Schnittstelle und kann gleichzeitig mit VICAP FULL arbeiten. Die DVP-Schnittstelle von VICAP FULL entspricht rkvicap_dvp, dessen MIPI-/LVDS-Schnittstelle rkvicap_mipi_lvds und VICAP LITE rkvicap_lite_mipi_lvds. Jeder Knoten kann unabhängig erfassen.

Bei RK356X besitzt VICAP nur einen Kern mit DVP- und MIPI-Schnittstelle. DVP entspricht rkvicap_dvp und MIPI rkvicap_mipi_lvds, also demselben Namen wie VICAP FULL auf RV1126/RV1109. Jeder Knoten kann unabhängig erfassen.

Um die von VICAP erfassten Daten mit dem ISP-Treiber zu synchronisieren, muss der logische sditf-Knoten des VICAP-Treibers mit dem vom ISP erzeugten virtuellen Geräteknoten verknüpft werden. DVP entspricht rkvicap_dvp_sditf, die MIPI-/LVDS-Schnittstelle von VICAP FULL rkvicap_mipi_lvds_sditf und VICAP LITE rkvicap_lite_sditf.

Zur DTS-Verknüpfung der jeweiligen Schnittstelle siehe CIS-Geräteregistrierung (DTS).

Die folgende Abbildung beschreibt die Topologie des durch RKVICAP gesteuerten Geräts:

Englische Originalabbildung 5, PDF-Seite 12

Englische Originalabbildung 5, PDF-Seite 12

Unterschiede zwischen Chipversionen

SoC VI-IP VI-Schnittstelle Maximale Bayer-CIS-
Auflösung
Merkmal
RV1109 ISP20 ( ISP +
ISPP): 1
VICAP Full: 1
VICAP Lite: 1
MIPI DPHY:
2 x 4Lanes 2.5Gbps/Lane
LVDS:
2 x 4Lanes 1.0Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
3072x2048 HDR mit bis zu
3 Bildern
RK3566 ISP21 Lite: 1
VICAP Full: 1
MIPI DPHY:
2 x 2Lanes oder 1 x 4Lanes
2.5Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4096x3072 Kein HDR
RK3568 ISP21:1
VICAP Full: 1
MIPI DPHY:
2 x 2Lanes oder 1 x 4Lanes
2.5Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4096x3072 HDR mit bis zu
2 Bildern
RV1126 ISP20 ( ISP +
ISPP): 1
VICAP Full: 1
VICAP Lite: 1
MIPI DPHY:
2 x 4Lanes 2.5Gbps/Lane
LVDS:
2 x 4Lanes 1.0Gbps/Lane
DVP:
BT601 / BT656 / BT1120
pclk: 150MHz
4416x3312 HDR mit bis zu
3 Bildern

CIS-Treiber (CMOS-Bildsensor)

CIS-Geräteregistrierung (DTS)

Einzelregistrierung

MIPI-Schnittstelle

Auf RV1126 und RV1106 gibt es zwei unabhängige vollständige standardkonforme physische MIPI-CSI2-DPHYs. Sie entsprechen csi_dphy0 und csi_dphy1 im DTS; siehe RV1126.dtsi. Eigenschaften:

Höchstens 4 Daten-Lanes.

Maximale Datenrate 2.5Gbps/lane.

RK356X besitzt nur eine standardkonforme physische MIPI-CSI2-DPHY. Sie arbeitet im vollständigen oder aufgeteilten Modus und kann drei logische DPHYs bilden: csi2_dphy0/csi2_dphy1/csi2_dphy2; siehe rk3568.dtsi. Eigenschaften:

Vollständiger Modus

Nur csi2_dphy0 verwenden. csi2_dphy0 und csi2_dphy1/csi2_dphy2 schließen sich gegenseitig aus und dürfen nicht gleichzeitig verwendet werden.

Höchstens 4 Daten-Lanes.

Maximale Datenrate 2.5Gbps/lane.

Aufgeteilter Modus

Nur csi2_dphy1 und csi2_dphy2 verwenden; sie schließen die gleichzeitige Verwendung von csi2_dphy0 aus.

csi2_dphy1 und csi2_dphy2 können gleichzeitig verwendet werden.

csi2_dphy1 und csi2_dphy2 besitzen jeweils höchstens 2 Daten-Lanes.

csi2_dphy1 entspricht lane0/lane1 der physischen DPHY.

csi2_dphy2 entspricht lane2/lane3 der physischen DPHY.

Maximale Datenrate 2.5Gbps/lane.

Konkrete DTS-Anwendungsfälle zeigen die folgenden Beispiele.

Verknüpfung mit dem ISP
Plattform RV1126/RV1106

Nachfolgend dienen RV1126 ISP und os04a10 als Beispiel.

Verknüpfung: sensor->csi_dphy->isp->ispp

arch/arm/boot/dts/RV1126-evb-v10.dtsi

Wichtige Konfigurationspunkte

data-lanes muss die Anzahl verwendeter Lanes angeben; andernfalls wird die Schnittstelle nicht als MIPI erkannt.

  cam_ircut0: cam_ircut {
      status = "okay";
      compatible = "rockchip,ircut";
      ircut-open-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
      ircut-close-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      rockchip,camera-module-index = <1>;
      rockchip,camera-module-facing = "front";
  };
  os04a10: os04a10@36 {
      // Need to be consistent with the matching string in the driver
      compatible = "ovti,os04a10";
      reg = <0x36>;// sensor I2CDevice address, 7 bits
      clocks = <&cru CLK_MIPICSI_OUT>;// sensor clickinConfiguration
      clock-names = "xvclk";
      power-domains = <&power RV1126_PD_VI>;
      pinctrl-names = "rockchip,camera_default";
      pinctrl-0 = <&mipi_csi_clk0>;// pinctl Set up
      //power supply
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // power Pin assignment and effective level
      pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
      // Module number, this number should not be repeated
      rockchip,camera-module-index = <1>;
      // Module orientation which are "back" and "front"
      rockchip,camera-module-facing = "front";
      // name of moudle
      rockchip,camera-module-name = "CMK-OT1607-FV1";
      // lens name
      rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
      //ir cut device
      ir-cut = <&cam_ircut0>;
      port {
          ucam_out0: endpoint {
              // mipi dphy port
              remote-endpoint = <&mipi_in_ucam0>;
              // number of mipi lane,1lane is <1>, 4lanei s <1 2 3 4>
              data-lanes = <1 2 3 4>;
          };
      };
   };
  &csi_dphy0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // mipi lane number,1lane is <1>, 4lane is <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // name of isp port
                  remote-endpoint = <&isp_in>;
              };
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  // name of mipi dphy port
                  remote-endpoint = <&csidphy0_out>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_out: endpoint@1 {
                  reg = <1>;
                  // ispp port name, isp output to ispp
                  remote-endpoint = <&ispp0_in>;
              };
          };
      };
  };
  &rkispp {
      status = "okay";
  };
  &rkispp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          Ispp0_in: endpoint@0 {
              reg = <0>;
              // isp port name, ispp input
              remote-endpoint = <&isp0_out>;
          };
      };
  };
Plattform RK356X

Als Beispiel dienen rk3566 ISP und gc8034 mit 4 Lanes:

Verknüpfung: sensor->csi2_dphy0->isp; wichtige Konfigurationspunkte

data-lanes konfigurieren und den Knoten csi2_dphy_hw aktivieren.

      /* full mode: lane0-3 */
      gc8034: gc8034@37 {
          //Need to be consistent with the matching string in the driver
          compatible = "galaxycore,gc8034";
          status = "okay";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // sensor mclk Source configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RK3568_PD_VI>;
          //sensor mclk pinctl set up
          pinctrl-names = "default";
          pinctrl-0 = <&cif_clk>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_LOW>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "back";
          // moudle name
          rockchip,camera-module-name = "RK-CMK-8M-2-v1";
          // lens name
          rockchip,camera-module-lens-name = "CK8401";
          port {
              gc8034_out: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&dphy0_in>;
                  // csi2 dphy lane number,1lane is <1>, 4lane is <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
      };
      &csi2_dphy_hw {
         status = "okay";
      };
      &csi2_dphy0 {
          //csi2_dphy0 is not used simultaneously with csi2_dphy1/csi2_dphy2, mutually exclusive
          status = "okay";
          /*
           * dphy0 only used for full mode,
           * full mode and split mode are mutually exclusive
           */
          ports {
              #address-cells = <1>;
              #size-cells = <0>;
              port@0 {
                  reg = <0>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_in: endpoint@1 {
                      reg = <1>;
                      // The port name of the sensor
                      remote-endpoint = <&gc8034_out>;
                      // csi2 dphy lane number
                      data-lanes = <1 2 3 4>;
                  };
              };
              port@1 {
                  reg = <1>;
                  #address-cells = <1>;
                  #size-cells = <0>;
                  dphy0_out: endpoint@1 {
                      reg = <1>;
                      // The port name of the isp
                      remote-endpoint = <&isp0_in>;
                  };
              };
          };
      };
  &rkisp {
      status = "okay";
  };
  &rkisp_mmu {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      port {
          #address-cells = <1>;
          #size-cells = <0>;
          isp0_in: endpoint@0 {
              reg = <0>;
              // The port name of csi2 dphy
              remote-endpoint = <&dphy0_out>;
          };
      };
  };
Verknüpfung mit VICAP
Plattform RV1126/RV1109

Beispiel für die Verbindung des MIPI-os04a10 mit 4 Lanes zu VICAP:

Verknüpfung: sensor->csi dphy->mipi csi host->vicap; wichtige Konfigurationspunkte

data-lanes muss die verwendete Lane-Anzahl angeben, andernfalls wird MIPI nicht erkannt. Die DPHY muss mit dem CSI-Host-Knoten verknüpft sein.

  os04a10: os04a10@36 {
          // Need to be consistent with the matching string in the driver
          compatible = "ovti,os04a10";
          // sensor I2C device address, 7 bits
          reg = <0x36>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //sensor mclk pinctlset up
          pinctrl-names = "rockchip,camera_default";
          pinctrl-0 = <&mipicsi_clk0>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // lens name
          rockchip,camera-module-lens-name = "M12-40IRC-4MP-F16";
          // ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&mipi_in_ucam0>;
                  // csi2 dphy lane number,1lane is <1>, 4lane is  <1 2 3 4>
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  &csi_dphy0 {
      //csi2_dphy0 is not simultaneous use with csi2_dphy1/csi2_dphy2 , mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // csi2 dphy lane number
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // csi2 host port name
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // csi2 dphy port name
                  remote-endpoint = <&csidphy0_out>;
                  // csi2 host lane number
                  data-lanes = <1 2 3 4>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // Port name on the vicap side
                  remote-endpoint = <&cif_mipi_in>;
                  // csi2 host lane number
                  data-lanes = <1 2 3 4>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          cif_mipi_in: endpoint {
              // csi2 hostport name
              remote-endpoint = <&mipi_csi2_output>;
              // vicap lane number
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* sditf endpoint */
          mipi_lvds_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //mipi csi2 dphy lane number, consistent with sensor
              data-lanes = <1 2 3 4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //Endpoint name of vicap sditf
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
Plattform RK356X

Beispiel für gc5025 mit 2 Lanes an lane2/lane3 der MIPI-CSI2-DPHY auf rk3566 evb2:

Verknüpfung: sensor->csi2 dphy->mipi csi host->vicap; wichtige Konfigurationspunkte

data-lanes muss die verwendete Lane-Anzahl angeben, andernfalls wird MIPI nicht erkannt. Die DPHY muss mit dem CSI-Host-Knoten verknüpft und der Knoten csi2 dphy hw aktiviert werden.

  /* split mode: lane:2/3 */
  gc5025: gc5025@37 {
          status = "okay";
          // Need to be consistent with the matching string in the driver
          compatible = "galaxycore,gc5025";
          // sensor I2C device address, 7 bits
          reg = <0x37>;
          // sensor mclkSource configuration
          clocks = <&pmucru CLK_WIFI>;
          clock-names = "xvclk";
          //sensor mclk pinctlset up
          pinctrl-names = "default";
          pinctrl-0 = <&refclk_pins>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
          //sensor Related power domain enable
          power-domains = <&power RK3568_PD_VI>;
          /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "TongJu";
          // lens name
          rockchip,camera-module-lens-name = "CHT842-MD";
          port {
              gc5025_out: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&dphy2_in>;
                  // csi2 dphy lane name,2lane is <1 2>, 4lane is <1 2 3 4>
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
          status = "okay";
   };
  &csi2_dphy2 {
      //csi2_dphy0 is not used simultaneously with csi2_dphy1/csi2_dphy2, mutually
  exclusivee;can be used in parallel with csi2_dphy1
      status = "okay";
      /*
       * dphy2 only used for split mode,
       * can be used  concurrently  with dphy1
       * full mode and split mode are mutually exclusive
       */
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&gc5025_out>;
                  // csi2 dphy lane name
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  // csi2 host port name
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  // csi2 dphy port name
                  remote-endpoint = <&dphy2_out>;
                  // csi2 host lane number
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  // vicapport name
                  remote-endpoint = <&cif_mipi_in>;
                  // csi2 host lane number
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              // csi2 hostport name
              remote-endpoint = <&mipi_csi2_output>;
              // vicap lane number
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          /* MIPI CSI-2 endpoint */
          mipi_lvds_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //mipi csi2 dphy lane number,consistent with sensor
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //vicap mipi sditf port name
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };
LVDS-Schnittstelle
Verknüpfung mit VICAP
Plattform RV1126/RV1109

Am Beispiel von imx327 mit 4 Lanes ergibt sich folgende Verknüpfung:

Verknüpfung: sensor->csi dphy->vicap; wichtige Konfigurationspunkte

Die DPHY darf nicht mit dem CSI-Host-Knoten verknüpft werden, sonst werden keine Daten empfangen. data-lanes muss die tatsächlich verwendete Lane-Anzahl angeben, sonst werden ebenfalls keine Daten empfangen. bus-type muss auf 3 gesetzt werden; andernfalls wird die Schnittstelle nicht als LVDS erkannt und die Verknüpfung scheitert.

  imx327: imx327@1a {
          // Need to be consistent with the matching string in the driver
          compatible = "sony,imx327";
          // sensor I2C device address, 7 bits
          reg = <0x1a>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_MIPICSI_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          power-domains = <&power RV1126_PD_VI>;
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          //sensor mclk pinctlset up
          pinctrl-names = "default";
          pinctrl-0 = <&mipicsi_clk0>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
          // resetPin assignment and effective level
          reset-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <1>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "front";
          // module name
          rockchip,camera-module-name = "CMK-OT1607-FV1";
          // lens name
          rockchip,camera-module-lens-name = "M12-4IR-4MP-F16";
          // ircut name
          ir-cut = <&cam_ircut0>;
          port {
              ucam_out0: endpoint {
                  // csi2 dphy port name
                  remote-endpoint = <&mipi_in_ucam0>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
  };
  &csi_dphy0 {
      //csi2_dphy0 is not simultaneous use with csi2_dphy1/csi2_dphy2, mutually exclusive
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_in_ucam0: endpoint@1 {
                  reg = <1>;
                  // The port name of the sensor
                  remote-endpoint = <&ucam_out0>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              csidphy0_out: endpoint@0 {
                  reg = <0>;
                  // vicap liteport name
                  remote-endpoint = <&cif_lite_lvds_in>;
                  // lvds lane number,1lane is <1>, 4lane is <4>,must be specified
                  data-lanes = <4>;
                  // Type of lvds interface, must be specified
                  bus-type = <3>;
              };
          };
      };
  };
  &rkcif_lite_mipi_lvds {
      status = "okay";
      port {
          /* lvds endpoint */
          cif_lite_lvds_in: endpoint {
              // csi2 dphy port name
              remote-endpoint = <&csidphy0_out>;
              //csi2 dphy lvds lane name,1lane is <1>, 4lane is <4>,must be specified
              data-lanes = <4>;
              //Type of lvds interface, must be specified
              bus-type = <3>;
          };
      };
  };
  &rkcif_lite_sditf {
      status = "okay";
      port {
          /* lvds endpoint */
          lite_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //csi2 dphy lane number, consistent with sensor
              data-lanes = <4>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //lite vicap lvds sditf port name
                  remote-endpoint = <&lite_sditf>;
              };
          };
      };
  };
DVP-Schnittstelle mit VICAP verknüpfen

Auf RV1126/RV1106/RK356X ist die DTS-Konfiguration der jeweiligen DVP-Schnittstellen gleich.

BT601

Am Beispiel von ar0230 BT601 ergibt sich folgende Verknüpfung:

Verknüpfung: sensor->vicap; wichtige Konfigurationspunkte

hsync-active/vsync-active müssen gesetzt sein, damit die asynchrone Registrierung des V4L2-Frameworks BT601 erkennt. Ohne diese Konfiguration wird BT656 erkannt. pclk-sample/bus-width sind optional. In g_mbus_config des Sensortreibers muss das Flag die gültige Polarität von hsync-acitve/vsync-active/pclk-ative des aktuellen Sensors angeben, andernfalls werden keine Daten empfangen. Die fehlerhaften Schreibweisen der Quelle bleiben erhalten. pinctrl muss referenziert werden, damit das entsprechende IOMUX für die BT601-GPIOs eingerichtet wird; andernfalls scheitert ebenfalls der Datenempfang.

Beispielcode für g_mbus_config:

  static int ar0230_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_PARALLEL;
      config->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
              V4L2_MBUS_VSYNC_ACTIVE_HIGH |
              V4L2_MBUS_PCLK_SAMPLE_FALLING;
      return 0;
  }

DTS-Konfigurationsbeispiel:

  ar0230: ar0230@10 {
          // Need to be consistent with the matching string in the driver
          compatible = "aptina,ar0230";
          // sensor I2C device address, 7 bits
          reg = <0x10>;
          // sensor mclkSource configuration
          clocks = <&cru CLK_CIF_OUT>;
          clock-names = "xvclk";
          //sensor Related power domain enable
          avdd-supply = <&vcc_avdd>;
          dovdd-supply = <&vcc_dovdd>;
          dvdd-supply = <&vcc_dvdd>;
          power-domains = <&power RV1126_PD_VI>;
          // powerdownPin assignment and effective level
          pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
          /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
          //Configure dvp related data pins and clock pins
          pinctrl-names = "default";
          pinctrl-0 = <&cifm0_dvp_ctl>;
          // Module number, this number should not be repeated
          rockchip,camera-module-index = <0>;
          // Module orientation, there are "back" and "front"
          rockchip,camera-module-facing = "back";
          // module name
          rockchip,camera-module-name = "CMK-OT0836-PT2";
          // lens name
          rockchip,camera-module-lens-name = "YT-2929";
          port {
              cam_para_out1: endpoint {
                  remote-endpoint = <&cif_para_in>;
              };
          };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //sensor port endpoint name
              remote-endpoint = <&cam_para_out1>;
              //Sensor configuration parameters
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              //Sensor configuration parameters
              bus-width = <12>;
              hsync-active = <1>;
              vsync-active = <1>;
              pclk-sample = <0>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //dvp sditf port name
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };
BT656/BT1120

BT656 und BT1120 werden im DTS gleich verwendet.

Am Beispiel von ava fpga bt1120 ergibt sich folgende Verknüpfung:

Verknüpfung: sensor->vicap; wichtige Konfigurationspunkte

hsync-active/vsync-active nicht konfigurieren; andernfalls erkennt das V4L2-Framework die Schnittstelle bei der asynchronen Registrierung als BT601.

pclk-sample/bus-width sind optional.

In g_mbus_config des Sensortreibers muss das Flag die gültige Polarität von pclk-ative des aktuellen Sensors angeben, andernfalls werden keine Daten empfangen. Die Schreibweise der Quelle bleibt erhalten.

querystd in v4l2_subdev_video_ops muss implementiert sein und die aktuelle Schnittstelle als ATSC kennzeichnen; andernfalls werden keine Daten empfangen.

pinctrl muss referenziert werden, um das entsprechende IOMUX für die BT656-/BT1120-GPIOs einzurichten; andernfalls scheitert der Datenempfang.

Beispielcode für g_mbus_config:

  static int avafpga_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)
  {
      config->type = V4L2_MBUS_BT656;
      config->flags = V4L2_MBUS_PCLK_SAMPLE_RISING;
      return 0;
  }

Beispiel für querystd:

  static int avafpga_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
  {
      *std = V4L2_STD_ATSC;
      return 0;
  }

DTS-Konfigurationsbeispiel:

  avafpga: avafpga@70 {
      // Need to be consistent with the matching string in the driver
      compatible = "ava,fpga";
      // sensor I2C device address, 7 bits
      reg = <0x10>;
      // sensor mclkSource configuration
      clocks = <&cru CLK_CIF_OUT>;
      clock-names = "xvclk";
      //sensor Related power domain enable
      avdd-supply = <&vcc_avdd>;
      dovdd-supply = <&vcc_dovdd>;
      dvdd-supply = <&vcc_dvdd>;
      // powerdownPin assignment and effective level
      power-domains = <&power RV1126_PD_VI>;
      pwdn-gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
      /*reset-gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>;*/
      //Configure dvp related data pins and clock pins
      pinctrl-names = "default";
      pinctrl-0 = <&cifm0_dvp_ctl>;
      // Module number, this number should not be repeated
      rockchip,camera-module-index = <0>;
      // Module orientation, there are "back" and "front"
      rockchip,camera-module-facing = "back";
      // module name
      rockchip,camera-module-name = "CMK-OT0836-PT2";
      // lens name
      rockchip,camera-module-lens-name = "YT-2929";
      port {
          cam_para_out2: endpoint {
              remote-endpoint = <&cif_para_in>;
          };
      };
  };
  &rkcif_dvp {
      status = "okay";
      port {
          /* Parallel bus endpoint */
          cif_para_in: endpoint {
              //sensor port endpoint name
              remote-endpoint = <&cam_para_out2>;
              //Sensor configuration parameters,Optional
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkcif_dvp_sditf {
      status = "okay";
      port {
          /* parallel endpoint */
          dvp_sditf: endpoint {
              //isp Virtual device port name
              remote-endpoint = <&isp_in>;
              bus-width = <16>;
              pclk-sample = <1>;
          };
      };
  };
  &rkisp {
      status = "okay";
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp_in: endpoint@0 {
                  reg = <0>;
                  //dvp sditf port name
                  remote-endpoint = <&dvp_sditf>;
              };
          };
      };
  };

Mehrere Sensoren registrieren

Ein einzelner Hardware-ISP bildet mehrere virtuelle Geräte und verarbeitet RAW-Daten mehrerer Sensoren im Zeitmultiplex.

Plattform RV1126/RV1106: isp0->ispp0 und isp1->ispp1 sind in RV1126.dtsi festgelegt; MIPI- oder CIF-Eingang zum ISP ist wählbar.

Beispiel:

sensor0->csi_dphy0->csi2->vicap->isp0->ispp0 sensor1->csi_dphy1->isp1->ispp1

Referenz: arch/arm/boot/dts/RV1109-evb-ddr3-v12-facial-gate.dts mit gc2053->csi_dphy0->csi2->cif->isp1->ispp1 und ov2718->csi_dphy1->isp0->ispp0. Bei unterschiedlichen Auflösungen ist folgende Konfiguration besonders wichtig:

&rkispp { status = "okay"; /* the max input w h and fps of mulit sensor */ max-input = <2688 1520 30>;//Take the maximum width and height and frame rate of different sensors };
Plattform RK3566/RK3568

Beispiel:

ov5695->dphy1->isp_vir0

gc5025->dphy2->csi2->vicap->isp_vir1

  ov5695: ov5695@36 {
          status = "okay";
          ...
          port {
              ov5695_out: endpoint {
                  remote-endpoint = <&dphy1_in>;
                  data-lanes = <1 2>;
              };
          };
  };
  gc5025: gc5025@37 {
          status = "okay";
          ...
          port {
              gc5025_out: endpoint {
                  remote-endpoint = <&dphy2_in>;
                  data-lanes = <1 2>;
              };
          };
  };
   &csi2_dphy_hw {
          status = "okay";
   };
  &csi2_dphy1 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&ov5695_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy1_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&isp0_in>;
              };
          };
      };
  };
  &csi2_dphy2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_in: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&gc5025_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              dphy2_out: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&mipi_csi2_input>;
              };
          };
      };
  };
  &mipi_csi2 {
      status = "okay";
      ports {
          #address-cells = <1>;
          #size-cells = <0>;
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_input: endpoint@1 {
                  reg = <1>;
                  remote-endpoint = <&dphy2_out>;
                  data-lanes = <1 2>;
              };
          };
          port@1 {
              reg = <1>;
              #address-cells = <1>;
              #size-cells = <0>;
              mipi_csi2_output: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&cif_mipi_in>;
                  data-lanes = <1 2>;
              };
          };
      };
  };
  &rkcif_mipi_lvds {
      status = "okay";
      port {
          cif_mipi_in: endpoint {
              remote-endpoint = <&mipi_csi2_output>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkcif_mipi_lvds_sditf {
      status = "okay";
      port {
          mipi_lvds_sditf: endpoint {
              remote-endpoint = <&isp1_in>;
              data-lanes = <1 2>;
          };
      };
  };
  &rkisp {
      status = "okay";
      /* the max input w h and fps of mulit sensor */
      max-input = <2592 1944 30>;
  };
  &rkisp_vir0 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp0_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&dphy1_out>;
              };
          };
      };
  };
  &rkisp_vir1 {
      status = "okay";
      ports {
          port@0 {
              reg = <0>;
              #address-cells = <1>;
              #size-cells = <0>;
              isp1_in: endpoint@0 {
                  reg = <0>;
                  remote-endpoint = <&mipi_lvds_sditf>;
              };
          };
      };
  };

Beschreibung des CIS-Treibers

Der Kamerasensor kommuniziert über I2C mit dem Host. Sein Treiber ist derzeit als I2C-Gerätetreiber implementiert und verwendet zugleich die V4L2-Subdevice-Schnittstelle zur Kommunikation mit dem Hosttreiber.

Kurze Beschreibung der Datentypen

struct i2c_driver

[Beschreibung]

Definiert Informationen des I2C-Gerätetreibers.

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver Enthält im Gerätetreibermodell hauptsächlich Treibername und of_match_table
zum Abgleich mit dem im DTS registrierten Gerät. Stimmen die compatible-Felder
von of_match_table und DTS überein, wird .probe aufgerufen.
@id_table Liste der unterstützten I2C-Geräte. Verwendet der Kernel nicht of_match_table
und DTS-Geräteregistrierung zum Abgleich, greift er auf diese Tabelle zurück.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  #if IS_ENABLED(CONFIG_OF)
  static const struct of_device_id os04a10_of_match[] = {
      { .compatible = "ovti,os04a10" },
      {},
  };
  MODULE_DEVICE_TABLE(of, os04a10_of_match);
  #endif
  static const struct i2c_device_id os04a10_match_id[] = {
      { "ovti,os04a10", 0 },
      { },
  };
  static struct i2c_driver os04a10_i2c_driver = {
      .driver = {
          .name = OS04A10_NAME,
          .pm = &os04a10_pm_ops,
          .of_match_table = of_match_ptr(os04a10_of_match),
      },
      .probe      = &os04a10_probe,
      .remove     = &os04a10_remove,
      .id_table   = os04a10_match_id,
  };
  static int __init sensor_mod_init(void)
  {
      return i2c_add_driver(&os04a10_i2c_driver);
  }
  static void __exit sensor_mod_exit(void)
  {
      i2c_del_driver(&os04a10_i2c_driver);
  }
  device_initcall_sync(sensor_mod_init);
  module_exit(sensor_mod_exit);
struct v4l2_subdev_ops

[Beschreibung]

Definiert die Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_ops {
      const struct v4l2_subdev_core_ops   *core;
      ……
      const struct v4l2_subdev_video_ops  *video;
      ……
      const struct v4l2_subdev_pad_ops    *pad;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.core Definiert die Core-Operations-Callbacks für Subdevices
.video Callbacks bei Öffnung des V4L-Geräts im Videomodus
.pad Operationen auf Pad-Ebene eines V4L2-Subdevices

[Beispiel]

  static const struct v4l2_subdev_ops os04a10_subdev_ops = {
      .core   = &os04a10_core_ops,
      .video  = &os04a10_video_ops,
      .pad    = &os04a10_pad_ops,
  };
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      int (*s_power)(struct v4l2_subdev *sd, int on);
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
          unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.s_power Versetzt das Subdevice in den Energiesparmodus (on == 0)
oder Normalbetrieb (on == 1).
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops os04a10_core_ops = {
      .s_power = os04a10_s_power,
      .ioctl = os04a10_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = os04a10_compat_ioctl32,
  #endif
  };
Folgende private ioctls dienen derzeit zur Modulabfrage sowie zum Abfragen und Setzen von OTP-Informationen
Privates ioctl Beschreibung
RKMODULE_GET_MODULE_INFO Modulinformationen abrufen; siehe struct rkmodule_inf.
RKMODULE_AWB_CFG AWB-Kompensation des Sensors umschalten. Ist im Modul kein Golden-AWB-Wert
gespeichert, kann er hier gesetzt werden. Siehe struct rkmodule awb_cfg;
die Schreibweise der Quelle bleibt erhalten.
RKMODULE_LSC_CFG LSC-Kompensation des Sensors umschalten; siehe struct rkmodule_lsc_cfg.
PREISP_CMD_SET_HDRAE_EXP HDR-Belichtung setzen; siehe struct preisp_hdrae_exp_s.
RKMODULE_SET_HDR_CFG Zwischen normalem und HDR-Modus umschalten. Der Treiber muss
beide Konfigurationsgruppen unterstützen. Siehe struct rkmodule_hdr_cfg.
RKMODULE_GET_HDR_CFG Aktuellen HDR-Modus abfragen; siehe struct rkmodule_hdr_cfg.
RKMODULE_SET_CONVERSION_GAIN Konversionsverstärkung im linearen Modus setzen, z. B. für imx347
oder os04a10 mit entsprechender Funktion. Unterstützt der Sensor diese nicht,
kann die Implementierung entfallen.
struct v4l2_subdev_video_ops

[Beschreibung]

Callbacks bei Öffnung des V4L-Geräts im Videomodus.

[Definition]

  struct v4l2_subdev_video_ops {
      ……
      int (*s_stream)(struct v4l2_subdev *sd, int enable);
      ……
      int (*g_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_frame_interval *interval);
      int (*g_mbus_config)(struct v4l2_subdev *sd,
                 struct v4l2_mbus_config *cfg);
   ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.g_frame_interval Callback der ioctl-Behandlung VIDIOC_SUBDEV_G_FRAME_INTERVAL
.s_stream Meldet dem Treiber den bevorstehenden Start oder erfolgten Stopp eines Videostreams
.g_mbus_config Unterstützte Media-Bus-Konfigurationen abfragen

[Beispiel]

  static const struct v4l2_subdev_video_ops os04a10_video_ops = {
      .s_stream = os04a10_s_stream,
      .g_frame_interval = os04a10_g_frame_interval,
      .g_mbus_config = os04a10_g_mbus_config,
  };
struct v4l2_subdev_pad_ops

[Beschreibung]

Operationen auf Pad-Ebene eines V4L2-Subdevices.

[Definition]

  struct v4l2_subdev_pad_ops {
      ……
      int (*enum_mbus_code)(struct v4l2_subdev *sd,
                 struct v4l2_subdev_pad_config *cfg,
                 struct v4l2_subdev_mbus_code_enum *code);
      int (*enum_frame_size)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_size_enum *fse);
      int (*get_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*set_fmt)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_format *format);
      int (*enum_frame_interval)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_frame_interval_enum *fie);
      int (*get_selection)(struct v4l2_subdev *sd,
                  struct v4l2_subdev_pad_config *cfg,
                  struct v4l2_subdev_selection *sel);
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
. enum_mbus_code Callback der ioctl-Behandlung VIDIOC_SUBDEV_ENUM_MBUS_CODE
. enum_frame_size Callback der ioctl-Behandlung VIDIOC_SUBDEV_ENUM_FRAME_SIZE
.s_fmt Callback der ioctl-Behandlung VIDIOC_SUBDEV_S_FMT
.g_fmt Callback der ioctl-Behandlung VIDIOC_SUBDEV_G_FMT
.enum_frame_interval Callback der ioctl-Behandlung VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL()
.get_selection Callback der ioctl-Behandlung VIDIOC_SUBDEV_G_SELECTION()

[Beispiel]

  static const struct v4l2_subdev_pad_ops os04a10_pad_ops = {
      .enum_mbus_code = os04a10_enum_mbus_code,
      .enum_frame_size = os04a10_enum_frame_sizes,
      .enum_frame_interval = os04a10_enum_frame_interval,
      .get_fmt = os04a10_get_fmt,
      .set_fmt = os04a10_set_fmt,
  };
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.s_ctrl Setzt den neuen Steuerwert tatsächlich.

[Beispiel]

  static const struct v4l2_ctrl_ops os04a10_ctrl_ops = {
      .s_ctrl = os04a10_set_ctrl,
  };

Der RKISP-Treiber verlangt die vom Framework bereitgestellten Benutzer-Steuerelemente. Der Kamerasensortreiber muss die folgenden Steuerfunktionen implementieren; siehe Liste 1 der V4L2-Controls des CIS-Treibers.

struct xxxx_mode

[Beschreibung]

Informationen zu den einzelnen vom Sensor unterstützten Modi.

Diese Struktur findet sich häufig in Sensortreibern, obwohl der V4L2-Standard sie nicht vorschreibt.

[Definition]

  struct xxxx_mode {
      u32 bus_fmt;
      u32 width;
      u32 height;
      struct v4l2_fract max_fps;
      u32 hts_def;
      u32 vts_def;
      u32 exp_def;
      const struct regval *reg_list;
      u32 hdr_mode;
      u32 vc[PAD_MAX];
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.bus_fmt Sensorausgabeformat; siehe MEDIA_BUS_FMT-Tabelle
.width Aktive Bildbreite; muss der Ausgabe des aktuell konfigurierten Sensors entsprechen
.height Aktive Bildhöhe; muss der Ausgabe des aktuell konfigurierten Sensors entsprechen
.max_fps Bildrate; denominator/numerator ergibt fps
hts_def Standard-HTS: aktive Bildbreite + HBLANK
vts_def Standard-VTS: aktive Bildhöhe + VBLANK
exp_def Standardbelichtungszeit
*reg_list Registerliste
.hdr_mode Sensorbetriebsmodus: linear, HDR-Zusammenführung aus zwei
oder drei Bildern
.vc[PAD_MAX] MIPI-VC-Kanal konfigurieren

[Beispiel]

   enum os04a10_max_pad {
      PAD0, /* link to isp */
      PAD1, /* link to csi rawwr0 | hdr x2:L x3:M */
      PAD2, /* link to csi rawwr1 | hdr    x3:L */
      PAD3, /* link to csi rawwr2 | hdr x2:M x3:S */
      PAD_MAX,
  };
  static const struct os04a10_mode supported_modes[] = {
      {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 300372,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0984,
          .reg_list = os04a10_linear12bit_2688x1520_regs,
          .hdr_mode = NO_HDR,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
      }, {
          .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
          .width = 2688,
          .height = 1520,
          .max_fps = {
              .numerator = 10000,
              .denominator = 225000,
          },
          .exp_def = 0x0240,
          .hts_def = 0x05c4 * 2,
          .vts_def = 0x0658,
          .reg_list = os04a10_hdr12bit_2688x1520_regs,
          .hdr_mode = HDR_X2,
          .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
          .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
          .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
      },
  };
struct v4l2_mbus_framefmt

[Beschreibung]

Bildformat auf dem Media-Bus.

[Definition]

  struct v4l2_mbus_framefmt {
      __u32           width;
      __u32           height;
      __u32           code;
      __u32           field;
      __u32           colorspace;
      __u16           ycbcr_enc;
      __u16           quantization;
      __u16           xfer_func;
      __u16           reserved[11];
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
width Bildbreite
height Bildhöhe
code Verweis auf die MEDIA_BUS_FMT-Tabelle
field V4L2_FIELD_NONE: Vollbildausgabe; V4L2_FIELD_INTERLACED:
Halbbildausgabe

[Beispiel]

struct rkmodule_base_inf

[Beschreibung]

Grundlegende Modulinformationen, anhand derer die höhere Schicht die passende IQ-Konfiguration auswählt.

[Definition]

  struct rkmodule_base_inf {
      char sensor[RKMODULE_NAME_LEN];
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
sensor Sensorname aus dem Sensortreiber
module Modulname aus der DTS-Konfiguration gemäß Moduldaten
lens Objektivname aus der DTS-Konfiguration gemäß Moduldaten

[Beispiel]

struct rkmodule_fac_inf

[Beschreibung]

OTP-Werksinformationen des Moduls.

[Definition]

  struct rkmodule_fac_inf {
      __u32 flag;
      char module[RKMODULE_NAME_LEN];
      char lens[RKMODULE_NAME_LEN];
      __u32 year;
      __u32 month;
      __u32 day;
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
flag Gültigkeit dieser Informationsgruppe
module Modulname; die Kennnummer aus OTP wird in den Modulnamen umgesetzt
lens Objektivname; die Kennnummer aus OTP wird in den Objektivnamen umgesetzt
year Produktionsjahr, beispielsweise 12 für 2012
month Produktionsmonat
day Produktionstag

[Beispiel]

struct rkmodule_awb_inf

[Beschreibung]

AWB-Messinformationen aus dem Modul-OTP.

[Definition]

  struct rkmodule_awb_inf {
      __u32 flag;
      __u32 r_value;
      __u32 b_value;
      __u32 gr_value;
      __u32 gb_value;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
flag Gültigkeit dieser Informationsgruppe
r_value AWB-R-Messinformation des aktuellen Moduls
b_value AWB-B-Messinformation des aktuellen Moduls
gr_value AWB-GR-Messinformation des aktuellen Moduls
gb_value AWB-GB-Messinformation des aktuellen Moduls
golden_r_value AWB-R-Messinformation eines typischen Moduls;
falls nicht programmiert, auf 0 setzen
golden_b_value AWB-B-Messinformation eines typischen Moduls;
falls nicht programmiert, auf 0 setzen
golden_gr_value AWB-GR-Messinformation eines typischen Moduls;
falls nicht programmiert, auf 0 setzen
golden_gb_value AWB-GB-Messinformation eines typischen Moduls;
falls nicht programmiert, auf 0 setzen

[Beispiel]

struct rkmodule_lsc_inf

[Beschreibung]

LSC-Messinformationen aus dem Modul-OTP.

[Definition]

  struct rkmodule_lsc_inf {
      __u32 flag;
      __u16 lsc_w;
      __u16 lsc_h;
      __u16 decimal_bits;
      __u16 lsc_r[RKMODULE_LSCDATA_LEN];
      __u16 lsc_b[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gr[RKMODULE_LSCDATA_LEN];
      __u16 lsc_gb[RKMODULE_LSCDATA_LEN];
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
flag Gültigkeit dieser Informationsgruppe
lsc_w Tatsächliche Breite der LSC-Tabelle
lsc_h Tatsächliche Höhe der LSC-Tabelle
decimal_bits Anzahl der Nachkommastellen der LSC-Messinformation;
falls nicht verfügbar, auf 0 setzen
lsc_r LSC-R-Messinformation
lsc_b LSC-B-Messinformation
lsc_gr LSC-GR-Messinformation
lsc_gb LSC-GB-Messinformation

[Beispiel]

struct rkmodule_af_inf

[Beschreibung]

AF-Messinformationen aus dem Modul-OTP.

[Definition]

  struct rkmodule_af_inf {
      __u32 flag; // Whether this group of information is a valid flag
      __u32 vcm_start; // vcm start current
      __u32 vcm_end; // vcm termination current
      __u32 vcm_dir; // vcm measurement direction
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
flag Gültigkeit dieser Informationsgruppe
vcm_start VCM-Anlaufstrom
vcm_end VCM-Endstrom
vcm_dir VCM-Bestimmungsrichtung

[Beispiel]

struct rkmodule_inf

[Beschreibung]

Modulinformationen.

[Definition]

  struct rkmodule_inf {
      struct rkmodule_base_inf base;
      struct rkmodule_fac_inf fac;
      struct rkmodule_awb_inf awb;
      struct rkmodule_lsc_inf lsc;
      struct rkmodule_af_inf af;
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
base Grundlegende Modulinformationen
fac OTP-Werksinformationen des Moduls
awb AWB-Messinformationen aus dem Modul-OTP
lsc LSC-Messinformationen aus dem Modul-OTP
af AF-Messinformationen aus dem Modul-OTP

[Beispiel]

struct rkmodule_awb_cfg

[Beschreibung]

AWB-Konfigurationsinformationen aus dem Modul-OTP.

[Definition]

  struct rkmodule_awb_cfg {
      __u32 enable;
      __u32 golden_r_value;
      __u32 golden_b_value;
      __u32 golden_gr_value;
      __u32 golden_gb_value;
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
enable Gibt an, ob die AWB-Korrektur aktiviert ist
golden_r_value AWB-R-Messinformation eines typischen Moduls
golden_b_value AWB-B-Messinformation eines typischen Moduls
golden_gr_value AWB-GR-Messinformation eines typischen Moduls
golden_gb_value AWB-GB-Messinformation eines typischen Moduls

[Beispiel]

struct rkmodule_lsc_cfg

[Beschreibung]

LSC-Konfigurationsinformationen aus dem Modul-OTP.

[Definition]

  struct rkmodule_lsc_cfg {
      __u32 enable;
  } __attribute__ ((packed));

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
enable Gibt an, ob die LSC-Korrektur aktiviert ist

[Beispiel]

struct rkmodule_hdr_cfg

[Beschreibung]

HDR-Konfigurationsinformationen.

[Definition]

  struct rkmodule_hdr_cfg {
      __u32 hdr_mode;
      struct rkmodule_hdr_esp esp;
  } __attribute__ ((packed));
  struct rkmodule_hdr_esp {
      enum hdr_esp_mode mode;
      union {
          struct {
              __u32 padnum;
              __u32 padpix;
          } lcnt;
          struct {
              __u32 efpix;
              __u32 obpix;
          } idcd;
      } val;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
hdr_mode NO_HDR=0 // normaler Modus
HDR_X2=5 // HDR-Modus mit 2 Bildern
HDR_X3=6 // HDR-Modus mit 3 Bildern
struct rkmodule_hdr_esp Besonderer HDR-Modus
enum hdr_esp_mode HDR_NORMAL_VC=0 // normaler Modus mit virtuellen Kanälen
HDR_LINE_CNT=1 // Zeilenzählermodus (AR0239)
HDR_ID_CODE=2 // Identifikationscodemodus (IMX327)

[Beispiel]

struct preisp_hdrae_exp_s

[Beschreibung]

HDR-Belichtungsparameter.

[Definition]

  struct preisp_hdrae_exp_s {
      unsigned int long_exp_reg;
      unsigned int long_gain_reg;
      unsigned int middle_exp_reg;
      unsigned int middle_gain_reg;
      unsigned int short_exp_reg;
      unsigned int short_gain_reg;
      unsigned int long_exp_val;
      unsigned int long_gain_val;
      unsigned int middle_exp_val;
      unsigned int middle_gain_val;
      unsigned int short_exp_val;
      unsigned int short_gain_val;
      unsigned char long_cg_mode;
      unsigned char middle_cg_mode;
      unsigned char short_cg_mode;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
long_exp_reg Belichtungsregisterwert des langen Bildes
long_gain_reg Verstärkungsregisterwert des langen Bildes
middle_exp_reg Belichtungsregisterwert des mittleren Bildes
middle_gain_reg; Verstärkungsregisterwert des mittleren Bildes
short_exp_reg Belichtungsregisterwert des kurzen Bildes
short_gain_reg Verstärkungsregisterwert des kurzen Bildes
long_cg_mode Konversionsverstärkung des langen Bildes: 0 LCG, 1 HCG
middle_cg_mode Konversionsverstärkung des mittleren Bildes: 0 LCG, 1 HCG
short_cg_mode Konversionsverstärkung des kurzen Bildes: 0 LCG, 1 HCG

[Beschreibung]

Bei preisp_hdrae_exp_s sind nur die unter „Wichtige Mitglieder“ beschriebenen Parameter zu beachten. Die Formeln zur Umrechnung von Belichtung und Verstärkung in Registerwerte stehen im IQ-XML; Einzelheiten enthält dessen Formatbeschreibung. Konversionsverstärkung muss vom Sensor selbst unterstützt werden. Ist dies nicht der Fall, sind die entsprechenden Parameter nicht relevant. Für HDR2X sind die übergebenen Parameter des mittleren und kurzen Bildes in die Belichtungsregister der beiden Sensorausgabebilder einzutragen.

[Beispiel]

Kurze API-Beschreibung

xxxx_set_fmt

[Beschreibung]

Sensorausgabeformat setzen.

[Syntax]

  static int xxxx_set_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
*cfg Zeiger auf die Informationsstruktur des Subdevice-Pads Eingabe
*fmt Zeiger auf die Media-Bus-Formatstruktur auf Pad-Ebene Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_get_fmt

[Beschreibung]

Sensorausgabeformat abfragen.

[Syntax]

  static int xxxx_get_fmt(struct v4l2_subdev *sd,
                          struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
*cfg Zeiger auf die Informationsstruktur des Subdevice-Pads Eingabe
*fmt Zeiger auf die Media-Bus-Formatstruktur auf Pad-Ebene Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Siehe die MEDIA_BUS_FMT-Tabelle.

xxxx_enum_mbus_code

[Beschreibung]

Die vom Sensor ausgegebenen Busformate aufzählen.

[Syntax]

  static int xxxx_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
*cfg Zeiger auf die Informationsstruktur des Subdevice-Pads Eingabe
*code Zeiger auf die Struktur zur Aufzählung der Media-Bus-Formate Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Die folgende Tabelle fasst die zu den verschiedenen Bildtypen gehörenden Formate zusammen; siehe MEDIA_BUS_FMT-Tabelle.

xxxx_enum_frame_sizes

[Beschreibung]

Sensorausgabegrößen aufzählen.

[Syntax]

  static int xxxx_enum_frame_sizes(struct v4l2_subdev *sd,
                              struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_size_enum *fse)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
*cfg Zeiger auf die Informationsstruktur des Subdevice-Pads Eingabe
*fse Zeiger auf die Media-Bus-Bildgrößenstruktur Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_g_frame_interval

[Beschreibung]

Ausgabebildrate des Sensors abfragen.

[Syntax]

  static int xxxx_g_frame_interval(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_frame_interval *fi)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
*fi Zeiger auf die Bildratenstruktur auf Pad-Ebene Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_s_stream

[Beschreibung]

Stream-Ein- und Ausgabe einstellen.

[Syntax]

  static int xxxx_s_stream(struct v4l2_subdev *sd, int on)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
on 1: Stream-Ausgabe starten; 0: Stream-Ausgabe stoppen Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_runtime_resume

[Beschreibung]

Callback beim Einschalten des Sensors.

[Syntax]

  static int xxxx_runtime_resume(struct device *dev)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*dev Zeiger auf die Gerätestruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_runtime_suspend

[Beschreibung]

Callback beim Ausschalten des Sensors.

[Syntax]

  static int xxxx_runtime_suspend(struct device *dev)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*dev Zeiger auf die Gerätestruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_set_ctrl

[Beschreibung]

Wert des jeweiligen Steuerelements setzen.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die Struktur v4l2_ctrl Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxx_enum_frame_interval

[Beschreibung]

Die vom Sensor unterstützten Bildintervallparameter aufzählen.

[Syntax]

  static int xxxx_enum_frame_interval(struct v4l2_subdev *sd,
                      struct v4l2_subdev_pad_config *cfg,
                      struct v4l2_subdev_frame_interval_enum *fie)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Subdevice-Instanz Eingabe
*cfg Pad-Konfigurationsparameter Eingabe
*fie Bildintervallparameter Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_g_mbus_config

[Beschreibung]

Unterstützte Buskonfiguration abfragen. Unterstützt ein Sensor beispielsweise mehrere MIPI-Übertragungsmodi, können die Parameter entsprechend seinem aktuellen MIPI-Modus gemeldet werden.

[Syntax]

  static int xxxx_g_mbus_config(struct v4l2_subdev *sd,
                  struct v4l2_mbus_config *config)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*config Buskonfigurationsparameter Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_get_selection

[Beschreibung]

Beschnittparameter konfigurieren. Die ISP-Eingangsbreite muss auf 16 und die Höhe auf 8 ausgerichtet sein. Entspricht die Sensorausgabe nicht dieser Ausrichtung oder keiner Standardauflösung, kann diese Funktion die Auflösung vor dem ISP-Eingang beschneiden.

[Syntax]

  static int xxxx_get_selection(struct v4l2_subdev *sd,
  struct v4l2_subdev_pad_config *cfg,
  struct v4l2_subdev_selection *sel)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Subdevice-Instanz Eingabe
*cfg Pad-Konfigurationsparameter Eingabe
*sel Beschnittparameter Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

1. Standardmäßigen I2C-Subdevice-Treiberteil implementieren

1.1 Folgende Mitglieder gemäß der Beschreibung von struct i2c_driver implementieren:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe: 1) Beim Erfassen der CIS-Geräteressourcen werden hauptsächlich die im DTS definierten Ressourcen ausgewertet; siehe CIS-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen verwenden die Benennung rockchip, camera-module- xxx. Der Treiber übermittelt diese Ressourcen an camera_engine im Userspace, damit passende IQ-Bildparameter bestimmt werden können.

1.2) CIS-Geräteressourcen umfassen in RK-Referenztreibern normalerweise Folgendes:

Mitgliedsname Beschreibung
Betriebsreferenztakt
des CIS-Geräts
Bei einem unabhängigen externen Quarzoszillator muss diese Ressource nicht angefordert werden.
Das RK-Referenzdesign verwendet normalerweise einen AP-Ausgabetakt, der angefordert werden muss.
Üblicher Name: xvclk.
Steuer-GPIOs
des CIS-Geräts
Beispielsweise Reset-Pin, in der Quelle „Resst“, und Powerdown-Pin
Steuerbare Stromversorgung
des CIS-Geräts
Passende Software-Ressourcen zur Versorgungskontrolle gemäß Hardwaredesign anfordern,
beispielsweise GPIO oder Regulator.

1.3) CIS-Geräte-ID prüfen. Nach dem Anfordern der nötigen Ressourcen sollte der Treiber die Geräte-ID lesen, um die Hardware zu überprüfen. Dieser Schritt ist jedoch nicht zwingend.

1.4) CIS-V4L2-Gerät und Media-Entities initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der RK-CIS-Treiber verlangt einen eigenen Geräteknoten des Subdevices für den Zugriff durch rk_aiq im Userspace; darüber wird die Belichtung gesteuert.

Media-Entity: media_entity_init

2. Den V4L2-Subdevice-Treiber anhand von struct v4l2_subdev_ops implementieren, insbesondere die folgenden 3 Mitglieder:

  struct v4l2_subdev_core_ops
  struct v4l2_subdev_video_ops
  struct v4l2_subdev_pad_ops

2.1 Die Callbacks gemäß struct v4l2_subdev_core_ops implementieren, insbesondere:

.s_power.ioctl
.compat_ioctl32

Die über ioctl implementierten privaten RK-Steuerbefehle umfassen:

Mitgliedsname Beschreibung
RKMODULE_GET_MODULE_INFO Übermittelt im DTS definierte Modulinformationen wie den Modulnamen
an camera_engine.
RKMODULE_AWB_CFG Bei aktivierten Modul-OTP-Informationen übermittelt camera_engine damit
den AWB-Kalibrierwert eines typischen Moduls. Der CIS-Treiber vergleicht ihn mit dem
AWB-Kalibrierwert des aktuellen Moduls, berechnet R/B Gain und setzt diese
im CIS-MWB-Modul.
RKMODULE_LSC_CFG Bei aktivierten Modul-OTP-Informationen steuert camera_engine damit
die Aktivierung der LSC-Kalibrierwerte.
PREISP_CMD_SET_HDRAE_EXP HDR-Belichtungseinstellungen; siehe struct preisp_hdrae_exp_s in diesem Dokument.
RKMODULE_SET_HDR_CFG Zwischen HDR- und Normalmodus wechseln. Der Treiber muss beide
Konfigurationsgruppen unterstützen; siehe struct rkmodule_hdr_cfg.
RKMODULE_GET_HDR_CFG Aktuellen HDR-Modus abfragen; siehe struct rkmodule_hdr_cfg.
RKMODULE_SET_CONVERSION_GAIN Konversionsverstärkung im linearen Modus setzen, z. B. bei imx347 oder
os04a10. Hohe Konversionsverstärkung kann bei geringer Beleuchtung ein besseres
Signal-Rausch-Verhältnis liefern. Ohne Sensorunterstützung kann die Implementierung entfallen.

2.2 Die Callbacks gemäß struct v4l2_subdev_video_ops implementieren, insbesondere:

Mitgliedsname Beschreibung
.s_stream Datenstrom ein-/ausschalten. Bei kontinuierlichem MIPI-Takt muss der Datenstrom
in diesem Callback gestartet werden. Ein vorzeitiger Start verhindert die Erkennung
des MIPI-LP-Zustands.
.g_frame_interval Bildintervallparameter beziehungsweise Bildrate abfragen
.g_mbus_config Buskonfiguration abfragen. Unterstützt der MIPI-Sensortreiber verschiedene
Lane-Konfigurationen oder HDR, wird die MIPI-Konfiguration des aktuellen Betriebsmodus geliefert.

2.3 Die Callbacks gemäß struct v4l2_subdev_pad_ops implementieren, insbesondere:

Mitgliedsname Beschreibung
.enum_mbus_code Vom aktuellen CIS-Treiber unterstützte Datenformate aufzählen
.enum_frame_size Vom aktuellen CIS-Treiber unterstützte Auflösungen aufzählen
.get_fmt Der RKISP-Treiber fragt darüber das CIS-Ausgabeformat ab; zwingend zu implementieren.
Formate für Bayer-RAW-, SoC-YUV- und Schwarzweiß-RAW-Sensoren siehe MEDIA_BUS_FMT-Tabelle.
Zur Halbbildausgabe siehe struct v4l2_mbus_framefmt.
.set_fmt Ausgabeformat und Auflösung des CIS-Treibers setzen; zwingend zu implementieren
.enum_frame_interval Unterstützte Sensor-Bildintervalle einschließlich Auflösung aufzählen
.get_selection Beschnittparameter konfigurieren. ISP-Eingangsbreite auf 16,
Eingangshöhe auf 8 ausrichten.

2.4 Gemäß struct v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

Mitgliedsname Beschreibung
.s_ctrl RKISP-Treiber und camera_engine steuern durch verschiedene Befehle die CIS-Belichtung.

Implementieren Sie die einzelnen Steuer-IDs anhand der V4L2-Control-Liste des CIS-Treibers. Die folgenden IDs dienen der Informationsabfrage und werden als standardmäßige Integer-Menü-Steuerelemente implementiert:

Mitgliedsname Beschreibung
V4L2_CID_LINK_FREQ Siehe Standarddefinition in der V4L2-Control-Liste des CIS-Treibers.
Der RKISP-Treiber ermittelt damit derzeit die MIPI-Busfrequenz.
V4L2_CID_PIXEL_RATE Für MIPI: pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
V4L2_CID_HBLANK Siehe Standarddefinition in der V4L2-Control-Liste des CIS-Treibers
V4L2_CID_VBLANK Siehe Standarddefinition in der V4L2-Control-Liste des CIS-Treibers

RK camera_engine ermittelt mit diesen Befehlen die zur Belichtungsberechnung nötigen Informationen. Es gelten folgende Formeln:

Formeln
line_time = HTS / PIXEL_RATE;
PIXEL_RATE = HTS * VTS * FPS
HTS = sensor_width_out + HBLANK;
VTS = sensor_height_out + VBLANK;

Die folgenden IDs dienen der Steuerung; darüber steuert RK camera_engine das CIS:

Mitgliedsname Beschreibung
V4L2_CID_VBLANK VBLANK und damit Bildrate sowie maximale Belichtungszeit anpassen
V4L2_CID_EXPOSURE Belichtungszeit setzen; Einheit: Anzahl belichteter Zeilen
V4L2_CID_ANALOGUE_GAIN Belichtungsverstärkung setzen; Gesamtverstärkung = analoge Verstärkung*digitaler Verstärkung.
Einheit: Verstärkungsregisterwert.
3. Der CIS-Treiber definiert keine Hardware-Datenschnittstelleninformationen. Die Verbindung zwischen CIS-Gerät und AP wird durch den Port des DTS-Geräteknotens beschrieben; siehe Port-Informationen unter CIS-Geräteregistrierung (DTS). 4. Liste der CIS-Referenztreiber

VCM-Treiber

VCM-Geräteregistrierung (DTS)

Private Parameter des RK-VCM-Treibers
Name Beschreibung
Anlaufstrom Strom, bei dem die VCM das Objektiv gerade vom nahen Ende seines mechanischen
Verfahrwegs aus bewegen kann; dieses entspricht dem Fernfokus des Moduls.
Der dabei vom VCM-Treiber-IC gelieferte Strom ist der Anlaufstrom.
Nennstrom Strom, bei dem die VCM das Objektiv gerade bis zum fernen Ende seines mechanischen
Verfahrwegs bewegen kann; dieses entspricht dem Nahfokus des Moduls.
Der dabei vom VCM-Treiber-IC gelieferte Strom ist der Nennstrom.
VCM-Stromausgabemodus Während der VCM-Bewegung treten Schwingungen auf. Änderungen des Treiberstroms
müssen deren Periode berücksichtigen, um sie zu minimieren. Der Ausgabemodus bestimmt
die Zeit bis zum Erreichen des Zielstroms.
  vm149c: vm149c@0c { // vcm driver configuration, this set up is required when supporting AF
      compatible = "silicon touch,vm149c";
      status = "okay";
      reg = <0x0c>;
      rockchip,vcm-start-current = <0>;// Starting current of the motor
      rockchip,vcm-rated-current = <100>; // Motor rated current
      rockchip,vcm-step-mode = <4>; // Current output mode of motor drive IC
      rockchip,camera-module-index = <0>; // Module number
      rockchip,camera-module-facing = "back"; // Module orientation, there are "back" and "front"
  };
  ov13850: ov13850@10 {
      ......
      lens-focus = <&vm149c>; // vcm driver set up, need to have this set up when supporting AF
      ......
  };

Beschreibung des VCM-Treibers

Kurze Beschreibung der Datentypen

struct i2c_driver

[Beschreibung]

Definiert Informationen des I2C-Gerätetreibers.

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver Enthält im Gerätetreibermodell hauptsächlich Treibername und of_match_table
zum Abgleich mit dem im DTS registrierten Gerät. Stimmen die compatible-Felder
von of_match_table und DTS überein, wird .probe aufgerufen.
@id_table Liste der unterstützten I2C-Geräte. Verwendet der Kernel nicht of_match_table
und DTS-Geräteregistrierung zum Abgleich, greift er auf diese Tabelle zurück.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  static const struct i2c_device_id vm149c_id_table[] = {
      { VM149C_NAME, 0 },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(i2c, vm149c_id_table);
  static const struct of_device_id vm149c_of_table[] = {
      { .compatible = "silicon touch,vm149c" },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(of, vm149c_of_table);
  static const struct dev_pm_ops vm149c_pm_ops = {
      SET_SYSTEM_SLEEP_PM_OPS(vm149c_vcm_suspend, vm149c_vcm_resume)
      SET_RUNTIME_PM_OPS(vm149c_vcm_suspend, vm149c_vcm_resume, NULL)
  };
  static struct i2c_driver vm149c_i2c_driver = {
      .driver = {
          .name = VM149C_NAME,
          .pm = &vm149c_pm_ops,
          .of_match_table = vm149c_of_table,
      },
      .probe = &vm149c_probe,
      .remove = &vm149c_remove,
      .id_table = vm149c_id_table,
  };
  module_i2c_driver(vm149c_i2c_driver);
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
                             unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops vm149c_core_ops = {
      .ioctl = vm149c_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = vm149c_compat_ioctl32
  #endif
  };

Das folgende private ioctl dient derzeit zur Abfrage von Zeitinformationen der Motorbewegung.

RK_VIDIOC_VCM_TIMEINFO
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
     int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
     int (*try_ctrl)(struct v4l2_ctrl *ctrl);
     int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.g_volatile_ctrl Neuen Steuerwert abfragen. Üblicherweise nur für volatile, meist schreibgeschützte
Steuerelemente relevant, beispielsweise eine fortlaufend veränderliche Signalstärke.
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops vm149c_vcm_ctrl_ops = {
      .g_volatile_ctrl = vm149c_get_ctrl,
      .s_ctrl = vm149c_set_ctrl,
  };

vm149c_get_ctrl und vm149c_set_ctrl unterstützen folgende Steuerelemente:

V4L2_CID_FOCUS_ABSOLUTE

Kurze API-Beschreibung

xxxx_get_ctrl

[Beschreibung]

Bewegungsposition des Motors abfragen.

[Syntax]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_set_ctrl

[Beschreibung]

Bewegungsposition des Motors setzen.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Die Implementierung des eigenen ioctl umfasst insbesondere die Abfrage von Zeitinformationen der Motorbewegung.

Ein eigenes RK_VIDIOC_COMPAT_VCM_TIMEINFO ist implementiert.

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

1. Standardmäßigen I2C-Subdevice-Treiberteil implementieren

1.1 Gemäß struct i2c_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1. VCM-Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe VCM-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx stellen hauptsächlich Geräteparameter für die Zuordnung zum Kameragerät bereit.

1.2) VCM-Parameter wie rockchip, vcm-xxx betreffen vor allem Anlaufstrom, Nennstrom und Bewegungsmodus. Sie hängen mit Bewegungsbereich und -geschwindigkeit des Motors zusammen.

2. VCM-V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der RK-VCM-Treiber verlangt einen eigenen Subdevice-Geräteknoten für camera_engine im Userspace; darüber wird die Fokussierung gesteuert.

Media-Entity: media_entity_init;

3. Der RK-AF-Algorithmus definiert den gesamten Verfahrweg des Objektivs als Positionsbereich [0,64]. Dem entspricht der VCM-Strombereich [Anlaufstrom, Nennstrom]. Die Umrechnung zwischen beiden Bereichen sollte in einer Funktion implementiert werden.

2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

.ioctl.compat_ioctl32

Dieser Callback implementiert vor allem folgende private RK-Steuerbefehle:

Mitgliedsname Beschreibung
RK_VIDIOC_VCM_TIMEINFO camera_engine ermittelt damit die Dauer der Objektivbewegung und entscheidet,
wann das Objektiv stillsteht und ob sich die CIS-Belichtungszeit mit der Bewegung überschneidet.
Die Bewegungsdauer hängt von Weglänge und Stromausgabemodus des VCM-Treiber-IC ab.

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl und .s_ctrl implementieren folgende Befehle mit standardmäßigen V4L2-Steuerelementen:

Mitgliedsname Beschreibung
V4L2_CID_FOCUS_ABSOLUTE camera_engine setzt und liest damit die absolute Objektivposition.
Der RK-AF-Algorithmus definiert den gesamten Verfahrweg als [0,64].

Blitzlichttreiber

Blitzlicht-Geräteregistrierung (DTS)

DTS-Referenz für SGM378
  &i2c1 {
      ...
      sgm3784: sgm3784@30 {//Flash equipment
          #address-cells = <1>;
          #size-cells = <0>;
          compatible = "sgmicro,gsm3784";
          reg = <0x30>;
          rockchip,camera-module-index = <0>;//The flash corresponds to the camera module number
          rockchip,camera-module-facing = "back";//The flash corresponds to the orientation of the camera module
          enable-gpio = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;//enable gpio
          strobe-gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;//flash trigger gpio
          status = "okay";
          sgm3784_led0: led@0 {//led0 device information
              reg = <0x0>;//index
              led-max-microamp = <299200>;//Torch mode maximum current
              flash-max-microamp = <1122000>;//flash mode maximum current
              flash-max-timeout-us = <1600000>;//maximum flash time
          };
          sgm3784_led1: led@1 {//led1 device information
              reg = <0x1>;//index
              led-max-microamp = <299200>;//Torch mode maximum current
              flash-max-microamp = <1122000>;//flash mode maximum current
              flash-max-timeout-us = <1600000>;//maximum flash time
          };
      };
      ...
      ov13850: ov13850@10 {
          ...
          flash-leds = <&sgm3784_led0 &sgm3784_led1>;//The flash device is hooked to the camera
          ...
      };
      ...
  }
DTS-Referenz für GPIO-/PWM-Steuerung
  flash_ir: flash-ir {
          status = "okay";
          compatible = "led,rgb13h";
          label = "pwm-flash-ir";
          led-max-microamp = <20000>;
          flash-max-microamp = <20000>;
          flash-max-timeout-us = <1000000>;
          pwms=<&pwm3 0 25000 0>;
          //enable-gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &i2c1 {
      imx415: imx415@1a {
          ...
          flash-leds = <&flash_ir>;
          ...
      }
  }
Hinweise

1. Die Software muss je nach Aufhelllichttyp unterschiedliche Abläufe verwenden. Bei Infrarot-Aufhelllicht muss das DTS-Knotenlabel ir enthalten, um den Hardwaretyp zu kennzeichnen. Bei LED-Aufhelllicht kann das Feld ir entfallen.

2. Bei dieser über einen einzelnen Pin gesteuerten Schaltung gibt es zwei Fälle: Feste Helligkeit wird direkt per GPIO gesteuert; regelbare Helligkeit per PWM über das Tastverhältnis. Wählen Sie im DTS entweder pwms oder enable-gpio.

Beschreibung des Blitzlichttreibers

Kurze Beschreibung der Datentypen

struct i2c_driver

[Beschreibung]

Definiert Informationen des I2C-Gerätetreibers.

[Definition]

  struct i2c_driver {
      ……
      /* Standard driver model interfaces */
      int (*probe)(struct i2c_client *, const struct i2c_device_id *);
      int (*remove)(struct i2c_client *);
      ……
      struct device_driver driver;
      const struct i2c_device_id *id_table;
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver Enthält im Gerätetreibermodell hauptsächlich Treibername und of_match_table
zum Abgleich mit dem im DTS registrierten Gerät. Stimmen die compatible-Felder
von of_match_table und DTS überein, wird .probe aufgerufen.
@id_table Liste der unterstützten I2C-Geräte. Verwendet der Kernel nicht of_match_table
und DTS-Geräteregistrierung zum Abgleich, greift er auf diese Tabelle zurück.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  static const struct i2c_device_id sgm3784_id_table[] = {
      { SGM3784_NAME, 0 },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(i2c, sgm3784_id_table);
  static const struct of_device_id sgm3784_of_table[] = {
      { .compatible = "sgmicro,sgm3784" },
      { { 0 } }
  };
  MODULE_DEVICE_TABLE(of, sgm3784_of_table);
  static const struct dev_pm_ops sgm3784_pm_ops = {
      SET_RUNTIME_PM_OPS(sgm3784_runtime_suspend, sgm3784_runtime_resume, NULL)
  };
  static struct i2c_driver sgm3784_i2c_driver = {
      .driver = {
          .name = sgm3784_NAME,
          .pm = &sgm3784_pm_ops,
          .of_match_table = sgm3784_of_table,
      },
      .probe = &sgm3784_probe,
      .remove = &sgm3784_remove,
      .id_table = sgm3784_id_table,
  };
  module_i2c_driver(vm149c_i2c_driver);
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops sgm3784_core_ops = {
      .ioctl = sgm3784_ioctl,
  #ifdef CONFIG_COMPAT
      .compat_ioctl32 = sgm3784_compat_ioctl32
  #endif
  };

Das folgende private ioctl dient derzeit zur Abfrage der Einschaltzeitinformationen des Blitzlichts.

RK_VIDIOC_FLASH_TIMEINFO
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.g_volatile_ctrl Neuen Steuerwert abfragen. Üblicherweise nur für volatile, meist schreibgeschützte
Steuerelemente relevant, beispielsweise eine fortlaufend veränderliche Signalstärke.
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops sgm3784_ctrl_ops[LED_MAX] = {
      [LED0] = {
          .g_volatile_ctrl = sgm3784_led0_get_ctrl,
          .s_ctrl = sgm3784_led0_set_ctrl,
      },
      [LED1] = {
          .g_volatile_ctrl = sgm3784_led1_get_ctrl,
          .s_ctrl = sgm3784_led1_set_ctrl,
      }
  };

Kurze API-Beschreibung

xxxx_set_ctrl

[Beschreibung]

Blitzmodus, Strom und Blitzzeitbegrenzung einstellen.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_get_ctrl

[Beschreibung]

Fehlerstatus des Blitzlichts abfragen.

[Syntax]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Die Implementierung des eigenen ioctl umfasst insbesondere die Abfrage von Zeitinformationen des Blitzlichts.

Ein eigenes RK_VIDIOC_COMPAT_FLASH_TIMEINFO ist implementiert.

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

Für direkt per GPIO gesteuerte LEDs siehe kernel/drivers/leds/leds-rgb13h.c und kernel/Documentation/devicetree/bindings/leds/leds-rgb13h.txt.

Der Treiber des Blitzlicht-IC kann wie folgt portiert werden:

1. Standardmäßigen I2C-Subdevice-Treiberteil implementieren

1.1 Gemäß struct i2c_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver.pm

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1. Blitzlicht-Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe Blitzlicht-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx stellen hauptsächlich Geräteparameter für die Zuordnung zum Kameragerät bereit.

2. Name des Blitzlichtgeräts:

Bei zwei Blitz-LEDs werden die Gerätenamen led0 und led1 zur Unterscheidung verwendet.

  /* NOTE: to distinguish between two led
   * name: led0 meet the main led
   * name: led1 meet the secondary led
   */
  snprintf(sd->name, sizeof(sd->name),
           "m%02d_%s_%s_led%d %s",
           flash->module_index, facing,
           SGM3784_NAME, i, dev_name(sd->dev));

3. Blitzlicht-V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der RK-Blitzlichttreiber verlangt einen eigenen Subdevice-Geräteknoten für camera_engine im Userspace; darüber werden die LEDs gesteuert.

Media-Entity: media_entity_init;

2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

.ioctl.compat_ioctl32

Dieser Callback implementiert vor allem folgende private RK-Steuerbefehle:

Mitgliedsname Beschreibung
RK_VIDIOC_FLASH_TIMEINFO camera_engine ermittelt damit den LED-Einschaltzeitpunkt und prüft,
ob die CIS-Belichtungszeit nach dem Einschalten des Blitzlichts liegt.

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl und .s_ctrl implementieren folgende Befehle mit standardmäßigen V4L2-Steuerelementen:

Mitgliedsname Beschreibung
V4L2_CID_FLASH_FAULT Blitzlichtfehlerinformationen abfragen
V4L2_CID_FLASH_LED_MODE LED-Modus einstellen:
V4L2_FLASH_LED_MODE_NONE
V4L2_FLASH_LED_MODE_TORCH
V4L2_FLASH_LED_MODE_FLASH
V4L2_CID_FLASH_STROBE Blitzlicht einschalten
V4L2_CID_FLASH_STROBE_STOP Blitzlicht ausschalten
V4L2_CID_FLASH_TIMEOUT Maximale ununterbrochene Leuchtdauer im Blitzmodus einstellen
V4L2_CID_FLASH_INTENSITY Strom im Blitzmodus einstellen
V4L2_CID_FLASH_TORCH_INTENSITY Strom im Dauerlichtmodus einstellen

Treiber für FOCUS, ZOOM und P-IRIS

Dieser Treiber steuert Autofokus (FOCUS), Zoom (ZOOM) und automatische Blende (P-IRIS) über Schrittmotoren. Wegen der gleichen Motorsteuerung und des Hardwaredesigns sind die drei Funktionen in einem Treiber zusammengefasst. Je nach Treiberchip kann dieser beispielsweise als SPI-Subdevice eingebunden werden. Dieses Kapitel erläutert anhand der Chips MP6507 und MS41908 die erforderlichen Datenstrukturen, das Framework und wichtige Hinweise.

MP6507-Geräteregistrierung (DTS)

  mp6507: mp6507 {
      status = "okay";
      compatible = "monolithicpower,mp6507";
      #pwm-cells = <3>;
      pwms = <&pwm6 0 25000 0>,
             <&pwm10 0 25000 0>,
             <&pwm9 0 25000 0>,
             <&pwm8 0 25000 0>;
      pwm-names = "ain1","ain2","bin1","bin2";
      rockchip,camera-module-index = <1>;
      rockchip,camera-module-facing = "front";
      iris_en-gpios  = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;
      focus_en-gpios  = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
      zoom_en-gpios  = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>;
      iris-step-max = <80>;
      focus-step-max = <7500>;
      zoom-step-max = <7500>;
      iris-start-up-speed = <1200>;
      focus-start-up-speed = <1200>;
      focus-max-speed = <2500>;
      zoom-start-up-speed = <1200>;
      zoom-max-speed = <2500>;
      focus-first-speed-step = <8>;
      zoom-first-speed-step = <8>;
      focus-speed-up-table = < 1176 1181 1188 1196
                               1206 1217 1231 1246
                               1265 1286 1309 1336
                               1365 1396 1429 1464
                               1500 1535 1570 1603
                               1634 1663 1690 1713
                               1734 1753 1768 1782
                               1793 1803 1811 1818>;
      focus-speed-down-table = < 1796 1788 1779 1768
                                 1756 1743 1728 1712
                                 1694 1674 1653 1630
                                 1605 1580 1554 1527
                                 1500 1472 1445 1419
                                 1394 1369 1346 1325
                                 1305 1287 1271 1256
                                 1243 1231 1220 1211
                                 1203 1195 1189 1184
                                 1179 1175>;
      zoom-speed-up-table = < 1198 1205 1212 1220
                              1228 1238 1249 1260
                              1272 1285 1299 1313
                              1328 1343 1359 1375
                              1390 1406 1421 1436
                              1450 1464 1477 1489
                              1500 1511 1521 1529
                              1537 1544 1551>;
      zoom-speed-down-table = < 1547 1540 1531 1522
                                1511 1499 1487 1473
                                1458 1443 1426 1409
                                1392 1375 1357 1340
                                1323 1306 1291 1276
                                1262 1250 1238 1227
                                1218 1209 1202 1195
                                1189 1184 1179 1175
                                1171 1168>;
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          lens-focus = <&mp6507>;
          ...
      }
  }
  &pwm6 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm6m1_pins_pull_up>;
  };
  &pwm8 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm8m1_pins_pull_down>;
      center-aligned;
  };
  &pwm9 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm9m1_pins_pull_down>;
      center-aligned;
  };
  &pwm10 {
      status = "okay";
      pinctrl-names = "active";
      pinctrl-0 = <&pwm10m1_pins_pull_down>;
  };
Private RK-Definitionen
Mitgliedsname Beschreibung
rockchip,
camera-
module-index
Kameranummer zur Zuordnung der Kamera
rockchip,
camera-
module-facing
Kameraausrichtung zur Zuordnung der Kamera
iris_en-gpios GPIO zur IRIS-Aktivierung
focus_en-gpios GPIO zur Fokusaktivierung
zoom_en-gpios GPIO zur Zoomaktivierung
rockchip,iris-
step-max
Maximale Schrittzahl des P-IRIS-Schrittmotors
rockchip,focus-
step-max
Maximale Schrittzahl des Fokus-Schrittmotors
zoom-step-
max
Maximale Schrittzahl des Zoom-Schrittmotors
iris-start-up-
speed
Startgeschwindigkeit des IRIS-Schrittmotors
focus-start-up-
speed
Startgeschwindigkeit des Fokus-Schrittmotors
focus-max-
speed
Maximale Betriebsgeschwindigkeit des Fokus-Schrittmotors
zoom-start-up-
speed
Startgeschwindigkeit des Zoom-Schrittmotors
zoom-max-
speed
Maximale Betriebsgeschwindigkeit des Zoom-Schrittmotors
focus-first-
speed-step
Schrittzahl bei Fokus-Startgeschwindigkeit. In nachfolgenden Beschleunigungsstufen
wird sie proportional erhöht, damit die Laufzeiten aller Geschwindigkeitsstufen
möglichst gleich sind.
zoom-first-
speed-step
Schrittzahl bei Zoom-Startgeschwindigkeit. In nachfolgenden Beschleunigungsstufen
wird sie proportional erhöht, damit die Laufzeiten aller Geschwindigkeitsstufen
möglichst gleich sind.
focus-speed-
up-table
Fokus-Beschleunigungskurve als Nachschlagetabelle. Durch Parameteranpassung
eine trapezförmige oder S-förmige Kurve erzeugen und deren Daten konfigurieren.
Ohne Konfiguration oder mit nur einem Wert läuft der Motor konstant mit Startgeschwindigkeit.
Der kleinste Kurvenwert darf die maximale Anlaufgeschwindigkeit nicht überschreiten,
der größte nicht die maximale Betriebsgeschwindigkeit des Motors.
focus-speed-
down-table
Fokus-Verzögerungskurve. Ihr Maximum muss unter dem Maximum der
Beschleunigungskurve liegen. Ist die Beschleunigungskurve ungültig, gilt dies auch
für die Verzögerungskurve; der Motor läuft durchgehend mit Startgeschwindigkeit.
Ohne eigene Verzögerungskurve wird sie symmetrisch aus der Beschleunigungskurve abgeleitet.
zoom-speed-
up-table
Zoom-Beschleunigungskurve als Nachschlagetabelle. Durch Parameteranpassung
eine trapezförmige oder S-förmige Kurve erzeugen und deren Daten konfigurieren.
Ohne Konfiguration oder mit nur einem Wert läuft der Motor konstant mit Startgeschwindigkeit.
Der kleinste Kurvenwert darf die maximale Anlaufgeschwindigkeit nicht überschreiten,
der größte nicht die maximale Betriebsgeschwindigkeit des Motors.
zoom-speed-
down-table
Zoom-Verzögerungskurve. Ihr Maximum muss unter dem Maximum der
Beschleunigungskurve liegen. Ist die Beschleunigungskurve ungültig, gilt dies auch
für die Verzögerungskurve; der Motor läuft durchgehend mit Startgeschwindigkeit.
Ohne eigene Verzögerungskurve wird sie symmetrisch aus der Beschleunigungskurve abgeleitet.

Kurze Beschreibung der Datentypen

struct platform_driver

[Beschreibung]

Definiert Informationen des Plattformgerätetreibers.

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver struct device_driver enthält hauptsächlich Treibername und of_match_table
zum Abgleich mit DTS-Geräten. Stimmen die compatible-Felder von of_match_table
und DTS überein, wird .probe aufgerufen.
@id_table Verwendet der Kernel nicht of_match_table und DTS-Geräte zum Abgleich,
verwendet er diese Tabelle.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  #if defined(CONFIG_OF)
  static const struct of_device_id motor_dev_of_match[] = {
      { .compatible = "monolithicpower,mp6507", },
      {},
  };
  #endif
  static struct platform_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .owner = THIS_MODULE,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe = motor_dev_probe,
      .remove = motor_dev_remove,
  };
  module_platform_driver(motor_dev_driver);
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.g_volatile_ctrl Neuen Steuerwert abfragen. Üblicherweise nur für volatile, meist schreibgeschützte
Steuerelemente relevant, beispielsweise eine fortlaufend veränderliche Signalstärke.
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

Kurze API-Beschreibung

xxxx_set_ctrl

[Beschreibung]

Fokus-, Zoom- und P-Blendenposition über standardmäßiges v4l2_control setzen.

Folgende standardmäßige V4L2-Befehle sind implementiert:

Mitgliedsname Beschreibung
V4L2_CID_FOCUS_ABSOLUTE Fokus steuern. Laut Quelle bedeutet 0 die kleinste Brennweite
und eine scharfe Nahaufnahme.
V4L2_CID_ZOOM_ABSOLUTE Zoomfaktor steuern. 0 bedeutet kleinster Zoomfaktor und größtes Sichtfeld.
V4L2_CID_IRIS_ABSOLUTE Öffnung der P-Blende steuern. 0 bedeutet geschlossene Blende.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_get_ctrl

[Beschreibung]

Aktuelle Fokus-, Zoom- und P-Blendenposition über standardmäßiges v4l2_control abfragen.

Folgende standardmäßige V4L2-Befehle sind implementiert:

Mitgliedsname Beschreibung
V4L2_CID_FOCUS_ABSOLUTE Fokus steuern. Laut Quelle bedeutet 0 die kleinste Brennweite
und eine scharfe Nahaufnahme.
V4L2_CID_ZOOM_ABSOLUTE Zoomfaktor steuern. 0 bedeutet kleinster Zoomfaktor und größtes Sichtfeld.
V4L2_CID_IRIS_ABSOLUTE Öffnung der P-Blende steuern. 0 bedeutet geschlossene Blende.

[Syntax]

  static int xxxx_get_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Das eigene ioctl ermittelt hauptsächlich Zeitinformationen für Fokus, Zoom und P-Blende, also Zeitstempel von Bewegungsbeginn und -ende. Da das verwendete Objektiv keine Positionserfassung besitzt, muss die Motorposition bei Bedarf zurückgesetzt werden.

Implementierte Erweiterungen
Mitgliedsname Beschreibung
RK_VIDIOC_VCM_TIMEINFO Fokussierungszeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der Fokussierung gültig ist
RK_VIDIOC_ZOOM_TIMEINFO Zoomzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss des Zoomens gültig ist
RK_VIDIOC_IRIS_TIMEINFO Blendenzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der Blendenanpassung gültig ist
RK_VIDIOC_FOCUS_CORRECTION Fokusposition korrigieren beziehungsweise zurücksetzen
RK_VIDIOC_ZOOM_CORRECTION Zoomposition korrigieren beziehungsweise zurücksetzen
RK_VIDIOC_IRIS_CORRECTION Blendenposition korrigieren beziehungsweise zurücksetzen

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

Bei SPI-gesteuerten Treiberchips kann die Portierung auf dem SPI-Framework aufbauen. Der RK-Referenztreiber verwendet MP6507: PWM erzeugt direkt die Steuerwellenformen, MP6507 übernimmt die Leistungsverstärkung. Daher wird das Plattformframework direkt verwendet. Treiberreferenz: /kernel/drivers/media/i2c/mp6507.c

Portierungsschritte:

1. Standardmäßigen Plattform-Subdevice-Treiberteil implementieren

1.1 Gemäß struct platform_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1. Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe MP6507-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx stellen hauptsächlich Geräteparameter für die Zuordnung zum Kameragerät bereit.

1.2) PWM-Konfiguration abrufen. Die Motorsteuerung verlangt 90 Grad Phasenverschiebung zwischen A und B. Dies lässt sich durch mittenausgerichtete PWM der B-Phase erreichen. Setzen Sie center-aligned am DTS-PWM-Knoten; siehe MP6507-Geräteregistrierung (DTS).

Englische Originalabbildung 6, PDF-Seite 85

Englische Originalabbildung 6, PDF-Seite 85

Erregungsfolge; Drehung der Ausgangswelle im Uhrzeigersinn (CW).

Phase / Schritt 1 2 3 4
A + + − −
A̅ − − + +
B − + + −
B̅ + − − +

1.3) Freigabepin anfordern. MP6507 benötigt 4 PWMs für die Schrittmotor-Steuerwellenformen. Da Hardware-PWMs begrenzt sind und Fokus, Zoom und P-Blende jeweils einen MP6507 verwenden, wird der jeweilige Treiber per GPIO aktiviert, um PWM im Zeitmultiplex gemeinsam zu nutzen. Nachteil: Nur ein Motor kann gleichzeitig laufen; die anderen beiden müssen warten. 1.4) Hardwaregrenzen und Ressourcen jedes Motors erfassen, etwa maximale Schrittzahl, maximale Anlauf- und Betriebsgeschwindigkeit sowie Beschleunigungskurvendaten.

2. Timer mit hrtimer_init initialisieren. PWM läuft kontinuierlich und benötigt einen Timer: Nach der vorgegebenen Anzahl von PWM-Perioden schaltet der Timerinterrupt PWM ab. Auch beim Beschleunigen ändert ein Timerinterrupt nach einer bestimmten Periodenzahl die PWM-Frequenz und beschleunigt so den Motor.

3. Synchronisation mittels init_completion einrichten. Die nächste Motoroperation darf erst beginnen, wenn die vorherige Bewegung abgeschlossen ist.

4. V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der Treiber verlangt einen eigenen Subdevice-Geräteknoten für rkaiq im Userspace; darüber wird der Motor gesteuert.

Media-Entity: media_entity_init;

5. Name des Blitzlichtgeräts; diese Bezeichnung steht so im Motorabschnitt der Quelle:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);
2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

  .ioctl
  .compat_ioctl32

Dieser Callback implementiert vor allem folgende private RK-Steuerbefehle:

Mitgliedsname Beschreibung
RK_VIDIOC_VCM_TIMEINFO Fokussierungszeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der Fokussierung gültig ist
RK_VIDIOC_ZOOM_TIMEINFO Zoomzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss des Zoomens gültig ist
RK_VIDIOC_IRIS_TIMEINFO Blendenzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der Blendenanpassung gültig ist
RK_VIDIOC_FOCUS_CORRECTION Fokusposition korrigieren beziehungsweise zurücksetzen
RK_VIDIOC_ZOOM_CORRECTION Zoomposition korrigieren beziehungsweise zurücksetzen
RK_VIDIOC_IRIS_CORRECTION Blendenposition korrigieren beziehungsweise zurücksetzen

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.g_volatile_ctrl
.s_ctrl

.g_volatile_ctrl und .s_ctrl implementieren folgende Befehle mit standardmäßigen V4L2-Steuerelementen:

Parametername Beschreibung
V4L2_CID_FOCUS_ABSOLUTE Fokus steuern. Laut Quelle bedeutet 0 die kleinste Brennweite
und eine scharfe Nahaufnahme.
V4L2_CID_ZOOM_ABSOLUTE Zoomfaktor steuern. 0 bedeutet kleinster Zoomfaktor und größtes Sichtfeld.
V4L2_CID_IRIS_ABSOLUTE Öffnung der P-Blende steuern. 0 bedeutet geschlossene Blende.
3. Referenz für die Beschleunigungskurve des Schrittmotors

3.1 Trapezkurve: Wie abgebildet kann mit gleichen Intervallen und Geschwindigkeitsänderungen beschleunigt und verzögert werden.

Englische Originalabbildung 7, PDF-Seite 86

Englische Originalabbildung 7, PDF-Seite 86

3.2 S-Kurve

Liefert die trapezförmige Beschleunigung kein gutes Ergebnis, kann eine S-förmige verwendet werden. Referenzformel: Speed = Vmin + ((Vmax-Vmin) / (1 + exp(-fac * (i-Num) / Num))); dabei ist Vmin die Anlaufgeschwindigkeit, Vmax die Zielgeschwindigkeit und fac der Kurvenkoeffizient, üblicherweise 4~6. Größere Werte machen die Kurvenmitte steiler. i ist die Nummer der Geschwindigkeitsstufe; bei 32 Stufen liegt sie in 0~31. Num ist die halbe Stufenanzahl; bei 32 Stufen beträgt num 16.

Englische Originalabbildung 8, PDF-Seite 87

Englische Originalabbildung 8, PDF-Seite 87

MS41908-Geräteregistrierung (DTS)

Manche Objektive unterstützen PIRIS, FOCUS, ZOOM und ZOOM1 oder die Kombination DC-IRIS, FOCUS und ZOOM. Deshalb sind diese Funktionen beim MS41908 konfigurierbar. Der Treiber kann mehrfach geladen werden, um mehrere Treiberchips zu kombinieren. Dies macht das DTS komplexer; lesen Sie jede Parameterbeschreibung sorgfältig.

  &spi0 {
      status = "okay";
      pinctrl-names = "default";
      pinctrl-0 = <&spi0m0_clk &spi0m0_cs0n &spi0m0_miso &spi0m0_mosi>;
      //If pinctrl is not configured, confirm whether the default pinctrl is the actual pin group
      assigned-clocks = <&pmucru CLK_SPI0>;
      assigned-clock-rates = <100000000>;
      ms41908: ms41908@00 {
          status = "okay";
          compatible = "relmon,ms41908";
          reg = <0>;
          pinctrl-names = "default";
          focus-start-up-speed = <800>;
          zoom-start-up-speed = <800>;
          focus-step-max = <3160>;
          zoom-step-max = <1520>;
          focus-backlash = <18>;
          vd_fz-period-us = <10000>;
          vd_fz-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
          use-focus;
          use-zoom;
          focus-used-pin = "cd";
          zoom-used-pin = "ab";
      };
  };
  &i2c1 {
      imx335: imx335@1a{
          ...
          lens-focus = <&ms41908>;
          //Multiple device registration,lens-focus = <&ms41908_0 &ms41908_1>;
          ...
      };
  };

Grundlegende Beschreibung

Mitgliedsname Beschreibung
pinctrl-0 SPI-Pindefinition gemäß tatsächlicher Pinbelegung zur Zuordnung der SPI-Funktion.
Beispiel: pinctrl-0 = <&spi0m0_clk &spi0m0_cs0n &spi0m0_miso
&spi0m0_mosi>;
assigned-clocks
assigned-clock-
rates
SPI-Taktkonfiguration; empfohlen sind 100MHz.
reg reg = <0>; verwendet cs0
reg = <1>; verwendet cs1
rockchip,camera-
module-index
Kameranummer zur Zuordnung zur Kamera
rockchip,camera-
module-facing
Kameraausrichtung zur Zuordnung zur Kamera
reset-gpios Reset-Pin von ms41908; bei festem Hardware-Pullup kann die Konfiguration entfallen.
vd_fz-period-us Periode des Impulses zur Aktualisierung der Schrittmotortreiberregister.
Beide Motoren verwenden dasselbe Impulssignal. Überschreitet die Bewegung die vd-Periode,
gehen Schritte verloren. Der Treiber hält die Dauer einer Einzelbewegung innerhalb dieser Periode.

FOCUS-Beschreibung

Mitgliedsname Beschreibung
use-focus Gibt an, ob die Fokusfunktion verwendet wird
focus-
used-pin
Jeder ms41908 steuert zwei Schrittmotoren über die Pingruppen „ab“ und „cd“.
Entsprechend der tatsächlichen Hardwareverdrahtung konfigurieren.
focus-
backlash
Durch Zahnradspiel verursachter Fehler: bei Richtungswechsel zu kompensierende
Schrittzahl, durch Tests am tatsächlichen Objektiv bestimmen.
focus-
start-up-
speed
Anlaufgeschwindigkeit des Schrittmotors in PPS
focus-
step-max
Effektiver Bewegungsbereich des Motors in Schritten
focus-
ppw
PWM-Tastverhältnis der ms41908-Ausgabe, 0-255. Größere Werte erhöhen
die Treiberleistung; entsprechend der Motorlast einstellen.
focus-
phmode
Phasenkorrektur der ms41908-PWM-Ausgabe; normalerweise nicht konfiguriert,
bei Bedarf einstellen.
focus-
micro
Mikroschritt-Unterteilung: 64, 128 oder 256; Standard: 256.
focus-
reback-
distance
Für genaue Positionen muss die Fokuskurve aus derselben Richtung angefahren werden.
Beispiel: Von Position 100 zu 90 zuerst bis 80 zurückfahren und anschließend 90 anfahren.
Der Parameter gibt die zusätzliche Rückfahr-Schrittzahl an.
focus-1-
2phase-
excitation
Standard ist 2-2-Phasen-Erregung; dieser Parameter wählt 1-2-Phasen-Erregung.
Beispiel: focus-1-2phase-excitation;
focus-dir-
opposite
Verläuft die Motorbewegung entgegengesetzt zur tatsächlichen Fokuskurve,
kehrt dieser Parameter die Richtung um. Beispiel: focus-dir-opposite;
Optokopplerbeschreibung
Mitgliedsname Beschreibung
focus-pic C-Pin des Optokopplers zur Erkennung des Pegelwechsels.
Der Übergangspunkt ist der Ursprung des Optokopplers.
focus-
pia
A-Pin des Optokopplers zur Ansteuerung der Fotodiode. Bei Kalibrierung auf High,
im Normalbetrieb auf Low setzen; andernfalls beeinflusst die Fotodiode die Bildaufnahme.
focus-
pie
Kann hardwareseitig direkt an Masse liegen. Bei GPIO-Steuerung
muss der Pin auf Low gesetzt werden.
focus-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.
focus-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.

Hinweis: Objektive ohne Optokoppler-Positionserfassung benötigen keine Optokopplerparameter.

ZOOM-Beschreibung

Mitgliedsname Beschreibung
use-zoom Gibt an, ob die Zoomfunktion verwendet wird
zoom-
used-pin
Jeder ms41908 steuert zwei Schrittmotoren über die Pingruppen „ab“ und „cd“.
Entsprechend der tatsächlichen Hardwareverdrahtung konfigurieren.
zoom-
backlash
Durch Zahnradspiel verursachter Fehler: bei Richtungswechsel zu kompensierende
Schrittzahl, durch Tests bestimmen.
zoom-
start-up-
speed
Anlaufgeschwindigkeit des Schrittmotors in PPS
zoom-
step-max
Effektiver Bewegungsbereich des Motors in Schritten
zoom-
ppw
PWM-Tastverhältnis der ms41908-Ausgabe, 0-255. Größere Werte erhöhen
die Treiberleistung; entsprechend der Motorlast einstellen.
zoom-
phmode
Phasenkorrektur der ms41908-PWM-Ausgabe; normalerweise nicht konfiguriert,
bei Bedarf einstellen.
zoom-
micro
Mikroschritt-Unterteilung: 64, 128 oder 256; Standard: 256.
zoom-1-
2phase-
excitation
Standard ist 2-2-Phasen-Erregung; dieser Parameter wählt 1-2-Phasen-Erregung.
Beispiel: zoom-1-2phase-excitation;
zoom-dir-
opposite
Verläuft die Motorbewegung entgegengesetzt zur tatsächlichen Fokuskurve,
kehrt dieser Parameter die Richtung um. Beispiel: zoom-dir-opposite;
Optokopplerbeschreibung
Mitgliedsname Beschreibung
zoom-
pic
C-Pin des Optokopplers zur Erkennung des Pegelwechsels.
Der Übergangspunkt ist der Ursprung des Optokopplers.
zoom-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.
zoom-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.

Hinweis: Objektive ohne Optokoppler-Positionserfassung benötigen keine Optokopplerparameter.

ZOOM1-Beschreibung

Mitgliedsname Beschreibung
use-
zoom1
Gibt an, ob zoom1 verwendet wird; manche Objektive unterstützen zwei Zoomgruppen.
zoom1-
used-pin
Jeder ms41908 steuert zwei Schrittmotoren über die Pingruppen „ab“ und „cd“.
Entsprechend der tatsächlichen Hardwareverdrahtung konfigurieren.
zoom1-
backlash
Durch Zahnradspiel verursachter Fehler: bei Richtungswechsel zu kompensierende
Schrittzahl, durch Tests bestimmen.
zoom1-
start-up-
speed
Anlaufgeschwindigkeit des Schrittmotors in PPS
zoom1-
step-max
Effektiver Bewegungsbereich des Motors in Schritten
zoom1-
ppw
PWM-Tastverhältnis der ms41908-Ausgabe, 0-255. Größere Werte erhöhen
die Treiberleistung; entsprechend der Motorlast einstellen.
zoom1-
phmode
Phasenkorrektur der ms41908-PWM-Ausgabe; normalerweise nicht konfiguriert,
bei Bedarf einstellen.
zoom1-
micro
Mikroschritt-Unterteilung: 64, 128 oder 256; Standard: 256.
zoom1-1-
2phase-
excitation
Standard ist 2-2-Phasen-Erregung; dieser Parameter wählt 1-2-Phasen-Erregung.
Beispiel: zoom1-1-2phase-excitation;
zoom1-
dir-
opposite
Verläuft die Motorbewegung entgegengesetzt zur tatsächlichen Fokuskurve,
kehrt dieser Parameter die Richtung um. Beispiel: zoom1-dir-opposite;
Optokopplerbeschreibung
Mitgliedsname Beschreibung
zoom1-
pic
C-Pin des Optokopplers zur Erkennung des Pegelwechsels.
Der Übergangspunkt ist der Ursprung des Optokopplers.
zoom1-
pia
A-Pin des Optokopplers zur Ansteuerung der Fotodiode. Bei Kalibrierung auf High,
im Normalbetrieb auf Low setzen; andernfalls beeinflusst die Fotodiode die Bildaufnahme.
zoom1-
pie
Kann hardwareseitig direkt an Masse liegen. Bei GPIO-Steuerung
muss der Pin auf Low gesetzt werden.
zoom1-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.
zoom1-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.

Hinweis: Objektive ohne Optokoppler-Positionserfassung benötigen keine Optokopplerparameter.

PIRIS-Beschreibung

Mitgliedsname Beschreibung
use-p-iris Gibt an, ob P-IRIS verwendet wird
piris-
used-pin
Jeder ms41908 steuert zwei Schrittmotoren über die Pingruppen „ab“ und „cd“.
Entsprechend der tatsächlichen Hardwareverdrahtung konfigurieren.
piris-
backlash
Durch Zahnradspiel verursachter Fehler: bei Richtungswechsel zu kompensierende
Schrittzahl, durch Tests am tatsächlichen Objektiv bestimmen.
piris-
start-up-
speed
Anlaufgeschwindigkeit des Schrittmotors in PPS
piris-
step-max
Effektiver Bewegungsbereich des Motors in Schritten
piris-ppw PWM-Tastverhältnis der ms41908-Ausgabe, 0-255. Größere Werte erhöhen
die Treiberleistung; entsprechend der Motorlast einstellen.
piris-
phmode
Phasenkorrektur der ms41908-PWM-Ausgabe; normalerweise nicht konfiguriert,
bei Bedarf einstellen.
piris-
micro
Mikroschritt-Unterteilung: 64, 128 oder 256; Standard: 256.
piris-1-
2phase-
excitation
Standard ist 2-2-Phasen-Erregung; dieser Parameter wählt 1-2-Phasen-Erregung.
Beispiel: piris-1-2phase-excitation;
piris-dir-
opposite
Verläuft die Motorbewegung entgegengesetzt zur tatsächlichen Fokuskurve,
kehrt dieser Parameter die Richtung um. Beispiel: piris-dir-opposite;
Optokopplerbeschreibung
Mitgliedsname Beschreibung
piris-pic C-Pin des Optokopplers zur Erkennung des Pegelwechsels.
Der Übergangspunkt ist der Ursprung des Optokopplers.
piris-pia A-Pin des Optokopplers zur Ansteuerung der Fotodiode. Bei Kalibrierung auf High,
im Normalbetrieb auf Low setzen; andernfalls beeinflusst die Fotodiode die Bildaufnahme.
piris-pie Kann hardwareseitig direkt an Masse liegen. Bei GPIO-Steuerung
muss der Pin auf Low gesetzt werden.
piris-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.
piris-
min-pos
Schrittzahlen links und rechts des Optokopplerursprungs messen und im DTS eintragen.
Die eingetragenen Werte dürfen größer als die tatsächlichen sein.

Hinweis: Objektive ohne Optokoppler-Positionserfassung benötigen keine Optokopplerparameter.

DCIRIS-Beschreibung

Mitgliedsname Beschreibung
use-dc-
iris
Gibt an, ob DC-IRIS verwendet wird
vd_iris-
gpios
Synchronimpulspin zur Übernahme der DC-Blendenregister
dc-iris-
reserved-
polarity
Polarität der DC-Blende. Bedeutet 0 vollständig geöffnet,
kann diese Property die Richtung umkehren.
dc-iris-
max-log
Zielwerte der DC-Blende: 0~1023. Der tatsächlich wirksame Bereich kann kleiner sein;
dieser Parameter begrenzt ihn.

Kurze Beschreibung der Datentypen

struct spi_driver

[Beschreibung]

Definiert Informationen des Plattformgerätetreibers.

[Definition]

  struct spi_driver {
          int (*probe)(struct spi_device *spi);
          int (*remove)(struct spi_device *spi);
          struct device_driver driver;
          const struct spi_device_id *id_table;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver struct device_driver enthält hauptsächlich Treibername und of_match_table
zum Abgleich mit DTS-Geräten. Stimmen die compatible-Felder von of_match_table
und DTS überein, wird .probe aufgerufen.
@id_table Verwendet der Kernel nicht of_match_table und DTS-Geräte zum Abgleich,
verwendet er diese Tabelle.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  static const struct spi_device_id motor_match_id[] = {
      {"relmon,ms41908", 0 },
      { }
  };
  static struct spi_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe      = &motor_dev_probe,
      .remove     = &motor_dev_remove,
      .id_table   = motor_match_id,
  };
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.g_volatile_ctrl Neuen Steuerwert abfragen. Üblicherweise nur für volatile, meist schreibgeschützte
Steuerelemente relevant, beispielsweise eine fortlaufend veränderliche Signalstärke.
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

Kurze API-Beschreibung

xxxx_set_ctrl

[Beschreibung]

Fokus-, Zoom- und P-Blendenposition über standardmäßiges v4l2_control setzen.

Der Treiber implementiert folgende standardmäßige V4L2-Befehle:

Parametername Beschreibung
V4L2_CID_FOCUS_ABSOLUTE Fokus steuern. Laut Quelle bedeutet 0 die kleinste Brennweite
und eine scharfe Nahaufnahme.
V4L2_CID_ZOOM_ABSOLUTE Zoomfaktor steuern. 0 bedeutet kleinster Zoomfaktor und größtes Sichtfeld.
V4L2_CID_IRIS_ABSOLUTE Blendenöffnung steuern. 0 bedeutet geschlossene Blende.
V4L2_CID_ZOOM_CONTINUOUS Zoomfaktor von zoom1 steuern; bei mehreren Zoomgruppen verwendet.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Das eigene ioctl ermittelt hauptsächlich Zeitinformationen für Fokus, Zoom und P-Blende, also Zeitstempel von Bewegungsbeginn und -ende. Da das verwendete Objektiv keine Positionserfassung besitzt, muss die Motorposition bei Bedarf zurückgesetzt werden.

Eigene Befehle des Treibers
Parametername Beschreibung
RK_VIDIOC_VCM_TIMEINFO Fokussierungszeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der Fokussierung gültig ist
RK_VIDIOC_ZOOM_TIMEINFO Zoomzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss des Zoomens gültig ist
RK_VIDIOC_IRIS_TIMEINFO Blendenzeitinformationen zur Prüfung, ob das aktuelle Bild
nach Abschluss der P-Blendenanpassung gültig ist
RK_VIDIOC_ZOOM1_TIMEINFO Bei mehreren Zoomgruppen: Zeitinformationen von zoom1 zur Prüfung,
ob das aktuelle Bild nach Abschluss des Zoomens gültig ist
RK_VIDIOC_IRIS_CORRECTION Blendenposition zurücksetzen; wirkt nur auf P-IRIS
RK_VIDIOC_FOCUS_CORRECTION Fokusposition zurücksetzen
RK_VIDIOC_ZOOM_CORRECTION Zoomposition zurücksetzen
RK_VIDIOC_ZOOM1_CORRECTION Position der zweiten Zoomgruppe eines Doppelzoomobjektivs zurücksetzen
RK_VIDIOC_FOCUS_SET_POSITION Fokusposition setzen
RK_VIDIOC_ZOOM_SET_POSITION Fokusnachführung konfigurieren und anhand der Zoomkurve
mehrstufige gekoppelte Zoom-/Fokusbewegungen ausführen

Hinweise:

1. Zahnradspiel beeinträchtigt die absolute Motorposition. Eine Bewegungsrichtung wird als positiv, die andere als negativ festgelegt; anfangs liegt das Zahnrad an der positiven Flanke an. Bei negativer Bewegung fährt es zunächst zusätzlich um n Schritte, wobei n größer als das Zahnradspiel ist, und dann n Schritte positiv zurück. So liegt es wieder an der positiven Flanke an. Dieses Rückfahren gewährleistet Positionsgenauigkeit. Bei wiederholten negativen Bewegungen während manueller oder automatischer Fokussierung würden solche Rückfahrten jedoch sichtbar ruckeln. Daher darf nicht jede negative Bewegung automatisch zurückfahren. Bei den neuen Schnittstellen RK_VIDIOC_FOCUS_SET_POSITION und RK_VIDIOC_ZOOM_SET_POSITION entscheidet der AF-Algorithmus darüber. Die Standardbefehle V4L2_CID_FOCUS_ABSOLUTE und V4L2_CID_ZOOM_ABSOLUTE führen keine Rückfahrt aus und sind nur für den manuellen Modus vorgesehen. RK_VIDIOC_ZOOM_SET_POSITION enthält Fokus- und Zoomparameter; beim Zoomen wird der Fokus synchron angepasst, um natürliche Bildübergänge zu erzielen.

2. Früher wurde Zahnradspiel über focus-backlash kompensiert, indem bei negativer Bewegung zusätzliche Schritte ausgeführt wurden. Individuelle Unterschiede zwischen Objektiven verursachen jedoch Kalibrierfehler und hohen Kalibrieraufwand. Deshalb wurde dieser Parameter verworfen. Der Treiber behält seine Implementierung bei; bei geringen Genauigkeitsanforderungen kann er weiterhin verwendet werden.

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

Für SPI-gesteuerte Treiberchips lässt sich das SPI-Framework zur Portierung verwenden. Referenz ist MS41908: /kernel/drivers/media/spi/ms41908.c

Portierungsschritte:

1. Standardmäßigen SPI-Subdevice-Treiberteil implementieren

1.1 Gemäß struct spi_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1) Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe MS41908-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx stellen hauptsächlich Geräteparameter für die Zuordnung zum Kameragerät bereit.

1.2) Motorbezogene Konfigurationsparameter abrufen. Diese richten sich nach den Funktionsanforderungen des Chips; Bewegungsparameter sollten möglichst konfigurierbar sein.

2. Timer mit hrtimer_init initialisieren. ms41908 verwendet vd als Triggersignal. Der Timer legt zur einfachen Steuerung eine feste vd-Periode fest. Register werden nach dem vd-Signal wirksam; Änderungen können jeweils vorher vorgenommen werden. Die durch Geschwindigkeit und Schrittzahl bestimmte Bewegung muss innerhalb einer vd-Periode liegen. Schritte außerhalb dieser Periode gehen verloren.

3) Synchronisation mittels init_completion einrichten. Beim selben Motor darf die nächste Operation erst nach Abschluss der vorherigen beginnen.

4. V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der Treiber verlangt einen eigenen Subdevice-Geräteknoten für rkaiq im Userspace; darüber wird der Motor gesteuert.

Media-Entity: media_entity_init;

5. Gerätename:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);
2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

  .ioctl
  .compat_ioctl32

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.g_volatile_ctrl
.s_ctrl

DC-IRIS-Treiber

Anders als bei P-IRIS ist die genaue Blendenöffnung bei DC-IRIS nicht bekannt. Normalerweise bleibt die Blende zunächst vollständig geöffnet. Ist das Bild trotz minimaler Belichtung noch überbelichtet, beginnt die Blendenanpassung; ebenso bei Unterbelichtung trotz maximaler Belichtung. Der DC-IRIS-Motor ist ein Gleichstrommotor, dessen Verstellgeschwindigkeit durch negative Rückkopplung eines Hall-Elements gedämpft wird. Der Treiber steuert ihn mit einer PWM. Unter 20% Tastverhältnis schließt die Blende langsam vollständig; kleinere Werte beschleunigen das Schließen. Oberhalb 40% öffnet sie sich langsam; größere Werte beschleunigen das Öffnen. Im Bereich 20%~40% hält sie ihre Position. Die Grenzen 20% und 40% sind nicht fest, sondern hängen von PWM-Frequenz und Genauigkeit der Hardwarebauteile ab. Referenztreiber: /kernel/drivers/media/i2c/hall-dc-motor.c

DC-IRIS-Geräteregistrierung (DTS)

  hal_dc_motor: hal_dc_motor{
          status = "okay";
          compatible = "rockchip,hall-dc";
          pwms = <&pwm6 0 2500 0>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &pwm6 {
          status = "okay";
          pinctrl-names = "active";
          pinctrl-0 = <&pwm6m0_pins_pull_down>;
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          lens-focus = <&hal_dc_motor>;
          ...
      }
  }

Kurze Beschreibung der Datentypen

struct platform_driver

[Beschreibung]

Definiert Informationen des Plattformgerätetreibers.

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver struct device_driver enthält hauptsächlich Treibername und of_match_table
zum Abgleich mit DTS-Geräten. Stimmen die compatible-Felder von of_match_table
und DTS überein, wird .probe aufgerufen.
@id_table Verwendet der Kernel nicht of_match_table und DTS-Geräte zum Abgleich,
verwendet er diese Tabelle.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  #if defined(CONFIG_OF)
  static const struct of_device_id motor_dev_of_match[] = {
      { .compatible = "rockchip,hall-dc", },
      {},
  };
  #endif
  static struct platform_driver motor_dev_driver = {
      .driver = {
          .name = DRIVER_NAME,
          .owner = THIS_MODULE,
          .of_match_table = of_match_ptr(motor_dev_of_match),
      },
      .probe = motor_dev_probe,
      .remove = motor_dev_remove,
  };
  module_platform_driver(motor_dev_driver);
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops motor_core_ops = {
      .ioctl = motor_ioctl,
  };
  static const struct v4l2_subdev_ops motor_subdev_ops = {
      .core   = &motor_core_ops,
  };
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops motor_ctrl_ops = {
      .s_ctrl = motor_s_ctrl,
  };

Kurze API-Beschreibung

xxxx_set_ctrl

[Beschreibung]

Die Blendenposition wird über standardmäßiges v4l2_control eingestellt. Da die genaue DC-Blendenposition nicht bekannt ist, bezeichnet der gesetzte Wert tatsächlich das PWM-Tastverhältnis.

Folgende standardmäßige V4L2-Befehle sind implementiert:

Parametername Beschreibung
V4L2_CID_IRIS_ABSOLUTE Tastverhältnis der blendensteuernden PWM setzen, Bereich 0~100

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Derzeit sind keine privaten Definitionen zu implementieren. Für die Registrierung im V4L2-Framework werden leere Funktionen benötigt.

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

Treiberreferenz: /kernel/drivers/media/i2c/hall-dc-motor.c

Portierungsschritte:

1. Standardmäßigen Plattform-Subdevice-Treiberteil implementieren

1.1 Gemäß struct platform_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1. Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe DC-IRIS-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx dienen vor allem der Zuordnung von Geräteparametern zur Kamera. 1.2) PWM-Ressourcen anfordern und prüfen, ob der PWM-Knoten aktiviert ist.

2. V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der Treiber verlangt einen eigenen Subdevice-Geräteknoten für rkaiq im Userspace; darüber wird der Motor gesteuert.

Media-Entity: media_entity_init;

3. Name des Blitzlichtgeräts; diese Bezeichnung steht so im Blendenabschnitt der Quelle:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           motor->module_index, facing,
           DRIVER_NAME);
2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

  ioctl
  .compat_ioctl32

Dieser Callback muss derzeit keine konkreten Befehle implementieren. Als V4L2-Subdevice benötigt er jedoch eine Operationsfunktion; daher wird eine leere Funktion implementiert.

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.g_volatile_ctrl.s_ctrl

.g_volatile_ctrl und .s_ctrl implementieren folgende Befehle mit standardmäßigen V4L2-Steuerelementen:

Mitgliedsname Beschreibung
V4L2_CID_IRIS_ABSOLUTE Tastverhältnis der blendensteuernden PWM setzen, Bereich 0~100

RK-IRCUT-Treiber

IRCUT wird über zwei Leitungen mit 3.5v~6v angesteuert. Durch Umpolen und Einhalten einer Einschaltdauer von 100ms±10% lässt sich der Filter umschalten. Der Treiber steuert die Stromrichtung des Motortreibers über zwei GPIOs, bezeichnet als open (rote Leitung) und close (schwarze Leitung). Strom von open nach close aktiviert den Infrarotsperrfilter für den Tagbetrieb; Strom von close nach open schaltet auf die weiße Glasscheibe für den Nachtbetrieb.

RK-IRCUT-Geräteregistrierung (DTS)

  cam_ircut0: cam_ircut {
          status = "okay";
          compatible = "rockchip,ircut";
          ircut-open-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>;
          ircut-close-gpios  = <&gpio2 RK_PA6 GPIO_ACTIVE_HIGH>;
          rockchip,camera-module-index = <1>;
          rockchip,camera-module-facing = "front";
  };
  &i2c1 {
      imx334: imx334@1a {
          ...
          ir-cut = <&cam_ircut0>;
          ...
      }
  }

Kurze Beschreibung der Datentypen

struct platform_driver

[Beschreibung]

Definiert Informationen des Plattformgerätetreibers.

[Definition]

  struct platform_driver {
          int (*probe)(struct platform_device *);
          int (*remove)(struct platform_device *);
          void (*shutdown)(struct platform_device *);
          int (*suspend)(struct platform_device *, pm_message_t state);
          int (*resume)(struct platform_device *);
          struct device_driver driver;
          const struct platform_device_id *id_table;
          bool prevent_deferred_probe;
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
@driver struct device_driver enthält hauptsächlich Treibername und of_match_table
zum Abgleich mit DTS-Geräten. Stimmen die compatible-Felder von of_match_table
und DTS überein, wird .probe aufgerufen.
@id_table Verwendet der Kernel nicht of_match_table und DTS-Geräte zum Abgleich,
verwendet er diese Tabelle.
@probe Callback zur Gerätebindung
@remove Callback zum Aufheben der Gerätebindung

[Beispiel]

  #if defined(CONFIG_OF)
  static const struct of_device_id ircut_of_match[] = {
      { .compatible = "rockchip,ircut", },
      {},
  };
  #endif
  static struct platform_driver ircut_driver = {
      .driver = {
          .name = RK_IRCUT_NAME,
          .of_match_table = of_match_ptr(ircut_of_match),
      },
      .probe = ircut_probe,
      .remove = ircut_drv_remove,
  };
  module_platform_driver(ircut_driver);
struct v4l2_subdev_core_ops

[Beschreibung]

Definiert die Core-Operations-Callbacks für Subdevices.

[Definition]

  struct v4l2_subdev_core_ops {
      ……
      long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
  #ifdef CONFIG_COMPAT
      long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
               unsigned long arg);
  #endif
      ……
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.ioctl Wird am Ende der ioctl()-Systemaufrufbehandlung im V4L2-Kern aufgerufen
und unterstützt treiberspezifische private ioctls.
.compat_ioctl32 Wird bei einer 32-Bit-Anwendung auf einem 64-Bit-Kernel aufgerufen,
um Daten beim Austausch mit dem Userspace anzupassen.

[Beispiel]

  static const struct v4l2_subdev_core_ops ircut_core_ops = {
      .ioctl = ircut_ioctl,
  };
  static const struct v4l2_subdev_ops ircut_subdev_ops = {
      .core   = &ircut_core_ops,
  };
struct v4l2_ctrl_ops

[Beschreibung]

Steuerungsoperationen, die der Treiber bereitstellen muss.

[Definition]

  struct v4l2_ctrl_ops {
      int (*s_ctrl)(struct v4l2_ctrl *ctrl);
  };

[Wichtige Mitglieder]

Mitgliedsname Beschreibung
.s_ctrl Neuen Steuerwert tatsächlich setzen; s_ctrl ist verpflichtend. Während des Aufrufs
wird ctrl->handler->lock gehalten, sodass niemand sonst auf die
Steuerelemente dieses Handlers zugreifen kann.

[Beispiel]

  static const struct v4l2_ctrl_ops ircut_ctrl_ops = {
      .s_ctrl = ircut_s_ctrl,
  };

Kurze API-Beschreibung

xxxx_set_ctrl

[Beschreibung]

IRCUT über standardmäßiges v4l2_control umschalten.

Folgende standardmäßige V4L2-Befehle sind implementiert:

Parametername Beschreibung
V4L2_CID_BAND_STOP_FILTER 0: CLOSE, Infrarotlicht kann eintreten;
3: OPEN, Infrarotlicht kann nicht eintreten.

[Syntax]

  static int xxxx_set_ctrl(struct v4l2_ctrl *ctrl)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*ctrl Zeiger auf die V4L2-Steuerstruktur Eingabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen
xxxx_ioctl xxxx_compat_ioctl

[Beschreibung]

Derzeit sind keine privaten Definitionen zu implementieren. Für die Registrierung im V4L2-Framework werden leere Funktionen benötigt.

[Syntax]

  static int xxxx_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  static long xxxx_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd,
  unsigned long arg)

[Parameter]

Parametername Beschreibung Eingabe und Ausgabe
*sd Zeiger auf die V4L2-Subdevice-Struktur Eingabe
cmd ioctl-Befehl Eingabe
*arg/arg Parameterzeiger Ausgabe

[Rückgabewert]

Rückgabewert Beschreibung
0 Erfolgreich
Ungleich 0 Fehlgeschlagen

Schritte zur Treiberportierung

Treiberreferenz: /kernel/drivers/media/i2c/rk_ircut.c

Portierungsschritte:

1. Standardmäßigen Plattform-Subdevice-Treiberteil implementieren

1.1 Gemäß struct platform_driver insbesondere folgende Teile implementieren:

struct driver.name

struct driver. of_match_table

probe-Funktion

remove-Funktion

1.2 Einzelheiten zur Implementierung von probe:

1. Geräteressourcen anfordern, hauptsächlich aus dem DTS; siehe RK-IRCUT-Geräteregistrierung (DTS).

1.1) Private RK-Ressourcen wie rockchip, camera-module-xxx stellen hauptsächlich Geräteparameter für die Zuordnung zum Kameragerät bereit.

1.2) GPIO-Ressourcen open und close anfordern.

2. Mit init_completion synchronisieren. Das Umschalten von IRCUT dauert etwa 100ms; die Completion stellt sicher, dass es abgeschlossen ist, bevor die nächste Operation beginnt.

3. Eine Arbeitswarteschlange anlegen und das Umschalten dort ausführen, um langes Blockieren zu vermeiden.

4. V4L2-Gerät und Media-Entity initialisieren.

V4L2-Subdevice: v4l2_i2c_subdev_init. Der Treiber verlangt einen eigenen Subdevice-Geräteknoten für rkaiq im Userspace; darüber wird IRCUT gesteuert.

Media-Entity: media_entity_init;

  sd->entity.function = MEDIA_ENT_F_LENS;
  sd->entity.flags = 1;//flag is fixed to 1, used to distinguish other sub-devices of MEDIA_ENT_F_LENS type

5. Gerätename:

  snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s",
           ircut->module_index, facing,
           RK_IRCUT_NAME);
2. V4L2-Subdevice-Treiber implementieren, insbesondere die folgenden 2 Mitglieder
  struct v4l2_subdev_core_ops
  struct v4l2_ctrl_ops

2.1 Gemäß v4l2_subdev_core_ops insbesondere folgende Callbacks implementieren:

  .ioctl
  .compat_ioctl32

Dieser Callback benötigt derzeit keine privaten Befehle, ist für die V4L2-Registrierung jedoch erforderlich. Deshalb wird eine leere Funktion implementiert, die später nach Bedarf ergänzt werden kann.

2.2 Gemäß v4l2_ctrl_ops insbesondere folgende Callbacks implementieren:

.s_ctrl

.s_ctrl implementiert folgende Befehle mit standardmäßigen V4L2-Steuerelementen:

Mitgliedsname Beschreibung
V4L2_CID_BAND_STOP_FILTER 0: CLOSE, Infrarotlicht kann eintreten;
3: OPEN, Infrarotlicht kann nicht eintreten.

Werkzeuge media-ctl und v4l2-ctl

media-ctl arbeitet über Media-Geräte wie /dev/medio0; diese Schreibweise der Quelle ist zu prüfen. Es verwaltet Format, Größe und Verknüpfungen der Knoten in der Media-Topologie.

v4l2-ctl arbeitet mit Videogeräten wie /dev/video0 und /dev/video1. Es führt Operationen wie set_fmt, reqbuf, qbuf, dqbuf, stream_on und stream_off aus.

Zur genauen Verwendung siehe die Hilfe des jeweiligen Befehls. Einige häufige Anwendungen folgen.

1. Topologie ausgeben

  media-ctl -p -d /dev/media0

Hinweis: ISP2 besitzt zahlreiche Geräteknoten; media0/media1/media2 können vorhanden sein. Listen Sie die Geräte einzeln auf und prüfen Sie ihre Informationen.

2. Verknüpfen

  media-ctl -l'"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[0]'
  media-ctl -l'"rkisp-isp-subdev":2->"rkisp_mainpath":0[1]'

Hinweis: Trennen Sie den ISPP-Pfad, verknüpfen Sie main_path und erfassen Sie RAW-Bilder über main_path. Ohne -d verwendet media-ctl standardmäßig /dev/media0. Prüfen Sie, welchem Geräteknoten rkisp-isp-subdev zugeordnet ist; üblicherweise /dev/media1.

3. fmt/size ändern

  media-ctl -d /dev/media0 \
  --set-v4l2'"ov5695 7-0036":0[fmt:SBGGR10_1X10/640x480]'

Hinweis: Prüfen Sie, welchem Media-Gerät der Kameraknoten ov5695 7-0036 zugeordnet ist.

4. fmt setzen und Bilder erfassen

  v4l2-ctl -d /dev/video0 \
  --set-fmt-video=width=720,height=480,pixelformat=NV12 \
  --stream-mmap=3 \
  --stream-skip=3 \
  --stream-to=/tmp/cif.out \
  --stream-count=1 \
  --stream-poll

5. Belichtung, Verstärkung und weitere Steuerelemente setzen

  v4l2-ctl -d /dev/video3 --set-ctrl'exposure=1216,analogue_gain=10'

Hinweis: Der ISP-Treiber ruft die Steuerbefehle des Kamera-Subdevices auf. Deshalb lässt sich die Belichtung beispielsweise über video3 (main_path oder self_path) setzen. VICAP ruft diese Befehle nicht auf; Steuerbefehle direkt am Erfassungsknoten schlagen fehl. Ermitteln Sie stattdessen den Kameraknoten /dev/v4l-subdevX und konfigurieren Sie ihn direkt.

Speicheroptimierung auf RV1109/RV1126

MIPI -> DDR_1 -> ISP -> DDR_2 -> ISPP(TNR) -> DDR_3 -> ISPP(NR&Sharp) -> DDR_4 -> ISPP(FEC) -> DDR_5

1. DDR_1: VICAP-RAW-Daten oder ISP-MIPI-RAW-Daten werden in DDR geschrieben; der ISP liest sie zur Verarbeitung wieder aus DDR.

Speicherbedarf: buf_cnt * buf_size * N, mit N = 1 im linearen Modus, 2 im HDR2-Modus und 3 im HDR3-Modus.

buf_size: ALIGN(width * bpp / 8, 256) * height; // bpp ist die Bitbreite: raw8, raw10 oder raw12.

buf_cnt: Standard 4, mindestens 3; definiert im AIQ-Bibliothekscode hwi/isp20/CamHwIsp20.h.

#define ISP_TX_BUF_NUM 4
#define VIPCAP_TX_BUF_NUM 4

2. DDR_2: ISP-FBC-YUV420- und Verstärkungsdaten werden in DDR geschrieben; ISPP liest sie zur Verarbeitung.

Speicherbedarf: buf_size * buf_cnt

buf_size: ALIGN(width, 64) * ALIGN(height, 128) / 16 + ALIGN(width, 16) * ALIGN(hieght, 16) * 1.5625

buf_cnt: 4 Puffer im TNR-3to1-Modus, 3 im 2to1-Modus; der Modus wird im IQ-XML konfiguriert.

3. DDR_3: ISPP-TNR-FBC-YUV420- und Verstärkungsdaten werden in DDR geschrieben; ISPP NR&Sharp liest sie erneut zur Verarbeitung.

Speicherbedarf: buf_size * buf_cnt

buf_size: ALIGN(width, 64) * ALIGN(height, 128) / 16 + ALIGN(width, 16) * ALIGN(hieght, 16) * 1.5625

buf_cnt: 2, der kleinstmögliche Wert.

4. DDR_4: ISPP-NR&Sharp-YUYV-Daten werden in DDR geschrieben und von ISPP FEC zur weiteren Verarbeitung gelesen.

Speicherbedarf: buf_size * buf_cnt; bei deaktivierter FEC-Funktion wird kein Speicher belegt.

buf_size: width * height * 2

buf_cnt: 2, der kleinstmögliche Wert.

5. DDR_5: Bildpuffer der vier ISPP-Ausgabekanäle. Die Größe berechnet sich aus benutzerseitig eingestellter Auflösung, Format und buf_cnt.

Die obigen buf_cnt-Werte bieten Ansatzpunkte zur Speicheroptimierung.

Für reservierten ISP-CMA-Speicher kann zunächst mehr Speicher vorgesehen werden. Nach dem Start der Kameraanwendung lässt sich die tatsächlich benötigte Größe ermitteln.

  isp_reserved: isp {
      compatible = "shared-dma-pool";
      inactive;
      reusable;
      size = <0x10000000>;//256M and need 4M align
  };
  enable cma debug
  +++ b/arch/arm/configs/rv1126_defconfig
  @@ -62,6 +62,8 @@ CONFIG_IOSCHED_BFQ=y
   CONFIG_KSM=y
   CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
   CONFIG_CMA=y
  +CONFIG_CMA_DEBUG=y
  +CONFIG_CMA_DEBUGFS=y
  one page is 4K, 26091 page is 104364K and need 4M align, so config 104M to
  isp_reserved
  [root@RV1126_RV1109:/sys/kernel/debug/cma/cma-isp@0]# ls
  alloc  base_pfn  bitmap  count free  maxchunk order_per_bit  used
  [root@RV1126_RV1109:/sys/kernel/debug/cma/cma-isp@0]# cat used
  26091

Latenzoptimierung auf RV1109/RV1126

1. VICAP wait-line konfigurieren

Setzen Sie wait-line am VICAP-Knoten im DTS. Bei Bildhöhe 1520 und wait-line=760 wird der Puffer bereits nach Erfassung der halben Bildhöhe an den ISP ausgegeben. Passen Sie wait-line an die Lesegeschwindigkeit des ISP an.

&rkcif_mipi_lvds {
      wait-line = <760>;
};

Die folgende Befehlsvariante unterstützt auch dynamische Konfiguration:

  echo 1000 > /sys/devices/platform/rkcif_mipi_lvds/wait_line

Hinweis: Bei zu kleinem wait-line greift der ISP zu früh auf den Puffer zu. Noch nicht erfasste Bereiche enthalten Daten des vorherigen Bildes. Bei starken Bildänderungen entstehen dadurch Fehler oder eine sichtbare Teilung am Bildende. Bestimmen Sie einen geeigneten Wert durch tatsächliche Tests.

2. ISP wait-line konfigurieren

Setzen Sie wait-line am ISP-Knoten im DTS. Bei Bildhöhe 1520 und wait-line=760 wird nach Verarbeitung von Zeile 760 an ISPP ausgegeben. Passen Sie den Wert an die Verarbeitungszeiten von ISP und ISPP an.

&rkisp_vir0 {
      wait-line = <760>;
};

Zur Diagnose kann auch /sys/module/video_rkisp/parameters/wait_line gesetzt werden, bevor das ISP-Videogerät geöffnet wird.

Hinweis: Ist wait-line zu klein und ISPP schneller als ISP, kann wegen des FBC-Kompressionsformats ein Haltezustand auftreten. Die Motion-Funktion und Mehrsensorbetrieb unterstützen dies nicht.

3. ISPP wait-line für vier Ausgabestreams konfigurieren

Setzen Sie wait-line am ISPP-Knoten im DTS. Bei Bildhöhe 1520 und wait-line=896 wird nach Verarbeitung von Zeile 896 an die nachgelagerte Verarbeitung ausgegeben. Passen Sie den Wert an die ISPP-Verarbeitungszeit für NR oder FEC und die nachgelagerte Verarbeitungszeit an.

&rkispp_vir0 {
     status = "okay";
     wait-line = <896>;
};

Zur Diagnose kann auch /sys/module/video_rkispp/parameters/wait_line gesetzt werden, bevor das ISPP-Videogerät geöffnet wird.

Hinweis: Ist wait-line zu klein und die nachgelagerte Verarbeitung schneller als ISPP, entstehen dort Bildverarbeitungsfehler. Mehrsensorbetrieb wird nicht unterstützt.

4. Hardwareverarbeitung beschleunigen

1) ISP-/ISPP-Takt erhöhen

drivers/media/platform/rockchip/isp/hw.c

static const struct isp_clk_info rv1126_isp_clk_rate[] = {
{
.clk_rate = 20,
.refer_data = 0,
}, {
.clk_rate = 600,
.refer_data = 1920, //width
}, {
.clk_rate = 600,
.refer_data = 2688,
}, {
.clk_rate = 600,
.refer_data = 3072,
}, {
.clk_rate = 600,
.refer_data = 3840,
}
};

drivers/media/platform/rockchip/ispp/hw.c

static const struct ispp_clk_info rv1126_ispp_clk_rate[] = {
{
.clk_rate = 150,
.refer_data = 0,
}, {
.clk_rate = 500,
.refer_data = 1920 //width
}, {
.clk_rate = 500,
.refer_data = 2688,
}, {
.clk_rate = 500,
.refer_data = 3072,
}, {
.clk_rate = 500,
.refer_data = 3840,
}
};

2) IOMMU deaktivieren und reservierten Speicher verwenden

   &rkisp_mmu {          status = "disabled";    };
  &rkisp {
        memory-region = <&isp_reserved>;
  };
  &rkispp_mmu {          status = "disabled";   };
  &rkispp {
        memory-region = <&isp_reserved>;
  };

Häufig gestellte Fragen

Treiberversion ermitteln

Aus dem Kernel-Startprotokoll ablesen:

  rkisp ffb50000.rkisp: rkisp driver version: v00.01.00
  rkispp ffb60000.rkispp: rkispp driver version: v00.01.00

Alternativ abrufen mit:

  cat /sys/module/video_rkisp/parameters/version
  cat /sys/module/video_rkispp/parameters/version

Ladezustand des RKISP-Treibers prüfen

Nach erfolgreichem Laden des RKISP-Treibers sind Video- und Media-Geräte unter /dev/ vorhanden. Es kann mehrere /dev/video-Geräte geben. Über /sys lassen sich die von RKISP registrierten Videoknoten bestimmen.

  localhost ~ # grep'' /sys/class/video4linux/video*/name

Auch media-ctl kann die Topologie ausgeben, um die Pipeline zu prüfen.

Zur Prüfung des Kameratreibers: Sobald alle Kameras registriert sind, gibt der Kernel folgendes Protokoll aus.

  localhost ~ # dmesg | grep Async
  [0.682982] RKISP: Async subdev notifier completed

Fehlt die Zeile Async subdev notifier completed, prüfen Sie zuerst Sensorfehlermeldungen und die erfolgreiche I2C-Kommunikation.

Vom CIS ausgegebene RAW- und YUV-Daten erfassen

Nach Abschluss der Treiberentwicklung können CIS-Ausgabedaten direkt mit dem standardmäßigen v4l2-ctl erfasst werden. Anwendungshilfe: https://www.mankier.com/1/v4l2-ctl

Beispiel
  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2

-d: Gerätenamen angeben.

–set-fmt-video: Auflösung einstellen; sie muss der Sensorausgabe entsprechen. Die aktuelle Sensorauflösung lässt sich mit media-ctl -p -d /dev/mediaX prüfen.

pixelformat: Ausgabedatenformat, beispielsweise BG12 oder NV12.

–stream-mmap: Anzahl der mmap-Puffer.

–stream-count: Anzahl zu erfassender Bilder; mehrere Bilder werden in derselben Datei gespeichert.

–stream-to: Speicherpfad angeben.

–stream-skip: Anzahl zu überspringender Bilder.

Unterstützte Geräte

RV1109/RV1126
Gerät Schnittstelle Format Geräteknotenname RAW-Ausgabe YUV-Ausgabe
VICAP DVP RAW video0~video3 Nicht kompakt
RAW
Nein
VICAP MIPI/LVDS RAW video0~video3 Nicht kompakt
RAW
Kompakt RAW
Nein
VICAP DVP / MIPI /
LVDS
YUV video0~video3 Nein nv12
nv16
ISP DVP / MIPI /
LVDS
RAW rkisp_rawwr0
rkisp_rawwr1
rkisp_rawwr2
rkisp_rawwr3
Nicht kompakt
RAW
Kompakt RAW
Nein
ISP MIPI / LVDS YUV rkisp_mainpath Nicht kompakt
RAW
nv12
nv16
ISPP Nur DDR-Lesen YUV rkispp_m_bypass
rkispp_scale0
rkispp_scale1
rkispp_scale2
Nein nv12
nv16
RK356X
Gerät Schnittstelle Format Geräteknotenname RAW-Ausgabe YUV-Ausgabe
VICAP DVP RAW video0~video3 Nicht kompakt
RAW
Nein
VICAP MIPI/LVDS RAW video0~video3 Nicht kompakt
RAW
Kompakt RAW
Nein
VICAP DVP / MIPI /
LVDS
YUV video0~video3 Nein nv12
nv16
ISP DVP / MIPI /
LVDS
RAW rkisp_rawwr0
rkisp_rawwr1
rkisp_rawwr2
rkisp_rawwr3
Nicht kompakt
RAW
Kompakt RAW
Nein
ISP MIPI / LVDS YUV rkisp_mainpath Nicht kompakt
RAW
nv12
nv16

Hinweise:

1. Geräteknoten mit media-ctl -p -d /dev/mediaX abfragen; X steht für 0, 1, 2, 3 usw.

RAW-Speicherformat

Nicht kompaktes RAW-Speicherformat

Im nicht kompakten Format werden raw10- und raw12-Sensordaten in 16 Bit gespeichert und an den höherwertigen Bits ausgerichtet. Die folgende Abbildung zeigt die RAW12-Anordnung am Beispiel eines 4-Byte-Speicherabschnitts:

Englische Originalabbildung 9, PDF-Seite 120

Englische Originalabbildung 9, PDF-Seite 120

Kompaktes RAW-Speicherformat

Die folgende Abbildung zeigt die RAW12-Anordnung am Beispiel eines 4-Byte-Speicherabschnitts:

Englische Originalabbildung 10, PDF-Seite 120

Englische Originalabbildung 10, PDF-Seite 120

Wichtiger Hinweis

Das ISP-mainpath-Gerät gibt bei Raw10- oder Raw12-Eingang einheitlich Raw12 im nicht kompakten RAW-Speicherformat aus.

Anwendungsbeispiele

RAW-Ausgabe über VICAP
  1. Standard ist das kompakte Format. Mit folgenden Befehlen lässt sich zwischen kompakt und nicht kompakt wechseln:
      echo 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test

0 bedeutet nicht kompakt, 1 kompakt. Für mehrere gleichzeitig verwendete Kanäle kann der Befehl wie folgt angepasst werden:

      echo 0 0 0 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test

Die Zahlen nach echo bestimmen nacheinander die Speicherformate von vc0, vc1, vc2 und vc3.

  1. video0~3 entsprechen vc0~vc3.

  2. v4l2-ctl-Befehl

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
Nicht kompakte RAW-Ausgabe über ISP-mainpath
  1. Für Bilder aus mainpath muss die standardmäßige ISP-Ausgabeverknüpfung rkisp-bridge-ispp mit folgendem Befehl auf mainpath umgestellt werden:
      media-ctl -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[0]'
      media-ctl -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[1]'

Hinweis: Ohne -d wird standardmäßig media0 verwendet. Liegt rkisp-isp-subdev nicht dort, geben Sie mit -d das zugehörige Media-Gerät an.

Die 0 hinter „rkisp-bridge-ispp“ bezeichnet pad0, einen Sink-Pad. Einzelheiten enthält die V4L2-Dokumentation.

2. Das ISP-Ausgabeformat ist standardmäßig YUYV8_2X8. Wechseln Sie mit folgendem Befehl auf Bayer RAW:

      media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[fmt:SBGGR12_1X12/2688x1520]'

Hinweis: rkisp-isp-subdev liegt nicht zwingend in media0. Ermitteln Sie das zugehörige Media-Gerät und geben Sie es mit -d an.

Die 2 hinter „rkisp-isp-subdev“ bezeichnet pad2, einen Source-Pad. Einzelheiten enthält die V4L2-Dokumentation.

Prüfen Sie anschließend mit media-ctl -p -d /dev/mediaX (X=0,1,2,…), ob die Änderung wirksam ist. Erst danach erfasste RAW-Daten entsprechen den ursprünglichen RAW-Daten.

  1. v4l2-ctl-Befehl
  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
YUV-Ausgabe über VICAP

Die Eingangsdaten müssen YUV sein. Bei RAW-Eingabe kann VICAP kein YUV ausgeben.

  v4l2-ctl -d /dev/video0  --set-fmt-video=width=1920,height=1080,pixelformat=NV12 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2
YUV-Ausgabe über ISP
  v4l2-ctl -d /dev/video5  --set-fmt-video=width=1920,height=1080,pixelformat=NV12 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.raw  --stream-skip=2

Hinweise:

1. Beim ISP können mainpath oder selfpath erfasst werden; video5 ist nur ein Beispiel und muss an die tatsächlichen Parameter angepasst werden. 2. Bei RAW-Eingabe kann der ISP nach verschiedenen Bildverarbeitungsschritten YUV ausgeben. Dafür muss RK AIQ die ISP-Bildverarbeitungsmodule steuern. Die hier gezeigten Befehle richten nur den Datenfluss ein; die Module verwenden Treiberstandardparameter, wodurch die Bildwirkung normalerweise nicht korrekt ist.

YUV-Ausgabe über ISPP

ISPP-Eingangsdatenquelle: rkisp-bridge-ispp.

Die Verknüpfungen von rkisp_mainpath, rkisp_selfpath und rkispp_input_image müssen deaktiviert sein.

Das Source-Format von rkisp-isp-subdev pad2 muss fmt:YUYV8_2X8 sein.

ISP ist standardmäßig mit ISPP verknüpft. Referenzbefehle:

  media-ctl -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[0]'
  media-ctl -l '"rkisp-isp-subdev":2->"rkisp_selfpath":0[0]'
  media-ctl -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[1]'
  media-ctl -d /dev/media1 -l '"rkispp_input_image":0->"rkispp-subdev":0[1]'
  v4l2-ctl -d /dev/video13 \
  --set-fmt-video=width=2688,height=1520,pixelformat=NV12 \
  --stream-mmap=3 --stream-to=/tmp/nv12.out --stream-count=20 --stram-poll

Hinweis: Wählen Sie für -d je nach Erfassungsanforderung einen der folgenden Knoten. Die tatsächlichen Namen liefert media-ctl -p -d /dev/mediaX.

Knoten Ausgabefähigkeit
rkispp_m_bypass Volle Auflösung und YUV-Format
rkispp_scale0 Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis [1 8], maximale Breite 3264.
rkispp_scale1 Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis [2 8], maximale Breite 1280.
rkispp_scale2 Volle oder skalierte Auflösung, YUV-Format.
Skalierungsverhältnis [2 8], maximale Breite 1280.

CIS-Ausgabeauflösung umschalten

  1. Unterstützt der Sensortreiber mehrere Auflösungen, lässt sich für RAW-Aufnahmen einer anderen Auflösung die aktuelle Sensorauflösung mit folgendem Befehl umschalten:
  media-ctl -d /dev/media0 --set-v4l2 '"m01_f_os04a10 1-0036-1":0[fmt:SBGGR12_1X12/2688x1520]'

Hinweis: m01_f_os04a10 1-0036-1 ist der Sensorknotenname; danach folgt das gewünschte Format. Der Sensortreiber muss diese Formatkonfiguration unterstützen.

  1. Bei VICAP genügt die Einstellung des Sensorknotens. Beim ISP müssen zusätzlich dessen Ein- und Ausgabeformat gesetzt werden. Referenzbefehle:
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":0[fmt:SBGGR12_1X12/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":0[crop:(0,0)/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[fmt:SBGGR12_1X12/2688x1520]'
  media-ctl -d /dev/media0 --set-v4l2 '"rkisp-isp-subdev":2[crop:(0,0)/2688x1520]'

CIS-Belichtungsparameter einstellen

  1. Ermitteln Sie mit media-ctl -p -d /dev/mediaX den Sensorknoten /dev/v4l-subdevX. Referenzbefehl:
  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl 'exposure=1216,analogue_gain=10'

Die Werte können auch einzeln gesetzt werden:

  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl exposure=1216
  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl analogue_gain=10
  1. Die maximale Belichtung ist durch Sensor-VTS begrenzt, beispielsweise auf vts-4 oder vts-10; maßgeblich ist das jeweilige Sensorhandbuch. Bei 30fps beträgt die maximale Belichtungszeit beispielsweise 33.3ms. Für 40ms muss VTS erhöht werden. Proportionale Umrechnung: vts_30fps * 30fps = vts_25fps * 25fps. Daraus ergibt sich VTS für 25fps; vblank ist (vts-height). Setzen Sie den berechneten vblank-Wert im Sensortreiber, um längere Belichtung zu erlauben. Referenzbefehl:

vts ist die Bildlänge einschließlich aktiver Zeilen und Austastzeilen.

  v4l2-ctl -d /dev/v4l-subdev4 --set-ctrl vertical_blanking=200

Schwarzweißkameras unterstützen

Der CIS-Treiber muss das Ausgabeformat des Schwarzweißsensors auf eines der folgenden drei Formate ändern:

  MEDIA_BUS_FMT_Y8_1X8 (sensor 8bit output)
  MEDIA_BUS_FMT_Y10_1X10 (sensor 10bit output)
  MEDIA_BUS_FMT_Y12_1X12 (sensor 12bit output)

Dieses Format wird in xxxx_get_fmt und xxxx_enum_mbus_code zurückgegeben.

Der RKISP-Treiber nimmt für diese drei Formate besondere Einstellungen vor, um Schwarzweißbilder zu erfassen.

Benötigt die Anwendung Y8-Bilder, muss außerdem SP Path verwendet werden, da nur dieser Y8-Ausgabe unterstützt.

Gerade und ungerade Halbbilder zusammenführen

Der RKISP-Treiber unterstützt die Zusammenführung gerader und ungerader Halbbilder unter folgenden Voraussetzungen:

1. MIPI muss die Bildnummer aus den Frame-Start-/Frame-End-Kurzpaketen ausgeben. Daraus bestimmt RKISP die Parität des aktuellen Halbbildes.

2. BT656 muss standardmäßiges SAV/EAV mit der Halbbildparität in bit6 ausgeben. Daraus bestimmt RKISP die Parität.

3. Nur der Videogeräteknoten RKISP1_selfpath besitzt diese Funktion. Verwendet die Anwendung versehentlich einen anderen Knoten, meldet der Treiber:

"Only selfpath support interlaced"

RKISP_selfpath-Informationen lassen sich mit media-ctl -p anzeigen:

  entity 3: rkisp_selfpath (1 pad, 1 link)
       type Node subtype V4L flags 0
        device node name /dev/video1
      pad0: Sink
         <- "rkisp-isp-subdev":2 [ENABLED]
Implementierung im Gerätetreiber

format.field muss V4L2_FIELD_INTERLACED sein, um gerade und ungerade Halbbilder als Ausgabe zu kennzeichnen. Dieser Wert ist in xxxx_get_fmt zurückzugeben. Referenz: driver/media/i2c/tc35874x.c.

Diagnoseinformationen anzeigen

1. Media-Pipeline-Informationen prüfen; sie entsprechen der Kamerakonfiguration im DTS.

  media-ctl -p -d /dev/mediaX (X = 0, 1, 2 ..)

2. proc-Informationen anzeigen: aktueller ISP-/ISPP-Zustand sowie Bildein-/ausgabeinformationen. cat kann mehrfach aufgerufen werden.

  cat /proc/rkisp*

3. Treiber-Diagnoseinformationen anzeigen: Debugstufe an ISP- und ISPP-Knoten setzen. Höhere Werte liefern mehr Informationen.

  echo n> /sys/module/video_rkisp/parameters/debug (n = 0, 1, 2, 3; 0 is off)
  echo n> /sys/module/video_rkispp/parameters/debug
  echo 8 > /proc/sys/kernel/printk

4. Registerinformationen prüfen und die Datei reg auslesen.

Für RV1109/RV1126:

      io -4 -l 0x10000 0xffb50000> /tmp/isp.reg
      io -4 -l 0x1000 0xffb60000> /tmp/ispp.reg

Für RK3566/RK3568:

      io -4 -l 0x10000 0xfdff0000> /tmp/isp.reg

5. Schritte zur Bereitstellung von Diagnoseinformationen:

1. Am Fehlerzustand: 1->2->4->3. 2. Zur Reproduktion: 3->Start->Reproduktion->1->2->4.

  1. Beschreibung der proc-Informationen
  [root@RV1126_RV1109:/]# cat /proc/rkisp*
  rkisp-vir0 Version:v01.06.00
  clk_isp    400000000
  aclk_isp   500000000
  hclk_isp   250000000
  Interrupt  Cnt:7521 ErrCnt:0
  Input      rkcif_mipi_lvds Format:SBGGR10_1X10 Size:2688x1520@30fps Offset(0,0)
  Isp Read   mode:frame2 (frame:1522 rate:33ms idle time:10ms) cnt(total:1522
  X1:1503 X2:18 X3:-1)
  Output     rkispp0 Format:FBC420 Size:2688x1520 (frame:1522 rate:32ms)
  DPCC0      ON(0x5)
  DPCC1      ON(0x5)
  DPCC2      ON(0x5)
  BLS        ON(0x1)
  SDG        OFF(0x80446197)
  LSC        ON(0x1)
  AWBGAIN    ON(0x80446197) (gain: 0x01110111, 0x028a0202)
  DEBAYER    ON(0x7000111)
  CCM        ON(0x80000001)
  GAMMA_OUT  ON(0x80000001)
  CPROC      ON(0xf)
  IE         OFF(0x0) (effect: BLACKWHITE)
  WDR        OFF(0x30cf0)
  HDRTMO     ON(0xa4f05a27)
  HDRMGE     ON(0x80000005)
  RAWNR      ON(0x80100001)
  GIC        OFF(0x0)
  DHAZ       ON(0x80101119)
  3DLUT      OFF(0x2)
  GAIN       ON(0x80010111)
  LDCH       OFF(0x0)
  CSM        FULL(0x80446197)
  SIAF       OFF(0x0)
  SIAWB      OFF(0x0)
  YUVAE      ON(0x400100f3)
  SIHST      ON(0x38000107)
  RAWAF      ON(0x7)
  RAWAWB     ON(0x776887)
  RAWAE0     ON(0x40000003)
  RAWAE1     ON(0x400000f5)
  RAWAE2     ON(0x400000f5)
  RAWAE3     ON(0x400000f5)
  RAWHIST0   ON(0x40000501)
  RAWHIST1   ON(0x60000501)
  RAWHIST2   ON(0x60000501)
  RAWHIST3   ON(0x60000501)
  Monitor    OFF Cnt:0

clk_isp: ISP-Taktfrequenz.

Interrupt: MIPI-Interrupt sowie Interrupts der einzelnen ISP-Module. Steigende Zähler zeigen Dateneingang zum ISP an. ErrCnt zählt Fehlerinterrupts.

Input: Eingangsquelle, Eingabeformat, Auflösung und Beschnittinformationen.

Isp read: mode ist one oder hdr2/3; frame ist die Sequenznummer; rate das Bildintervall; idle/working der ISP-Betriebszustand; time die Hardwareverarbeitungszeit des ISP. cnt zählt Rücklesevorgänge insgesamt sowie mit einem, zwei oder drei Durchläufen.

Output: Ausgabeziel, Ausgabeformat, Auflösung; frame ist die Sequenznummer, rate das Bildintervall.

Other: Aktivierungszustand der einzelnen ISP-Module.

Monitor: Fehlererkennung und Rücksetzen.

  [root@RV1126_RV1109:/]# cat /proc/rkisp*
  rkispp-vir0 Version:v01.06.00
  clk_ispp   350000000
  aclk_ispp  500000000
  hclk_ispp  250000000
  Interrupt  Cnt:79532 ErrCnt:0
  Input      rkisp0 Format:FBC420 Size:2688x1520 (frame:26510 rate:32ms
  delay:13ms)
  Output     rkispp_m_bypass Format:NV12 Size:2688x1520 (frame:26509 rate:32ms
  delay:30ms)
  TNR        ON(0xf00000f) (mode: 3to1) (global gain: disable) (frame:26510
  time:8ms idle) CNT:0x0 STATE:0x1e000000
  NR         ON(0x57) (external gain: enable) (frame:26510 time:6ms working)
  0x5f0:0x19 0x5f4:0x780f
  SHARP      ON(0x19) (YNR input filter: ON) (local ratio: OFF) 0x630:0x19
  FEC        OFF(0x2) (frame:0 time:0ms idle) 0xc90:0x0
  ORB        OFF(0x0)
  Monitor    ON Cnt:0

clk_ispp: ISPP-Taktfrequenz.

Interrupt: Verarbeitungsinterrupts von ISPP. Steigende Zähler zeigen Dateneingang an; ErrCnt zählt Fehlerinterrupts.

Input: Eingangsquelle, Eingabeformat, Auflösung; frame ist die Sequenznummer, rate das Bildintervall, delay die Differenz zwischen Eingangsbildzeit und MIPI-Bildzeit.

Output: Ausgabeziel, Ausgabeformat, Auflösung; frame ist die Sequenznummer, rate das Bildintervall, delay die Differenz zwischen Ausgabe- und MIPI-Bildzeit. Letztere hängt auch vom Ausgabebildpuffer ab.

Other: Aktivierungszustand der einzelnen ISPP-Module; frame ist die Sequenznummer, time die Hardwareverarbeitungszeit des Moduls, idle/working dessen Betriebszustand.

Monitor: Fehlererkennung und Rücksetzen.

  [root@RV1126_RV1109:/]# cat /proc/rkcif_mipi_lvds
  Driver Version:v00.01.0a
  Work Mode:ping pong
  Monitor Mode:idle
  aclk_cif:500000000
  hclk_cif:250000000
  dclk_cif:297000000
  Input Info:
          src subdev:m01_f_os04a10 1-0036-1
          interface:mipi csi2
          lanes:4
          vc channel: 0 1
          hdr mode: hdr_x2
          format:SBGGR10_1X10/2688x1520@30
          crop.bounds:(0, 0)/2688x1520
  Output Info:
          format:BG10/2688x1520(0,0)
          compact:enable
          frame amount:264
          early:10 ms
          single readout:30 ms
          total readout:30 ms
          rate:33 ms
          fps:30
          irq statistics:
                          total:515
                          csi over flow:0
                          csi bandwidth lack:0
                          all err count:0
                          frame dma end:515

Work Mode: Nach RV1109 wird standardmäßig Ping-Pong verwendet; dieser Modus wird empfohlen.

Monitor Mode: Überwachungsmodus. Ist er aktiviert und erkennt MIPI einen Fehler, wird VICAP zurückgesetzt.

Input Info: Zusammenfassung der Eingangsinformationen.

src subdev: Eingabegerät, üblicherweise der Sensor. Enthält Kameraausrichtung, Index, Gerätename, I2C-Bus, 7-Bit-Slave-Adresse und weitere Informationen.

interface: Physische Datenschnittstelle, etwa MIPI, LVDS oder DVP.

vc channel: Tatsächlich verwendeter virtueller Kanal der Mehrkanalübertragung im MIPI-Protokoll.

hdr mode: Sensorbetriebsmodus normal, hdr_x2 oder hdr_x3.

format: Eingabedatentyp.

crop.bounds: Beschnittparameter lassen sich in .get_selection des Sensortreibers konfigurieren, um die Eingangsdaten passend zu beschneiden.

Output Info: Zusammenfassung der Ausgabeinformationen.

format: Ausgabedatentyp.

compact: Standardmäßig kompakte Ausgabe. Definitionen siehe „Vom CIS ausgegebene RAW- und YUV-Daten erfassen“.

frame amount: Bildanzahl.

early: Im Wake-up-Modus wird der Puffer bereits nach Erfassung von wait_line Zeilen an den ISP übergeben. Standardmäßig geschieht dies erst nach dem vollständigen Bild. early bezeichnet den Zeitgewinn durch diese vorgezogene Übergabe. Konfiguration siehe Latenzoptimierung auf RV1109/RV1126.

single readout: Im HDR-Modus ist die Übertragungszeit eines Einzelbildes diejenige des langen Bildes.

total readout: Im HDR-Modus bezeichnet die Zeit zwischen Beginn der Übertragung des langen Bildes und Ende der Übertragung des kurzen Bildes die ursprüngliche Übertragungszeit eines zusammengeführten Bildes.

rate: Bildintervall.

fps: Bildrate.

irq statistics: Interruptinformationen.

total: Gesamtzahl der Interrupts einschließlich Bildende und Fehlern.

csi over flow: Anzahl der Überlaufinterrupts.

csi bandwidth lack: Anzahl der Interrupts wegen unzureichender Bandbreite.

frame dma end: Anzahl der Bildende-Interrupts; sie entspricht der Zahl der seit Streamstart vom Sensor ausgegebenen Bilder.

Anhang A: V4L2-Control-Liste des CIS-Treibers

CID Beschreibung
V4L2_CID_VBLANK Vertikale Austastung: Ruhephase nach jedem Bild ohne erzeugte Bilddaten.
Einheit ist eine Zeile. Deren Länge entspricht Bildbreite plus horizontaler Austastung
bei der durch V4L2_CID_PIXEL_RATE desselben Subdevices definierten Pixelrate.
V4L2_CID_HBLANK Horizontale Austastung: Ruhephase nach jeder Bilddatenzeile ohne erzeugte
Bilddaten. Einheit ist Pixel.
V4L2_CID_EXPOSURE Bestimmt die Belichtungszeit des Kamerasensors; diese ist durch das Bildintervall begrenzt.
V4L2_CID_ANALOGUE_GAIN Analoge Verstärkung aller Farbkomponenten der Pixelmatrix.
Die Verstärkung erfolgt im analogen Bereich vor der A/D-Wandlung.
V4L2_CID_PIXEL_RATE Pixelrate an den Source-Pads des Subdevices. Schreibgeschützt,
Einheit Pixel/Sekunde. Beispiel MIPI:
pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
V4L2_CID_LINK_FREQ Datenbusfrequenz. Zusammen mit Media-Bus-Pixelcode und Bustyp
(Taktzyklen pro Abtastwert) bestimmt sie die Pixelrate V4L2_CID_PIXEL_RATE
im Pixelarray oder gegebenenfalls anderswo bei Geräten ohne Bildsensor.
Aus Pixeltakt, Bildbreite/-höhe und horizontaler/vertikaler Austastung lässt sich die Bildrate berechnen.
Die Pixelratensteuerung kann auch außerhalb des Subdevices mit dem Pixelarray definiert sein;
daraus allein ist jedoch keine Bildrate ableitbar. Nur im Pixelarray dürfen horizontale
und vertikale Austastinformationen als exakt gelten, da dort keine weitere Austastung zulässig ist.
Die Bildrate wird durch Auswahl der horizontalen und vertikalen Austastung eingestellt.
Einheit: Hz.

Anhang B: MEDIA_BUS_FMT-Tabelle

CIS-Sensortyp Sensorausgabeformat
Bayer RAW MEDIA_BUS_FMT_SBGGR10_1X10
MEDIA_BUS_FMT_SRGGB10_1X10
MEDIA_BUS_FMT_SGBRG10_1X10
MEDIA_BUS_FMT_SGRBG10_1X10
MEDIA_BUS_FMT_SRGGB12_1X12
MEDIA_BUS_FMT_SBGGR12_1X12
MEDIA_BUS_FMT_SGBRG12_1X12
MEDIA_BUS_FMT_SGRBG12_1X12
MEDIA_BUS_FMT_SRGGB8_1X8
MEDIA_BUS_FMT_SBGGR8_1X8
MEDIA_BUS_FMT_SGBRG8_1X8
MEDIA_BUS_FMT_SGRBG8_1X8
YUV MEDIA_BUS_FMT_YUYV8_2X8
MEDIA_BUS_FMT_YVYU8_2X8
MEDIA_BUS_FMT_UYVY8_2X8
MEDIA_BUS_FMT_VYUY8_2X8
MEDIA_BUS_FMT_YUYV10_2X10
MEDIA_BUS_FMT_YVYU10_2X10
MEDIA_BUS_FMT_UYVY10_2X10
MEDIA_BUS_FMT_VYUY10_2X10
MEDIA_BUS_FMT_YUYV12_2X12
MEDIA_BUS_FMT_YVYU12_2X12
MEDIA_BUS_FMT_UYVY12_2X12
MEDIA_BUS_FMT_VYUY12_2X12
Nur Y (Schwarzweiß), RAW-BW-Sensor MEDIA_BUS_FMT_Y8_1X8
MEDIA_BUS_FMT_Y10_1X10
MEDIA_BUS_FMT_Y12_1X12

Anhang C: Liste der CIS-Referenztreiber

CIS-Datenschnittstelle CIS-Ausgabedatentyp Vollbild/Halbbild Referenztreiber
MIPI Bayer RAW Vollbild 0.3M
ov7750.c
gc0403.c
1.2M
ov9750.c
jx-h65.c
2M
ov2685.c
ov2680.c
ov2735.c
gc2385.c
gc2355.c
gc2053.c
sc2239.c
sc210iot.c
4M
gc4c33.c
5M
ov5695.c
ov5648.c
ov5670.c
gc5024.c
gc5025.c
gc5035.c
8M
ov8858.c
imx378.c
imx317.c
imx219.c
gc8034.c
13M
ov13850.c
imx258.c
MIPI Bayer raw hdr Vollbild 2M
imx307.c
imx327.c
gc2093.c
ov02k10
ov2718.c
sc200ai.c
sc2310.c
jx-f37.c
4M
ov4689.c
os04a10.c
imx347.c
sc4238.c
5M
imx335.c
8M
imx334.c
imx415.c
MIPI YUV Vollbild 2M
gc2145.c
MIPI RAW BW Vollbild 0.3M
ov7251.c
1M
ov9281.c
1.3M
sc132gs.c
MIPI YUV Halbbild tc35874x.c
ITU.BT601 Bayer RAW   2M
imx323.c
ar0230.c
ITU.BT601 YUV   0.3M
gc0329.c
gc0312.c
gc032a.c
2M
gc2145.c
gc2155.c
gc2035.c
bf3925.c
ITU.BT601 RAW BW    
ITU.BT656 Bayer RAW   2M
imx323 (Unterstützung möglich)

Anhang D: Referenztreiber für VCM-Treiber-ICs

Referenztreiber

vm149c.c

dw9714.c

fp5510.c

Anhang E: Referenztreiber für Blitzlicht-Treiber-ICs

Referenztreiber

sgm3784.c

leds-rgb13h.c (GPIO-Steuerung)

Dieses Thema entdecken → · Lernpfade →