diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..29a30cc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+root = true
+
+[{*.{awk,c,dts,dtsi,dtso,h,mk,s,S},Kconfig,Makefile,Makefile.*}]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = tab
+indent_size = 8
+
+[*.{json,py,rs}]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+
+# this must be below the general *.py to overwrite it
+[tools/{perf,power,rcu,testing/kunit}/**.py,]
+indent_style = tab
+indent_size = 8
+
+[*.yaml]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 2
diff --git a/.github/workflows/build-drivers-hosted.yaml b/.github/workflows/build-drivers-hosted.yaml
new file mode 100644
index 0000000..4d7e880
--- /dev/null
+++ b/.github/workflows/build-drivers-hosted.yaml
@@ -0,0 +1,19 @@
+name: Build and install camera drivers
+
+on:
+ workflow_call:
+ inputs:
+ platform:
+ required: false
+ type: string
+
+jobs:
+ build-drivers:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ timeout-minutes: 5
+ steps:
+ - uses: actions/checkout@v3
+ - name: Build deb package
+ run: cd ./pkg/ && ./create_deb_pkg.sh
+ - name: Install deb package and build drivers with DKMS
+ run: yes Y | sudo dpkg -i *.deb
diff --git a/.github/workflows/camera-hotplug-hosted.yaml b/.github/workflows/camera-hotplug-hosted.yaml
new file mode 100644
index 0000000..7466fd1
--- /dev/null
+++ b/.github/workflows/camera-hotplug-hosted.yaml
@@ -0,0 +1,52 @@
+name: Hot plug cameras
+
+on:
+ workflow_call:
+ inputs:
+ platform:
+ required: false
+ type: string
+ dt-overlay-options:
+ required: true
+ type: string
+
+jobs:
+ camera-hotplug:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ timeout-minutes: 3
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ - name: Build dtbocfg
+ run: |
+ cd ./scripts/common/hotplug/dtbocfg/
+ make
+ ls -l ./dtbocfg.ko
+ sudo rmmod dtbocfg || true
+ sudo insmod ./dtbocfg.ko || true
+ lsmod | grep dtbocfg
+ - name: Hotplug
+ run: |
+ ./scripts/common/hotplug/camera-hotplug.sh ${{ inputs.dt-overlay-options }}
+
+ post-hotplug-checks:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ needs: camera-hotplug
+ timeout-minutes: 3
+ steps:
+ - run: |
+ find /proc/device-tree/ -name "*isx*" || find /proc/device-tree/ -name "*imx*"
+ find /proc/device-tree/ -name "*max9295*"
+ find /proc/device-tree/ -name "*max9296*"
+ find /proc/device-tree/ -name "*fpga*"
+ ls -l /dev/video*
+ ls -l /dev/v4l-*
+ ls -l /dev/media*
+ ls -l /dev/gmsl/
+ for media_device in $(find /dev/ -type c -name "media*"); do
+ media-ctl -d "${media_device}" -p
+ done
+ for video_device in $(find /dev/ -type c -name "video*"); do
+ v4l2-ctl -d "${video_device}" --all
+ done
diff --git a/.github/workflows/ecu-rqx58g-a.yaml b/.github/workflows/ecu-rqx58g-a.yaml
new file mode 100644
index 0000000..b6b55f6
--- /dev/null
+++ b/.github/workflows/ecu-rqx58g-a.yaml
@@ -0,0 +1,40 @@
+name: ROSCube RQX-58G A C1x8
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build-drivers:
+ uses: ./.github/workflows/build-drivers-hosted.yaml
+ with:
+ platform: rqx58g-a
+
+ camera-hotplug:
+ needs: build-drivers
+ uses: ./.github/workflows/camera-hotplug-hosted.yaml
+ with:
+ platform: rqx58g-a
+ dt-overlay-options: roscube R32.6.1 -8 C1
+
+ test-8-cameras:
+ needs: camera-hotplug
+ strategy:
+ matrix:
+ dev-index: [0, 1, 2, 3, 4, 5, 6, 7]
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-a
+ video-device: /dev/video${{ matrix.dev-index }}
+ gstreamer-options: 'video/x-raw, width=1920, height=1280, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c1-${{ matrix.dev-index }}
+
+ unload-camera-drivers:
+ needs: test-8-cameras
+ uses: ./.github/workflows/unload-drivers-hosted.yaml
+ with:
+ platform: rqx58g-a
diff --git a/.github/workflows/ecu-rqx58g-b.yaml b/.github/workflows/ecu-rqx58g-b.yaml
new file mode 100644
index 0000000..d13ddab
--- /dev/null
+++ b/.github/workflows/ecu-rqx58g-b.yaml
@@ -0,0 +1,40 @@
+name: ROSCube RQX-58G B C2x8
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build-drivers:
+ uses: ./.github/workflows/build-drivers-hosted.yaml
+ with:
+ platform: rqx58g-b
+
+ camera-hotplug:
+ needs: build-drivers
+ uses: ./.github/workflows/camera-hotplug-hosted.yaml
+ with:
+ platform: rqx58g-b
+ dt-overlay-options: roscube R32.6.1 -8 C2
+
+ test-8-cameras:
+ needs: camera-hotplug
+ strategy:
+ matrix:
+ dev-index: [0, 1, 2, 3, 4, 5, 6, 7]
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-b
+ video-device: /dev/video${{ matrix.dev-index }}
+ gstreamer-options: 'video/x-raw, width=2880, height=1860, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c2-${{ matrix.dev-index }}
+
+ unload-camera-drivers:
+ needs: test-8-cameras
+ uses: ./.github/workflows/unload-drivers-hosted.yaml
+ with:
+ platform: rqx58g-b
diff --git a/.github/workflows/ecu-rqx58g-c.yaml b/.github/workflows/ecu-rqx58g-c.yaml
new file mode 100644
index 0000000..7288e29
--- /dev/null
+++ b/.github/workflows/ecu-rqx58g-c.yaml
@@ -0,0 +1,100 @@
+name: ROSCube RQX-58G C C1x2 C2x2 C1x2 C2x2
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build-drivers:
+ uses: ./.github/workflows/build-drivers-hosted.yaml
+ with:
+ platform: rqx58g-c
+
+ camera-hotplug:
+ needs: build-drivers
+ uses: ./.github/workflows/camera-hotplug-hosted.yaml
+ with:
+ platform: rqx58g-c
+ dt-overlay-options: roscube R32.6.1 -2 C1 -2 C2 -2 C1 -2 C2
+
+ test-camera-0:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-isx021-cam1
+ gstreamer-options: 'video/x-raw, width=1920, height=1280, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c1-0
+
+ test-camera-1:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-isx021-cam2
+ gstreamer-options: 'video/x-raw, width=1920, height=1280, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c1-1
+
+ test-camera-2:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-imx490-cam3
+ gstreamer-options: 'video/x-raw, width=2880, height=1860, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c2-2
+
+ test-camera-3:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-imx490-cam4
+ gstreamer-options: 'video/x-raw, width=2880, height=1860, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c2-3
+
+ test-camera-4:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-isx021-cam5
+ gstreamer-options: 'video/x-raw, width=1920, height=1280, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c1-4
+
+ test-camera-5:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-isx021-cam6
+ gstreamer-options: 'video/x-raw, width=1920, height=1280, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c1-5
+
+ test-camera-6:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-imx490-cam7
+ gstreamer-options: 'video/x-raw, width=2880, height=1860, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c2-6
+
+ test-camera-7:
+ needs: camera-hotplug
+ uses: ./.github/workflows/test-v4l2-gstreamer-hosted.yaml
+ with:
+ platform: rqx58g-c
+ video-device: /dev/gmsl/tier4-imx490-cam8
+ gstreamer-options: 'video/x-raw, width=2880, height=1860, framerate=30/1, format=UYVY'
+ artifact-name: gstreamer-v4l2-mjpeg-c2-7
+
+ unload-camera-drivers:
+ needs: [test-camera-0, test-camera-1, test-camera-2, test-camera-3, test-camera-4, test-camera-5, test-camera-6, test-camera-7]
+ uses: ./.github/workflows/unload-drivers-hosted.yaml
+ with:
+ platform: rqx58g-c
diff --git a/.github/workflows/test-make-overlay-dts.yaml b/.github/workflows/test-make-overlay-dts.yaml
new file mode 100644
index 0000000..63e2500
--- /dev/null
+++ b/.github/workflows/test-make-overlay-dts.yaml
@@ -0,0 +1,171 @@
+name: Test camera devicetree overlay generation scripts
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize]
+ paths:
+ - 'tools/dts_generator/make_overlay_dts*.py'
+
+jobs:
+ test-make-overlay-dts-roscube:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R32.5.1, R32.5.2, R32.6.1, R35.4.1]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_roscube.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
+ test-make-overlay-dts-roscube-orin:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R35.1, R35.2.1]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_roscube-orin.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
+ test-make-overlay-dts-orin-devkit:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R35.1, R35.2.1]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_orin-devkit.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
+ test-make-overlay-dts-xavier-devkit:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R32.5.1, R32.5.2, R32.6.1, R35.1, R35.2.1, R35.3.1]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_xavier-devkit.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
+ test-make-overlay-dts-eac-5000:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R35.3.1]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_eac-5000.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
+ test-make-overlay-dts-anvil:
+ runs-on: ubuntu-20.04
+ timeout-minutes: 3
+ strategy:
+ matrix:
+ revision: [R35]
+ camera-combination: [
+ "-8 C1", "-8 C2",
+ "-6 C1 -2 C2", "-6 C2 -2 C1", "-2 C1 -6 C2", "-2 C2 -6 C1",
+ "-4 C1 -4 C2", "-4 C2 -4 C1",
+ "-4 C1 -2 C1 -2 C2", "-4 C1 -2 C2 -2 C1", "-4 C2 -2 C1 -2 C2", "-4 C2 -2 C2 -2 C1",
+ "-2 C1 -2 C2 -4 C1", "-2 C2 -2 C1 -4 C1", "-2 C1 -2 C2 -4 C2", "-2 C2 -2 C1 -4 C2",
+ "-2 C1 -2 C2 -2 C1 -2 C2", "-2 C2 -2 C1 -2 C2 -2 C1"
+ ]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install device-tree-compiler
+ run: command -v dtc || ( sudo apt-get update && sudo apt-get install -y device-tree-compiler )
+ - name: Generate devicetree overlay
+ run: |
+ ./tools/dts_generator/make_overlay_dts_anvil.py "${{ matrix.revision }}" ${{ matrix.camera-combination }}
+ ls -l *.dts
+ - name: Compile the generated devicetree overlay
+ run: |
+ dtc -O dtb -@ *.dts -o compiled.dtbo
+ ls -l *.dtbo
+
diff --git a/.github/workflows/test-v4l2-gstreamer-hosted.yaml b/.github/workflows/test-v4l2-gstreamer-hosted.yaml
new file mode 100644
index 0000000..485ebdd
--- /dev/null
+++ b/.github/workflows/test-v4l2-gstreamer-hosted.yaml
@@ -0,0 +1,44 @@
+name: GStreamer V4L2 tests
+
+on:
+ workflow_call:
+ inputs:
+ platform:
+ required: false
+ type: string
+ video-device:
+ required: true
+ type: string
+ gstreamer-options:
+ required: true
+ type: string
+ artifact-name:
+ required: false
+ type: string
+
+jobs:
+ check-camera:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ timeout-minutes: 3
+ steps:
+ - run: |
+ ls -l ${{ inputs.video-device }}
+ ls -l /dev/v4l-subdev*
+ ls -l /dev/media*
+ v4l2-ctl -d "${{ inputs.video-device }}" --all
+
+ dump-v4l2-stream:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ needs: check-camera
+ timeout-minutes: 3
+ steps:
+ - run: |
+ gst-launch-1.0 -e v4l2src io-mode=0 device=${{ inputs.video-device }} do-timestamp=true num-buffers=60 ! '${{ inputs.gstreamer-options }}' ! nvvidconv ! nvjpegenc ! qtmux ! filesink location=output.mov
+ ls -l output.mov
+ test -s output.mov
+ - name: Upload the captured Motion JPEG video
+ if: ${{ inputs.artifact-name != '' }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ inputs.artifact-name }}
+ path: output.mov
diff --git a/.github/workflows/unload-drivers-hosted.yaml b/.github/workflows/unload-drivers-hosted.yaml
new file mode 100644
index 0000000..dbba4d5
--- /dev/null
+++ b/.github/workflows/unload-drivers-hosted.yaml
@@ -0,0 +1,16 @@
+name: Unload camera drivers
+
+on:
+ workflow_call:
+ inputs:
+ platform:
+ required: false
+ type: string
+
+jobs:
+ unload-camera-drivers:
+ runs-on: [self-hosted, linux, ARM64, "${{ inputs.platform }}"]
+ timeout-minutes: 2
+ steps:
+ - name: Unload camera modules
+ run: sudo modprobe -r tier4-imx728
diff --git a/.gitignore b/.gitignore
index 8442dd3..778cf2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,20 @@ modules.order
Module.symvers
Mkfile.old
build
+
+.tag
+.tags
+
+# deb package
+debhelper-build-stamp
+.DS_Store
+**/*.debhelper
+*.deb
+*.dsc
+*.build
+*.buildinfo
+*.changes
+*.tar.gz
+*.log
+*.substvars
+**/debian/files
diff --git a/drivers/README.md b/drivers/README.md
deleted file mode 100644
index 608d5f1..0000000
--- a/drivers/README.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# tier4-camera-gmsl-dkms
-
-This driver has been developed on ROScube RQX58G/Jetson Orin Devkit, it could not be cross-compiled at this moment.
-
-## Preparation
-
-``` sh
-sudo apt update
-sudo apt install make build-essential debhelper debmake devscripts dkms
-```
-
-## Build debian-dkms package
-
-``` sh
-dpkg-buildpackage -b -rfakeroot -us -uc
-```
-
-## Install the debian-dkms package
-
-``` sh
-cd ..
-sudo apt update
-sudo apt install ./tier4-isx021-gmsl_1.4.1_arm64.deb
-```
-
-## Confirm the dtbo file exists
-
-```
-ls /boot/*.dtbo
-```
-
-
-## Combine dtbo file with vanilla dtb
-
-
-``` sh
-sudo /opt/nvidia/jetson-io/config-by-hardware.py -n 2="TIERIV ISX021 GMSL2 Camera Device Tree Overlay"
-```
-
-if you use r32.5.1 BSP, you should use the command below
-
-``` sh
-sudo /opt/nvidia/jetson-io/config-by-hardware.py -n "TIERIV ISX021 GMSL2 Camera Device Tree Overlay"
-```
-
-
-## Confirm custom dtb file has been generated
-
-``` sh
-ls -al /boot/*user-custom.dtb
-```
-
-
-## Then, shutdown the system
-
-$> sudo shutdown -h now
-
-## Power on again
\ No newline at end of file
diff --git a/drivers/create_deb_pkg.sh b/drivers/create_deb_pkg.sh
deleted file mode 100755
index 3ca53b2..0000000
--- a/drivers/create_deb_pkg.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-if [ -e ./src/tier4-isx021.bin ]
-then
- grep -q "TIER4_ISX021_REG_0_ADDR" ./src/tier4-isx021.c
- if [ ! $? = 0 ]
- then
- echo "The register address is not hidden."
- echo "exec python ./tool/gen_firmware.py ./src/tier4-isx021.c"
- python3 ./tools/gen_firmware.py ./src/tier4-isx021.c
- fi
- dpkg-buildpackage -b -rfakeroot -us -uc
-fi
-
-#dpkg-buildpackage -b -rfakeroot -us -uc
diff --git a/drivers/debian/etc/modprobe.d/tier4-isx021.conf b/drivers/debian/etc/modprobe.d/tier4-isx021.conf
deleted file mode 100644
index 5c33b9e..0000000
--- a/drivers/debian/etc/modprobe.d/tier4-isx021.conf
+++ /dev/null
@@ -1,19 +0,0 @@
-# Configurations:
-# "trigger_mode=0" run cameras in master mode. (Default)
-# "trigger_mode=1" run cameras in slave(External pulse sync) mode, and valid for ADLINK RQX-58G only.
-#
-# "enable_auto_exposure=0" disable auto-exposure feature.
-# "enable_auto_exposure=1" enable auto-exposure feature. (Default)
-#
-# "enable_distortion_correction=0" disable distortion correction feature. (Default)
-# "enable_distortion_correction=1" enable distortion correction feature.
-#
-
-options tier4_isx021 trigger_mode=0 enable_auto_exposure=1 enable_distortion_correction=1
-
-# The following parameter is valid for ADLINK RQX-58G only.
-# "generate_fsync=0" External pulse is not automatically genereated by FPGA. (Default)
-# "generate_fsync=1" External pulse is automatically genereated by FPGA( not supported yet).
-#
-
-options tier4_fpga generate_fsync=0
diff --git a/drivers/debian/udev b/drivers/debian/udev
deleted file mode 100644
index 9854e42..0000000
--- a/drivers/debian/udev
+++ /dev/null
@@ -1,16 +0,0 @@
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 30-002b", SYMLINK+= "gmsl/tier4-imx490-cam1"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 30-001b", SYMLINK+= "gmsl/tier4-isx021-cam1"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 30-002c", SYMLINK+= "gmsl/tier4-imx490-cam2"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 30-001c", SYMLINK+= "gmsl/tier4-isx021-cam2"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 31-002b", SYMLINK+= "gmsl/tier4-imx490-cam3"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 31-001b", SYMLINK+= "gmsl/tier4-isx021-cam3"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 31-002c", SYMLINK+= "gmsl/tier4-imx490-cam4"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 31-001c", SYMLINK+= "gmsl/tier4-isx021-cam4"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 32-002b", SYMLINK+= "gmsl/tier4-imx490-cam5"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 32-001b", SYMLINK+= "gmsl/tier4-isx021-cam5"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 32-002c", SYMLINK+= "gmsl/tier4-imx490-cam6"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 32-001c", SYMLINK+= "gmsl/tier4-isx021-cam6"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 33-002b", SYMLINK+= "gmsl/tier4-imx490-cam7"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 33-001b", SYMLINK+= "gmsl/tier4-isx021-cam7"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_imx490 33-002c", SYMLINK+= "gmsl/tier4-imx490-cam8"
-SUBSYSTEM=="video4linux", ATTR{name}=="vi-output, tier4_isx021 33-001c", SYMLINK+= "gmsl/tier4-isx021-cam8"
diff --git a/drivers/src/.clang-format b/drivers/src/.clang-format
deleted file mode 100755
index e03f80b..0000000
--- a/drivers/src/.clang-format
+++ /dev/null
@@ -1,48 +0,0 @@
----
-BasedOnStyle: Google
-AccessModifierOffset: -2
-ConstructorInitializerIndentWidth: 2
-AlignEscapedNewlinesLeft: false
-AlignTrailingComments: true
-AllowAllParametersOfDeclarationOnNextLine: false
-AllowShortIfStatementsOnASingleLine: false
-AllowShortLoopsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: None
-AllowShortLoopsOnASingleLine: false
-AlwaysBreakTemplateDeclarations: true
-AlwaysBreakBeforeMultilineStrings: false
-BreakBeforeBinaryOperators: false
-BreakBeforeTernaryOperators: false
-BreakConstructorInitializersBeforeComma: true
-BinPackParameters: true
-ColumnLimit: 120
-ConstructorInitializerAllOnOneLineOrOnePerLine: true
-DerivePointerBinding: true
-ExperimentalAutoDetectBinPacking: false
-IndentCaseLabels: true
-MaxEmptyLinesToKeep: 1
-NamespaceIndentation: None
-ObjCSpaceBeforeProtocolList: true
-PenaltyBreakBeforeFirstCallParameter: 19
-PenaltyBreakComment: 60
-PenaltyBreakString: 1
-PenaltyBreakFirstLessLess: 1000
-PenaltyExcessCharacter: 1000
-PenaltyReturnTypeOnItsOwnLine: 90
-PointerBindsToType: false
-SpacesBeforeTrailingComments: 2
-Cpp11BracedListStyle: false
-Standard: Auto
-IndentWidth: 2
-TabWidth: 2
-UseTab: Never
-BreakBeforeBraces: Allman
-IndentFunctionDeclarationAfterType: false
-SpacesInParentheses: false
-SpacesInAngles: false
-SpaceInEmptyParentheses: false
-SpacesInCStyleCastParentheses: false
-SpaceAfterControlStatementKeyword: true
-SpaceBeforeAssignmentOperators: true
-ContinuationIndentWidth: 4
-...
diff --git a/drivers/src/tier4-fpga.c b/drivers/src/tier4-fpga.c
deleted file mode 100644
index 207dd66..0000000
--- a/drivers/src/tier4-fpga.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * tier4_fpga.c - tier4_fpga driver
- *
- * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-//#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tier4-gmsl-link.h"
-#include "tier4-fpga.h"
-
-//#define DEBUG_INFO
-
-#define FPGA_ENABLED 0xF0
-#define FPGA_DISABLED 0xFF
-#define NO_ERROR 0
-
-#define FPGA_REG_VERSION_ADDR 0x1
-#define FPGA_REG_ENABLE_ADDR 0x4
-//#define FPGA_REG_FREQ_BASE_ADDR 0x8
-
-#define FREQ_10HZ 10
-#define FREQ_20HZ 20
-#define FREQ_30HZ 30
-
-static int fsync_mode; // 0: disabled, 1: enable auto mode, 2: enable manual mode
-
-module_param(fsync_mode, int, S_IRUGO | S_IWUSR);
-
-
-static int fps_cam1_cam2 = 0xCAFE;
-static int fps_cam3_cam4 = 0xCAFE;
-static int fps_cam5_cam6 = 0xCAFE;
-static int fps_cam7_cam8 = 0xCAFE;
-
-module_param(fps_cam1_cam2, int, S_IRUGO | S_IWUSR);
-module_param(fps_cam3_cam4, int, S_IRUGO | S_IWUSR);
-module_param(fps_cam5_cam6, int, S_IRUGO | S_IWUSR);
-module_param(fps_cam7_cam8, int, S_IRUGO | S_IWUSR);
-
-
-struct tier4_fpga
-{
- struct i2c_client *i2c_client;
- struct regmap *regmap;
- struct tier4_gmsl_link_ctx g_ctx;
- struct mutex lock;
- /* FPGA slave address */
- __u32 reg_addr;
-// bool generate_fsync;
-};
-
-//static int generate_fsync;
-//module_param(generate_fsync, int, S_IRUGO | S_IWUSR);
-
-static struct regmap_config tier4_fpga_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
-};
-
-/* count channel */
-static __u32 channel_count_fpga; /* should be 1 */
-
-#if 1
-static int tier4_fpga_read_reg(struct device *dev, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
- struct tier4_fpga *priv = dev_get_drvdata(dev);
-
- err = regmap_read(priv->regmap, addr, ®_val);
-
- *val = reg_val & 0xFF;
-
- return err;
-}
-#endif
-
-static int tier4_fpga_write_reg(struct device *dev, u16 addr, u8 val)
-{
- struct tier4_fpga *priv = dev_get_drvdata(dev);
- int err = 0;
-
- err = regmap_write(priv->regmap, addr, val);
-
- if (err)
- {
- dev_err(dev, "[%s] FPGA I2C write Reg at 0x%04X:[0x%02X] failed.\n", __func__, addr, val);
- }
-#ifdef DEBUG_INFO
- else
- {
- dev_info(dev, "[%s] FPGA I2C write Reg at 0x%04X:[0x%02X].\n", __func__, addr, val);
- }
-#endif
-
- /* delay before next i2c command as required for SERDES link */
- usleep_range(200, 220);
-// tier4_fpga_read_reg(dev, addr, &e);
-// usleep_range(100, 110);
-
- return err;
-}
-
-int tier4_fpga_get_fsync_mode(void)
-{
- return fsync_mode; // 0: disabled, 1: enable auto mode, 2: enable manual mode
-}
-EXPORT_SYMBOL(tier4_fpga_get_fsync_mode);
-
-int tier4_fpga_enable_fsync_mode(struct device *dev)
-{
- int err = 0;
-// u8 val = 0;
-
-// err = tier4_fpga_read_reg(dev, FPGA_REG_MODE_ADDR, &val);
-// if ((val & 0xFF) == FPGA_MODE_FSYNC) {
-// // skip writing the same value to reg in order to save the flash write cycles
-// dev_info(dev, "[%s] : Keep FSYNC mode enabled.\n", __func__);
-// return err;
-// }
-
- err = tier4_fpga_write_reg(dev, FPGA_REG_MODE_ADDR, FPGA_MODE_FSYNC);
- if (err)
- {
- dev_err(dev, "[%s] Enabling FSYNC mode failed.\n", __func__);
- }
-#ifdef DEBUG_INFO
- else
- {
- dev_info(dev, "[%s] Enabling FSYNC mode.\n", __func__);
- }
-#endif
-
- return err;
-}
-EXPORT_SYMBOL(tier4_fpga_enable_fsync_mode);
-
-int tier4_fpga_disable_fsync_mode(struct device *dev)
-{
- int err = 0;
-// u8 val = 0;
-
-// err = tier4_fpga_read_reg(dev, FPGA_REG_MODE_ADDR, &val);
-// if ((val & 0xFF) == FPGA_MODE_FREE_RUN) {
-// // skip writing the same value to reg in order to save the flash write cycles
-// dev_info(dev, "[%s] : Keep FSYNC mode disabled.\n", __func__);
-// return err;
-// }
-
- err = tier4_fpga_write_reg(dev, FPGA_REG_MODE_ADDR, FPGA_MODE_FREE_RUN);
- if (err)
- {
- dev_err(dev, "[%s] Disabling FSYNC mode failed.\n", __func__);
- }
-#ifdef DEBUG_INFO
- else
- {
- dev_info(dev, "[%s] Disabling FSYNC mode.\n", __func__);
- }
-#endif
- return err;
-}
-EXPORT_SYMBOL(tier4_fpga_disable_fsync_mode);
-
-int tier4_fpga_set_fsync_auto_trigger(struct device *dev)
-{
- int err = 0;
-// u8 val = 0;
-
-// err = tier4_fpga_read_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, &val);
-// if ((val & 0xFF) == FPGA_FSYNC_AUTO) {
-// // skip writing the same value to reg in order to save the flash write cycles
-// dev_info(dev, "[%s] : Keep FSYNC Auto Trigger mode.\n", __func__);
-// return err;
-// }
-
- err = tier4_fpga_write_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, FPGA_FSYNC_AUTO);
- if (err)
- {
- dev_err(dev, "[%s] Enabling FSYNC Auto Trigger mode failed.\n", __func__);
- }
-#ifdef DEBUG_INFO
- else
- {
- dev_info(dev, "[%s] Enabling FSYNC Auto Trigger mode.\n", __func__);
- }
-#endif
- return err;
-}
-EXPORT_SYMBOL(tier4_fpga_set_fsync_auto_trigger);
-
-int tier4_fpga_set_fsync_manual_trigger(struct device *dev)
-{
- int err = 0;
-// u8 val = 0;
-
-// err = tier4_fpga_read_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, &val);
-// if ((val & 0xFF) == FPGA_FSYNC_MANUAL) {
-// // skip writing the same value to reg in order to save the flash write cycles
-// dev_info(dev, "[%s] : Keep FSYNC Auto Trigger mode.\n", __func__);
-// return err;
-// }
-
- err = tier4_fpga_write_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, FPGA_FSYNC_MANUAL);
- if (err)
- {
- dev_err(dev, "[%s] Enabling FSYNC Manual Trigger mode failed.\n", __func__);
- }
-#ifdef DEBUG_INFO
- else
- {
- dev_info(dev, "[%s] Enabling FSYNC Manual Trigger mode failed.\n", __func__);
- }
-#endif
-
- return err;
-}
-EXPORT_SYMBOL(tier4_fpga_set_fsync_manual_trigger);
-
-// ***************
-
-int tier4_fpga_check_access(struct device *dev)
-{
- int err = 0;
- int i;
- u8 dummy8 = 0;
-
- for (i=0; i < 5 ; i++ )
- {
- err = tier4_fpga_read_reg(dev, FPGA_REG_VERSION_ADDR, &dummy8);
- if (!err)
- {
- break;
- }
- usleep_range(10000,11000); // sleep 10 msec
- }
-
- if (err)
- {
- dev_err(dev, "[%s] Accessing FPGA failed.\n", __func__);
- return err;
- }
- return NO_ERROR;
-}
-EXPORT_SYMBOL(tier4_fpga_check_access);
-
-
-static int tier4_fpga_get_fps_camx_camy(struct device *dev, int des_number, int fps, int trigger_mode)
-{
- int freq;
- char str_fps_camx_camy[15] = "\0";
-
-#ifdef DEBUG_INFO
- dev_info(dev, "[%s] dns_number=%d trigger_mode=%de.\n", __func__, des_number, trigger_mode);
-#endif
-
- switch (des_number){
- case 0:
- strcpy(str_fps_camx_camy,"fps_cam1_cam2");
- break;
- case 1:
- strcpy(str_fps_camx_camy,"fps_cam3_cam4");
- break;
- case 2:
- strcpy(str_fps_camx_camy,"fps_cam5_cam6");
- break;
- case 3:
- strcpy(str_fps_camx_camy,"fps_cam7_cam8");
- break;
- default:
- strcpy(str_fps_camx_camy,"fps_cam?_cam?");
- break;
- }
-
- if (trigger_mode == 1)
- {
- if ((fps > 5) && (fps <= 10))
- {
- freq = fps;
- }
- else
- {
- freq = FREQ_10HZ;
- dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.", __func__, str_fps_camx_camy, fps, str_fps_camx_camy, freq);
-
- }
- }
- else if (trigger_mode == 3)
- {
- if ((fps > 10) && (fps <= 20))
- {
- freq = fps;
- }
- else
- {
- freq = FREQ_20HZ;
- dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.", __func__, str_fps_camx_camy, fps, str_fps_camx_camy, freq);
- }
- }
- else if (trigger_mode == 5)
- {
- if ((fps > 20) && (fps <= 30))
- {
- freq = fps;
- }
- else
- {
- freq = FREQ_30HZ;
- dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.", __func__, str_fps_camx_camy, fps, str_fps_camx_camy, freq);
- }
- }
-
-#ifdef DEBUG_INFO
- dev_info(dev, "[%s] freq=%d.\n", __func__, freq);
-#endif
-
- return freq;
-}
-
-// --------------------------------------------
-
-int tier4_fpga_set_fsync_signal_frequency(struct device *dev, int des_number, int trigger_mode)
-{
- int err = 0;
- u8 val8, addr8;
- int freq = 0;
- // u8 read_val = 0;
- u8 freq_bitmask = 0x3F; // bit[0:5]
-
-
- switch (des_number){
- case 0:
- freq = tier4_fpga_get_fps_camx_camy(dev, des_number, fps_cam1_cam2, trigger_mode);
- break;
- case 1:
- freq = tier4_fpga_get_fps_camx_camy(dev, des_number, fps_cam3_cam4, trigger_mode);
- break;
- case 2:
- freq = tier4_fpga_get_fps_camx_camy(dev, des_number, fps_cam5_cam6, trigger_mode);
- break;
- case 3:
- freq = tier4_fpga_get_fps_camx_camy(dev, des_number, fps_cam7_cam8, trigger_mode);
- break;
- default:
- dev_err(dev, "[%s] Invalid des_number(%d)\n", __func__, des_number);
- break;
- }
-
- addr8 = (u8)(FPGA_REG_FREQ_BASE_ADDR + 12 * (des_number));
- val8 = (u8)(freq & freq_bitmask);
-
-#ifdef DEBUG_INFO
- dev_info(dev, "[%s] freq=%d.\n", __func__, freq);
-#endif
-
-// err = tier4_fpga_read_reg(dev, addr8, &read_val);
-// if ((read_val & freq_bitmask) == val8) {
-// // skip writing the same value to reg in order to save the flash write cycles
-// dev_info(dev, "[%s] : Keep the frequency of fsync trigger to %d\n", __func__, val8);
-// return err;
-// }
-
- err = tier4_fpga_write_reg(dev, addr8, val8);
-
- if (err)
- {
- dev_err(dev, "[%s] Setting the frequency of fsync trigger failed.\n", __func__);
- return err;
- }
- else
- {
- dev_info(dev, "[%s] Setting the frequency of fsync trigger to %d.\n", __func__, val8);
- }
-
- return NO_ERROR;
-}
-EXPORT_SYMBOL(tier4_fpga_set_fsync_signal_frequency);
-
-int tier4_fpga_get_slave_addr(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx)
-{
- struct tier4_fpga *priv = dev_get_drvdata(dev);
-
- if (!g_ctx)
- {
- dev_err(dev, "[%s] g_ctx is null\n", __func__);
- return -1;
- }
-
- g_ctx->sdev_fpga_reg = priv->reg_addr;
-
- return 0;
-}
-EXPORT_SYMBOL(tier4_fpga_get_slave_addr);
-
-const struct of_device_id tier4_fpga_of_match[] = {
- {
- .compatible = "nvidia,tier4_fpga",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, tier4_fpga_of_match);
-
-// -----------------------------------------------------
-
-static int tier4_fpga_parse_dt(struct tier4_fpga *priv, struct i2c_client *client)
-{
- struct device_node *node = client->dev.of_node;
- int err = 0;
-
- if (!node)
- return -EINVAL;
-
- err = of_property_read_u32(node, "reg", &priv->reg_addr);
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] fpga reg not found\n", __func__);
- return -EINVAL;
- }
-
- priv->g_ctx.sdev_fpga_reg = priv->reg_addr;
-
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------
-
-static int tier4_fpga_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct tier4_fpga *priv;
- int err = 0;
- int inhibit_fpga_access = 0;
-
- dev_info(&client->dev, "[%s] probing FPGA\n", __func__);
-
- priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
- priv->i2c_client = client;
-
- priv->regmap = devm_regmap_init_i2c(priv->i2c_client, &tier4_fpga_regmap_config);
- if (IS_ERR(priv->regmap))
- {
- dev_err(&client->dev, "[%s] devm_regmap_init() failed: %ld\n", __func__, PTR_ERR(priv->regmap));
- return -ENODEV;
- }
-
- err = tier4_fpga_parse_dt(priv, client);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] Unable to parse fpga dt\n", __func__);
- return -EFAULT;
- }
-
- mutex_init(&priv->lock);
-
- dev_set_drvdata(&client->dev, priv);
-
- err = tier4_fpga_check_access(&client->dev);
-
- if (err)
- {
- inhibit_fpga_access = 1;
- }
-
- // default mode is disabling gnereation of fsync
-
- err = tier4_fpga_disable_fsync_mode(&client->dev);
-
-
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] Unable to disable generation of fsync.\n", __func__);
- if ( inhibit_fpga_access )
- {
- return NO_ERROR;
- }
- else
- {
- return -EINVAL;
- }
- }
-
- channel_count_fpga++;
-
- dev_info(&client->dev, "[%s] Probing FPGA succeeded.\n", __func__);
-
- return err;
-}
-
-static int tier4_fpga_remove(struct i2c_client *client)
-{
- struct tier4_fpga *priv;
-
- if (channel_count_fpga > 0)
- channel_count_fpga--;
-
- if (client != NULL)
- {
- priv = dev_get_drvdata(&client->dev);
- mutex_destroy(&priv->lock);
- }
-
- return 0;
-}
-
-// ----------------------------------------------
-
-static const struct i2c_device_id tier4_fpga_id[] = {
- { "tier4_fpga", 0 },
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, tier4_fpga_id);
-
-static struct i2c_driver tier4_fpga_i2c_driver = {
- .driver = {
- .name = "tier4_fpga",
- .owner = THIS_MODULE,
- },
- .probe = tier4_fpga_probe,
- .remove = tier4_fpga_remove,
- .id_table = tier4_fpga_id,
-};
-
-static int __init tier4_fpga_init(void)
-{
- printk("FPGA Driver for Tier4 Cameras.\n");
-
- return i2c_add_driver(&tier4_fpga_i2c_driver);
-}
-
-static void __exit tier4_fpga_exit(void)
-{
- i2c_del_driver(&tier4_fpga_i2c_driver);
-}
-
-module_init(tier4_fpga_init);
-module_exit(tier4_fpga_exit);
-
-MODULE_DESCRIPTION("FPGA driver tier4_fpga");
-MODULE_AUTHOR("Kohji Iwasaki");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-gw5300.c b/drivers/src/tier4-gw5300.c
deleted file mode 100644
index d2357a0..0000000
--- a/drivers/src/tier4-gw5300.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- * tier4_gw5300.c - tier4_gw5300 ISP driver
- *
- * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-#include
-
-#include "tier4-gmsl-link.h"
-#include "tier4-gw5300.h"
-
-struct tier4_gw5300
-{
- struct i2c_client *i2c_client;
- struct tier4_gmsl_link_ctx g_client;
- struct mutex lock;
- /* primary ISP properties */
- __u32 def_addr;
-};
-
-#define MAX_CHANNEL_NUM 8
-
-#define NO_ERROR 0
-
-/* count channel,the max MAX_CHANNEL_NUM*/
-static __u32 channel_count_gw5300;
-
-static struct tier4_gw5300 *prim_priv__[MAX_CHANNEL_NUM];
-
-static u8 master_30fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00
- , 0x00, 0x6A
-};
-
-static u8 master_10fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00
- , 0x00, 0x38
-};
-
-static u8 slave_10fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00
- , 0x00, 0x42
-};
-
-static u8 master_20fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00
- , 0x00, 0x74
-};
-
-static u8 slave_20fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00
- , 0x00, 0x79
-};
-
-static u8 slave_30fps[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00
- , 0x00, 0x6F
-};
-
-static u8 master_10fps_slow[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- , 0x00, 0x17
-};
-
-static u8 slave_10fps_slow[] = {
- 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00, 0x12, 0x00
- , 0x80, 0x03, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00
- , 0x00, 0x65
-};
-
-
-/*
- * C3 camera mode support
- */
-struct mode_command {
- u8 *command;
- size_t len;
- unsigned int delay_ms;
-};
-
-#define MODE_CMD(cmd, delay) \
- { \
- .command = (cmd), \
- .len = sizeof (cmd), \
- .delay_ms = delay, \
- }
-
-#define NUM_VA_ARGS(type, ...) (sizeof ((type[]) {__VA_ARGS__}) / sizeof (type))
-
-#define MODE_SEQ(h_line_time_ns, ...) \
- { \
- .commands = (struct mode_command[]){ \
- __VA_ARGS__ \
- }, \
- .len = NUM_VA_ARGS(struct mode_command, __VA_ARGS__), \
- .h_line_ns = (h_line_time_ns) \
- }
-
-struct mode_sequence {
- struct mode_command *commands;
- size_t len;
- u32 h_line_ns;
-};
-
-/*
- * C3 preset modes
- */
-
-static u8 c3_master_5fps_cmd[] = {
- 0x33, 0x47, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17
-};
-
-/* mode 0 */
-static struct mode_sequence c3_master_5fps_seq =
- MODE_SEQ(
- 40000,
- MODE_CMD(c3_master_5fps_cmd, 0),
- );
-
-/* mode 4 */
-static u8 c3_master_20fps_cmd[] = {
- 0x33, 0x47, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x80, 0x3, 0x0, 0x0, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x65
-};
-static struct mode_sequence c3_master_20fps_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_cmd, 0)
- );
-
-static u8 c3_master_20fps_ebd_cmd[] = {
- 0x33, 0x47, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x80, 0x3, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x6a
-};
-
-/* mode 10 */
-static struct mode_sequence c3_master_20fps_ebd_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_ebd_cmd, 0)
- );
-
-static u8 c3_master_30fps_cmd[] = {
- 0x33, 0x47, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x80, 0x3, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x38
-};
-
-/* mode 6 */
-static struct mode_sequence c3_master_30fps_seq =
- MODE_SEQ(
- 13890,
- MODE_CMD(c3_master_30fps_cmd, 0)
- );
-
-static u8 c3_master_30fps_ebd_cmd[] = {
- 0x33, 0x47, 0xb, 0x0, 0x0, 0x0, 0x12, 0x0, 0x80, 0x3, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x42
-};
-
-/* mode 12 */
-static struct mode_sequence c3_master_30fps_ebd_seq =
- MODE_SEQ(
- 13890,
- MODE_CMD(c3_master_30fps_ebd_cmd, 0)
- );
-
-
-/*
- * C3 derived modes
- */
-static u8 c3_regmap_ffff[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x25
-};
-
-static u8 c3_standby_mode[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x4, 0x1b, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x2, 0x1, 0x45
-};
-
-static u8 c3_drive_mode_sel[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x1, 0x68
-};
-
-static u8 c3_master_sync_mode[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x41, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x2, 0x1, 0x6d
-};
-
-static u8 c3_sensor_streaming[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x4, 0x1b, 0x0, 0x0, 0x5c, 0x0, 0x0, 0x0, 0x2, 0x1, 0xa2
-};
-
-static u8 c3_master_sync_mode_2[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x4, 0x1b, 0x0, 0x0, 0xa3, 0x0, 0x0, 0x0, 0x2, 0x1, 0xe9
-};
-
-/* mode 1 */
-static struct mode_sequence c3_slave_5fps_seq =
- MODE_SEQ(
- 40000,
- MODE_CMD(c3_master_5fps_cmd, 5000),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-static u8 c3_20_to_10fps_cmd_1[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x50, 0x97, 0x0, 0x0, 0xc4, 0x0, 0x0, 0x0, 0x2, 0x1, 0xd2,
-};
-
-static u8 c3_20_to_10fps_cmd_2[] = {
- 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0,
- 0x0, 0x51, 0x97, 0x0, 0x0, 0x09, 0x0, 0x0, 0x0, 0x2, 0x1, 0x18,
-};
-
-/* mode 2 */
-static struct mode_sequence c3_master_10fps_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
- );
-
-/* mode 3 */
-static struct mode_sequence c3_slave_10fps_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-/* mode 5 */
-static struct mode_sequence c3_slave_20fps_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_cmd, 5000),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-/* mode 7 */
-static struct mode_sequence c3_slave_30fps_seq =
- MODE_SEQ(
- 13890,
- MODE_CMD(c3_master_30fps_cmd, 5000),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-/* mode 8 */
-static struct mode_sequence c3_master_10fps_ebd_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
- );
-
-/* mode 9 */
-static struct mode_sequence c3_slave_10fps_ebd_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-/* mode 11 */
-static struct mode_sequence c3_slave_20fps_ebd_seq =
- MODE_SEQ(
- 20000,
- MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-/* mode 13 */
-static struct mode_sequence c3_slave_30fps_ebd_seq =
- MODE_SEQ(
- 13890,
- MODE_CMD(c3_master_30fps_ebd_cmd, 5000),
-
- MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
- MODE_CMD(c3_20_to_10fps_cmd_2, 500),
-
- MODE_CMD(c3_regmap_ffff, 500),
- MODE_CMD(c3_standby_mode, 500),
- MODE_CMD(c3_drive_mode_sel, 500),
- MODE_CMD(c3_master_sync_mode, 500),
- MODE_CMD(c3_sensor_streaming, 500),
- MODE_CMD(c3_master_sync_mode_2, 500),
- );
-
-static struct mode_sequence c3_mode_seqs[GW5300_MODE_MAX];
-
-
-struct map_ctx
-{
- u8 dt;
- u16 addr;
- u8 val;
- u8 st_id;
-};
-
-#if 0
-static int tier4_gw5300_receive_msg(struct device *dev, u8 *data, int data_size )
-{
- int err = 0;
- struct i2c_msg msg;
- struct tier4_gw5300 *priv = dev_get_drvdata(dev);
-
- msg.addr = priv->i2c_client->addr;
- msg.flags = I2C_M_RD; // I2C Read
- msg.len = data_size;
- msg.buf = data;
-
- err = i2c_transfer(priv->i2c_client->adapter, &msg, 1);
-
- if (err <= 0 ) {
- dev_err(dev, "[%s] : i2c_transer receive message failed : slave addr = 0x%x\n", __func__, msg.addr );
- }
-
- return err;
-}
-#endif
-
-// -------------------------------------------------------------------
-
-static int tier4_gw5300_send_and_recv_msg(struct device *dev, u8 *wdata, int wdata_size, u8 *rdata, int rdata_size)
-{
- int err = 0;
- struct i2c_msg msg[2];
- struct tier4_gw5300 *priv = dev_get_drvdata(dev);
-
- msg[0].addr = priv->i2c_client->addr;
- msg[0].flags = 0; // I2C Write
- msg[0].len = wdata_size;
- msg[0].buf = wdata;
-
- msg[1].addr = priv->i2c_client->addr;
- msg[1].flags = I2C_M_RD; // I2C Read
- msg[1].len = rdata_size;
- msg[1].buf = rdata;
-
- err = i2c_transfer(priv->i2c_client->adapter, msg, 2);
-
- if (err <= 0)
- {
- dev_err(dev, "[%s] : i2c_transer send message failed. %d: slave addr = 0x%x\n", __func__, err, msg[0].addr);
- }
-
- return err; // the total number of bytes to have been sent or recived
-}
-
-// -------------------------------------------------------------------
-
-static int tier4_gw5300_c3_send_and_recv_msg(struct device *dev, u8 *wdata, int wdata_size, u8 *rdata, int rdata_size)
-{
- return tier4_gw5300_send_and_recv_msg(dev, wdata, wdata_size, rdata, rdata_size);
-}
-
-static int tier4_gw5300_mode_seq_send_and_recv_msg(struct device *dev, struct mode_sequence *mode_seq, u8 *rdata, int rdata_size)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < mode_seq->len; ++i) {
- struct mode_command *cmd = &mode_seq->commands[i];
-
- err = tier4_gw5300_send_and_recv_msg(dev, cmd->command, cmd->len, rdata, rdata_size);
- msleep(cmd->delay_ms);
- if (err < 0) {
- dev_err(dev, "%s: Failed to send a command[%d]: %d\n", __func__, i, err);
- break;
- }
- }
-
-
- return err;
-}
-
-// -------------------------------------------------------------------
-
-uint8_t calcCheckSum(const uint8_t *data, size_t size){
- uint8_t result = 0;
- size_t i =0;
- for(i=0; i> 8)&0xFF;
- uint8_t b3 = 0;
- uint8_t b4 = 0;
-
- dev_info(dev, "%s: integration time(%u[ns/H line]): max=(%d[us], %d[line]) min=(%d[us], %d[line])\n",
- __func__, h_line_ns, max_integration_time, max_line, min_integration_time, min_line);
-
- cmd_integration_max[max_val_pos] = b1;
- cmd_integration_max[max_val_pos+1] = b2;
- cmd_integration_max[max_val_pos+2] = b3;
- cmd_integration_max[max_val_pos+3] = b4;
- cmd_integration_max[sizeof(cmd_integration_max)-1] = calcCheckSum(cmd_integration_max, sizeof(cmd_integration_max));
-
-
- b1 = min_line &0xFF;
- b2 = (min_line >> 8)&0xFF;
-
- cmd_integration_min[min_val_pos] = b1;
- cmd_integration_min[min_val_pos+1] = b2;
-
- cmd_integration_min[sizeof(cmd_integration_min)-1] = calcCheckSum(cmd_integration_min, sizeof(cmd_integration_min));
-
-
- msleep(20);
- ret += tier4_gw5300_send_and_recv_msg(dev, cmd_integration_max, sizeof(cmd_integration_max), buf, sizeof(buf));
- msleep(20);
- ret += tier4_gw5300_send_and_recv_msg(dev, cmd_integration_min, sizeof(cmd_integration_min), buf, sizeof(buf));
-
- return ret;
-
-}
-
-int tier4_gw5300_c2_set_integration_time_on_aemode(struct device *dev, int trigger_mode, u32 max_integration_time, u32 min_integration_time)
-{
- size_t h_line_ns = 12500;
-
- if (trigger_mode == GW5300_MASTER_MODE_10FPS_SLOW ||
- trigger_mode == GW5300_SLAVE_MODE_10FPS_SLOW)
- h_line_ns = 50000;
-
- return tier4_gw5300_set_integration_time_on_aemode(dev, h_line_ns, max_integration_time, min_integration_time);
-}
-EXPORT_SYMBOL(tier4_gw5300_c2_set_integration_time_on_aemode);
-
-
-int tier4_gw5300_c3_set_integration_time_on_aemode(struct device *dev, int trigger_mode, u32 max_integration_time, u32 min_integration_time)
-{
- return tier4_gw5300_set_integration_time_on_aemode(dev, c3_mode_seqs[trigger_mode].h_line_ns,
- max_integration_time, min_integration_time);
-}
-EXPORT_SYMBOL(tier4_gw5300_c3_set_integration_time_on_aemode);
-
-// ------------------------------------------------------------------
-
-int tier4_gw5300_set_distortion_correction(struct device *dev, bool val)
-{
-int ret = 0;
- u8 buf[6];
- u8 cmd_dwp_on[]={0x33, 0x47, 0x06, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x80, 0x04, 0x00, 0x01, 0x52};
- u8 cmd_dwp_off[]={0x33, 0x47, 0x03, 0x00, 0x00, 0x00, 0x45, 0x00, 0x80, 0x42};
-
- if(val){
- ret += tier4_gw5300_send_and_recv_msg(dev, cmd_dwp_on, sizeof(cmd_dwp_on), buf, sizeof(buf));
- }else{
- ret += tier4_gw5300_send_and_recv_msg(dev, cmd_dwp_off, sizeof(cmd_dwp_off), buf, sizeof(buf));
- }
- return ret;
-}
-EXPORT_SYMBOL(tier4_gw5300_set_distortion_correction);
-
-// ------------------------------------------------------------------
-
-int tier4_gw5300_c3_set_distortion_correction(struct device *dev, bool val)
-{
-int ret = 0;
- u8 buf[6];
- u8 cmd_dwp_on[] ={ 0x33, 0x47, 0x6, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x80, 0x04, 0x00, 0x01, 0x52};
- u8 cmd_dwp_off[] ={ 0x33, 0x47, 0x3, 0x00, 0x00, 0x00, 0x45, 0x00, 0x80, 0x042};
-
- if(val){
- ret += tier4_gw5300_c3_send_and_recv_msg(dev, cmd_dwp_on, sizeof(cmd_dwp_on), buf, sizeof(buf));
- }else{
- ret += tier4_gw5300_c3_send_and_recv_msg(dev, cmd_dwp_off, sizeof(cmd_dwp_off), buf, sizeof(buf));
- }
- return ret;
-}
-EXPORT_SYMBOL(tier4_gw5300_c3_set_distortion_correction);
-
-// ------------------------------------------------------------------
-
-int tier4_gw5300_c3_set_auto_exposure(struct device *dev, bool val)
-{
- int ret = 0;
- u8 buf[6];
- u8 cmd_auto_exp_on[] ={ 0x33, 0x47, 0x0C, 0x00, 0x00, 0x00, 0x55, 0x00, 0x80, 0x05, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x69 };
- u8 cmd_auto_exp_off[] ={ 0x33, 0x47, 0x0C, 0x00, 0x00, 0x00, 0x55, 0x00, 0x80, 0x05, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x6A };
-
- dev_info(dev, "%s: auto exposure is %s\n", __func__, val ? "on" : "off");
-
- if (val) {
- ret += tier4_gw5300_c3_send_and_recv_msg(dev, cmd_auto_exp_on, sizeof(cmd_auto_exp_on), buf, sizeof(buf));
- } else {
- ret += tier4_gw5300_c3_send_and_recv_msg(dev, cmd_auto_exp_off, sizeof(cmd_auto_exp_off), buf, sizeof(buf));
- }
- return ret;
-}
-EXPORT_SYMBOL(tier4_gw5300_c3_set_auto_exposure);
-
-// ------------------------------------------------------------------
-
-int tier4_gw5300_check_device(struct device *dev, u8 *rdata, int rdata_size )
-{
- int err = 0;
- struct i2c_msg msg[2];
- struct tier4_gw5300 *priv = dev_get_drvdata(dev);
-
- msg[0].addr = priv->i2c_client->addr;
- msg[0].flags = I2C_M_RD; // I2C Read
- msg[0].len = rdata_size;
- msg[0].buf = rdata;
-
- err = i2c_transfer(priv->i2c_client->adapter, msg, 1);
-
- if (err <= 0)
- {
- dev_err(dev, "[%s] : i2c_transer send message failed. : slave addr = 0x%x\n", __func__, msg[0].addr);
- }
- else
- {
- err = NO_ERROR;
- }
-
- return err;
-}
-EXPORT_SYMBOL(tier4_gw5300_check_device);
-
-int tier4_gw5300_prim_slave_addr(struct tier4_gmsl_link_ctx *g_ctx)
-{
- if (!g_ctx)
- {
- dev_err(&prim_priv__[channel_count_gw5300 - 1]->i2c_client->dev, "[%s] : Failed. g_ctx is null\n", __func__);
- return -1;
- }
-
- g_ctx->sdev_isp_def = prim_priv__[channel_count_gw5300 - 1]->def_addr;
-
- return 0;
-}
-EXPORT_SYMBOL(tier4_gw5300_prim_slave_addr);
-
-int tier4_gw5300_setup_sensor_mode(struct device *dev, int sensor_mode)
-{
- int err = 0;
- u8 buf[6];
-
- memset(buf, 0x00, 6);
-
- switch (sensor_mode)
- {
- case GW5300_MASTER_MODE_10FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, master_10fps, sizeof(master_10fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Master mode 10fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Master mode 10fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
-
- case GW5300_SLAVE_MODE_10FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, slave_10fps, sizeof(slave_10fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Slave mode 10fps failed. %d message has been sent to gw5300.\n", __func__, err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Slave mode 10fps failed. %d message has been sent to gw5300.\n", __func__, err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- case GW5300_MASTER_MODE_20FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, master_20fps, sizeof(master_20fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Master mode 20fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Master mode 20fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- case GW5300_SLAVE_MODE_20FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, slave_20fps, sizeof(slave_20fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Slave mode 20fps failed. %d message has been sent to gw5300.\n", __func__, err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Slave mode 20fps failed. %d message has been sent to gw5300.\n", __func__, err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- case GW5300_MASTER_MODE_30FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, master_30fps, sizeof(master_30fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Master mode 30fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Master mode 30fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
-
- case GW5300_SLAVE_MODE_30FPS:
- err = tier4_gw5300_send_and_recv_msg(dev, slave_30fps, sizeof(slave_30fps), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Slave mode 30fps failed. %d message has been sent to gw5300.\n", __func__, err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Slave mode 30fps failed. %d message has been sent to gw5300.\n", __func__, err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- case GW5300_MASTER_MODE_10FPS_SLOW:
- err = tier4_gw5300_send_and_recv_msg(dev, master_10fps_slow, sizeof(master_10fps_slow), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Slow clock Master mode 10fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Slow clock Master mode 10fps failed. %d message has been sent to gw5300.\n", __func__,
- err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- case GW5300_SLAVE_MODE_10FPS_SLOW:
- err = tier4_gw5300_send_and_recv_msg(dev, slave_10fps_slow, sizeof(slave_10fps_slow), buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up Slow clock Slave mode 10fps failed. %d message has been sent to gw5300.\n", __func__, err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up Slow clock Slave mode 10fps failed. %d message has been sent to gw5300.\n", __func__, err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- default:
- break;
- }
-
-error:
-
- return err;
-}
-EXPORT_SYMBOL(tier4_gw5300_setup_sensor_mode);
-
-// ----------- for C3 camera ----------
-
-int tier4_gw5300_c3_setup_sensor_mode(struct device *dev, int sensor_mode)
-{
- int err = 0;
- u8 buf[6];
-
- memset(buf, 0x00, 6);
-
- switch (sensor_mode)
- {
- case GW5300_MASTER_MODE_10FPS:
- case GW5300_SLAVE_MODE_10FPS:
- case GW5300_MASTER_MODE_20FPS:
- case GW5300_SLAVE_MODE_20FPS:
- case GW5300_MASTER_MODE_30FPS:
- case GW5300_SLAVE_MODE_30FPS:
- case GW5300_MASTER_MODE_5FPS:
- case GW5300_SLAVE_MODE_5FPS:
- case GW5300_MASTER_MODE_10FPS_EBD:
- case GW5300_SLAVE_MODE_10FPS_EBD:
- case GW5300_MASTER_MODE_20FPS_EBD:
- case GW5300_SLAVE_MODE_20FPS_EBD:
- case GW5300_MASTER_MODE_30FPS_EBD:
- case GW5300_SLAVE_MODE_30FPS_EBD:
- err = tier4_gw5300_mode_seq_send_and_recv_msg(dev, &c3_mode_seqs[sensor_mode], buf, sizeof(buf));
- if (err < 0)
- {
- dev_err(dev, "[%s] : Setting up %s failed. %d message has been sent to gw5300.\n", __func__,
- gw5300_mode_name[sensor_mode], err);
- goto error;
- }
- else if (err == 0)
- { // it means that 0 message has been sent.
- dev_err(dev, "[%s] : Setting up %s failed. %d message has been sent to gw5300.\n", __func__,
- gw5300_mode_name[sensor_mode], err);
- err = -999;
- goto error;
- }
- else
- {
- err = 0;
- }
- break;
- default:
- break;
- }
-
-error:
-
- return err;
-}
-EXPORT_SYMBOL(tier4_gw5300_c3_setup_sensor_mode);
-
-
-static int tier4_gw5300_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tier4_gw5300 *priv;
- int err = 0;
- struct device_node *node = client->dev.of_node;
-
- dev_info(&client->dev, "[%s] : probing GW5300 ISP\n", __func__);
-
- priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
- priv->i2c_client = client;
-
- mutex_init(&priv->lock);
-
- if (of_get_property(node, "is-prim-isp", NULL))
- {
- if (prim_priv__[channel_count_gw5300] && channel_count_gw5300 >= MAX_CHANNEL_NUM)
- {
- dev_err(&client->dev, "[%s] : prim-isp already exists\n", __func__);
- return -EEXIST;
- }
-
- err = of_property_read_u32(node, "reg", &priv->def_addr);
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] : reg not found\n", __func__);
- return -EINVAL;
- }
-
- prim_priv__[channel_count_gw5300] = priv;
- channel_count_gw5300++;
- }
-
- dev_set_drvdata(&client->dev, priv);
-
- /* dev communication gets validated when GMSL link setup is done */
- dev_info(&client->dev, "[%s] : Probing succeeded\n", __func__);
-
- return err;
-}
-
-static int tier4_gw5300_remove(struct i2c_client *client)
-{
- struct tier4_gw5300 *priv;
-
- if (channel_count_gw5300 > 0)
- channel_count_gw5300--;
-
- if (client != NULL)
- {
- priv = dev_get_drvdata(&client->dev);
- mutex_destroy(&priv->lock);
- }
-
- return 0;
-}
-
-static const struct i2c_device_id tier4_gw5300_id[] = {
- { "tier4_gw5300", 0 },
- {},
-};
-
-const struct of_device_id tier4_gw5300_of_match[] = {
- {
- .compatible = "nvidia,tier4_gw5300",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, tier4_gw5300_of_match);
-MODULE_DEVICE_TABLE(i2c, tier4_gw5300_id);
-
-static struct i2c_driver tier4_gw5300_i2c_driver = {
- .driver = {
- .name = "tier4_gw5300",
- .owner = THIS_MODULE,
- },
- .probe = tier4_gw5300_probe,
- .remove = tier4_gw5300_remove,
- .id_table = tier4_gw5300_id,
-};
-
-static int __init tier4_gw5300_init(void)
-{
- printk(KERN_INFO "ISP Driver for TIERIV Camera.\n");
-
- c3_mode_seqs[GW5300_MASTER_MODE_5FPS] = c3_master_5fps_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_5FPS] = c3_slave_5fps_seq;
-
- c3_mode_seqs[GW5300_MASTER_MODE_10FPS] = c3_master_10fps_seq;
- c3_mode_seqs[GW5300_MASTER_MODE_10FPS_EBD] = c3_master_10fps_ebd_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_10FPS] = c3_slave_10fps_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_10FPS_EBD] = c3_slave_10fps_ebd_seq;
-
- c3_mode_seqs[GW5300_MASTER_MODE_20FPS] = c3_master_20fps_seq;
- c3_mode_seqs[GW5300_MASTER_MODE_20FPS_EBD] = c3_master_20fps_ebd_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_20FPS] = c3_slave_20fps_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_20FPS_EBD] = c3_slave_20fps_ebd_seq;
-
- c3_mode_seqs[GW5300_MASTER_MODE_30FPS] = c3_master_30fps_seq;
- c3_mode_seqs[GW5300_MASTER_MODE_30FPS_EBD] = c3_master_30fps_ebd_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_30FPS] = c3_slave_30fps_seq;
- c3_mode_seqs[GW5300_SLAVE_MODE_30FPS_EBD] = c3_slave_30fps_ebd_seq;
-
- return i2c_add_driver(&tier4_gw5300_i2c_driver);
-}
-
-static void __exit tier4_gw5300_exit(void)
-{
- i2c_del_driver(&tier4_gw5300_i2c_driver);
-}
-
-module_init(tier4_gw5300_init);
-module_exit(tier4_gw5300_exit);
-
-MODULE_DESCRIPTION("GW5300 ISP driver tier4_gw5300");
-MODULE_AUTHOR("Kohji Iwasaki");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-imx490.c b/drivers/src/tier4-imx490.c
deleted file mode 100644
index d3a35eb..0000000
--- a/drivers/src/tier4-imx490.c
+++ /dev/null
@@ -1,1966 +0,0 @@
-/*
- * tier4_imsx490.c - imx490 sensor driver
- *
- * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
- * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tier4-fpga.h"
-#include "tier4-gmsl-link.h"
-#include "tier4-gw5300.h"
-#include "tier4-hw-model.h"
-#include "tier4-isx021-extern.h"
-#include "tier4-max9295.h"
-#include "tier4-max9296.h"
-
-MODULE_SOFTDEP("pre: tier4_max9296");
-MODULE_SOFTDEP("pre: tier4_max9295");
-MODULE_SOFTDEP("pre: tier4_gw5300");
-MODULE_SOFTDEP("pre: tier4_fpga");
-MODULE_SOFTDEP("pre: tier4_isx021");
-
-#define USE_DISTORTION_CORRECTION 1
-
-// Register Address
-
-#define IMX490_DEFAULT_FRAME_LENGTH (2000)
-
-#define BIT_SHIFT_8 8
-#define BIT_SHIFT_16 16
-#define MASK_1_BIT 0x1
-#define MASK_4_BIT 0xF
-#define MASK_8_BIT 0xFF
-
-#define NO_ERROR 0
-#define NO_C2_CAMERA (-490)
-
-#define TIME_120_MILISEC 120000
-#define TIME_121_MILISEC 121000
-
-#define ISP_PRIM_SLAVE_ADDR 0x6D
-
-#define TIER4_C2_CAMERA 1
-
-#define SENSOR_ID_IMX490 490
-
-#define MAX_NUM_CAMERA 8
-
-#define FSYNC_FREQ_HZ 10
-
-enum
-{
- IMX490_MODE_2880x1860_CROP_30FPS,
- IMX490_MODE_START_STREAM,
- IMX490_MODE_STOP_STREAM,
-};
-
-static const int tier4_imx490_30fps[] = {
- 30,
-};
-static const struct camera_common_frmfmt tier4_imx490_frmfmt[] = {
- { { 2880, 1860 }, tier4_imx490_30fps, 1, 0, IMX490_MODE_2880x1860_CROP_30FPS },
-};
-
-const struct of_device_id tier4_imx490_of_match[] = {
- {
- .compatible = "nvidia,tier4_imx490",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, tier4_imx490_of_match);
-
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
-// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
-
-static const u32 ctrl_cid_list[] = {
- TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE, TEGRA_CAMERA_CID_EXPOSURE_SHORT,
- TEGRA_CAMERA_CID_FRAME_RATE, TEGRA_CAMERA_CID_HDR_EN,
- // TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
-};
-
-struct tier4_imx490
-{
- struct i2c_client *i2c_client;
- const struct i2c_device_id *id;
- struct v4l2_subdev *subdev;
- struct device *ser_dev;
- struct device *dser_dev;
- struct device *isp_dev;
- struct tier4_gmsl_link_ctx g_ctx;
- u32 frame_length;
- struct camera_common_data *s_data;
- struct tegracam_device *tc_dev;
- int trigger_mode;
- bool distortion_correction;
- bool last_distortion_correction;
- bool auto_exposure;
- bool inhibit_fpga_access;
- struct device *fpga_dev;
-};
-
-static const struct regmap_config tier4_sensor_regmap_config = {
- .reg_bits = 16,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
-};
-
-struct st_priv
-{
- struct i2c_client *p_client;
- struct tier4_imx490 *p_priv;
- struct tegracam_device *p_tc_dev;
- bool isp_ser_shutdown;
- bool des_shutdown;
- bool running;
-};
-
-static struct st_priv wst_priv[MAX_NUM_CAMERA];
-
-static struct mutex tier4_imx490_lock;
-
-static int camera_channel_count = 0;
-
-// --- module parameter ---
-
-static int trigger_mode;
-static int fsync_mfp = 0;
-static int enable_distortion_correction = 1;
-
-
-#define IMX490_MIN_EXPOSURE_TIME 11000 // 11 milisecond
-#define IMX490_MAX_EXPOSURE_TIME 33000 // 33 milisecond
-
-static int shutter_time_min = IMX490_MIN_EXPOSURE_TIME;
-static int shutter_time_max = IMX490_MAX_EXPOSURE_TIME;
-
-module_param(trigger_mode, int, 0644);
-module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
-module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
-
-
-module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
-module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
-
-// ------------------------
-static char upper(char c)
-{
- if ('a' <= c && c <= 'z')
- {
- c = c - ('a' - 'A');
- }
- return c;
-}
-
-static void to_upper_string(char *out, const char *in)
-{
- int i;
-
- i = 0;
- while (in[i] != '\0')
- {
- out[i] = upper(in[i]);
- i++;
- }
-}
-
-static inline int tier4_imx490_read_reg(struct camera_common_data *s_data, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
-
- err = regmap_read(s_data->regmap, addr, ®_val);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C read failed, address=0x%x\n", __func__, addr);
- }
- else
- {
- *val = reg_val & 0xFF;
- }
- return err;
-}
-
-static int tier4_imx490_write_reg(struct camera_common_data *s_data, u16 addr, u8 val)
-{
- int err = 0;
-
- err = regmap_write(s_data->regmap, addr, val);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C write failed at x%x=[0x%x]\n", __func__, addr, val);
- }
-
- return err;
-}
-
-// ------------------------------------------------
-
-static int tier4_imx490_set_fsync_trigger_mode(struct tier4_imx490 *priv, int mode)
-{
- int err = 0;
- struct device *dev = priv->s_data->dev;
- int des_num = 0;
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- priv->inhibit_fpga_access = false;
-
- dev_info(dev, "[%s] : Set fsync trigger mode.\n", __func__);
-
- err = tier4_fpga_check_access(priv->fpga_dev);
- if (err)
- {
- priv->inhibit_fpga_access = true;
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE)
- {
- dev_info(dev, "[%s] : Disabling FPGA fsync.\n", __func__);
-
- err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Disabling FPGA fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else
- {
- err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA generate fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_AUTO)
- {
- // Auto Trigger Mode
- err = tier4_fpga_set_fsync_auto_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- des_num = priv->g_ctx.reg_mux;
- err = tier4_fpga_set_fsync_signal_frequency(priv->fpga_dev, des_num, priv->trigger_mode);
- if (err)
- {
- dev_err(dev, "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_MANUAL)
- {
- // Manual Trigger Mode
- dev_info(dev, "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n", __func__);
-
- err = tier4_fpga_set_fsync_manual_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- }
- }
-
- err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
-
- if (err)
- {
- dev_err(dev, "[%s] :tier4_max9296_setup_gpi() failed\n", __func__);
- return err;
- }
-
- err = tier4_max9295_setup_gpo(priv->ser_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9295_setup_gpo() failed\n", __func__);
- return err;
- }
-
- err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, mode);
- if (err)
- {
- dev_err(dev, "[%s] : tier4_gw5300_setup_sensor_mode() failed\n", __func__);
- return err;
- }
-
- return err;
-}
-
-static struct mutex serdes_lock__;
-
-static int tier4_imx490_gmsl_serdes_setup(struct tier4_imx490 *priv)
-{
- int err = 0;
- int des_err = 0;
- struct device *dev;
-
- if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client)
- {
- return -EINVAL;
- }
-
- dev = &priv->i2c_client->dev;
-
- mutex_lock(&serdes_lock__);
-
- /* For now no separate power on required for serializer device */
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) && (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_on(priv->dser_dev);
- }
-
- /* setup serdes addressing and control pipeline */
-
-
- err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : GMSL deserializer link config failed\n", __func__);
- goto error;
- }
-
- err = tier4_max9295_setup_control(priv->ser_dev);
-
- /* proceed even if ser setup failed, to setup deser correctly */
- if (err)
- {
- dev_err(dev, "[%s] : GMSL serializer setup failed\n", __func__);
- goto error;
- }
-
- des_err = tier4_max9296_setup_control(priv->dser_dev, &priv->i2c_client->dev);
-
- if (des_err)
- {
- dev_err(dev, "[%s] : GMSL deserializer : setup failed\n", __func__);
- err = des_err;
- }
-
-error:
- mutex_unlock(&serdes_lock__);
- return err;
-}
-
-static void tier4_imx490_gmsl_serdes_reset(struct tier4_imx490 *priv)
-{
- mutex_lock(&serdes_lock__);
-
- /* reset serdes addressing and control pipeline */
- tier4_max9295_reset_control(priv->ser_dev);
-
- tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev, true);
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
- (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_off(priv->dser_dev);
- }
-
- mutex_unlock(&serdes_lock__);
-}
-
-static int tier4_imx490_power_on(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_on)
- {
- err = pdata->power_on(pw);
-
- if (err)
- {
- dev_err(dev, "[%s] : failed.\n", __func__);
- }
- else
- {
- pw->state = SWITCH_ON;
- }
- return err;
- }
-
- pw->state = SWITCH_ON;
-
- return err;
-}
-
-static int tier4_imx490_power_off(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_off)
- {
- err = pdata->power_off(pw);
-
- if (!err)
- {
- goto power_off_done;
- }
- else
- {
- dev_err(dev, "[%s] : power off failed.\n", __func__);
- }
- return err;
- }
-
-power_off_done:
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-static int tier4_imx490_power_get(struct tegracam_device *tc_dev)
-{
- struct camera_common_power_rail *pw = tc_dev->s_data->power;
- int err = 0;
-
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-static int tier4_imx490_power_put(struct tegracam_device *tc_dev)
-{
- if (unlikely(!tc_dev->s_data->power))
- {
- return -EFAULT;
- }
-
- return NO_ERROR;
-}
-
-static int tier4_imx490_set_group_hold(struct tegracam_device *tc_dev, bool val)
-{
- volatile int err = 0;
-
- return err;
-}
-
-static int tier4_imx490_set_gain(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- // struct camera_common_data *s_data = tc_dev->s_data;
-
- // struct device *dev = tc_dev->dev;
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_imx490_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
- // struct device dev = tc_dev->dev;
-
- /* fixed 30fps */
- priv->frame_length = IMX490_DEFAULT_FRAME_LENGTH;
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_imx490_set_auto_exposure(struct tegracam_device *tc_dev)
-{
- int err = 0;
- //struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_imx490_set_exposure(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
- tier4_gw5300_c2_set_integration_time_on_aemode(priv->isp_dev, priv->trigger_mode, val, val);
-
- return err;
-}
-// --------------------------------------------------------------------------------------
-// Enable Distortion Coreection
-// --------------------------------------------------------------------------------------
-#if USE_DISTORTION_CORRECTION
-
-static int tier4_imx490_set_distortion_correction(struct tegracam_device *tc_dev, bool val)
-{
- int err = 0;
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
-
- if (priv->last_distortion_correction != val)
- {
- dev_info(&priv->i2c_client->dev, "[%s] : Setting distortion correction mode :%s.\n", __func__,val?"True":"False");
-
- err = tier4_gw5300_set_distortion_correction(priv->isp_dev, val);
- if (err <= 0)
- {
- dev_info(&priv->i2c_client->dev, "[%s] : Setting distortion correction mode failed.\n", __func__ );
- }
- else
- {
- err = 0;
- priv->last_distortion_correction = val;
- }
- }
-
- return err;
-}
-#endif
-
-// --------------------------------------------------------------------------------------
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
-// please add the new memeber and the function at the following table.
-
-static struct tegracam_ctrl_ops tier4_imx490_ctrl_ops = {
- .numctrls = ARRAY_SIZE(ctrl_cid_list),
- .ctrl_cid_list = ctrl_cid_list,
- .set_gain = tier4_imx490_set_gain,
- .set_exposure = tier4_imx490_set_exposure,
- .set_exposure_short = tier4_imx490_set_exposure,
- .set_frame_rate = tier4_imx490_set_frame_rate,
- .set_group_hold = tier4_imx490_set_group_hold,
- // .set_distortion_correction = tier4_imx490_set_distortion_correction,
-};
-
-// --------------------------------------------------------------------------------------
-
-static struct camera_common_pdata *tier4_imx490_parse_dt(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct camera_common_pdata *board_priv_pdata;
- const struct of_device_id *match;
- int err;
-
- if (!node)
- {
- return NULL;
- }
-
- match = of_match_device(tier4_imx490_of_match, dev);
-
- if (!match)
- {
- dev_err(dev, "[%s] : Failed to find matching dt id\n", __func__);
- return NULL;
- }
-
- board_priv_pdata = devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
-
- err = of_property_read_string(node, "mclk", &board_priv_pdata->mclk_name);
-
- if (err)
- {
- dev_err(dev, "[%s] : mclk not in DT\n", __func__);
- }
-
- return board_priv_pdata;
-}
-
-/* tier4_imx490_set_mode() can not be needed. But it remains for compatiblity */
-
-static int tier4_imx490_set_mode(struct tegracam_device *tc_dev)
-{
- volatile int err = 0;
-
- return err;
-}
-
-static int tier4_imx490_start_one_streaming(struct tegracam_device *tc_dev)
-{
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
- int err;
-
- /* enable serdes streaming */
-
- err = tier4_max9295_setup_streaming(priv->ser_dev);
-
- if (err)
- {
- goto exit;
- }
-
- err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Setup Streaming failed\n", __func__);
- goto exit;
- }
-
- if (priv->auto_exposure == true)
- {
- err = tier4_imx490_set_auto_exposure(tc_dev);
- }
-
-
- if (err)
- {
- dev_err(dev, "[%s] : Setting Digital Gain to default value failed\n", __func__);
- goto exit;
- }
-
- dev_info(dev, "[%s] : trigger_mode = %d\n", __func__, trigger_mode);
-
- priv->trigger_mode = trigger_mode;
-
- switch (priv->trigger_mode)
- {
-
- case GW5300_MASTER_MODE_10FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to Master mode 10fps\n", __func__);
-
- err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, GW5300_MASTER_MODE_10FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Master mode 10fps failed\n", __func__);
- return err;
- }
-
- priv->last_distortion_correction = 1;
-
- break;
-
- case GW5300_SLAVE_MODE_10FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to Slave mode 10fps\n", __func__);
-
- err = tier4_imx490_set_fsync_trigger_mode(priv, GW5300_SLAVE_MODE_10FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Slave mode 10fps failed\n", __func__);
- goto exit;
- }
-
- priv->last_distortion_correction = 1;
-
- msleep(20);
-
- break;
-
- case GW5300_MASTER_MODE_20FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to Master mode 20fps\n", __func__);
-
- err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, GW5300_MASTER_MODE_20FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Master mode 20fps failed\n", __func__);
- return err;
- }
-
- priv->last_distortion_correction = 1;
-
- break;
-
- case GW5300_SLAVE_MODE_20FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to Slave mode 20fps\n", __func__);
-
- err = tier4_imx490_set_fsync_trigger_mode(priv, GW5300_SLAVE_MODE_20FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Slave mode 20fps failed\n", __func__);
- return err;
- }
-
- priv->last_distortion_correction = 1;
-
- break;
-
- case GW5300_MASTER_MODE_30FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to Master mode 30fps\n", __func__);
-
- err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, GW5300_MASTER_MODE_30FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Master mode 30fps failed\n", __func__);
- return err;
- }
-
- break;
-
- case GW5300_SLAVE_MODE_30FPS:
-
- dev_info(dev, "[%s] : Setting camera sensor to slave mode 30fps\n", __func__);
-
- err = tier4_imx490_set_fsync_trigger_mode(priv, GW5300_SLAVE_MODE_30FPS);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Slave mode 30fps failed\n", __func__);
- return err;
- }
-
- priv->last_distortion_correction = 1;
-
- break;
-
- case GW5300_SLAVE_MODE_10FPS_SLOW:
-
- err = tier4_imx490_set_fsync_trigger_mode(priv, GW5300_SLAVE_MODE_10FPS_SLOW);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Slow clock Slave mode 10fps failed\n", __func__);
- goto exit;
- }
-
- priv->last_distortion_correction = 1;
-
- msleep(20);
-
- break;
-
- case GW5300_MASTER_MODE_10FPS_SLOW:
-
- err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, GW5300_MASTER_MODE_10FPS_SLOW);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to Slow clock Master mode 10fps failed\n", __func__);
- return err;
- }
-
- priv->last_distortion_correction = 1;
-
- break;
-
- default: // case of trigger_mode < 0
-
- dev_err(dev, "[%s] : The camera sensor mode(fsync mode) is invalid.\n", __func__);
-
- return err;
- }
-
-
-#if USE_DISTORTION_CORRECTION
-
- if (priv->last_distortion_correction != enable_distortion_correction )
- {
- usleep_range(900000, 910000);
- //msleep(900);
- }
-
- if (enable_distortion_correction == 0xCAFE)
- {
- // if not set kernel param, read device tree param
- if (priv->distortion_correction == false)
- {
- err = tier4_imx490_set_distortion_correction(tc_dev, priv->distortion_correction);
-
- if (err)
- {
- dev_err(dev, "[%s] : Disabling Distortion Correction failed\n", __func__);
- goto exit;
- }
- msleep(20);
- }
- }else{
- err = tier4_imx490_set_distortion_correction(tc_dev, enable_distortion_correction==1);
- if (err)
- {
- dev_err(dev, "[%s] : Setup Distortion Correction failed\n", __func__);
- goto exit;
- }
- msleep(20);
- }
-
-#endif
-
- err = tier4_max9296_start_streaming(priv->dser_dev, dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_start_stream() failed\n", __func__);
- return err;
- }
-
- msleep(200);
-
-//#if 0
- msleep(1000);
- tier4_gw5300_c2_set_integration_time_on_aemode(priv->isp_dev, priv->trigger_mode, shutter_time_max, shutter_time_min);
-//#endif
-
- dev_info(dev, "[%s] : Camera has started streaming\n", __func__);
-
- return NO_ERROR;
-
-exit:
-
- dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
-
- return err;
-}
-
-static bool tier4_imx490_is_camera_connected_to_port(int nport)
-{
- if (wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx490_check_null_tc_dev_for_port(int nport)
-{
- if (wst_priv[nport].p_tc_dev == NULL)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx490_is_camera_running_on_port(int nport)
-{
- if (wst_priv[nport].running)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx490_is_current_port(struct tier4_imx490 *priv, int nport)
-{
- if (priv->i2c_client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_imx490_set_running_flag(int nport, bool flag)
-{
- wst_priv[nport].running = flag;
-}
-
-static int tier4_imx490_stop_streaming(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
- int i, err = 0;
-
- mutex_lock(&tier4_imx490_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_imx490_is_camera_connected_to_port(i))
- {
- if (tier4_imx490_is_current_port(priv, i) && tier4_imx490_is_camera_running_on_port(i))
- {
- /* disable serdes streaming */
- err = tier4_max9296_stop_streaming(priv->dser_dev, dev);
- if (err)
- {
- return err;
- }
- tier4_imx490_set_running_flag(i, false);
- break;
- }
- }
- }
-
- mutex_unlock(&tier4_imx490_lock);
-
- return NO_ERROR;
-}
-
-/* *************************************************************************** */
-/* 1. In the case where a camera is connected to GMSL A port on a Des. */
-/* */
-/* a > Check if another camera is connected to GMSL B port */
-/* a-1) Connected: */
-/* b > Check if another camera on GMSL B port is running */
-/* b-1) Running: */
-/* c > Check if the camera on GMSL A port is running */
-/* c-1) Running : */
-/* Do nothing and return */
-/* c-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* b-2) Not Running: */
-/* Start the camera on GMSL B port. */
-/* a-2) Not connected : */
-/* b > Check if the camera on GMSL A port is running */
-/* b-1) Running : */
-/* Do nothing and return */
-/* b-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* */
-/* 2. In the case where a camera is connected to GMSL B port on a Des. */
-/* */
-/* a > Check if the camera on GMSL B port is running */
-/* a-1) Running : */
-/* Do nothing and return */
-/* a-2) Not running : */
-/* Start the camera on GMSL B port. */
-/* *************************************************************************** */
-
-static int tier4_imx490_start_streaming(struct tegracam_device *tc_dev)
-{
- int i, err = 0;
- // struct tier4_imx490 *next_client_priv;
- struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
-
- mutex_lock(&tier4_imx490_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (i & 0x1)
- { // if i = 1,3,5,7 ( GMSL B port of a Des )
-
- if (tier4_imx490_is_camera_connected_to_port(i))
- { // a camera is connected to GMSL B portL
-
- if ((tier4_imx490_is_current_port(priv, i) == true) && (tier4_imx490_is_camera_running_on_port(i) == false))
- {
- err = tier4_imx490_start_one_streaming(wst_priv[i].p_tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming.\n", __func__);
- goto error_exit;
- }
- // wst_priv[i].running = true;
- tier4_imx490_set_running_flag(i, true);
- break;
- }
- }
- }
- else
- { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
-
- if ((tier4_imx490_is_camera_connected_to_port(i) == true) && (tier4_imx490_is_current_port(priv, i) == true))
- {
- if (tier4_imx490_is_camera_connected_to_port(i + 1) == false)
- { // if another one camera( GMSL B port) is not
- // connected to Des.
- if (tier4_imx490_is_camera_running_on_port(i) == false)
- { // and if the camera is not running.
-
- err = tier4_imx490_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for next imx490 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx490_set_running_flag(i, true);
- }
- break;
- }
-
- // two cameras are connected to one Des.
-
- if (tier4_imx490_check_null_tc_dev_for_port(i + 1))
- { // check if tc_dev is null
- dev_err(dev, "[%s] : wst_priv[%d].p_tc_dev is NULL.\n", __func__, i + 1);
- err = -EINVAL;
- goto error_exit;
- }
-
- if (tier4_imx490_is_camera_running_on_port(i + 1) == false)
- {
- err = tier4_imx490_start_one_streaming(wst_priv[i + 1].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for the next imx490 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx490_set_running_flag(i + 1, true);
- usleep_range(200000, 220000);
- //msleep(200);
- mutex_unlock(&tier4_imx490_lock);
- tier4_imx490_stop_streaming(wst_priv[i + 1].p_tc_dev);
- mutex_lock(&tier4_imx490_lock);
- tier4_imx490_set_running_flag(i + 1, false);
- }
-
- if (tier4_imx490_is_camera_running_on_port(i) == false)
- {
- err = tier4_imx490_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for current imx490 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx490_set_running_flag(i, true);
- }
- }
- }
- } // for loop
-
- err = NO_ERROR;
-
-error_exit:
-
- mutex_unlock(&tier4_imx490_lock);
-
- // tier4_imx490_sensor_mutex_unlock();
-
- return err;
-}
-
-static struct camera_common_sensor_ops tier4_imx490_common_ops = {
- .numfrmfmts = ARRAY_SIZE(tier4_imx490_frmfmt),
- .frmfmt_table = tier4_imx490_frmfmt,
- .power_on = tier4_imx490_power_on,
- .power_off = tier4_imx490_power_off,
- .write_reg = tier4_imx490_write_reg,
- .read_reg = tier4_imx490_read_reg,
- .parse_dt = tier4_imx490_parse_dt,
- .power_get = tier4_imx490_power_get,
- .power_put = tier4_imx490_power_put,
- .set_mode = tier4_imx490_set_mode,
- .start_streaming = tier4_imx490_start_streaming,
- .stop_streaming = tier4_imx490_stop_streaming,
-};
-
-static int tier4_imx490_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
- //struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- return NO_ERROR;
-}
-
-static const struct v4l2_subdev_internal_ops tier4_imx490_subdev_internal_ops = {
- .open = tier4_imx490_open,
-};
-
-static const char *of_stdout_options;
-
-static int tier4_imx490_board_setup(struct tier4_imx490 *priv)
-{
- struct tegracam_device *tc_dev = priv->tc_dev;
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct device_node *ser_node;
- struct i2c_client *ser_i2c = NULL;
- struct device_node *dser_node;
- struct i2c_client *dser_i2c = NULL;
- struct device_node *isp_node;
- struct i2c_client *isp_i2c = NULL;
- struct device_node *fpga_node = NULL;
- struct i2c_client *fpga_i2c = NULL;
- struct device_node *gmsl;
- struct device_node *root_node;
- int value = 0xFFFF;
- const char *str_value;
- const char *str_value1[2];
- int i;
- int err;
- const char *str_model;
- char upper_str_model[64];
- char *str_err;
- char *sub_str_err;
-
- root_node = of_find_node_opts_by_path("/", &of_stdout_options);
-
- err = of_property_read_string(root_node, "model", &str_model);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : model not found\n", __func__);
- goto error;
- }
-
- memset(upper_str_model, 0, 64);
-
- to_upper_string(upper_str_model, str_model);
-
- priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
-
- if (str_err)
- {
-
- sub_str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
-
- if (sub_str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_ORIN;
- }
- else
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_ORIN_DEVKIT;
- }
- }
-
-
- dev_info(dev, "[%s] : model=%s\n", __func__, str_model);
- dev_info(dev, "[%s] : hardware_model=%d\n", __func__, priv->g_ctx.hardware_model);
-
- if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN)
- {
- dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_isp_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : def-addr not found\n", __func__);
- goto error;
- }
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_isp_def);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : def-addr not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg_mux not found\n", __func__);
- goto error;
- }
-
-// err = of_property_read_string(node, "fsync-mode", &str_value);
-//
-// if (err < 0)
-// {
-// dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
-// goto error;
-// }
-//
-// if (!strcmp(str_value, "true"))
-// {
-// priv->fsync_mode = true;
-// }
-// else
-// {
-// priv->fsync_mode = false;
-// }
-
- err = of_property_read_string(node, "distortion-correction", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No distortion-correction found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "true"))
- {
- priv->distortion_correction = true;
- }
- else
- {
- priv->distortion_correction = false;
- }
-
- err = of_property_read_string(node, "auto-exposure", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : Inavlid Exposure mode.\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "true"))
- {
- priv->auto_exposure = true;
- }
- else
- {
- priv->auto_exposure = false;
- }
-
-#if 0
- priv->g_ctx.fpga_generate_fsync = false;
-
- if (( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER ) ||
- ( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN )) {
-
- err = of_property_read_string(node, "fpga-generate-fsync", &str_value);
-
- if ( err < 0) {
- if ( err == -EINVAL ) {
- dev_info(dev, "[%s] : Parameter of fpga-generate-fsync does not exist.\n", __func__);
- } else {
- dev_err(dev, "[%s] : Parameter of fpga-generate-fsync is invalid .\n", __func__);
- goto error;
- }
- } else {
- if (!strcmp(str_value, "true")) {
- priv->g_ctx.fpga_generate_fsync = true;
- }
- }
- }
-#endif
-
- // For Ser node
- ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
-
- if (ser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-ser-device");
- goto error;
- }
-
- err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
- goto error;
- }
-
- ser_i2c = of_find_i2c_device_by_node(ser_node);
-
- of_node_put(ser_node);
-
- if (ser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing Serializer Dev Handle\n", __func__);
- goto error;
- }
- if (ser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
- goto error;
- }
-
- priv->ser_dev = &ser_i2c->dev;
-
- // For ISP node
-
- isp_node = of_parse_phandle(node, "nvidia,isp-device", 0);
-
- if (isp_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,isp-device");
- goto error;
- }
-
- err = of_property_read_u32(isp_node, "reg", &priv->g_ctx.sdev_isp_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : ISP reg not found\n", __func__);
- goto error;
- }
-
- isp_i2c = of_find_i2c_device_by_node(isp_node);
-
- of_node_put(isp_node);
-
- if (isp_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing ISP Dev Handle\n", __func__);
- goto error;
- }
- if (isp_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing ISP driver\n", __func__);
- goto error;
- }
-
- priv->isp_dev = &isp_i2c->dev;
-
- err = tier4_gw5300_prim_slave_addr(&priv->g_ctx);
- if (err)
- {
- dev_err(dev, "[%s] : ISP Prim slave address is unavailable, the default address(0x6D) is applied.\n", __func__);
- priv->g_ctx.sdev_isp_def = ISP_PRIM_SLAVE_ADDR;
- }
-
- priv->g_ctx.sdev_reg = priv->g_ctx.sdev_isp_reg;
- priv->g_ctx.sdev_def = priv->g_ctx.sdev_isp_def;
-
- // For Dser node
-
- dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
-
- if (dser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-dser-device");
- goto error;
- }
-
- dser_i2c = of_find_i2c_device_by_node(dser_node);
-
- of_node_put(dser_node);
-
- if (dser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer dev handle\n", __func__);
- goto error;
- }
-
- if (dser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
- goto error;
- }
-
- priv->dser_dev = &dser_i2c->dev;
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- // for FPGA node
-
- fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
-
- if (fpga_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,fpga-device");
- goto error;
- }
-
- err = of_property_read_u32(fpga_node, "reg", &priv->g_ctx.sdev_fpga_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
- goto error;
- }
-
- fpga_i2c = of_find_i2c_device_by_node(fpga_node);
-
- of_node_put(fpga_node);
-
- if (fpga_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA Dev Handle\n", __func__);
- goto error;
- }
- if (fpga_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
- goto error;
- }
-
- priv->fpga_dev = &fpga_i2c->dev;
- }
-
- /* populate g_ctx from DT */
-
- gmsl = of_get_child_by_name(node, "gmsl-link");
-
- if (gmsl == NULL)
- {
- dev_err(dev, "[%s] : Missing GMSL-Link device node\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "src-csi-port", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "csi-mode", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No csi-mode found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "1x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
- }
- else if (!strcmp(str_value, "2x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
- }
- else if (!strcmp(str_value, "4x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
- }
- else if (!strcmp(str_value, "2x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
- }
- else
- {
- dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
- goto error;
- }
-
- err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ? GMSL_SERDES_CSI_LINK_A : GMSL_SERDES_CSI_LINK_B;
-
- err = of_property_read_u32(gmsl, "st-vc", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No st-vc info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.st_vc = value;
-
- err = of_property_read_u32(gmsl, "vc-id", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No vc-id info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_vc = value;
-
- err = of_property_read_u32(gmsl, "num-lanes", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No num-lanes info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.num_csi_lanes = value;
-
- priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
-
- if (priv->g_ctx.num_streams <= 0)
- {
- dev_err(dev, "[%s] : No streams found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- for (i = 0; i < priv->g_ctx.num_streams; i++)
- {
- of_property_read_string_index(gmsl, "streams", i, &str_value1[i]);
-
- if (!str_value1[i])
- {
- dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value1[i], "raw12"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_RAW_12;
- }
- else if (!strcmp(str_value1[i], "yuv8"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
- }
- else if (!strcmp(str_value1[i], "embed"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
- }
- else if (!strcmp(str_value1[i], "ued-u1"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_UED_U1;
- }
- else
- {
- dev_err(dev, "[%s] : Invalid stream data type\n", __func__);
- goto error;
- }
- }
-
- priv->g_ctx.s_dev = dev;
-
- return NO_ERROR;
-
-error:
- dev_err(dev, "[%s] : Board Setup failed\n", __func__);
- return err;
-}
-
-static int tier4_imx490_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct device *dev = &client->dev;
- struct device_node *node = dev->of_node;
- struct tegracam_device *tc_dev;
- struct tier4_imx490 *priv;
- int err = 0;
-
- dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
-
- if (!IS_ENABLED(CONFIG_OF) || !node)
- {
- return -EINVAL;
- }
-
- wst_priv[camera_channel_count].p_client = NULL;
- wst_priv[camera_channel_count].p_priv = NULL;
- wst_priv[camera_channel_count].p_tc_dev = NULL;
-
- wst_priv[camera_channel_count].isp_ser_shutdown = false;
- wst_priv[camera_channel_count].des_shutdown = false;
- wst_priv[camera_channel_count].running = false;
-
- priv = devm_kzalloc(dev, sizeof(struct tier4_imx490), GFP_KERNEL);
-
- if (!priv)
- {
- dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
- return -ENOMEM;
- }
-
- tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
-
- if (!tc_dev)
- {
- return -ENOMEM;
- }
-
- priv->i2c_client = tc_dev->client = client;
-
- tc_dev->dev = dev;
-
- strncpy(tc_dev->name, "imx490", sizeof(tc_dev->name));
-
- tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
- tc_dev->sensor_ops = &tier4_imx490_common_ops;
- tc_dev->v4l2sd_internal_ops = &tier4_imx490_subdev_internal_ops;
- tc_dev->tcctrl_ops = &tier4_imx490_ctrl_ops;
-
- err = tegracam_device_register(tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Driver Registration failed\n", __func__);
- return err;
- }
-
- priv->tc_dev = tc_dev;
- priv->s_data = tc_dev->s_data;
- priv->subdev = &tc_dev->s_data->subdev;
-
- tegracam_set_privdata(tc_dev, (void *)priv);
-
- priv->g_ctx.sensor_id = SENSOR_ID_IMX490;
-
- tier4_isx021_sensor_mutex_lock();
-
- err = tier4_imx490_board_setup(priv);
-
- if (err)
- {
- dev_err(dev, "[%s] : Board Setup failed\n", __func__);
- goto err_tegracam_unreg;
- }
-
- /* Pair sensor to serializer dev */
-
- err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed\n", __func__);
- goto err_tegracam_unreg;
- }
- /* Register sensor to deserializer dev */
-
- err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Deserializer Register failed\n", __func__);
- goto err_max9295_unpair;
- }
-
- /*
- * gmsl serdes setup
- *
- * Sensor power on/off should be the right place for serdes
- * setup/reset. But the problem is, the total required delay
- * in serdes setup/reset exceeds the frame wait timeout, looks to
- * be related to multiple channel open and close sequence
- * issue (#BUG 200477330).
- * Once this bug is fixed, these may be moved to power on/off.
- * The delays in serdes is as per guidelines and can't be reduced,
- * so it is placed in probe/remove, though for that, deserializer
- * would be powered on always post boot, until 1.2v is supplied
- * to deserializer from CVB.
- */
-
- err = tier4_imx490_gmsl_serdes_setup(priv);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Serdes setup failed\n", __func__);
- goto err_max9296_unreg;
- }
-
- err = tegracam_v4l2subdev_register(tc_dev, true);
-
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Subdev Registration failed\n", __func__);
- goto err_max9296_unreg;
- }
-
- wst_priv[camera_channel_count].p_client = client;
- wst_priv[camera_channel_count].p_priv = priv;
- wst_priv[camera_channel_count].p_tc_dev = tc_dev;
-
- camera_channel_count++;
-
- tier4_isx021_sensor_mutex_unlock();
-
- return NO_ERROR;
-
-// tier4_isx021_sensor_mutex_unlock();
-
-// dev_info(&client->dev, "Detected Tier4 IMX490 sensor\n");
-
-err_max9296_unreg:
- tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
-err_max9295_unpair:
- tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
-err_tegracam_unreg:
- tegracam_device_unregister(priv->tc_dev);
-
- tier4_isx021_sensor_mutex_unlock();
-
-// dev_info(dev, "[%s] :camera_channel_count = %d p_client = %p \n", __func__, camera_channel_count,
-// wst_priv[camera_channel_count].p_client);
-
-
- return err;
- //return NO_ERROR; // err;
-}
-
-static void tier4_imx490_shutdown(struct i2c_client *client);
-
-static int tier4_imx490_remove(struct i2c_client *client)
-{
- struct camera_common_data *s_data = to_camera_common_data(&client->dev);
- struct tier4_imx490 *priv = (struct tier4_imx490 *)s_data->priv;
-
- tier4_imx490_shutdown(client);
-
- tier4_imx490_gmsl_serdes_reset(priv);
-
- tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
- tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
-
- tegracam_v4l2subdev_unregister(priv->tc_dev);
-
- tegracam_device_unregister(priv->tc_dev);
-
- return NO_ERROR;
-}
-
-static struct mutex tier4_imx490_lock;
-
-static bool tier4_imx490_is_isp_ser_shutdown(int nport)
-{
- if (wst_priv[nport].isp_ser_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx490_is_des_shutdown(int nport)
-{
- if (wst_priv[nport].des_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_imx490_set_isp_ser_shutdown(int nport, bool val)
-{
- wst_priv[nport].isp_ser_shutdown = val;
-}
-
-static void tier4_imx490_set_des_shutdown(int nport, bool val)
-{
- wst_priv[nport].des_shutdown = val;
-}
-
-static bool tier4_imx490_is_current_i2c_client(struct i2c_client *client, int nport)
-{
- if (client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-// ----------------------------------------------------------------------------
-
-static void tier4_imx490_shutdown(struct i2c_client *client)
-{
- struct tier4_imx490 *priv = NULL;
- int i;
-
- tier4_isx021_sensor_mutex_lock();
-
- mutex_lock(&tier4_imx490_lock);
-
- if (!client)
- {
- goto error_exit;
- }
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_imx490_is_current_i2c_client(client, i))
- {
- priv = wst_priv[i].p_priv;
-
- if (i & 0x1)
- { // Even port number( GMSL B port on a Des : i = port_number -1 )
-
- if (tier4_imx490_is_camera_connected_to_port(i - 1))
- { // if a camera connected to another(GMSL A)port on a Des.
- // a camera is connected to each port of the Des.
- if (tier4_imx490_is_isp_ser_shutdown(i - 1))
- { // ISP and Ser on another(GMSL A) port have been already shut down ?
-
- if (tier4_imx490_is_des_shutdown(i - 1) == false)
- { // if Des on another(GMSL A)port is not shutdown yet
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, true); // Des will be shut down
- }
- else
- { // if Des on the another port is already shut down. This is Error case.
- tier4_imx490_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx490_set_des_shutdown(i, false); // Des will not be shutdown
- }
- }
- else
- { // The camera ISP and Ser on another(GMSL A) port are not shut down yet.
-
- if (tier4_imx490_is_des_shutdown(i - 1) == false)
- { // if Des is not shut down yet.
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, false); // The Des won't be shut down.
- }
- else
- { // Only Des on another port is already shut down. This is Error case.
- tier4_imx490_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx490_set_des_shutdown(i, false); // Des will not be shut down.
- }
- } // a camera is connected to only (GMSL B) port on Des.
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, true); // The Des won't be shut down.
- }
- }
- else
- { // if ( i & 0x1 ) == 0
-
- if (tier4_imx490_is_camera_connected_to_port(i + 1))
- { // Another camera is connected to another(GMSL B) port on the Des
-
- if (tier4_imx490_is_isp_ser_shutdown(i + 1))
- { // if the ISP and Ser on another port are already shut down
-
- if (tier4_imx490_is_des_shutdown(i + 1) == false)
- { // if Des is not shut down yet.
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, false); // The Des will be shut down.
- }
- else
- { // Des is already shut down. This is Error case.
- tier4_imx490_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx490_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- else
- { // The ISP and Ser on another(GMSL B) port are not shut down yet.
-
- if (tier4_imx490_is_des_shutdown(i + 1) == false)
- { // if Des on another(GMSL B) port is not shut down yet.
-
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- else
- { // Only Des on another(GMSL B) port is already shut down.
- // This is Error case.
- tier4_imx490_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx490_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- }
- else
- {
- tier4_imx490_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx490_set_des_shutdown(i, true); // The Des will be shut down.
- }
- } // if ( i & 0x1 )
- // break;
-
- if (tier4_imx490_is_isp_ser_shutdown(i))
- {
- // Reset camera sensor
- tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX490, false);
- // S/W Reset max9295
- tier4_max9295_reset_control(priv->ser_dev);
- }
-
- if (tier4_imx490_is_des_shutdown(i))
- {
- // S/W Reset max9296
- tier4_max9296_reset_control(priv->dser_dev, &client->dev, true);
- }
-
- if (priv == NULL || i >= camera_channel_count)
- {
- mutex_unlock(&tier4_imx490_lock);
- tier4_isx021_sensor_mutex_unlock();
- return;
- }
- }
-
- } // for loop
-
-error_exit:
-
- mutex_unlock(&tier4_imx490_lock);
-
- tier4_isx021_sensor_mutex_unlock();
-}
-static const struct i2c_device_id tier4_imx490_id[] = { { "tier4_imx490", 0 }, {} };
-
-MODULE_DEVICE_TABLE(i2c, tier4_imx490_id);
-
-static struct i2c_driver tier4_imx490_i2c_driver = {
- .driver = {
- .name = "tier4_imx490",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(tier4_imx490_of_match),
- },
- .probe = tier4_imx490_probe,
- .remove = tier4_imx490_remove,
- .shutdown = tier4_imx490_shutdown,
- .id_table = tier4_imx490_id,
-};
-
-static int __init tier4_imx490_init(void)
-{
- mutex_init(&serdes_lock__);
- mutex_init(&tier4_imx490_lock);
-
- printk(KERN_INFO "TIERIV Automotive HDR Camera driver.\n");
-
- return i2c_add_driver(&tier4_imx490_i2c_driver);
-}
-
-static void __exit tier4_imx490_exit(void)
-{
- mutex_destroy(&serdes_lock__);
- mutex_destroy(&tier4_imx490_lock);
-
- i2c_del_driver(&tier4_imx490_i2c_driver);
-}
-
-module_init(tier4_imx490_init);
-module_exit(tier4_imx490_exit);
-
-MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
-MODULE_AUTHOR("Originaly NVIDIA Corporation");
-MODULE_AUTHOR("K.Iwasaki");
-MODULE_AUTHOR("Y.Fujii");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-imx728.c b/drivers/src/tier4-imx728.c
deleted file mode 100644
index 4db760e..0000000
--- a/drivers/src/tier4-imx728.c
+++ /dev/null
@@ -1,1891 +0,0 @@
-/*
- * tier4_imx728.c - imx728 sensor driver
- *
- * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
- * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tier4-fpga.h"
-#include "tier4-gmsl-link.h"
-#include "tier4-gw5300.h"
-#include "tier4-hw-model.h"
-#include "tier4-isx021-extern.h"
-#include "tier4-max9295.h"
-#include "tier4-max9296.h"
-
-MODULE_SOFTDEP("pre: tier4_max9296");
-MODULE_SOFTDEP("pre: tier4_max9295");
-MODULE_SOFTDEP("pre: tier4_gw5300");
-MODULE_SOFTDEP("pre: tier4_fpga");
-MODULE_SOFTDEP("pre: tier4_isx021");
-MODULE_SOFTDEP("pre: tier4_imx490");
-
-#define USE_DISTORTION_CORRECTION 1
-
-// Register Address
-
-#define IMX728_DEFAULT_FRAME_LENGTH (2350)
-
-#define BIT_SHIFT_8 8
-#define BIT_SHIFT_16 16
-#define MASK_1_BIT 0x1
-#define MASK_4_BIT 0xF
-#define MASK_8_BIT 0xFF
-
-#define POWER_ON 1
-#define POWER_OFF 0
-
-#define NO_ERROR 0
-//#define NO_C3_CAMERA (-728)
-
-//#define TIME_120_MILISEC 120000
-//#define TIME_121_MILISEC 121000
-
-#define ISP_PRIM_SLAVE_ADDR 0x6D
-
-//#define TIER4_C3_CAMERA 1
-
-#define MAX_NUM_CAMERA 8
-
-//#define FSYNC_FREQ_HZ 10
-
-enum
-{
- IMX728_MODE_3840x2160_CROP_20FPS,
- IMX728_MODE_START_STREAM,
- IMX728_MODE_STOP_STREAM,
-};
-
-static const int tier4_imx728_20fps[] = {
- 20,
-};
-static const struct camera_common_frmfmt tier4_imx728_frmfmt[] = {
- { { 3840, 2160 }, tier4_imx728_20fps, 1, 0, IMX728_MODE_3840x2160_CROP_20FPS },
-// { { 3840, 2163 }, tier4_imx728_20fps, 1, 0, IMX728_MODE_3840x2160_CROP_20FPS },
-};
-
-const struct of_device_id tier4_imx728_of_match[] = {
- {
- .compatible = "nvidia,tier4_imx728",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, tier4_imx728_of_match);
-
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
-// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
-
-static const u32 ctrl_cid_list[] = {
- TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE, TEGRA_CAMERA_CID_EXPOSURE_SHORT,
- TEGRA_CAMERA_CID_FRAME_RATE, TEGRA_CAMERA_CID_HDR_EN,
- // TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
-};
-
-struct tier4_imx728
-{
- struct i2c_client *i2c_client;
- const struct i2c_device_id *id;
- struct v4l2_subdev *subdev;
- struct device *ser_dev;
- struct device *dser_dev;
- struct device *isp_dev;
- struct tier4_gmsl_link_ctx g_ctx;
- u32 frame_length;
- struct camera_common_data *s_data;
- struct tegracam_device *tc_dev;
- int trigger_mode;
- bool distortion_correction;
- bool last_distortion_correction;
- bool inhibit_fpga_access;
- struct device *fpga_dev;
-};
-
-static const struct regmap_config tier4_sensor_regmap_config = {
- .reg_bits = 16,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
-};
-
-struct st_priv
-{
- struct i2c_client *p_client;
- struct tier4_imx728 *p_priv;
- struct tegracam_device *p_tc_dev;
- bool isp_ser_shutdown;
- bool des_shutdown;
- bool running;
-};
-
-static struct st_priv wst_priv[MAX_NUM_CAMERA];
-
-static struct mutex tier4_imx728_lock;
-
-static int camera_channel_count = 0;
-
-// --- module parameter ---
-
-static int trigger_mode;
-static int fsync_mfp = 0;
-static int enable_distortion_correction = 1;
-static int enable_auto_exposure = 0xCAFE;
-
-
-#define IMX728_MIN_EXPOSURE_TIME 11000 // 11 milisecond
-#define IMX728_MAX_EXPOSURE_TIME 33000 // 33 milisecond
-
-static int shutter_time_min = IMX728_MIN_EXPOSURE_TIME;
-static int shutter_time_max = IMX728_MAX_EXPOSURE_TIME;
-
-module_param(trigger_mode, int, 0644);
-module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
-module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
-
-
-module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
-module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
-module_param(enable_auto_exposure, int, S_IRUGO | S_IWUSR);
-
-// ------------------------
-static char upper(char c)
-{
- if ('a' <= c && c <= 'z')
- {
- c = c - ('a' - 'A');
- }
- return c;
-}
-
-static void to_upper_string(char *out, const char *in)
-{
- int i;
-
- i = 0;
- while (in[i] != '\0')
- {
- out[i] = upper(in[i]);
- i++;
- }
-}
-
-static inline int tier4_imx728_read_reg(struct camera_common_data *s_data, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
-
- err = regmap_read(s_data->regmap, addr, ®_val);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C read failed, address=0x%x\n", __func__, addr);
- }
- else
- {
- *val = reg_val & 0xFF;
- }
- return err;
-}
-
-static int tier4_imx728_write_reg(struct camera_common_data *s_data, u16 addr, u8 val)
-{
- int err = 0;
-
- err = regmap_write(s_data->regmap, addr, val);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C write failed at x%x=[0x%x]\n", __func__, addr, val);
- }
-
- return err;
-}
-
-// ------------------------------------------------
-
-static int tier4_imx728_set_fsync_trigger_mode(struct tier4_imx728 *priv, int mode)
-{
- int err = 0;
- struct device *dev = priv->s_data->dev;
- int des_num = 0;
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- priv->inhibit_fpga_access = false;
-
- dev_info(dev, "[%s] : Set fsync trigger mode.\n", __func__);
-
- err = tier4_fpga_check_access(priv->fpga_dev);
- if (err)
- {
- priv->inhibit_fpga_access = true;
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE)
- {
- dev_info(dev, "[%s] : Disabling FPGA fsync.\n", __func__);
-
- err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Disabling FPGA fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else
- {
- err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA generate fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_AUTO)
- {
- // Auto Trigger Mode
- err = tier4_fpga_set_fsync_auto_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- des_num = priv->g_ctx.reg_mux;
- err = tier4_fpga_set_fsync_signal_frequency(priv->fpga_dev, des_num, priv->trigger_mode);
- if (err)
- {
- dev_err(dev, "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_MANUAL)
- {
- // Manual Trigger Mode
- dev_info(dev, "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n", __func__);
-
- err = tier4_fpga_set_fsync_manual_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- }
- }
-
- err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
-
- if (err)
- {
- dev_err(dev, "[%s] :tier4_max9296_setup_gpi() failed\n", __func__);
- return err;
- }
-
- err = tier4_max9295_setup_gpo(priv->ser_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9295_setup_gpo() failed\n", __func__);
- return err;
- }
-
- // Power on GW5300 via Max9295 in C3 camera
-// err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
-// if (err)
-// {
-// dev_err(dev, "[%s] : Power on gw5300 in C3 camaera failed.\n", __func__);
-// return err;
-// }
-
- err = tier4_gw5300_c3_setup_sensor_mode(priv->isp_dev, mode);
- if (err)
- {
- dev_err(dev, "[%s] : tier4_gw5300_c3_setup_sensor_mode() failed\n", __func__);
- return err;
- }
-
- return err;
-}
-
-static struct mutex serdes_lock__;
-
-static int tier4_imx728_gmsl_serdes_setup(struct tier4_imx728 *priv)
-{
- int err = 0;
- int des_err = 0;
- struct device *dev;
-
- if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client)
- {
- return -EINVAL;
- }
-
- dev = &priv->i2c_client->dev;
-
- mutex_lock(&serdes_lock__);
-
- /* For now no separate power on required for serializer device */
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) && (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_on(priv->dser_dev);
- }
-
- /* setup serdes addressing and control pipeline */
-
-
- err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : GMSL deserializer link config failed\n", __func__);
- goto error;
- }
-
- err = tier4_max9295_setup_control(priv->ser_dev);
-
- /* proceed even if ser setup failed, to setup deser correctly */
- if (err)
- {
- dev_err(dev, "[%s] : GMSL serializer setup failed\n", __func__);
- goto error;
- }
-
- des_err = tier4_max9296_setup_control(priv->dser_dev, &priv->i2c_client->dev);
-
- if (des_err)
- {
- dev_err(dev, "[%s] : GMSL deserializer : setup failed\n", __func__);
- err = des_err;
- }
-
-error:
- mutex_unlock(&serdes_lock__);
- return err;
-}
-
-static void tier4_imx728_gmsl_serdes_reset(struct tier4_imx728 *priv)
-{
- mutex_lock(&serdes_lock__);
-
- /* reset serdes addressing and control pipeline */
- tier4_max9295_reset_control(priv->ser_dev);
-
- tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev, true);
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
- (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_off(priv->dser_dev);
- }
-
- mutex_unlock(&serdes_lock__);
-}
-
-static int tier4_imx728_power_on(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_on)
- {
- err = pdata->power_on(pw);
-
- if (err)
- {
- dev_err(dev, "[%s] : failed.\n", __func__);
- }
- else
- {
- pw->state = SWITCH_ON;
- }
- return err;
- }
-
- pw->state = SWITCH_ON;
-
- return err;
-}
-
-static int tier4_imx728_power_off(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_off)
- {
- err = pdata->power_off(pw);
-
- if (!err)
- {
- goto power_off_done;
- }
- else
- {
- dev_err(dev, "[%s] : power off failed.\n", __func__);
- }
- return err;
- }
-
-power_off_done:
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-static int tier4_imx728_power_get(struct tegracam_device *tc_dev)
-{
- struct camera_common_power_rail *pw = tc_dev->s_data->power;
- int err = 0;
-
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-static int tier4_imx728_power_put(struct tegracam_device *tc_dev)
-{
- if (unlikely(!tc_dev->s_data->power))
- {
- return -EFAULT;
- }
-
- return NO_ERROR;
-}
-
-static int tier4_imx728_set_group_hold(struct tegracam_device *tc_dev, bool val)
-{
- volatile int err = 0;
-
- return err;
-}
-
-static int tier4_imx728_set_gain(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- // struct camera_common_data *s_data = tc_dev->s_data;
-
- // struct device *dev = tc_dev->dev;
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_imx728_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
- // struct device dev = tc_dev->dev;
-
- /* fixed 20fps */
- priv->frame_length = IMX728_DEFAULT_FRAME_LENGTH;
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_imx728_set_exposure(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
- tier4_gw5300_c3_set_integration_time_on_aemode(priv->isp_dev, priv->trigger_mode, val, val);
-
- return err;
-}
-// --------------------------------------------------------------------------------------
-// Enable Distortion Coreection
-// --------------------------------------------------------------------------------------
-#if USE_DISTORTION_CORRECTION
-
-static int tier4_imx728_set_distortion_correction(struct tegracam_device *tc_dev, bool val)
-{
- int err = 0;
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
-
- if (priv->last_distortion_correction != val)
- {
- dev_info(&priv->i2c_client->dev, "[%s] : Setting distortion correction mode :%s.\n", __func__,val?"True":"False");
-
- err = tier4_gw5300_c3_set_distortion_correction(priv->isp_dev, val);
- if ( err <= 0)
- {
- dev_info(&priv->i2c_client->dev, "[%s] : Setting distortion correction mode failed.\n", __func__ );
- }
- else
- {
- err = 0;
- priv->last_distortion_correction = val;
- }
- }
-
- return err;
-}
-#endif
-
-// --------------------------------------------------------------------------------------
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
-// please add the new memeber and the function at the following table.
-
-static struct tegracam_ctrl_ops tier4_imx728_ctrl_ops = {
- .numctrls = ARRAY_SIZE(ctrl_cid_list),
- .ctrl_cid_list = ctrl_cid_list,
- .set_gain = tier4_imx728_set_gain,
- .set_exposure = tier4_imx728_set_exposure,
- .set_exposure_short = tier4_imx728_set_exposure,
- .set_frame_rate = tier4_imx728_set_frame_rate,
- .set_group_hold = tier4_imx728_set_group_hold,
- // .set_distortion_correction = tier4_imx728_set_distortion_correction,
-};
-
-// --------------------------------------------------------------------------------------
-
-static struct camera_common_pdata *tier4_imx728_parse_dt(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct camera_common_pdata *board_priv_pdata;
- const struct of_device_id *match;
- int err;
-
- if (!node)
- {
- return NULL;
- }
-
- match = of_match_device(tier4_imx728_of_match, dev);
-
- if (!match)
- {
- dev_err(dev, "[%s] : Failed to find matching dt id\n", __func__);
- return NULL;
- }
-
- board_priv_pdata = devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
-
- err = of_property_read_string(node, "mclk", &board_priv_pdata->mclk_name);
-
- if (err)
- {
- dev_err(dev, "[%s] : mclk not in DT\n", __func__);
- }
-
- return board_priv_pdata;
-}
-
-/* tier4_imx728_set_mode() can not be needed. But it remains for compatiblity */
-
-static int tier4_imx728_set_mode(struct tegracam_device *tc_dev)
-{
- volatile int err = 0;
-
- return err;
-}
-
-static int tier4_imx728_start_one_streaming(struct tegracam_device *tc_dev)
-{
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
- int err;
-
- /* enable serdes streaming */
-
- err = tier4_max9295_setup_streaming(priv->ser_dev);
-
- if (err)
- {
- goto exit;
- }
-
- err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Setup Streaming failed\n", __func__);
- goto exit;
- }
-
- dev_info(dev, "[%s] : trigger_mode = %d\n", __func__, trigger_mode);
-
- priv->trigger_mode = trigger_mode;
-
- switch (priv->trigger_mode)
- {
- case GW5300_MASTER_MODE_5FPS:
- case GW5300_MASTER_MODE_10FPS:
- case GW5300_MASTER_MODE_10FPS_EBD:
- case GW5300_MASTER_MODE_20FPS:
- case GW5300_MASTER_MODE_20FPS_EBD:
- case GW5300_MASTER_MODE_30FPS:
- case GW5300_MASTER_MODE_30FPS_EBD:
- dev_info(dev, "[%s] : Setting camera sensor to %s\n", __func__, gw5300_mode_name[priv->trigger_mode]);
-
- err = tier4_gw5300_c3_setup_sensor_mode(priv->isp_dev, priv->trigger_mode);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to %s failed\n", __func__, gw5300_mode_name[priv->trigger_mode]);
- return err;
- }
-
- priv->last_distortion_correction = 1;
- break;
-
- case GW5300_SLAVE_MODE_5FPS:
- case GW5300_SLAVE_MODE_10FPS:
- case GW5300_SLAVE_MODE_10FPS_EBD:
- case GW5300_SLAVE_MODE_20FPS:
- case GW5300_SLAVE_MODE_20FPS_EBD:
- case GW5300_SLAVE_MODE_30FPS:
- case GW5300_SLAVE_MODE_30FPS_EBD:
- dev_info(dev, "[%s] : Setting camera sensor to %s\n", __func__, gw5300_mode_name[priv->trigger_mode]);
-
- err = tier4_imx728_set_fsync_trigger_mode(priv, priv->trigger_mode);
- if (err)
- {
- dev_err(dev, "[%s] : setting camera sensor to %s failed\n", __func__, gw5300_mode_name[priv->trigger_mode]);
- return err;
- }
-
- priv->last_distortion_correction = 1;
- break;
-
- default: // case of trigger_mode < 0
- dev_err(dev, "[%s] : The camera sensor mode(trigger mode)=%d is invalid.\n", __func__, priv->trigger_mode);
-
- return err;
- }
-
- usleep_range(500000, 510000);
- err = tier4_gw5300_c3_set_auto_exposure(priv->isp_dev, enable_auto_exposure);
- if (err <= 0)
- {
- dev_err(dev, "[%s] : Setting Digital Gain to default value failed\n", __func__);
- goto exit;
- }
- else
- {
- err = 0;
- }
-
-#if USE_DISTORTION_CORRECTION
-
- if (priv->last_distortion_correction != enable_distortion_correction)
- {
- usleep_range(500000, 510000);
- //msleep(900);
- }
-
- if (enable_distortion_correction == 0xCAFE)
- {
- // if not set kernel param, read device tree param
- if (priv->distortion_correction == false)
- {
- err = tier4_imx728_set_distortion_correction(tc_dev, priv->distortion_correction);
-
- if (err)
- {
- dev_err(dev, "[%s] : Disabling Distortion Correction failed\n", __func__);
- goto exit;
- }
- msleep(20);
- }
- }else{
- err = tier4_imx728_set_distortion_correction(tc_dev, enable_distortion_correction==1);
- if (err)
- {
- dev_err(dev, "[%s] : Setup Distortion Correction failed\n", __func__);
- goto exit;
- }
- msleep(20);
- }
-
-#endif
-
-
-// Reset GW5300 via Max9295 in C3 camera
-// err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
-// if (err)
-// {
-// dev_err(dev, "[%s] : Reset gw5300 in C3 camaera failed.\n", __func__);
-// goto exit;
-// }
-//
-// usleep_range(500000, 510000);
-
- err = tier4_max9296_start_streaming(priv->dser_dev, dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_start_stream() failed\n", __func__);
- return err;
- }
-
- msleep(1000);
- tier4_gw5300_c3_set_integration_time_on_aemode(priv->isp_dev, priv->trigger_mode, shutter_time_max, shutter_time_min);
-
-// Reset GW5300 via Max9295 in C3 camera
-// err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
-// if (err)
-// {
-// dev_err(dev, "[%s] : Reset gw5300 in C3 camaera failed.\n", __func__);
-// goto exit;
-// }
-
- dev_info(dev, "[%s] : Camera has started streaming\n", __func__);
-
- return NO_ERROR;
-
-exit:
-
- dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
-
- return err;
-}
-
-static bool tier4_imx728_is_camera_connected_to_port(int nport)
-{
- if (wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx728_check_null_tc_dev_for_port(int nport)
-{
- if (wst_priv[nport].p_tc_dev == NULL)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx728_is_camera_running_on_port(int nport)
-{
- if (wst_priv[nport].running)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx728_is_current_port(struct tier4_imx728 *priv, int nport)
-{
- if (priv->i2c_client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_imx728_set_running_flag(int nport, bool flag)
-{
- wst_priv[nport].running = flag;
-}
-
-static int tier4_imx728_stop_streaming(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
- int i, err = 0;
-
- mutex_lock(&tier4_imx728_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_imx728_is_camera_connected_to_port(i))
- {
- if (tier4_imx728_is_current_port(priv, i) && tier4_imx728_is_camera_running_on_port(i))
- {
- /* disable serdes streaming */
- err = tier4_max9296_stop_streaming(priv->dser_dev, dev);
- if (err)
- {
- return err;
- }
- tier4_imx728_set_running_flag(i, false);
- break;
- }
- }
- }
-
- mutex_unlock(&tier4_imx728_lock);
-
- return NO_ERROR;
-}
-
-/* *************************************************************************** */
-/* 1. In the case where a camera is connected to GMSL A port on a Des. */
-/* */
-/* a > Check if another camera is connected to GMSL B port */
-/* a-1) Connected: */
-/* b > Check if another camera on GMSL B port is running */
-/* b-1) Running: */
-/* c > Check if the camera on GMSL A port is running */
-/* c-1) Running : */
-/* Do nothing and return */
-/* c-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* b-2) Not Running: */
-/* Start the camera on GMSL B port. */
-/* a-2) Not connected : */
-/* b > Check if the camera on GMSL A port is running */
-/* b-1) Running : */
-/* Do nothing and return */
-/* b-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* */
-/* 2. In the case where a camera is connected to GMSL B port on a Des. */
-/* */
-/* a > Check if the camera on GMSL B port is running */
-/* a-1) Running : */
-/* Do nothing and return */
-/* a-2) Not running : */
-/* Start the camera on GMSL B port. */
-/* *************************************************************************** */
-
-static int tier4_imx728_start_streaming(struct tegracam_device *tc_dev)
-{
- int i, err = 0;
- // struct tier4_imx728 *next_client_priv;
- struct tier4_imx728 *priv = (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
-
- mutex_lock(&tier4_imx728_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (i & 0x1)
- { // if i = 1,3,5,7 ( GMSL B port of a Des )
-
- if (tier4_imx728_is_camera_connected_to_port(i))
- { // a camera is connected to GMSL B portL
-
- if ((tier4_imx728_is_current_port(priv, i) == true) && (tier4_imx728_is_camera_running_on_port(i) == false))
- {
- err = tier4_imx728_start_one_streaming(wst_priv[i].p_tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming.\n", __func__);
- goto error_exit;
- }
- // wst_priv[i].running = true;
- tier4_imx728_set_running_flag(i, true);
- break;
- }
- }
- }
- else
- { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
-
- if ((tier4_imx728_is_camera_connected_to_port(i) == true) && (tier4_imx728_is_current_port(priv, i) == true))
- {
- if (tier4_imx728_is_camera_connected_to_port(i + 1) == false)
- { // if another one camera( GMSL B port) is not
- // connected to Des.
- if (tier4_imx728_is_camera_running_on_port(i) == false)
- { // and if the camera is not running.
-
- err = tier4_imx728_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for next imx728 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx728_set_running_flag(i, true);
- }
- break;
- }
-
- // two cameras are connected to one Des.
-
- if (tier4_imx728_check_null_tc_dev_for_port(i + 1))
- { // check if tc_dev is null
- dev_err(dev, "[%s] : wst_priv[%d].p_tc_dev is NULL.\n", __func__, i + 1);
- err = -EINVAL;
- goto error_exit;
- }
-
- if (tier4_imx728_is_camera_running_on_port(i + 1) == false)
- {
- err = tier4_imx728_start_one_streaming(wst_priv[i + 1].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for the next imx728 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx728_set_running_flag(i + 1, true);
- usleep_range(200000, 220000);
- //msleep(200);
- mutex_unlock(&tier4_imx728_lock);
- tier4_imx728_stop_streaming(wst_priv[i + 1].p_tc_dev);
- mutex_lock(&tier4_imx728_lock);
- tier4_imx728_set_running_flag(i + 1, false);
- }
-
- if (tier4_imx728_is_camera_running_on_port(i) == false)
- {
- err = tier4_imx728_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Failed to start one streaming for current imx728 client.\n", __func__);
- goto error_exit;
- }
- tier4_imx728_set_running_flag(i, true);
- }
- }
- }
- } // for loop
-
- err = NO_ERROR;
-
-error_exit:
-
- mutex_unlock(&tier4_imx728_lock);
-
- // tier4_imx728_sensor_mutex_unlock();
-
- return err;
-}
-
-static struct camera_common_sensor_ops tier4_imx728_common_ops = {
- .numfrmfmts = ARRAY_SIZE(tier4_imx728_frmfmt),
- .frmfmt_table = tier4_imx728_frmfmt,
- .power_on = tier4_imx728_power_on,
- .power_off = tier4_imx728_power_off,
- .write_reg = tier4_imx728_write_reg,
- .read_reg = tier4_imx728_read_reg,
- .parse_dt = tier4_imx728_parse_dt,
- .power_get = tier4_imx728_power_get,
- .power_put = tier4_imx728_power_put,
- .set_mode = tier4_imx728_set_mode,
- .start_streaming = tier4_imx728_start_streaming,
- .stop_streaming = tier4_imx728_stop_streaming,
-};
-
-static int tier4_imx728_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
- //struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- return NO_ERROR;
-}
-
-static const struct v4l2_subdev_internal_ops tier4_imx728_subdev_internal_ops = {
- .open = tier4_imx728_open,
-};
-
-static const char *of_stdout_options;
-
-static int tier4_imx728_board_setup(struct tier4_imx728 *priv)
-{
- struct tegracam_device *tc_dev = priv->tc_dev;
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct device_node *ser_node;
- struct i2c_client *ser_i2c = NULL;
- struct device_node *dser_node;
- struct i2c_client *dser_i2c = NULL;
- struct device_node *isp_node;
- struct i2c_client *isp_i2c = NULL;
- struct device_node *fpga_node = NULL;
- struct i2c_client *fpga_i2c = NULL;
- struct device_node *gmsl;
- struct device_node *root_node;
- int value = 0xFFFF;
- const char *str_value;
- const char *str_value1[2];
- int i;
- int err;
- const char *str_model;
- char upper_str_model[64];
- char *str_err;
- char *sub_str_err;
-
- root_node = of_find_node_opts_by_path("/", &of_stdout_options);
-
- err = of_property_read_string(root_node, "model", &str_model);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : model not found\n", __func__);
- goto error;
- }
-
- memset(upper_str_model, 0, 64);
-
- to_upper_string(upper_str_model, str_model);
-
- priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
-
- if (str_err)
- {
-
- sub_str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
-
- if (sub_str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_ORIN;
- }
- else
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_ORIN_DEVKIT;
- }
- }
-
-
- dev_info(dev, "[%s] : model=%s\n", __func__, str_model);
- dev_info(dev, "[%s] : hardware_model=%d\n", __func__, priv->g_ctx.hardware_model);
-
- if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN)
- {
- dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_isp_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : def-addr not found\n", __func__);
- goto error;
- }
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_isp_def);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : def-addr not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg_mux not found\n", __func__);
- goto error;
- }
-
-// err = of_property_read_string(node, "fsync-mode", &str_value);
-//
-// if (err < 0)
-// {
-// dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
-// goto error;
-// }
-//
-// if (!strcmp(str_value, "true"))
-// {
-// priv->fsync_mode = true;
-// }
-// else
-// {
-// priv->fsync_mode = false;
-// }
-
- err = of_property_read_string(node, "distortion-correction", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No distortion-correction found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "true"))
- {
- priv->distortion_correction = true;
- }
- else
- {
- priv->distortion_correction = false;
- }
-
- if (enable_auto_exposure == 0xCAFE)
- {
- err = of_property_read_string(node, "auto-exposure", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : Inavlid Exposure mode.\n", __func__);
- goto error;
- }
-
- enable_auto_exposure = !strcmp(str_value, "true");
- } else {
- dev_info(dev, "[%s] : Parameter[enable_auto_exposure] = %d.\n", __func__, enable_auto_exposure);
- }
-
-#if 0
- priv->g_ctx.fpga_generate_fsync = false;
-
- if (( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER ) ||
- ( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN )) {
-
- err = of_property_read_string(node, "fpga-generate-fsync", &str_value);
-
- if ( err < 0) {
- if ( err == -EINVAL ) {
- dev_info(dev, "[%s] : Parameter of fpga-generate-fsync does not exist.\n", __func__);
- } else {
- dev_err(dev, "[%s] : Parameter of fpga-generate-fsync is invalid .\n", __func__);
- goto error;
- }
- } else {
- if (!strcmp(str_value, "true")) {
- priv->g_ctx.fpga_generate_fsync = true;
- }
- }
- }
-#endif
-
- // For Ser node
- ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
-
- if (ser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-ser-device");
- goto error;
- }
-
- err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
- goto error;
- }
-
- ser_i2c = of_find_i2c_device_by_node(ser_node);
-
- of_node_put(ser_node);
-
- if (ser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing Serializer Dev Handle\n", __func__);
- goto error;
- }
- if (ser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
- goto error;
- }
-
- priv->ser_dev = &ser_i2c->dev;
-
- // For ISP node
-
- isp_node = of_parse_phandle(node, "nvidia,isp-device", 0);
-
- if (isp_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,isp-device");
- goto error;
- }
-
- err = of_property_read_u32(isp_node, "reg", &priv->g_ctx.sdev_isp_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : ISP reg not found\n", __func__);
- goto error;
- }
-
- isp_i2c = of_find_i2c_device_by_node(isp_node);
-
- of_node_put(isp_node);
-
- if (isp_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing ISP Dev Handle\n", __func__);
- goto error;
- }
- if (isp_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing ISP driver\n", __func__);
- goto error;
- }
-
- priv->isp_dev = &isp_i2c->dev;
-
- err = tier4_gw5300_prim_slave_addr(&priv->g_ctx);
- if (err)
- {
- dev_err(dev, "[%s] : ISP Prim slave address is unavailable, the default address(0x6D) is applied.\n", __func__);
- priv->g_ctx.sdev_isp_def = ISP_PRIM_SLAVE_ADDR;
- }
-
- priv->g_ctx.sdev_reg = priv->g_ctx.sdev_isp_reg;
- priv->g_ctx.sdev_def = priv->g_ctx.sdev_isp_def;
-
- // For Dser node
-
- dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
-
- if (dser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-dser-device");
- goto error;
- }
-
- dser_i2c = of_find_i2c_device_by_node(dser_node);
-
- of_node_put(dser_node);
-
- if (dser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer dev handle\n", __func__);
- goto error;
- }
-
- if (dser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
- goto error;
- }
-
- priv->dser_dev = &dser_i2c->dev;
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- // for FPGA node
-
- fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
-
- if (fpga_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,fpga-device");
- goto error;
- }
-
- err = of_property_read_u32(fpga_node, "reg", &priv->g_ctx.sdev_fpga_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
- goto error;
- }
-
- fpga_i2c = of_find_i2c_device_by_node(fpga_node);
-
- of_node_put(fpga_node);
-
- if (fpga_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA Dev Handle\n", __func__);
- goto error;
- }
- if (fpga_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
- goto error;
- }
-
- priv->fpga_dev = &fpga_i2c->dev;
- }
-
- /* populate g_ctx from DT */
-
- gmsl = of_get_child_by_name(node, "gmsl-link");
-
- if (gmsl == NULL)
- {
- dev_err(dev, "[%s] : Missing GMSL-Link device node\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "src-csi-port", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "csi-mode", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No csi-mode found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "1x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
- }
- else if (!strcmp(str_value, "2x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
- }
- else if (!strcmp(str_value, "4x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
- }
- else if (!strcmp(str_value, "2x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
- }
- else
- {
- dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
- goto error;
- }
-
- err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ? GMSL_SERDES_CSI_LINK_A : GMSL_SERDES_CSI_LINK_B;
-
- err = of_property_read_u32(gmsl, "st-vc", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No st-vc info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.st_vc = value;
-
- err = of_property_read_u32(gmsl, "vc-id", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No vc-id info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_vc = value;
-
- err = of_property_read_u32(gmsl, "num-lanes", &value);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : No num-lanes info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.num_csi_lanes = value;
-
- priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
-
- if (priv->g_ctx.num_streams <= 0)
- {
- dev_err(dev, "[%s] : No streams found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- for (i = 0; i < priv->g_ctx.num_streams; i++)
- {
- of_property_read_string_index(gmsl, "streams", i, &str_value1[i]);
-
- if (!str_value1[i])
- {
- dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value1[i], "raw12"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_RAW_12;
- }
- else if (!strcmp(str_value1[i], "yuv8"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
- }
- else if (!strcmp(str_value1[i], "embed"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
- }
- else if (!strcmp(str_value1[i], "ued-u1"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_UED_U1;
- }
- else
- {
- dev_err(dev, "[%s] : Invalid stream data type\n", __func__);
- goto error;
- }
- }
-
- priv->g_ctx.s_dev = dev;
-
- return NO_ERROR;
-
-error:
- dev_err(dev, "[%s] : Board Setup failed\n", __func__);
- return err;
-}
-
-static int tier4_imx728_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct device *dev = &client->dev;
- struct device_node *node = dev->of_node;
- struct tegracam_device *tc_dev;
- struct tier4_imx728 *priv;
- int err = 0;
-
- dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
-
- if (!IS_ENABLED(CONFIG_OF) || !node)
- {
- return -EINVAL;
- }
-
- wst_priv[camera_channel_count].p_client = NULL;
- wst_priv[camera_channel_count].p_priv = NULL;
- wst_priv[camera_channel_count].p_tc_dev = NULL;
-
- wst_priv[camera_channel_count].isp_ser_shutdown = false;
- wst_priv[camera_channel_count].des_shutdown = false;
- wst_priv[camera_channel_count].running = false;
-
- priv = devm_kzalloc(dev, sizeof(struct tier4_imx728), GFP_KERNEL);
-
- if (!priv)
- {
- dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
- return -ENOMEM;
- }
-
- tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
-
- if (!tc_dev)
- {
- return -ENOMEM;
- }
-
- priv->i2c_client = tc_dev->client = client;
-
- tc_dev->dev = dev;
-
- strncpy(tc_dev->name, "imx728", sizeof(tc_dev->name));
-
- tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
- tc_dev->sensor_ops = &tier4_imx728_common_ops;
- tc_dev->v4l2sd_internal_ops = &tier4_imx728_subdev_internal_ops;
- tc_dev->tcctrl_ops = &tier4_imx728_ctrl_ops;
-
- err = tegracam_device_register(tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Driver Registration failed\n", __func__);
- return err;
- }
-
- priv->tc_dev = tc_dev;
- priv->s_data = tc_dev->s_data;
- priv->subdev = &tc_dev->s_data->subdev;
-
- tegracam_set_privdata(tc_dev, (void *)priv);
-
- priv->g_ctx.sensor_id = SENSOR_ID_IMX728;
-
- tier4_isx021_sensor_mutex_lock();
-
- err = tier4_imx728_board_setup(priv);
-
- if (err)
- {
- dev_err(dev, "[%s] : Board Setup failed\n", __func__);
- goto err_tegracam_unreg;
- }
-
- /* Pair sensor to serializer dev */
-
- err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed\n", __func__);
- goto err_tegracam_unreg;
- }
- /* Register sensor to deserializer dev */
-
- err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Deserializer Register failed\n", __func__);
- goto err_max9295_unpair;
- }
-
- /*
- * gmsl serdes setup
- *
- * Sensor power on/off should be the right place for serdes
- * setup/reset. But the problem is, the total required delay
- * in serdes setup/reset exceeds the frame wait timeout, looks to
- * be related to multiple channel open and close sequence
- * issue (#BUG 200477330).
- * Once this bug is fixed, these may be moved to power on/off.
- * The delays in serdes is as per guidelines and can't be reduced,
- * so it is placed in probe/remove, though for that, deserializer
- * would be powered on always post boot, until 1.2v is supplied
- * to deserializer from CVB.
- */
-
- err = tier4_imx728_gmsl_serdes_setup(priv);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Serdes setup failed\n", __func__);
- goto err_max9296_unreg;
- }
-
- err = tegracam_v4l2subdev_register(tc_dev, true);
-
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Subdev Registration failed\n", __func__);
- goto err_max9296_unreg;
- }
-
- wst_priv[camera_channel_count].p_client = client;
- wst_priv[camera_channel_count].p_priv = priv;
- wst_priv[camera_channel_count].p_tc_dev = tc_dev;
-
- camera_channel_count++;
-
- tier4_isx021_sensor_mutex_unlock();
-
- return NO_ERROR;
-
-// tier4_isx021_sensor_mutex_unlock();
-
-// dev_info(&client->dev, "Detected Tier4 IMX490 sensor\n");
-
-err_max9296_unreg:
- tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
-err_max9295_unpair:
- tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
-err_tegracam_unreg:
- tegracam_device_unregister(priv->tc_dev);
-
- tier4_isx021_sensor_mutex_unlock();
-
-// dev_info(dev, "[%s] :camera_channel_count = %d p_client = %p \n", __func__, camera_channel_count,
-// wst_priv[camera_channel_count].p_client);
-
-
- return err;
- //return NO_ERROR; // err;
-}
-
-static int tier4_imx728_remove(struct i2c_client *client)
-{
- struct camera_common_data *s_data = to_camera_common_data(&client->dev);
- struct tier4_imx728 *priv = (struct tier4_imx728 *)s_data->priv;
-
- tier4_imx728_gmsl_serdes_reset(priv);
-
- tegracam_v4l2subdev_unregister(priv->tc_dev);
-
- tegracam_device_unregister(priv->tc_dev);
-
- return NO_ERROR;
-}
-
-static struct mutex tier4_imx728_lock;
-
-static bool tier4_imx728_is_isp_ser_shutdown(int nport)
-{
- if (wst_priv[nport].isp_ser_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_imx728_is_des_shutdown(int nport)
-{
- if (wst_priv[nport].des_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_imx728_set_isp_ser_shutdown(int nport, bool val)
-{
- wst_priv[nport].isp_ser_shutdown = val;
-}
-
-static void tier4_imx728_set_des_shutdown(int nport, bool val)
-{
- wst_priv[nport].des_shutdown = val;
-}
-
-static bool tier4_imx728_is_current_i2c_client(struct i2c_client *client, int nport)
-{
- if (client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-// ----------------------------------------------------------------------------
-
-static void tier4_imx728_shutdown(struct i2c_client *client)
-{
- struct tier4_imx728 *priv = NULL;
- int i;
-
- tier4_isx021_sensor_mutex_lock();
-
- mutex_lock(&tier4_imx728_lock);
-
- if (!client)
- {
- goto error_exit;
- }
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_imx728_is_current_i2c_client(client, i))
- {
- priv = wst_priv[i].p_priv;
-
- if (i & 0x1)
- { // Even port number( GMSL B port on a Des : i = port_number -1 )
-
- if (tier4_imx728_is_camera_connected_to_port(i - 1))
- { // if a camera connected to another(GMSL A)port on a Des.
- // a camera is connected to each port of the Des.
- if (tier4_imx728_is_isp_ser_shutdown(i - 1))
- { // ISP and Ser on another(GMSL A) port have been already shut down ?
-
- if (tier4_imx728_is_des_shutdown(i - 1) == false)
- { // if Des on another(GMSL A)port is not shutdown yet
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, true); // Des will be shut down
- }
- else
- { // if Des on the another port is already shut down. This is Error case.
- tier4_imx728_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx728_set_des_shutdown(i, false); // Des will not be shutdown
- }
- }
- else
- { // The camera ISP and Ser on another(GMSL A) port are not shut down yet.
-
- if (tier4_imx728_is_des_shutdown(i - 1) == false)
- { // if Des is not shut down yet.
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, false); // The Des won't be shut down.
- }
- else
- { // Only Des on another port is already shut down. This is Error case.
- tier4_imx728_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx728_set_des_shutdown(i, false); // Des will not be shut down.
- }
- } // a camera is connected to only (GMSL B) port on Des.
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, true); // The Des won't be shut down.
- }
- }
- else
- { // if ( i & 0x1 ) == 0
-
- if (tier4_imx728_is_camera_connected_to_port(i + 1))
- { // Another camera is connected to another(GMSL B) port on the Des
-
- if (tier4_imx728_is_isp_ser_shutdown(i + 1))
- { // if the ISP and Ser on another port are already shut down
-
- if (tier4_imx728_is_des_shutdown(i + 1) == false)
- { // if Des is not shut down yet.
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, false); // The Des will be shut down.
- }
- else
- { // Des is already shut down. This is Error case.
- tier4_imx728_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx728_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- else
- { // The ISP and Ser on another(GMSL B) port are not shut down yet.
-
- if (tier4_imx728_is_des_shutdown(i + 1) == false)
- { // if Des on another(GMSL B) port is not shut down yet.
-
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- else
- { // Only Des on another(GMSL B) port is already shut down.
- // This is Error case.
- tier4_imx728_set_isp_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_imx728_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- }
- else
- {
- tier4_imx728_set_isp_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_imx728_set_des_shutdown(i, true); // The Des will be shut down.
- }
- } // if ( i & 0x1 )
- // break;
-
- if (tier4_imx728_is_isp_ser_shutdown(i))
- {
- // Reset camera sensor
- tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, false);
- // S/W Reset max9295
- tier4_max9295_reset_control(priv->ser_dev);
- }
-
- if (tier4_imx728_is_des_shutdown(i))
- {
- // S/W Reset max9296
- tier4_max9296_reset_control(priv->dser_dev, &client->dev, true);
- }
-
- if (priv == NULL || i >= camera_channel_count)
- {
- mutex_unlock(&tier4_imx728_lock);
- tier4_isx021_sensor_mutex_unlock();
- return;
- }
- }
-
- } // for loop
-
-error_exit:
-
- mutex_unlock(&tier4_imx728_lock);
-
- tier4_isx021_sensor_mutex_unlock();
-}
-static const struct i2c_device_id tier4_imx728_id[] = { { "tier4_imx728", 0 }, {} };
-
-MODULE_DEVICE_TABLE(i2c, tier4_imx728_id);
-
-static struct i2c_driver tier4_imx728_i2c_driver = {
- .driver = {
- .name = "tier4_imx728",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(tier4_imx728_of_match),
- },
- .probe = tier4_imx728_probe,
- .remove = tier4_imx728_remove,
- .shutdown = tier4_imx728_shutdown,
- .id_table = tier4_imx728_id,
-};
-
-static int __init tier4_imx728_init(void)
-{
- mutex_init(&serdes_lock__);
- mutex_init(&tier4_imx728_lock);
-
- printk(KERN_INFO "TIERIV Automotive HDR Camera driver.\n");
-
- return i2c_add_driver(&tier4_imx728_i2c_driver);
-}
-
-static void __exit tier4_imx728_exit(void)
-{
- mutex_destroy(&serdes_lock__);
- mutex_destroy(&tier4_imx728_lock);
-
- i2c_del_driver(&tier4_imx728_i2c_driver);
-}
-
-module_init(tier4_imx728_init);
-module_exit(tier4_imx728_exit);
-
-MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
-MODULE_AUTHOR("Originaly NVIDIA Corporation");
-MODULE_AUTHOR("K.Iwasaki");
-MODULE_AUTHOR("Y.Fujii");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-isx021.c b/drivers/src/tier4-isx021.c
deleted file mode 100644
index 409e162..0000000
--- a/drivers/src/tier4-isx021.c
+++ /dev/null
@@ -1,3121 +0,0 @@
-/*
- * isx021.c - isx021 sensor driver
- *
- * Copyright (c) 2022-2023, TIERIV INC. All rights reserved.
- * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// ---------------------------------------------------------------
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
-#include
-#endif
-
-#include
-
-#include "tier4-fpga.h"
-#include "tier4-gmsl-link.h"
-#include "tier4-hw-model.h"
-#include "tier4-max9295.h"
-#include "tier4-max9296.h"
-
-#define USE_FIRMWARE
-
-//#define USE_I2C_TRANSFER
-#define USE_I2C_READ_REG
-
-#undef SHOW_I2C_READ_MSG
-
-#define SHOW_I2C_WRITE_MSG
-//#undef SHOW_I2C_WRITE_MSG
-
-#undef USE_CHECK_MODE_SEL
-
-#undef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
-
-MODULE_SOFTDEP("pre: tier4_max9296");
-MODULE_SOFTDEP("pre: tier4_max9295");
-MODULE_SOFTDEP("pre: tier4_fpga");
-
-// Register Address
-
-#define ISX021_SG_MODE_INTERNAL_SYNC 0
-
-#define ISX021_SG_MODE_INTERNAL_SYNC 0
-
-#define ISX021_MIN_GAIN 0
-#define ISX021_MAX_GAIN 48
-
-#define ISX021_MIN_EXPOSURE_TIME 0
-#define ISX021_MID_EXPOSURE_TIME 11010 // 11 milisecond
-#define ISX021_MAX_EXPOSURE_TIME 33000 // 33 milisecond
-
-#define ISX021_GAIN_DEFAULT_VALUE 6
-
-#define ISX021_DEFAULT_FRAME_LENGTH (1125)
-
-// --- Start of Register definition ------------------
-
-#define TIER4_ISX021_REG_0_ADDR 0
-#define TIER4_ISX021_REG_1_ADDR 1
-#define TIER4_ISX021_REG_2_ADDR 2
-#define TIER4_ISX021_REG_3_ADDR 3
-#define TIER4_ISX021_REG_4_ADDR 4
-#define TIER4_ISX021_REG_5_ADDR 5
-#define TIER4_ISX021_REG_6_ADDR 6
-#define TIER4_ISX021_REG_7_ADDR 7
-#define TIER4_ISX021_REG_8_ADDR 8
-#define TIER4_ISX021_REG_9_ADDR 9
-#define TIER4_ISX021_REG_10_ADDR 10
-#define TIER4_ISX021_REG_11_ADDR 11
-#define TIER4_ISX021_REG_12_ADDR 12
-#define TIER4_ISX021_REG_13_ADDR 13
-
-#define TIER4_ISX021_REG_14_ADDR 14
-
-// AE mode
-
-#define TIER4_ISX021_REG_15_ADDR 15
-#define TIER4_ISX021_REG_16_ADDR 16
-#define TIER4_ISX021_REG_17_ADDR 17
-#define TIER4_ISX021_REG_18_ADDR 18
-
-#define TIER4_ISX021_REG_19_ADDR 19
-#define TIER4_ISX021_REG_20_ADDR 20
-#define TIER4_ISX021_REG_21_ADDR 21
-#define TIER4_ISX021_REG_22_ADDR 22
-
-// ME mode
-
-#define TIER4_ISX021_REG_23_ADDR 23
-#define TIER4_ISX021_REG_24_ADDR 24
-#define TIER4_ISX021_REG_25_ADDR 25
-#define TIER4_ISX021_REG_26_ADDR 26
-
-#define TIER4_ISX021_REG_27_ADDR 27
-#define TIER4_ISX021_REG_28_ADDR 28
-#define TIER4_ISX021_REG_29_ADDR 29
-#define TIER4_ISX021_REG_30_ADDR 30
-
-// Analog Gain
-
-#define TIER4_ISX021_REG_31_ADDR 31
-#define TIER4_ISX021_REG_32_ADDR 32
-
-#define TIER4_ISX021_REG_33_ADDR 33
-#define TIER4_ISX021_REG_34_ADDR 34
-
-#define TIER4_ISX021_REG_35_ADDR 35
-#define TIER4_ISX021_REG_36_ADDR 36
-
-#define TIER4_ISX021_REG_37_ADDR 37
-#define TIER4_ISX021_REG_38_ADDR 38
-
-#define TIER4_ISX021_REG_39_ADDR 39
-#define TIER4_ISX021_REG_40_ADDR 40
-
-#define TIER4_ISX021_REG_41_ADDR 41
-#define TIER4_ISX021_REG_42_ADDR 42
-
-#define TIER4_ISX021_REG_43_ADDR 43
-#define TIER4_ISX021_REG_44_ADDR 44
-
-#define TIER4_ISX021_REG_45_ADDR 45
-#define TIER4_ISX021_REG_46_ADDR 46
-
-// Exposure
-
-#define TIER4_ISX021_REG_47_ADDR 47
-#define TIER4_ISX021_REG_48_ADDR 48
-#define TIER4_ISX021_REG_49_ADDR 49
-
-#define TIER4_ISX021_REG_50_ADDR 50
-#define TIER4_ISX021_REG_51_ADDR 51
-#define TIER4_ISX021_REG_52_ADDR 52
-#define TIER4_ISX021_REG_53_ADDR 53
-
-#define TIER4_ISX021_REG_54_ADDR 54
-#define TIER4_ISX021_REG_55_ADDR 55
-#define TIER4_ISX021_REG_56_ADDR 56
-#define TIER4_ISX021_REG_57_ADDR 57
-
-#define TIER4_ISX021_REG_58_ADDR 58
-#define TIER4_ISX021_REG_59_ADDR 59
-#define TIER4_ISX021_REG_60_ADDR 60
-#define TIER4_ISX021_REG_61_ADDR 61
-
-#define TIER4_ISX021_REG_62_ADDR 62
-
-#define TIER4_ISX021_REG_63_ADDR 63
-#define TIER4_ISX021_REG_64_ADDR 64
-#define TIER4_ISX021_REG_65_ADDR 65
-
-#define TIER4_ISX021_REG_66_ADDR 66
-
-// AE mode
-
-#define TIER4_ISX021_REG_67_ADDR 67
-
-#define TIER4_ISX021_REG_68_ADDR 68
-#define TIER4_ISX021_REG_69_ADDR 69
-
-#define TIER4_ISX021_REG_70_ADDR 70
-
-// Digital Gain
-
-#define TIER4_ISX021_REG_71_ADDR 71
-#define TIER4_ISX021_REG_72_ADDR 72
-
-// Distortion Corretion
-
-#define TIER4_ISX021_REG_73_ADDR 73
-#define TIER4_ISX021_REG_74_ADDR 74
-#define TIER4_ISX021_REG_75_ADDR 75
-#define TIER4_ISX021_REG_76_ADDR 76
-
-// Mode change
-
-#define TIER4_ISX021_REG_77_ADDR 77
-
-#define TIER4_ISX021_REG_78_ADDR 78
-
-#define TIER4_ISX021_REG_79_ADDR 79
-
-// Embedded data
-
-#define TIER4_ISX021_REG_80_ADDR 80
-#define TIER4_ISX021_REG_81_ADDR 81
-
-#define TIER4_ISX021_REG_82_ADDR 82
-
-#define TIER4_ISX021_REG_83_ADDR 83
-#define TIER4_ISX021_REG_84_ADDR 84
-#define TIER4_ISX021_REG_85_ADDR 85
-#define TIER4_ISX021_REG_86_ADDR 86
-#define TIER4_ISX021_REG_87_ADDR 87
-#define TIER4_ISX021_REG_88_ADDR 88
-#define TIER4_ISX021_REG_89_ADDR 89
-
-#define TIER4_ISX021_REG_90_ADDR 90
-#define TIER4_ISX021_REG_91_ADDR 91
-
-#define TIER4_ISX021_REG_92_ADDR 92
-#define TIER4_ISX021_REG_93_ADDR 93
-
-// --- End of Register definition ------------------------
-
-#define MAX_NUM_OF_REG (100)
-
-#define ISX021_AUTO_EXPOSURE_MODE 0x00
-#define ISX021_AE_TIME_UNIT_MICRO_SECOND 0x03
-
-#define BIT_SHIFT_8 8
-#define BIT_SHIFT_16 16
-#define MASK_1_BIT 0x1
-#define MASK_4_BIT 0xF
-#define MASK_8_BIT 0xFF
-
-#define NO_ERROR 0
-
-#define TIME_1_MS 1000
-#define TIME_2_MS 2000
-#define TIME_5_MS 5000
-#define TIME_10_MS 10000
-#define TIME_20_MS 20000
-#define TIME_30_MS 30000
-#define TIME_35_MS 35000
-#define TIME_40_MS 40000
-#define TIME_50_MS 50000
-#define TIME_60_MS 60000
-#define TIME_70_MS 70000
-#define TIME_80_MS 80000
-#define TIME_100_MS 100000
-#define TIME_120_MS 120000
-#define TIME_121_MS 121000
-#define TIME_200_MS 200000
-#define TIME_250_MS 250000
-#define TIME_300_MS 300000
-#define TIME_500_MS 500000
-#define TIME_800_MS 800000
-#define TIME_1000_MS 1000000
-
-#define PLUS_10(x) ((x)+(x)/10)
-
-#define MAX_NUM_CAMERA 8
-
-#define FIRMWARE_BIN_FILE "/lib/firmware/tier4-isx021.bin"
-
-#define FSYNC_FREQ_HZ 10
-
-#define DISABLE_BOTH_EMBEDDED_DATA 0x0
-#define ENABLE_FRONT_EMBEDDED_DATA 0x1
-#define ENABLE_REAR_EMBEDDED_DATA 0x2
-#define ENABLE_BOTH_EMBEDDED_DATA ((ENABLE_FRONT_EMBEDDED_DATA)|(ENABLE_REAR_EMBEDDED_DATA))
-
-enum
-{
- ISX021_MODE_1920X1280_CROP_30FPS,
- ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA,
- ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA,
- ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA,
- ISX021_MODE_START_STREAM,
- ISX021_MODE_STOP_STREAM
-};
-
-static const int tier4_isx021_30fps[] = {
- 30,
-};
-static const struct camera_common_frmfmt tier4_isx021_frmfmt[] = {
- { { 1920, 1280 }, tier4_isx021_30fps, 1, 0, ISX021_MODE_1920X1280_CROP_30FPS },
- { { 1920, 1281 }, tier4_isx021_30fps, 1, 0, ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA }, // added 1 lines of embedded data
- { { 1920, 1294 }, tier4_isx021_30fps, 1, 0, ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA }, // added 14 lines of embedded data
- { { 1920, 1295 }, tier4_isx021_30fps, 1, 0, ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA }, // added 15 lines of embedded data
-};
-
-const struct of_device_id tier4_isx021_of_match[] = {
- {
- .compatible = "nvidia,tier4_isx021",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, tier4_isx021_of_match);
-
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
-// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
-
-static const u32 ctrl_cid_list[] = {
- TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE, TEGRA_CAMERA_CID_EXPOSURE_SHORT,
- TEGRA_CAMERA_CID_FRAME_RATE, TEGRA_CAMERA_CID_HDR_EN,
- //TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
-};
-
-struct tier4_isx021
-{
- struct i2c_client *i2c_client;
- const struct i2c_device_id *id;
- struct v4l2_subdev *subdev;
- struct device *ser_dev;
- struct device *dser_dev;
- struct tier4_gmsl_link_ctx g_ctx;
- u32 frame_length;
- struct camera_common_data *s_data;
- struct tegracam_device *tc_dev;
-// bool fsync_mode;
- bool distortion_correction;
- bool auto_exposure;
- u16 *firmware_buffer;
- int es_number;
- struct device *fpga_dev;
- int trigger_mode;
- bool inhibit_fpga_access;
- int enable_embedded_data; // 0:disable all embedded data 1: enable front embedded data 2:enable rear embedded data 3: enable front and rear embedded data
-};
-
-static const struct regmap_config tier4_sensor_regmap_config = {
- .reg_bits = 16,
- .val_bits = 8,
- //.cache_type = REGCACHE_RBTREE,
- .cache_type = REGCACHE_NONE,
-};
-
-struct st_priv
-{
- struct i2c_client *p_client;
- struct tier4_isx021 *p_priv;
- struct tegracam_device *p_tc_dev;
- bool sensor_ser_shutdown;
- bool des_shutdown;
- bool running;
-};
-
-static struct st_priv wst_priv[MAX_NUM_CAMERA];
-
-static int camera_channel_count = 0;
-
-static int trigger_mode = 0xCAFE;
-static int enable_auto_exposure = 0xCAFE;
-static int enable_distortion_correction = 0xCAFE;
-static int shutter_time_min = ISX021_MIN_EXPOSURE_TIME;
-static int shutter_time_mid = ISX021_MID_EXPOSURE_TIME;
-static int shutter_time_max = ISX021_MAX_EXPOSURE_TIME;
-static int fsync_mfp = 0;
-// static int debug_i2c_write = 0;
-
-module_param(trigger_mode, int, S_IRUGO | S_IWUSR);
-module_param(enable_auto_exposure, int, S_IRUGO | S_IWUSR);
-module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
-module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
-module_param(shutter_time_mid, int, S_IRUGO | S_IWUSR);
-module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
-
-module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
-// module_param(debug_i2c_write, int, S_IRUGO | S_IWUSR);
-
-static struct mutex tier4_sensor_lock__;
-
-static struct mutex tier4_isx021_lock;
-
-void tier4_isx021_sensor_mutex_lock(void)
-{
- mutex_lock(&tier4_sensor_lock__);
-}
-EXPORT_SYMBOL(tier4_isx021_sensor_mutex_lock);
-
-void tier4_isx021_sensor_mutex_unlock(void)
-{
- mutex_unlock(&tier4_sensor_lock__);
-}
-EXPORT_SYMBOL(tier4_isx021_sensor_mutex_unlock);
-
-// -------------------------------
-
-static char upper(char c)
-{
- if ('a' <= c && c <= 'z')
- {
- c = c - ('a' - 'A');
- }
- return c;
-}
-
-static void to_upper_string(char *out, const char *in)
-{
- int i;
-
- i = 0;
- while (in[i] != '\0')
- {
- out[i] = upper(in[i]);
- i++;
- }
-}
-
-#ifndef USE_I2C_TRANSFER // with regmap functions
-
-static inline int tier4_isx021_read_reg(struct camera_common_data *s_data, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
- u16 reg_addr = 0;
-
-#ifdef USE_FIRMWARE
- reg_addr = priv->firmware_buffer[addr];
-#else
- reg_addr = addr;
-#endif
-
- err = regmap_read(s_data->regmap, reg_addr, ®_val);
-
- *val = reg_val & 0xFF;
-
- if (err)
- {
- dev_err(s_data->dev, "[%s ] : I2C Read register failed at 0x%04X\n", __func__, reg_addr);
- }
-#ifdef SHOW_I2C_READ_MSG
- else
- {
- dev_info(s_data->dev, "[%s] : I2C Read regiser at %d(0x%04X)=[0x%02X]\n", __func__, addr, reg_addr, reg_val);
- }
-#endif
-
- usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
-
- return err;
-}
-
-static int tier4_isx021_write_reg(struct camera_common_data *s_data, u16 addr, u8 val)
-{
- int err = 0;
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
- u16 reg_addr = 0;
-
-#ifdef USE_FIRMWARE
- reg_addr = priv->firmware_buffer[addr];
-#else
- reg_addr = addr;
-#endif
-
- err = regmap_write(s_data->regmap, reg_addr, val);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n", __func__, addr, reg_addr, val);
- }
-#ifdef SHOW_I2C_WRITE_MSG
- else
- {
- dev_info(s_data->dev, "[%s] : I2C write register at %d(0x%04X)=[0x%02X]\n", __func__, addr, reg_addr, val);
- }
-#endif
-
- usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
-
- return err;
-}
-
-#ifdef USE_WRITE_AND_VEIFY
-
-static int tier4_isx021_write_reg_and_verify(struct camera_common_data *s_data, u16 addr, u8 val8)
-{
- u32 r_val32;
- u8 r_val8;
- int err = 0;
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
- u16 reg_addr = 0;
-
-#ifdef USE_FIRMWARE
- reg_addr = priv->firmware_buffer[addr];
-#else
- reg_addr = addr;
-#endif
-
- err = regmap_write(s_data->regmap, reg_addr, val8);
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n", __func__, addr, reg_addr, val8);
- }
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = regmap_read(s_data->regmap, reg_addr, &r_val32);
-
- r_val8 = r_val32 & 0xFF;
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C Read register failed at 0x%04X=[0x%02X]\n", __func__, reg_addr, r_val8);
- }
-
- return err;
-
-}
-
-#endif // ifdef USE_WRITE_AND_VEIFY
-
-#else // ifndef USE_I2C_TRANSFER ( with i2c_transfer function )
-
-#ifdef USE_I2C_READ_REG
-
-static int tier4_isx021_read_reg(struct camera_common_data *s_data, u16 addr, u8 *val8 ) // with i2c_tranfer
-{
- int err = 0;
- u16 reg_addr = 0;
- struct i2c_msg msg[2];
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
- u8 w_buf[5];
-
-#ifdef USE_FIRMWARE
- reg_addr = priv->firmware_buffer[addr];
-#else
- reg_addr = addr;
-#endif
-
- w_buf[0] = ( reg_addr >> 8 ) & 0xFF;
- w_buf[1] = reg_addr & 0xFF;
-
- msg[0].addr = priv->i2c_client->addr;
- msg[0].flags = 0; // I2C Write
- msg[0].len = 2;
- msg[0].buf = w_buf;
-
- msg[1].addr = priv->i2c_client->addr;
- msg[1].flags = I2C_M_RD; // I2C Read
- msg[1].len = 1;
- msg[1].buf = val8;
-
- err = i2c_transfer(priv->i2c_client->adapter, msg, 2);
-
- if ( err < 0)
- {
- dev_err(s_data->dev, "[%s ] : I2C Read register failed at 0x%04X\n", __func__, reg_addr);
- }
- else
- {
- err = 0;
- }
-
- usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
-
- return err;
-}
-
-#endif // ifdef USE_I2C_READ_REG
-
-// -------------------------------------------------------------------
-
-static int tier4_isx021_write_reg(struct camera_common_data *s_data, u16 addr, u8 val8 ) // with i2c_tranfer
-{
- int err = 0;
- u16 reg_addr = 0;
- struct i2c_msg msg[2];
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
- u8 w_buf[5];
-
-#ifdef USE_FIRMWARE
- reg_addr = priv->firmware_buffer[addr];
-#else
- reg_addr = addr;
-#endif
-
- w_buf[0] = ( reg_addr >> 8 ) & 0xFF;
- w_buf[1] = reg_addr & 0xFF;
- w_buf[2] = val8 & 0xFF;
-
- msg[0].addr = priv->i2c_client->addr;
- msg[0].flags = 0; // I2C Write
- msg[0].len = 3;
- msg[0].buf = w_buf;
-
- err = i2c_transfer(priv->i2c_client->adapter, msg, 1);
-
- if (err < 0 )
- {
- dev_err(s_data->dev, "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n", __func__, addr, reg_addr, val8);
- }
- else
- {
- err = 0;
- }
-
- usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
-
- return err;
-}
-
-#endif // ifndef USE_I2C_TRANSFER
-
-
-// ------------------------------------------------------------------
-
-static int tier4_isx021_write_mode_set_f_lock_register(struct camera_common_data *s_data, u8 val8 )
-{
- int err = 0;
-
- usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR, 0x06); // ACK Response mode
-
- usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_77_ADDR, val8);
-
- usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR, 0x02); // NAK Response mode
-
- return 0;
-}
-// ------------------------------------------------------------------
-
-#ifdef USE_REMAP_REGISTER
-
-static int tier4_isx021_write_remap_register(struct camera_common_data *s_data, u8 val8 )
-{
- int err = 0;
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR, 0x06); // ACK Response mode
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_73_ADDR, val8);
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR, 0x02); // NAK Response mode
-
- return 0;
-}
-#endif
-
-// -------------------------------------------------------------------
-
-static int tier4_isx021_transit_to_streaming_state(struct tegracam_device *tc_dev)
-{
- struct camera_common_data *s_data = tc_dev->s_data;
- struct device *dev = tc_dev->dev;
- int err = 0;
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR, 0x80); // transit to Streaming state
- if ( err ) {
- dev_err(dev, "[%s] : Write to MODE_SET_F register failed.\n", __func__);
- }
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
- //msleep(120);
-
- return err;
-}
-
-// -------------------------------------------------------------------
-
-static int tier4_isx021_transit_to_startup_state(struct tegracam_device *tc_dev)
-{
- struct camera_common_data *s_data = tc_dev->s_data;
- struct device *dev = tc_dev->dev;
- int err = 0;
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR, 0x00); // transit to Startup state
-
- if ( err ) {
- dev_err(dev, "[%s] : Write to MODE_SET_F register failed.\n", __func__);
- }
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
- //msleep(120);
-
- return err;
-}
-
-// ------------------------------------------------------------------
-
-#ifdef USE_CHECK_MODE_SEL
-
-static int tier4_isx021_check_mode_sel(struct camera_common_data *s_data, u8 *val8)
-{
- //int mode_size = sizeof(remap_mode);
- u8 rval8 = 0;
- int err = 0;
- struct device *dev = s_data->dev;
-
- err = tier4_isx021_read_reg(s_data, TIER4_ISX021_REG_89_ADDR, &rval8 );
- if (err)
- {
- dev_err(dev, "[%s] : Write to MODE_SEL register failed.\n", __func__);
- return err;
- }
-
- *val8 = rval8;
-
- return err;
-}
-#endif // ifdef USE_CHECK_MODE_SEL
-
-// ------------------------------------------------------------------
-
-static int tier4_isx021_set_fsync_trigger_mode(struct tier4_isx021 *priv)
-{
- int err = 0;
- struct camera_common_data *s_data = priv->s_data;
- struct device *dev = s_data->dev;
- int des_num = 0;
-
- dev_info(dev, "[%s] : hardware_model=%d.\n", __func__, priv->g_ctx.hardware_model );
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- priv->inhibit_fpga_access = false;
-
- err = tier4_fpga_check_access(priv->fpga_dev);
- if (err)
- {
- priv->inhibit_fpga_access = true;
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE)
- {
- dev_info(dev, "[%s] : Disabling FPGA fsync.\n", __func__);
-
- err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Disabling FPGA generate fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else
- {
- err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA generate fsync failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
-
- if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_AUTO)
- {
- // Auto Trigger Mode
- dev_info(dev, "[%s] : Enabling FPGA Fsync Auto Trigger mode.\n", __func__);
-
- err = tier4_fpga_set_fsync_auto_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
-
- des_num = priv->g_ctx.reg_mux;
- err = tier4_fpga_set_fsync_signal_frequency(priv->fpga_dev, des_num, priv->trigger_mode);
- if (err)
- {
- dev_err(dev, "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- }
- else if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_MANUAL)
- {
- // Manual Trigger Mode
- dev_info(dev, "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n", __func__);
-
- err = tier4_fpga_set_fsync_manual_trigger(priv->fpga_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n", __func__);
- if ( !priv->inhibit_fpga_access )
- {
- return err;
- }
- }
- } // if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_MANUAL)
- } // else (tier4_fpga_get_fsync_mode() != FPGA_FSYNC_MODE_DISABLE)
- } // if (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER)
-
- err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_setup_gpi failed.\n", __func__);
- return err;
- }
-
- err = tier4_max9295_setup_gpo(priv->ser_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9295_setup_gpo failed.\n", __func__);
- return err;
- }
-
- // transit to Startup state
-
- err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
- if (err)
- {
- dev_err(dev, "[%s] : Time out Error occurred in tier4_isx021_write_register_mode_set_f_lock.\n", __func__);
- return err;
- }
-
- usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR, 0x00);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_isx021_write_reg failed.\n", __func__);
- return err;
- }
-
- usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
-
- // set FSYNC_FUNCSEL to 0 for FSYNC triggered mode
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_92_ADDR, 0x00);
-
- if (err)
- {
- goto error_exit;
- }
-
- usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
-
- // set FSYNC_DRVABTY to 3 for FSYNC triggered mode
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_93_ADDR, 0xFF);
-
- if (err)
- {
- goto error_exit;
- }
-
- usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
-
- // set SG_MODE_CTL to 0 for transition to FSYNC mode
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_63_ADDR, 0x02); // set FSYNC mode
-
- if (err)
- {
- goto error_exit;
- }
-
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
-
- // set SG_MODE_APL to 0 for transition to FSYNC mode
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_78_ADDR, 0x02);
-
- if (err)
- {
- goto error_exit;
- }
-
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
-
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
-
-error_exit:
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_set_response_mode(struct tier4_isx021 *priv)
-{
- int err = 0;
- struct tegracam_device *tc_dev = priv->tc_dev;
- struct camera_common_data *s_data = priv->s_data;
- struct device *dev = s_data->dev;
- u8 r_val;
-
- err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
- if (err)
- {
- dev_err(dev, "[%s] : Write to MODE_SET_F_LOCK register caused Time out.\n", __func__);
- return err;
- }
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = tier4_isx021_transit_to_startup_state(tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Transition to Startup state failed.\n", __func__);
- goto error_exit;
- }
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS)); // For ES3 and MP
-
- err = tier4_isx021_read_reg(s_data, TIER4_ISX021_REG_66_ADDR, &r_val);
-
- if (r_val == 0x04)
- {
- priv->es_number = 2;
- }
- else
- {
- priv->es_number = 3;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_66_ADDR, 0x06);
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS)); // For ES3 and MP
-
-error_exit:
-
- return err;
-}
-
-static int tier4_isx021_gmsl_serdes_setup(struct tier4_isx021 *priv)
-{
- int err = 0;
- int des_err = 0;
- struct device *dev;
-
- if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client)
- {
- return -EINVAL;
- }
-
- dev = &priv->i2c_client->dev;
-
- /* For now no separate power on required for serializer device */
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
- (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_on(priv->dser_dev);
- }
- /* setup serdes addressing and control pipeline */
-
- err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Configuration of GMSL Deserializer link failed.\n", __func__);
- goto error;
- }
-
- err = tier4_max9295_setup_control(priv->ser_dev);
-
- /* proceed even if ser setup failed, to setup deser correctly */
- if (err)
- {
- dev_err(dev, "[%s] : Setup for GMSL Serializer failed.\n", __func__);
- goto error;
- }
-
- des_err = tier4_max9296_setup_control(priv->dser_dev, &priv->i2c_client->dev);
-
- if (des_err)
- {
- dev_err(dev, "[%s] : Setup for GMSL Deserializer failed.\n", __func__);
- err = des_err;
- }
-error:
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static void tier4_isx021_gmsl_serdes_reset(struct tier4_isx021 *priv)
-{
- /* reset serdes addressing and control pipeline */
- tier4_max9295_reset_control(priv->ser_dev);
-
- tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev, false);
-
- if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
- (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- tier4_max9296_power_off(priv->dser_dev);
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_power_on(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_on)
- {
- err = pdata->power_on(pw);
-
- if (err)
- {
- dev_err(dev, "[%s] : Turning on the power failed.\n", __func__);
- }
- else
- {
- pw->state = SWITCH_ON;
- }
- return err;
- }
-
- pw->state = SWITCH_ON;
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_power_off(struct camera_common_data *s_data)
-{
- int err = 0;
- struct camera_common_power_rail *pw = s_data->power;
- struct camera_common_pdata *pdata = s_data->pdata;
- struct device *dev = s_data->dev;
-
- if (pdata && pdata->power_off)
- {
- err = pdata->power_off(pw);
-
- if (!err)
- {
- goto power_off_done;
- }
- else
- {
- dev_err(dev, "[%s] : Turning off the power failed.\n", __func__);
- }
- return err;
- }
-
-power_off_done:
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_power_get(struct tegracam_device *tc_dev)
-{
- struct camera_common_power_rail *pw = tc_dev->s_data->power;
- int err = 0;
-
- pw->state = SWITCH_OFF;
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_power_put(struct tegracam_device *tc_dev)
-{
- if (unlikely(!tc_dev->s_data->power))
- {
- return -EFAULT;
- }
-
- return NO_ERROR;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_set_group_hold(struct tegracam_device *tc_dev, bool val)
-{
- volatile int err = 0;
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_copy_reg_value(struct camera_common_data *s_data, u16 ae_addr, u16 me_addr)
-{
- int err = 0;
- u8 val8 = 0;
-
- err = tier4_isx021_read_reg(s_data, ae_addr, &val8);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C Read Register failed at 0x%x\n", __func__, ae_addr);
- }
-
- err = tier4_isx021_write_reg(s_data, me_addr, val8);
-
- if (err)
- {
- dev_err(s_data->dev, "[%s] : I2C write Register failed at 0x%x =[ 0x%x]\n", __func__, me_addr, val8);
- }
-
- return err;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int tier4_isx021_set_gain(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- s64 gain;
- u8 digital_gain_low_byte;
- u8 digital_gain_high_byte;
-
- struct camera_common_data *s_data = tc_dev->s_data;
- struct device *dev = tc_dev->dev;
-
- if (val > ISX021_MAX_GAIN)
- {
- val = ISX021_MAX_GAIN;
- }
- else if (val < ISX021_MIN_GAIN)
- {
- val = ISX021_MIN_GAIN;
- }
-
- dev_info(dev, "[%s] :Gain is set to %lld\n", __func__, val);
-
- gain = 10 * val;
-
- digital_gain_low_byte = gain & 0xFF;
-
- digital_gain_high_byte = (gain >> 8) & 0xFF;
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_68_ADDR, 0x01);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_69_ADDR, 0x01);
-
- if (err)
- {
- goto fail;
- }
-
- // Shutter 0 value
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_15_ADDR, TIER4_ISX021_REG_23_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_16_ADDR, TIER4_ISX021_REG_24_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_17_ADDR, TIER4_ISX021_REG_25_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_18_ADDR, TIER4_ISX021_REG_26_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- // Shutter 1 value
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_19_ADDR, TIER4_ISX021_REG_27_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_20_ADDR, TIER4_ISX021_REG_28_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_21_ADDR, TIER4_ISX021_REG_29_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_22_ADDR, TIER4_ISX021_REG_30_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- // Set Analog Gain for shutter 0
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_31_ADDR, digital_gain_low_byte);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_32_ADDR, digital_gain_high_byte);
-
- if (err)
- {
- goto fail;
- }
-
- // copy AE Analog gain value to ME analog gain registers for shutter 1 to 3
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_35_ADDR, TIER4_ISX021_REG_37_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_36_ADDR, TIER4_ISX021_REG_38_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_39_ADDR, TIER4_ISX021_REG_41_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_40_ADDR, TIER4_ISX021_REG_42_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_43_ADDR, TIER4_ISX021_REG_45_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_44_ADDR, TIER4_ISX021_REG_46_ADDR);
-
- if (err)
- {
- goto fail;
- }
-
- msleep(100); // For ES3
-
- // Change AE mode
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_67_ADDR, 0x03);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_71_ADDR, digital_gain_low_byte);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_72_ADDR, digital_gain_high_byte);
-
- if (err)
- {
- goto fail;
- }
-
- return NO_ERROR;
-
-fail:
- dev_err(dev, "[%s] : Gain control Error\n", __func__);
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_isx021_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
-{
- struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
-
- /* fixed 10fps */
- priv->frame_length = ISX021_DEFAULT_FRAME_LENGTH;
-
- return NO_ERROR;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_isx021_set_auto_exposure(struct tegracam_device *tc_dev)
-{
- int err = 0;
- struct camera_common_data *s_data = tc_dev->s_data;
-
- // Change to Auto exposure mode
-
- msleep(100); // For ES3
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_67_ADDR, ISX021_AUTO_EXPOSURE_MODE);
-
- // Set min exposure time unit
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_47_ADDR, ISX021_AE_TIME_UNIT_MICRO_SECOND);
- if (err)
- {
- goto fail;
- }
-
- // Set mid exposure time unit
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_48_ADDR, ISX021_AE_TIME_UNIT_MICRO_SECOND);
- if (err)
- {
- goto fail;
- }
-
- // Set max exposure time unit
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_49_ADDR, ISX021_AE_TIME_UNIT_MICRO_SECOND);
- if (err)
- {
- goto fail;
- }
-
- // Set min exposure time
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_50_ADDR, shutter_time_min & 0xFF);
- if (err)
- {
- goto fail;
- }
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_51_ADDR, (shutter_time_min >> 8) & 0xFF);
- if (err)
- {
- goto fail;
- }
-
- // Set mid exposure time
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_54_ADDR, shutter_time_mid & 0xFF);
- if (err)
- {
- goto fail;
- }
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_55_ADDR, (shutter_time_mid >> 8) & 0xFF);
- if (err)
- {
- goto fail;
- }
-
- // Set max exposure time
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_58_ADDR, shutter_time_max & 0xFF);
- if (err)
- {
- goto fail;
- }
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_59_ADDR, (shutter_time_max >> 8) & 0xFF);
- if (err)
- {
- goto fail;
- }
-
-fail:
-
- return err;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int tier4_isx021_set_exposure(struct tegracam_device *tc_dev, s64 val)
-{
- int err = 0;
-
- u8 exp_time_byte0;
- u8 exp_time_byte1;
- u8 exp_time_byte2;
- u8 exp_time_byte3;
- // struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
- struct camera_common_data *s_data = tc_dev->s_data;
-
- // unit for val is micro-second
-
- if (val > ISX021_MAX_EXPOSURE_TIME)
- {
- val = ISX021_MAX_EXPOSURE_TIME;
- }
- else if (val < ISX021_MIN_EXPOSURE_TIME)
- {
- val = ISX021_MIN_EXPOSURE_TIME;
- }
-
- exp_time_byte0 = val & 0xFF;
-
- exp_time_byte1 = (val >> 8) & 0xFF;
-
- exp_time_byte2 = (val >> 16) & 0xFF;
-
- exp_time_byte3 = (val >> 24) & 0xFF;
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_48_ADDR, 0x03);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_49_ADDR, 0x03);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_54_ADDR, exp_time_byte0);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_55_ADDR, exp_time_byte1);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_56_ADDR, exp_time_byte2);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_57_ADDR, exp_time_byte3);
-
- if (err)
- {
- goto fail;
- }
-
- // Shutter2
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_58_ADDR, exp_time_byte0);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_59_ADDR, exp_time_byte1);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_60_ADDR, exp_time_byte2);
-
- if (err)
- {
- goto fail;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_61_ADDR, exp_time_byte3);
-
- if (err)
- {
- goto fail;
- }
-
- return NO_ERROR;
-
-fail:
-
- return err;
-}
-// --------------------------------------------------------------------------------------
-// Enable Distortion Coreection
-// --------------------------------------------------------------------------------------
-static int tier4_isx021_enable_distortion_correction(struct tegracam_device *tc_dev, bool is_enabled)
-{
- int err = 0;
- struct device *dev = tc_dev->dev;
- struct camera_common_data *s_data = tc_dev->s_data;
-
- err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
- if (err)
- {
- dev_err(dev, "[%s] : Write to MODE_SET_F_LOCK register caused Time out.\n", __func__);
- return err;
- }
-
- usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
-
- err = tier4_isx021_transit_to_startup_state(tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Transition to Startup state failed.\n", __func__);
- goto error_exit;
- }
-
- usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
- //msleep(35);
-
- if (is_enabled)
- {
- err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_74_ADDR, 0x01);
-
- usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
- //msleep(35);
-
- err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_75_ADDR, 0x01);
- if (err)
- {
- goto error_exit;
- }
- }
- else
- {
- dev_info(tc_dev->dev, "[%s] : Disabled Distortion Correction.", __func__);
-
- err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_74_ADDR, 0x00);
-
- usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
- //msleep(35);
-
- err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_75_ADDR, 0x00);
- if (err)
- {
- goto error_exit;
- }
- }
-
-error_exit:
-
- if ( err && !is_enabled )
- {
- dev_err(tc_dev->dev, "[%s] : Disabling Distortion Correction failed.", __func__);
- } else if ( err && is_enabled ) {
-
- dev_err(tc_dev->dev, "[%s] : Enabling Distortion Correction failed.", __func__);
- }
-
- return err;
-}
-
-// Please refer to the section for embedded data in ISX021 application note
-
-static int tier4_isx021_setup_embedded_data(struct tegracam_device *tc_dev, int enable_embedded_data )
-{
-
- struct camera_common_data *s_data = tc_dev->s_data;
- struct device *dev = s_data->dev;
- int err = 0;
- int rc = 0;
-
- dev_dbg(dev, "[%s] : Setup for Embedded data.\n", __func__ );
-
- err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
-
- if ( err ) {
- dev_err(dev, "[%s] : Write to MODE_SET_F_LOCK Register failed\n", __func__);
- //goto error_exit;
- }
-
- usleep_range(TIME_100_MS, PLUS_10(TIME_100_MS));
- //msleep(100);
-
- err = tier4_isx021_transit_to_startup_state(tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Transition to Startup state failed.\n", __func__);
- goto error_exit;
- }
-
- usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
- //msleep(120);
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_91_ADDR, 0x00); // DCROP_ON_APL Regsiter
-
- if ( err ) {
- dev_err(dev, "[%s] : Write to ISX021_DCROP_ON Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_82_ADDR, 0x00); // DCROP_ON register : Enable 0 Padding after Embedded data
-
- if ( err ) {
- dev_err(dev, "[%s] : Write to ISX021_DCROP_ON Register failed.\n", __func__);
- goto error_exit;
- }
-
- dev_dbg(dev, "[%s] : enable_embedded_data = %d\n", __func__, enable_embedded_data );
-
- // Enable Front Embedded data
-
- if ( enable_embedded_data & ENABLE_FRONT_EMBEDDED_DATA ) {
-
- dev_info(dev, "[%s] : Enabling Front Embedded.\n", __func__ );
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_80_ADDR, 0x1); // Enable outputting Front Embedded Data
- if ( err ) {
- dev_err(dev, "[%s] : Write to IR_DR_I2I_FEBD_EN Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_83_ADDR, 0x1);
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_FEBD_SEL Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_85_ADDR, 0x1E); // EBD data are encoded as YcbCr(YUV422: applied in this driver )
-
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_FEBD Register failed.\n", __func__);
- goto error_exit;
- }
-
- }
- else
- { // Diable Front Embedded data
-
- dev_info(dev, "[%s] : Disabling Front Embedded.\n", __func__ );
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_80_ADDR, 0x0); // Disable outputting Front Embedded Data
- if ( err ) {
- dev_err(dev, "[%s] : Write to IR_DR_I2I_FEBD_EN Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_83_ADDR, 0x0); // Front Embedded data type is not selected by IR_DR_I2I_FEBD
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_FEBD_SEL Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_85_ADDR, 0x12); // Default data type for Front Embedded
- if ( err ) {
- dev_err(dev, "[%s] : Write to IR_DR_I2I_FEBD Register failed.\n", __func__);
- goto error_exit;
- }
-
- }
-
- if ( enable_embedded_data & ENABLE_REAR_EMBEDDED_DATA )
- { // Enable Rear Embedded data
-
- dev_info(dev, "[%s] : Enabling Rear Embedded.\n", __func__ );
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_81_ADDR, 0x1); // Enable outputting Rear Embedded Data
- if ( err )
- {
- dev_err(dev, "[%s] : Write to IR_DR_I2I_REBD_EN Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_84_ADDR, 0x0D);
- if ( err )
- {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_REBD_SEL Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_86_ADDR, 0x1E);
- if ( err )
- {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_REBD Register failed.\n", __func__);
- goto error_exit;
- }
-
- }
- else
- { // Diabled Rear Embedded data
-
- dev_info(dev, "[%s] : Disabling Rear Embedded.\n", __func__ );
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_81_ADDR, 0x0); // Disable outputting Rear Embedded Data
- if ( err ) {
- dev_err(dev, "[%s] : Write to IR_DR_I2I_REBD_EN Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_84_ADDR, 0x0C);
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_REBD_SEL Register failed.\n", __func__);
- goto error_exit;
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_86_ADDR, 0x35);
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_REBD Register failed.\n", __func__);
- goto error_exit;
- }
- }
-
- err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_87_ADDR, 0x1E);
- if ( err ) {
- dev_err(dev, "[%s] : Write to IFD_DATATYPE_VISIBLE Register failed.\n", __func__);
- goto error_exit;
- }
-
-error_exit:
-
-#if 1
-
- rc = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
- if ( rc )
- {
- dev_err(dev, "[%s] : Write to MODE_SET_F_LOCK Register failed.\n", __func__);
- }
-#endif
-
- return ( err | rc ) ;
-}
-
-// --------------------------------------------------------------------------------------
-// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
-// please add the new memeber and the function at the following table.
-
-static struct tegracam_ctrl_ops tier4_isx021_ctrl_ops = {
- .numctrls = ARRAY_SIZE(ctrl_cid_list),
- .ctrl_cid_list = ctrl_cid_list,
- .set_gain = tier4_isx021_set_gain,
- .set_exposure = tier4_isx021_set_exposure,
- .set_exposure_short = tier4_isx021_set_exposure,
- .set_frame_rate = tier4_isx021_set_frame_rate,
- .set_group_hold = tier4_isx021_set_group_hold,
- // .set_distortion_correction = tier4_isx021_set_distortion_correction,
-};
-
-// --------------------------------------------------------------------------------------
-
-static struct camera_common_pdata *tier4_isx021_parse_dt(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct camera_common_pdata *board_priv_pdata;
- const struct of_device_id *match;
- int err;
-
- if (!node)
- {
- return NULL;
- }
-
- match = of_match_device(tier4_isx021_of_match, dev);
-
- if (!match)
- {
- dev_err(dev, "[%s] : Finding matching dt id failed.\n", __func__);
- return NULL;
- }
-
- board_priv_pdata = devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
-
- err = of_property_read_string(node, "mclk", &board_priv_pdata->mclk_name);
-
- if (err)
- {
- dev_err(dev, "[%s] : mclk not in DT.\n", __func__);
- }
-
- return board_priv_pdata;
-}
-
-/* tier4_isx021_set_mode() can not be needed. But it remains for compatiblity */
-
-static int tier4_isx021_set_mode(struct tegracam_device *tc_dev)
-{
- struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
- struct camera_common_data *s_data = tc_dev->s_data;
- struct device *dev = tc_dev->dev;
-
- int err = 0;
-
- switch( s_data->mode )
- {
- case ISX021_MODE_1920X1280_CROP_30FPS :
- priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
- break;
- case ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA :
- priv->enable_embedded_data = ENABLE_FRONT_EMBEDDED_DATA;
- break;
- case ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA :
- priv->enable_embedded_data = ENABLE_REAR_EMBEDDED_DATA;
- break;
- case ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA :
- priv->enable_embedded_data = ENABLE_BOTH_EMBEDDED_DATA;
- break;
- default :
- priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
- break;
- }
-
- dev_dbg(dev,"[%s]: priv->enable_embedded_data = %d \n",__func__, priv->enable_embedded_data);
-
- return err;
-}
-
-// -------------------------------------------------------------------
-
-static int tier4_isx021_start_one_streaming(struct tegracam_device *tc_dev)
-{
- struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
- int err;
-
- /* enable serdes streaming */
-
- err = tier4_max9295_setup_streaming(priv->ser_dev);
- if (err)
- {
- goto exit;
- }
-
- err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
- if (err)
- {
- dev_err(dev, "[%s] : Setup for Streaming failed.\n", __func__);
- goto exit;
- }
-
- err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_ISX021, true);
- if (err)
- {
- dev_err(dev, "[%s] : Power on Camera Sensor failed.\n", __func__);
- goto exit;
- }
- if (enable_auto_exposure == 1)
- {
- priv->auto_exposure = true;
- dev_info(dev, "[%s] : Parameter[enable_auto_exposure] = 1.\n", __func__);
- }
-
- if (priv->auto_exposure == true)
- {
- err = tier4_isx021_set_auto_exposure(tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling Auto Exposure failed.\n", __func__);
- goto exit;
- }
- else
- {
- dev_info(dev, "[%s] : Enabled Auto Exposure.\n", __func__);
- }
- }
- else
- {
- dev_info(dev, "[%s] : Disabled Auto Exposure.\n", __func__);
- }
- if (err)
- {
- dev_err(dev, "[%s] : Setting digital gain to the default value failed.\n", __func__);
- }
-
- dev_info(dev, "[%s] : trigger_mode = %d.\n", __func__, trigger_mode);
-
- priv->trigger_mode = trigger_mode;
-
- if (priv->trigger_mode == 1)
- {
-// priv->fsync_mode = true;
- dev_info(dev, "[%s] : Enabled Slave(fsync triggered) mode.\n", __func__);
- }
-
-
-// if (priv->fsync_mode == true)
- if (priv->trigger_mode == 1)
- {
- err = tier4_isx021_set_fsync_trigger_mode(priv);
- if (err)
- {
- dev_err(dev, "[%s] : Camera sensor is unable to work with Slave(fsync triggered) mode.\n", __func__);
-// goto exit;
- }
- }
-
- usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
-
- if (enable_distortion_correction == 1)
- {
- priv->distortion_correction = true;
- dev_info(dev, "[%s] : Prameter[enable_distortion_correction] = 1 .\n", __func__);
- }
- err = tier4_isx021_enable_distortion_correction(tc_dev, priv->distortion_correction);
- if (err)
- {
- dev_err(dev, "[%s] : Enabling Distortion Correction failed.\n", __func__);
- goto exit;
- }
-
- err = tier4_isx021_setup_embedded_data(tc_dev, priv->enable_embedded_data );
- if (err)
- {
- dev_err(dev, "[%s] : Setup for Embedded data failed.\n", __func__);
- goto exit;
- }
-
- err = tier4_isx021_transit_to_streaming_state(tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Transition to Streaming state failed.\n", __func__);
- return err;
- }
-
- usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
-
- err = tier4_max9296_start_streaming(priv->dser_dev, dev);
- if (err)
- {
- dev_err(dev, "[%s] : Des(Max9296) failed to start streaming.\n", __func__);
- return err;
- }
-
- dev_info(dev, "[%s] : Camera has started streaming.\n", __func__);
-
- return NO_ERROR;
-
-exit:
-
- dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
-
- return err;
-}
-
-//-------------------------------------------------------------------
-
-static bool tier4_isx021_is_camera_connected_to_port(int nport)
-{
- if (wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_isx021_check_null_tc_dev_for_port(int nport)
-{
- if (wst_priv[nport].p_tc_dev == NULL)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_isx021_is_camera_running_on_port(int nport)
-{
- if (wst_priv[nport].running)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_isx021_is_current_port(struct tier4_isx021 *priv, int nport)
-{
- if (priv->i2c_client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_isx021_set_running_flag(int nport, bool flag)
-{
- wst_priv[nport].running = flag;
-}
-
-// static void tier4_isx021_reset_running_flag(int nport)
-//{
-// wst_priv[nport].running = false;
-//}
-
-static int tier4_isx021_stop_streaming(struct tegracam_device *tc_dev)
-{
- struct device *dev = tc_dev->dev;
- struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
- int i, err = 0;
-
- mutex_lock(&tier4_isx021_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_isx021_is_camera_connected_to_port(i))
- {
- if (tier4_isx021_is_current_port(priv, i) && tier4_isx021_is_camera_running_on_port(i))
- {
- /* disable serdes streaming */
- err = tier4_max9296_stop_streaming(priv->dser_dev, dev);
- if (err)
- {
- return err;
- }
- tier4_isx021_set_running_flag(i, false);
- break;
- }
- }
- }
-
- mutex_unlock(&tier4_isx021_lock);
-
- return NO_ERROR;
-}
-
-/* *************************************************************************** */
-/* 1. In the case where a camera is connected to GMSL A port on a Des. */
-/* */
-/* a > Check if another camera is connected to GMSL B port */
-/* a-1) Connected: */
-/* b > Check if another camera on GMSL B port is running */
-/* b-1) Running: */
-/* c > Check if the camera on GMSL A port is running */
-/* c-1) Running : */
-/* Do nothing and return */
-/* c-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* b-2) Not Running: */
-/* Start the camera on GMSL B port. */
-/* a-2) Not connected : */
-/* b > Check if the camera on GMSL A port is running */
-/* b-1) Running : */
-/* Do nothing and return */
-/* b-2) Not running : */
-/* Start the camera on GMSL A port. */
-/* */
-/* 2. In the case where a camera is connected to GMSL B port on a Des. */
-/* */
-/* a > Check if the camera on GMSL B port is running */
-/* a-1) Running : */
-/* Do nothing and return */
-/* a-2) Not running : */
-/* Start the camera on GMSL B port. */
-/* *************************************************************************** */
-
-static int tier4_isx021_start_streaming(struct tegracam_device *tc_dev)
-{
- int i, err = 0;
- // struct tier4_isx021 *next_client_priv;
- struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
- struct device *dev = tc_dev->dev;
-
- mutex_lock(&tier4_isx021_lock);
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (i & 0x1)
- { // if i = 1,3,5,7 ( GMSL B port of a Des )
-
- if (tier4_isx021_is_camera_connected_to_port(i))
- { // a camera is connected to GMSL B portL
-
- if ((tier4_isx021_is_current_port(priv, i) == true) && (tier4_isx021_is_camera_running_on_port(i) == false))
- {
- // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
- err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Starting one streaming on Camera sensor failed.\n", __func__);
- goto error_exit;
- }
- wst_priv[i].running = true;
- break;
- }
- }
- }
- else
- { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
-
- if ((tier4_isx021_is_camera_connected_to_port(i) == true) && (tier4_isx021_is_current_port(priv, i) == true))
- {
- if (tier4_isx021_is_camera_connected_to_port(i + 1) == false)
- { // if another one camera( GMSL B port)
- // is not connected to Des
- if (tier4_isx021_is_camera_running_on_port(i) == false)
- { // and if the camera is not running.
-
- // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
- err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Starting one streaming for next isx021 client failed.\n", __func__);
- goto error_exit;
- }
- tier4_isx021_set_running_flag(i, true);
- }
- break;
- }
-
- // two cameras are connected to one Des.
-
- if (tier4_isx021_check_null_tc_dev_for_port(i + 1))
- { // check if tc_dev is null
- dev_err(dev, "[%s] : wst_priv[%d].p_tc_dev is NULL.\n", __func__, i + 1);
- err = -EINVAL;
- goto error_exit;
- }
-
- if (tier4_isx021_is_camera_running_on_port(i + 1) == false)
- {
- // err = tier4_isx021_start_one_streaming(wst_priv[i+1].p_tc_dev, wst_priv[i+1].p_priv);
- err = tier4_isx021_start_one_streaming(wst_priv[i + 1].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Start one streaming for the next isx021 client failed.\n", __func__);
- goto error_exit;
- }
- tier4_isx021_set_running_flag(i + 1, true);
- usleep_range(TIME_200_MS, PLUS_10(TIME_200_MS));
- //msleep(200);
- mutex_unlock(&tier4_isx021_lock); // stop streaming on GMSL B port
- tier4_isx021_stop_streaming(wst_priv[i + 1].p_tc_dev);
- mutex_lock(&tier4_isx021_lock);
- }
-
- if (tier4_isx021_is_camera_running_on_port(i) == false)
- {
- // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
- err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev);
- if (err)
- {
- dev_err(dev, "[%s] : Starting one streaming for current isx021 client failed.\n", __func__);
- goto error_exit;
- }
- tier4_isx021_set_running_flag(i, true);
- }
- }
- }
- } // for loop
-
- err = NO_ERROR;
-
-error_exit:
-
- mutex_unlock(&tier4_isx021_lock);
-
- // tier4_isx021_sensor_mutex_unlock();
-
- return err;
-}
-
-static struct camera_common_sensor_ops tier4_isx021_common_ops = {
- .numfrmfmts = ARRAY_SIZE(tier4_isx021_frmfmt),
- .frmfmt_table = tier4_isx021_frmfmt,
- .power_on = tier4_isx021_power_on,
- .power_off = tier4_isx021_power_off,
- .write_reg = tier4_isx021_write_reg,
- .read_reg = tier4_isx021_read_reg,
- .parse_dt = tier4_isx021_parse_dt,
- .power_get = tier4_isx021_power_get,
- .power_put = tier4_isx021_power_put,
- .set_mode = tier4_isx021_set_mode,
- .start_streaming = tier4_isx021_start_streaming,
- .stop_streaming = tier4_isx021_stop_streaming,
-};
-
-static int tier4_isx021_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
- // struct i2c_client *client = v4l2_get_subdevdata(sd);
-
- return NO_ERROR;
-}
-
-static const struct v4l2_subdev_internal_ops tier4_isx021_subdev_internal_ops = {
- .open = tier4_isx021_open,
-};
-
-static const char *of_stdout_options;
-
-static int tier4_isx021_board_setup(struct tier4_isx021 *priv)
-{
- struct tegracam_device *tc_dev = priv->tc_dev;
- struct device *dev = tc_dev->dev;
- struct device_node *node = dev->of_node;
- struct device_node *mode_node;
- struct device_node *ser_node;
- struct device_node *root_node;
- struct i2c_client *ser_i2c = NULL;
- struct device_node *dser_node;
- struct i2c_client *dser_i2c = NULL;
- struct device_node *fpga_node = NULL;
- struct i2c_client *fpga_i2c = NULL;
- struct device_node *gmsl;
- int value = 0xFFFF;
- const char *str_value;
- const char *str_value1[2];
- int i;
- int err;
- const char *str_model;
- char upper_str_model[64];
- char *str_err;
- //char *sub_str_err;
-
- root_node = of_find_node_opts_by_path("/", &of_stdout_options);
- err = of_property_read_string(root_node, "model", &str_model);
- if (err < 0)
- {
- dev_err(dev, "[%s] : model not found\n", __func__);
- goto error;
- }
-
- memset(upper_str_model, 0, 64);
- to_upper_string(upper_str_model, str_model);
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
- priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
-
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_ORIN_DEVKIT;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
- }
-
- str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
- if (str_err)
- {
- priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_ORIN;
- }
-
- dev_info(dev, "[%s] : hardware_model=%d\n", __func__, priv->g_ctx.hardware_model);
- dev_info(dev, "[%s] : model string=%s\n", __func__, str_model);
-
- // priv->g_ctx.debug_i2c_write = debug_i2c_write;
-
- if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN)
- {
- dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_reg);
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_def);
- if (err < 0)
- {
- dev_err(dev, "[%s] : def-addr not found\n", __func__);
- goto error;
- }
-
- err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
- if (err < 0)
- {
- dev_err(dev, "[%s] : reg_mux not found\n", __func__);
- goto error;
- }
-
-#if 0
- err = of_property_read_string(node, "fsync-mode", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "true"))
- {
- priv->fsync_mode = true;
- }
- else
- {
- priv->fsync_mode = false;
- }
-#endif
-
- if (enable_distortion_correction == 0xCAFE)
- {
- // if not set kernel param, read device tree param
- err = of_property_read_string(node, "distortion-correction", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No distortion-correction found. set enable_distortion-correction = true\n", __func__);
- }
- else
- {
-
- if (!strcmp(str_value, "true"))
- {
- enable_distortion_correction = 1;
- }
- else
- {
- enable_distortion_correction = 0;
- }
- }
- }
-
- priv->distortion_correction = enable_distortion_correction != 0 ? true : false;
-
- if (enable_auto_exposure == 0xCAFE)
- {
- // if not set kernel param, read device tree param
- err = of_property_read_string(node, "auto-exposure", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No auto-exposure mode found. set enable_auto_exposure = true\n", __func__);
- }
- else
- {
- if (!strcmp(str_value, "true"))
- {
- enable_auto_exposure = 1;
- }
- else
- {
- enable_auto_exposure = 0;
- }
- }
- }
-
- priv->auto_exposure = enable_auto_exposure != 0 ? true : false;
-
- mode_node = of_get_child_by_name(node, "mode0");
-
- dev_dbg(dev, "[%s] : node->full_name = %s, mode_node->full_name = %s.\n", __func__, node->full_name, mode_node->full_name );
-
-#ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
- /* check embedded_metadata_height */
-
- err = of_property_read_string(mode_node, "embedded_metadata_height", &str_value);
- dev_info(dev, "[%s] : err = %d, embedded_metadata_height = %s\n", __func__, err, str_value );
-
- err = kstrtoul(str_value, 10, &u_value);
- embedded_metadata_height = u_value;
- if (err)
- {
- embedded_metadata_height = 0;
- }
- else
- {
- embedded_metadata_height = u_value;
- }
-
- switch( embedded_metadata_height )
- {
- case 0:
- priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
- break;
- case 1:
- priv->enable_embedded_data = ENABLE_FRONT_EMBEDDED_DATA;
- break;
- case 14:
- priv->enable_embedded_data = ENABLE_REAR_EMBEDDED_DATA;
- break;
- case 15:
- priv->enable_embedded_data = ENABLE_BOTH_EMBEDDED_DATA;
- break;
- default:
- priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
- }
-#else // ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
-
- priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA; // priv->enable_embedded_data is defined by camera sensor image mode
-
-#endif // ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
-
- // for Ser node
-
- ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
-
- if (ser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-ser-device");
- goto error;
- }
-
- err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
- goto error;
- }
-
- ser_i2c = of_find_i2c_device_by_node(ser_node);
-
- of_node_put(ser_node);
-
- if (ser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing Serializer Dev Handle\n", __func__);
- goto error;
- }
-
- if (ser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
- goto error;
- }
-
- priv->ser_dev = &ser_i2c->dev;
-
- // for Dser node
-
- dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
- if (dser_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,gmsl-dser-device");
- goto error;
- }
-
- dser_i2c = of_find_i2c_device_by_node(dser_node);
- of_node_put(dser_node);
- if (dser_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer dev handle\n", __func__);
- goto error;
- }
-
- if (dser_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
- goto error;
- }
-
- priv->dser_dev = &dser_i2c->dev;
-
- if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
- (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN))
- {
- // for FPGA node
-
- fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
-
- if (fpga_node == NULL)
- {
- dev_err(dev, "[%s] : Missing %s handle\n", __func__, "nvidia,fpga-device");
- goto error;
- }
-
- err = of_property_read_u32(fpga_node, "reg", &priv->g_ctx.sdev_fpga_reg);
-
- if (err < 0)
- {
- dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
- goto error;
- }
-
- fpga_i2c = of_find_i2c_device_by_node(fpga_node);
-
- of_node_put(fpga_node);
-
- if (fpga_i2c == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA Dev Handle\n", __func__);
- goto error;
- }
-
- if (fpga_i2c->dev.driver == NULL)
- {
- dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
- goto error;
- }
-
- priv->fpga_dev = &fpga_i2c->dev;
-
- }
-
- /* populate g_ctx from DT */
-
- gmsl = of_get_child_by_name(node, "gmsl-link");
-
- if (gmsl == NULL)
- {
- dev_err(dev, "[%s] : Missing GMSL-Link device node\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "src-csi-port", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A : GMSL_CSI_PORT_B;
-
- err = of_property_read_string(gmsl, "csi-mode", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No csi-mode found\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value, "1x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
- }
- else if (!strcmp(str_value, "2x4"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
- }
- else if (!strcmp(str_value, "4x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
- }
- else if (!strcmp(str_value, "2x2"))
- {
- priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
- }
- else
- {
- dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
- goto error;
- }
-
- err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
- goto error;
- }
-
- priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ? GMSL_SERDES_CSI_LINK_A : GMSL_SERDES_CSI_LINK_B;
-
- err = of_property_read_u32(gmsl, "st-vc", &value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No st-vc info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.st_vc = value;
-
- err = of_property_read_u32(gmsl, "vc-id", &value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No vc-id info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.dst_vc = value;
-
- err = of_property_read_u32(gmsl, "num-lanes", &value);
- if (err < 0)
- {
- dev_err(dev, "[%s] : No num-lanes info\n", __func__);
- goto error;
- }
-
- priv->g_ctx.num_csi_lanes = value;
-
- priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
- if (priv->g_ctx.num_streams <= 0)
- {
- dev_err(dev, "[%s] : No streams found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- for (i = 0; i < priv->g_ctx.num_streams; i++)
- {
- of_property_read_string_index(gmsl, "streams", i, &str_value1[i]);
- if (!str_value1[i])
- {
- dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
- goto error;
- }
-
- if (!strcmp(str_value1[i], "raw12"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_RAW_12;
- }
- else if (!strcmp(str_value1[i], "yuv8"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
- }
- else if (!strcmp(str_value1[i], "embed"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
- }
- else if (!strcmp(str_value1[i], "ued-u1"))
- {
- priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_UED_U1;
- }
- else
- {
- dev_err(dev, "[%s] : Invalid stream data type.\n", __func__);
- goto error;
- }
- }
-
- priv->g_ctx.s_dev = dev;
-
- return NO_ERROR;
-
-error:
- dev_err(dev, "[%s] : Board Setup failed.\n", __func__);
- return err;
-}
-
-static int tier4_isx021_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- int err = 0;
- char *path = FIRMWARE_BIN_FILE;
- void *firmware_buffer;
-
- struct device *dev = &client->dev;
- struct device_node *node = dev->of_node;
- struct tegracam_device *tc_dev;
- struct tier4_isx021 *priv;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 65)
- loff_t size;
-#endif
-
- tier4_isx021_sensor_mutex_lock();
-
-// dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
-
- if (!IS_ENABLED(CONFIG_OF) || !node)
- {
- err = -EINVAL;
- goto errret;
- }
-
- wst_priv[camera_channel_count].p_client = NULL;
- wst_priv[camera_channel_count].p_priv = NULL;
- wst_priv[camera_channel_count].p_tc_dev = NULL;
- wst_priv[camera_channel_count].sensor_ser_shutdown = false;
- wst_priv[camera_channel_count].des_shutdown = false;
- wst_priv[camera_channel_count].running = false;
-
- priv = devm_kzalloc(dev, sizeof(struct tier4_isx021), GFP_KERNEL);
-
- if (!priv)
- {
- dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
- err = -ENOMEM;
- goto errret;
- }
-
- tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
-
- if (!tc_dev)
- {
- err = -ENOMEM;
- goto errret;
- }
-
- priv->i2c_client = tc_dev->client = client;
-
- tc_dev->dev = dev;
-
- strncpy(tc_dev->name, "isx021", sizeof(tc_dev->name));
-
- tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
- tc_dev->sensor_ops = &tier4_isx021_common_ops;
- tc_dev->v4l2sd_internal_ops = &tier4_isx021_subdev_internal_ops;
- tc_dev->tcctrl_ops = &tier4_isx021_ctrl_ops;
-
- firmware_buffer = devm_kzalloc(dev, sizeof(u16) * MAX_NUM_OF_REG, GFP_KERNEL);
-
- if (!firmware_buffer)
- {
- dev_err(dev, "[%s] : Allocating firmware buffer failed.\n", __func__);
- err = -ENOMEM;
- goto errret;
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
- err = kernel_read_file_from_path(path, 0, &firmware_buffer, INT_MAX, NULL,
- READING_POLICY); // err is errono and number of bytes actually read
- if (!err)
- {
- dev_err(dev, "Loading %s failed with error %d\n", path, err);
-#ifdef USE_FIRMWARE
- goto errret;
-#endif
- }
-#else
- err = kernel_read_file_from_path(path, &firmware_buffer, &size, INT_MAX,
- READING_FIRMWARE); // size : number of bytes actually read
- if (err)
- {
- dev_err(dev, "Loading %s failed with error %d\n", path, err);
-#ifdef USE_FIRMWARE
- goto errret;
-#endif
- }
-#endif
-
- priv->firmware_buffer = (u16 *)firmware_buffer;
-
- err = tegracam_device_register(tc_dev);
-
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Driver Registration failed.\n", __func__);
- goto errret;
- }
-
- priv->tc_dev = tc_dev;
- priv->s_data = tc_dev->s_data;
- priv->subdev = &tc_dev->s_data->subdev;
-
- tegracam_set_privdata(tc_dev, (void *)priv);
-
- err = tier4_isx021_board_setup(priv);
-
- if (err)
- {
- dev_err(dev, "[%s] : Board Setup failed.\n", __func__);
- goto err_tegracam_unreg;
- }
-
- priv->trigger_mode = trigger_mode; // trigger_mode per camaera
-
- /* Pair sensor to serializer dev */
- err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed.\n", __func__);
- goto err_tegracam_unreg;
- }
-
- /* Register sensor to deserializer dev */
-
- //dev_info(dev, "[%s]: Before tier4_max9296_sdev_register() : priv->g_ctx.serdes_csi_link = %u\n" , __func__, priv->g_ctx.serdes_csi_link );
-
- //asm("dmb sy");
-
- err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
-
- if (err)
- {
- dev_err(&client->dev, "[%s] : Failed to register GMSL Deserializer.\n", __func__);
- goto err_max9295_unpair;
- }
-
- /*
- * gmsl serdes setup
- *
- * Sensor power on/off should be the right place for serdes
- * setup/reset. But the problem is, the total required delay
- * in serdes setup/reset exceeds the frame wait timeout, looks to
- * be related to multiple channel open and close sequence
- * issue (#BUG 200477330).
- * Once this bug is fixed, these may be moved to power on/off.
- * The delays in serdes is as per guidelines and can't be reduced,
- * so it is placed in probe/remove, though for that, deserializer
- * would be powered on always post boot, until 1.2v is supplied
- * to deserializer from CVB.
- */
-
- err = tier4_isx021_gmsl_serdes_setup(priv);
- if (err)
- {
- dev_err(&client->dev, "[%s] : Setup for GMSL Serdes failed.\n", __func__);
- goto err_max9296_unreg;
- }
-
- err = tegracam_v4l2subdev_register(tc_dev, true);
- if (err)
- {
- dev_err(dev, "[%s] : Tegra Camera Subdev Registration failed.\n", __func__);
- goto err_max9296_unreg;
- }
-
- tier4_isx021_sensor_mutex_unlock();
-
- err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_90_ADDR, 0x06);
-
- err = tier4_isx021_set_response_mode(priv);
- if (err)
- {
- dev_warn(dev, "[%s] : Transition to response mode failed.\n", __func__);
- goto err_tegracam_v4l2_unreg;
- }
-
- dev_info(&client->dev, "Detected ISX021 sensor.\n");
-
- wst_priv[camera_channel_count].p_client = client;
- wst_priv[camera_channel_count].p_priv = priv;
- wst_priv[camera_channel_count].p_tc_dev = tc_dev;
-
- camera_channel_count++;
-
- tier4_isx021_sensor_mutex_unlock();
-
-#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65) ) & 0
-
- dev_info(&client->dev, "Detected ISX021 sensor\n");
- return NO_ERROR;
-#else
- return err;
-#endif
-
-err_tegracam_v4l2_unreg:
- tegracam_v4l2subdev_unregister(priv->tc_dev);
-err_max9296_unreg:
- tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
-err_max9295_unpair:
- tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
-err_tegracam_unreg:
- tegracam_device_unregister(priv->tc_dev);
-errret:
- tier4_isx021_sensor_mutex_unlock();
-
- dev_err(&client->dev, "Detection for ISX021 sensor failed.\n");
-
- return err;
-}
-
-static void tier4_isx021_shutdown(struct i2c_client *client);
-
-static int tier4_isx021_remove(struct i2c_client *client)
-{
- struct camera_common_data *s_data = to_camera_common_data(&client->dev);
- struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
-
- tier4_isx021_shutdown(client);
-
- tier4_isx021_gmsl_serdes_reset(priv);
-
- tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
- tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
-
- tegracam_v4l2subdev_unregister(priv->tc_dev);
-
- tegracam_device_unregister(priv->tc_dev);
-
- return NO_ERROR;
-}
-
-static bool tier4_isx021_is_sensor_ser_shutdown(int nport)
-{
- if (wst_priv[nport].sensor_ser_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static bool tier4_isx021_is_des_shut_down(int nport)
-{
- if (wst_priv[nport].des_shutdown)
- {
- return true;
- }
- return false;
-}
-
-static void tier4_isx021_set_sensor_ser_shutdown(int nport, bool val)
-{
- wst_priv[nport].sensor_ser_shutdown = val;
-}
-
-static void tier4_isx021_set_des_shutdown(int nport, bool val)
-{
- wst_priv[nport].des_shutdown = val;
-}
-
-static bool tier4_isx021_is_current_i2c_client(struct i2c_client *client, int nport)
-{
- if (client == wst_priv[nport].p_client)
- {
- return true;
- }
- return false;
-}
-
-/**
-* The shutdown routine is needed only when you use ROcube and you would like to reboot command on Linux *
-* if not so, you don't need shutdown function *
-*/
-
-static void tier4_isx021_shutdown(struct i2c_client *client)
-{
- struct tier4_isx021 *priv = NULL;
- int i;
-
- tier4_isx021_sensor_mutex_unlock();
-
- mutex_lock(&tier4_isx021_lock);
-
- if (!client)
- {
- goto error_exit;
- }
-
- for (i = 0; i < camera_channel_count; i++)
- {
- if (tier4_isx021_is_current_i2c_client(client, i))
- {
- priv = wst_priv[i].p_priv;
-
- if (i & 0x1)
- { // Even port number( GMSL B port on a Des : i = port_number -1 )
-
- if (tier4_isx021_is_camera_connected_to_port(i - 1))
- { // if a camera connected to another(GMSL A)port on a Des.
-
- if (tier4_isx021_is_sensor_ser_shutdown(i - 1))
- { // ISP and Ser on another(GMSL A) port have been
-
- if (tier4_isx021_is_des_shut_down(i - 1) == false)
- { // if Des on another(GMSL A)port is not shutdown yet
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, true); // Des will be shut down
- }
- else
- { // if Des on the another port is already shut down.
- tier4_isx021_set_sensor_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_isx021_set_des_shutdown(i, false); // Des will not be shutdown
- }
- }
- else
- { // The camera ISP and Ser on another(GMSL A) port
- if (tier4_isx021_is_des_shut_down(i - 1) == false)
- { // if Des is not shut down yet.
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, false); // The Des won't be shut down.
- }
- else
- { // Only Des on another port is already shut down.
- tier4_isx021_set_sensor_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_isx021_set_des_shutdown(i, false); // Des will not be shut down.
- }
- }
- }
- else
- { // a camera is connected to only (GMSL B) port on Des.
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, true); // The Des won't be shut down.
- }
- }
- else
- { // if ( i & 0x1 ) == 0 : Camera is connected to Odd port number. ( GMSL A potr on a Des : i = port_number -1
- // )
-
- if (tier4_isx021_is_camera_connected_to_port(i + 1))
- { // Another camera is connected to
- // another(GMSL B) port on the Des
- if (tier4_isx021_is_sensor_ser_shutdown(i + 1))
- { // if the ISP and Ser on another port
- // are already shut down
- if (tier4_isx021_is_des_shut_down(i + 1) == false)
- { // if Des is not shut down yet.
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- else
- { // Des is already shut down. This is Error case.
- tier4_isx021_set_sensor_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_isx021_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- else
- { // The ISP and Ser on another(GMSL B) port
- // are not shut down yet.
- if (tier4_isx021_is_des_shut_down(i + 1) == false)
- { // if Des on another(GMSL B) port is not shut down yet.
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- else
- { // Only Des on another(GMSL B) port is already shut down.
- // This is Error case.
- tier4_isx021_set_sensor_ser_shutdown(i, false); // ISP and Ser will not be shut down
- tier4_isx021_set_des_shutdown(i, false); // The Des will not be shut down.
- }
- }
- }
- else
- {
- tier4_isx021_set_sensor_ser_shutdown(i, true); // ISP and Ser will be shut down
- tier4_isx021_set_des_shutdown(i, true); // The Des will be shut down.
- }
- } // if ( i & 0x1 )
- // break;
-
- if (tier4_isx021_is_sensor_ser_shutdown(i))
- {
- // Reset camera sensor
- tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_ISX021, false);
- // S/W Reset max9295
- tier4_max9295_reset_control(priv->ser_dev);
- }
-
- if (tier4_isx021_is_des_shut_down(i))
- {
- // S/W Reset max9296
- tier4_max9296_reset_control(priv->dser_dev, &client->dev, true);
- }
-
- if (priv == NULL || i >= camera_channel_count)
- {
- mutex_unlock(&tier4_isx021_lock);
- tier4_isx021_sensor_mutex_unlock();
- return;
- }
- }
- } // for loop
-
-error_exit:
-
- mutex_unlock(&tier4_isx021_lock);
-
- tier4_isx021_sensor_mutex_unlock();
-}
-
-static const struct i2c_device_id tier4_isx021_id[] = { { "tier4_isx021", 0 }, {} };
-
-MODULE_DEVICE_TABLE(i2c, tier4_isx021_id);
-
-static struct i2c_driver tier4_isx021_i2c_driver = {
- .driver = {
- .name = "tier4_isx021",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(tier4_isx021_of_match),
- },
- .probe = tier4_isx021_probe,
- .remove = tier4_isx021_remove,
- .shutdown = tier4_isx021_shutdown,
- .id_table = tier4_isx021_id,
-};
-
-static int __init tier4_isx021_init(void)
-{
- mutex_init(&tier4_sensor_lock__);
- mutex_init(&tier4_isx021_lock);
-
-// printk(KERN_INFO "TIERIV Automotive HDR Camera driver : %s\n", BUILD_STAMP);
-
- return i2c_add_driver(&tier4_isx021_i2c_driver);
-}
-
-static void __exit tier4_isx021_exit(void)
-{
- mutex_destroy(&tier4_sensor_lock__);
- mutex_destroy(&tier4_isx021_lock);
-
- printk(KERN_INFO "[%s]: Exit TIERIV Automotive HDR Camera driver.\n", __func__);
-
- i2c_del_driver(&tier4_isx021_i2c_driver);
-}
-
-module_init(tier4_isx021_init);
-module_exit(tier4_isx021_exit);
-
-MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
-MODULE_AUTHOR("K.Iwasaki");
-MODULE_AUTHOR("Y.Fujii");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-max9295.c b/drivers/src/tier4-max9295.c
deleted file mode 100644
index 0912dee..0000000
--- a/drivers/src/tier4-max9295.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * tier4_max9295.c - tier4_max9295 GMSL Serializer driver
- *
- * Copyright (c) 2022-2023, TIERIV Inc. All rights reserved.
- * Copyright (c) 2020, Leopard Imaging Inc. All rights reserved.
- * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-
-#include "tier4-max9295.h"
-#include "tier4-gmsl-link.h"
-
-#define MAX9295_SHOW_I2C_WRITE_MSG 1
-
-/* register specifics */
-
-#define MAX9295_DEV_ADDR 0x0000
-#define MAX9295_PIPE_EN_ADDR 0x0002
-#define MAX9295_CLK_OUTPUT_ADDR 0x0003
-#define MAX9295_CTRL0_ADDR 0x0010
-
-#define MAX9295_I2C4_ADDR 0x0044
-#define MAX9295_I2C5_ADDR 0x0045
-
-#define MAX9295_CFGV_VIDEO_Y_ADDR 0x0057
-#define MAX9295_CFGV_VIDEO_Z_ADDR 0x005B
-
-#define MAX9295_VIDEO_TX0_ADDR 0x0110
-#define MAX9295_VIDEO_TX1_ADDR 0x0111
-#define MAX9295_VIDEO_TX2_ADDR 0x0112
-#define MAX9295_SRC_CTRL_ADDR 0x02BF
-#define MAX9295_SRC_PWDN_ADDR 0x02BE
-
-#define MAX9295_GPIO_3_CONFIG_MFP3_ADDR 0x02C7
-#define MAX9295_GPIO_3_GPIO_TX_ID_ADDR 0x02C8
-#define MAX9295_GPIO_3_GPIO_RX_ID_ADDR 0x02C9
-#define MAX9295_GPIO_4_ADDR 0x02CA
-#define MAX9295_GPIO_5_ADDR 0x02CD
-
-#define MAX9295_GPIO_8_ADDR 0x02D6
-
-#define MAX9295_CSI_PORT_SEL_ADDR 0x0308
-
-#define MAX9295_START_PIPE_ADDR 0x0311
-#define MAX9295_SEND_Z_PIPE_ADDR 0x0312
-#define MAX9295_PIPE_X_DT_ADDR 0x0314
-#define MAX9295_PIPE_Y_DT_ADDR 0x0316
-#define MAX9295_PIPE_Z_DT_ADDR 0x0318
-#define MAX9295_PIPE_U_DT_ADDR 0x031A
-#define MAX9295_OVERRIDE_Z_PIPE_ADDR 0x031E
-
-#define MAX9295_MIPI_RX0_ADDR 0x0330
-#define MAX9295_MIPI_RX1_ADDR 0x0331
-#define MAX9295_MIPI_RX2_ADDR 0x0332
-#define MAX9295_MIPI_RX3_ADDR 0x0333
-
-#define MAX9295_REF_VTG0_ADDR 0x03F0
-#define MAX9295_SRC_OUT_RCLK_ADDR 0x03F1
-
-#define MAX9295_REG570_ADDR 0x0570
-
-#define MAX9295_STREAM_PIPE_UNUSED 0x22
-#define MAX9295_CSI_MODE_1X4 0x00
-#define MAX9295_CSI_MODE_2X2 0x03
-#define MAX9295_CSI_MODE_2X4 0x06
-
-#define MAX9295_CSI_PORT_B(num_lanes) (((num_lanes) << 4) & 0xF0)
-#define MAX9295_CSI_PORT_A(num_lanes) ((num_lanes)&0x0F)
-
-#define MAX9295_CSI_1X4_MODE_LANE_MAP1 0xE0
-#define MAX9295_CSI_1X4_MODE_LANE_MAP2 0x04
-
-#define MAX9295_CSI_2X4_MODE_LANE_MAP1 0xEE
-#define MAX9295_CSI_2X4_MODE_LANE_MAP2 0xE4
-
-#define MAX9295_CSI_2X2_MODE_LANE_MAP1 MAX9295_CSI_2X4_MODE_LANE_MAP1
-#define MAX9295_CSI_2X2_MODE_LANE_MAP2 MAX9295_CSI_2X4_MODE_LANE_MAP2
-
-#define MAX9295_ST_ID_0 0x0
-#define MAX9295_ST_ID_1 0x1
-#define MAX9295_ST_ID_2 0x2
-#define MAX9295_ST_ID_3 0x3
-
-#define MAX9295_PIPE_X_START_B 0x80
-#define MAX9295_PIPE_Y_START_B 0x40
-#define MAX9295_PIPE_Z_START_B 0x20
-#define MAX9295_PIPE_U_START_B 0x10
-
-#define MAX9295_PIPE_X_START_A 0x1
-#define MAX9295_PIPE_Y_START_A 0x2
-#define MAX9295_PIPE_Z_START_A 0x4
-#define MAX9295_PIPE_U_START_A 0x8
-
-#define MAX9295_START_PORT_A 0x10
-#define MAX9295_START_PORT_B 0x20
-
-#define MAX9295_CSI_LN2 0x1
-#define MAX9295_CSI_LN4 0x3
-
-#define MAX9295_EN_LINE_INFO 0x40
-
-#define MAX9295_VID_TX_EN_X 0x10
-#define MAX9295_VID_TX_EN_Y 0x20
-#define MAX9295_VID_TX_EN_Z 0x40
-#define MAX9295_VID_TX_EN_U 0x80
-
-#define MAX9295_VID_INIT 0x3
-#define MAX9295_SRC_RCLK 0x89
-
-#define MAX9295_RESET_ALL 0x80
-#define MAX9295_RESET_SRC 0x60
-#define MAX9295_PWDN_GPIO 0x90
-
-#define MAX9295_MAX_PIPES 0x4
-
-struct tier4_max9295_client_ctx
-{
- struct tier4_gmsl_link_ctx *g_ctx;
- bool st_done;
-};
-
-struct tier4_max9295
-{
- struct i2c_client *i2c_client;
- struct regmap *regmap;
- struct tier4_max9295_client_ctx g_client;
- struct mutex lock;
- /* primary serializer properties */
- __u32 def_addr;
- __u32 pst2_ref;
-};
-
-#define MAX_CHANNEL_NUM 8
-
-/* count channel,the max MAX_CHANNEL_NUM*/
-static __u32 channel_count_isx021;
-
-static struct tier4_max9295 *prim_priv__[MAX_CHANNEL_NUM];
-
-struct map_ctx
-{
- u8 dt;
- u16 addr;
- u8 val;
- u8 st_id;
-};
-
-#if 0
-
-static int tier4_max9295_read_reg(struct device *dev, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- char str_bus_num[4], str_sl_addr[4];
- int len = 0;
-
- memset(str_bus_num,0,4);
- memset(str_sl_addr,0,4);
-
- err = regmap_read(priv->regmap, addr, ®_val);
-
- *val = reg_val & 0xFF;
-
- dev_info(dev, "[%s ] : Max9295 I2C Read at 0x%04X=[0x%02X].\n", __func__, addr, *val );
-
- if (( err == 0 ) && ( dev != NULL ) ) {
- len = strlen(dev->kobj.name);
- if (dev) {
- strncpy(str_bus_num, &dev->kobj.name[0], 2);
- strncpy(str_sl_addr, &dev->kobj.name[len-2], 2);
- }
- }
- return err;
-}
-#endif
-
-static int tier4_max9295_write_reg(struct device *dev, u16 addr, u8 val)
-{
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- int err = 0;
- // u8 e;
- char str_bus_num[4], str_sl_addr[4];
- int len;
-
- memset(str_bus_num, 0, 4);
- memset(str_sl_addr, 0, 4);
-
- len = strlen(dev->kobj.name);
-
- if ((err == 0) && (dev != NULL))
- {
- strncpy(str_bus_num, &dev->kobj.name[0], 2);
- strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
- }
-
- err = regmap_write(priv->regmap, addr, val);
-
- if (err)
- {
- dev_err(dev, "[%s] : Max9295 I2C write failed Reg at 0x%04X:[0x%02X].\n", __func__, addr, val);
- }
-#if MAX9295_SHOW_I2C_WRITE_MSG
- else
- {
- dev_info(dev, "[%s] : Max9295 I2C write register at 0x%04X:[0x%02X]\n", __func__, addr, val);
- }
-#endif
-
- /* delay before next i2c command as required for SERDES link */
-
- usleep_range(100, 110);
- //msleep(100);
- // tier4_max9295_read_reg(dev, addr, &e);
- usleep_range(100, 110);
- //msleep(100);
-
- return err;
-}
-
-int tier4_max9295_setup_streaming(struct device *dev)
-{
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- int err = 0;
- u32 csi_mode;
- u32 lane_map1;
- u32 lane_map2;
- u32 port;
- u32 rx1_lanes;
- u32 st_pipe;
- u32 pipe_en;
- u32 port_sel = 0;
- struct tier4_gmsl_link_ctx *g_ctx;
- u32 i;
- u32 j;
- u32 st_en;
-
- struct map_ctx map_pipe_dtype[] = {
- { GMSL_CSI_DT_YUV_8, MAX9295_PIPE_Z_DT_ADDR, 0x1E, // For YUV8
- MAX9295_ST_ID_2 },
- { GMSL_CSI_DT_UED_U1, MAX9295_PIPE_X_DT_ADDR, 0x30, // User defined embedded data type
- MAX9295_ST_ID_0 },
- { GMSL_CSI_DT_EMBED, MAX9295_PIPE_Y_DT_ADDR, 0x12, MAX9295_ST_ID_1 },
- };
-
- mutex_lock(&priv->lock);
-
- if (!priv->g_client.g_ctx)
- {
- dev_err(dev, "[%s] : No sdev client found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- if (priv->g_client.st_done)
- {
- dev_dbg(dev, "[%s] : Stream setup is already done\n", __func__);
- goto error;
- }
-
- g_ctx = priv->g_client.g_ctx;
-
- switch (g_ctx->csi_mode)
- {
- case GMSL_CSI_1X4_MODE:
- csi_mode = MAX9295_CSI_MODE_1X4;
- lane_map1 = MAX9295_CSI_1X4_MODE_LANE_MAP1;
- lane_map2 = MAX9295_CSI_1X4_MODE_LANE_MAP2;
- rx1_lanes = MAX9295_CSI_LN4;
- break;
- case GMSL_CSI_2X2_MODE:
- csi_mode = MAX9295_CSI_MODE_2X2;
- lane_map1 = MAX9295_CSI_2X2_MODE_LANE_MAP1;
- lane_map2 = MAX9295_CSI_2X2_MODE_LANE_MAP2;
- rx1_lanes = MAX9295_CSI_LN2;
- break;
- case GMSL_CSI_2X4_MODE:
- csi_mode = MAX9295_CSI_MODE_2X4;
- lane_map1 = MAX9295_CSI_2X4_MODE_LANE_MAP1;
- lane_map2 = MAX9295_CSI_2X4_MODE_LANE_MAP2;
- rx1_lanes = MAX9295_CSI_LN4;
- break;
- default:
- dev_err(dev, "[%s] : Invalid csi mode\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- port = (g_ctx->src_csi_port == GMSL_CSI_PORT_B) ? MAX9295_CSI_PORT_B(rx1_lanes) : MAX9295_CSI_PORT_A(rx1_lanes);
-
- tier4_max9295_write_reg(dev, MAX9295_MIPI_RX0_ADDR, csi_mode);
- tier4_max9295_write_reg(dev, MAX9295_MIPI_RX1_ADDR, port);
- tier4_max9295_write_reg(dev, MAX9295_MIPI_RX2_ADDR, lane_map1);
- tier4_max9295_write_reg(dev, MAX9295_MIPI_RX3_ADDR, lane_map2);
-
- for (i = 0; i < g_ctx->num_streams; i++)
- {
- struct tier4_gmsl_stream *g_stream = &g_ctx->streams[i];
-
- g_stream->st_id_sel = GMSL_ST_ID_UNUSED;
-
- for (j = 0; j < ARRAY_SIZE(map_pipe_dtype); j++)
- {
- if (map_pipe_dtype[j].dt == g_stream->st_data_type)
- {
- /*
- * TODO:
- * 1) Remove link specific overrides, depends
- * on #2.
- * 2) Add support for vc id based stream sel
- * overrides TX_SRC_SEL. would be useful in
- * using same mappings in all ser devs.
- */
- if (g_ctx->serdes_csi_link == GMSL_SERDES_CSI_LINK_B)
- {
- map_pipe_dtype[j].addr += 2;
- map_pipe_dtype[j].st_id += 1;
- }
-
- g_stream->st_id_sel = map_pipe_dtype[j].st_id;
-
- st_en = (map_pipe_dtype[j].addr == MAX9295_PIPE_X_DT_ADDR) ? 0xC0 : 0x40;
-
- tier4_max9295_write_reg(dev, map_pipe_dtype[j].addr, (st_en | map_pipe_dtype[j].val));
- }
- }
- }
-
- for (i = 0; i < g_ctx->num_streams; i++)
- if (g_ctx->streams[i].st_id_sel != GMSL_ST_ID_UNUSED)
- port_sel |= (1 << g_ctx->streams[i].st_id_sel);
-
- if (g_ctx->src_csi_port == GMSL_CSI_PORT_B)
- {
- st_pipe = (MAX9295_PIPE_X_START_B | MAX9295_PIPE_Y_START_B | MAX9295_PIPE_Z_START_B | MAX9295_PIPE_U_START_B);
- port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_B);
- }
- else
- {
- st_pipe = MAX9295_PIPE_X_START_A | MAX9295_PIPE_Y_START_A | MAX9295_PIPE_Z_START_A | MAX9295_PIPE_U_START_A;
- port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_A);
- }
-
- pipe_en = (MAX9295_VID_TX_EN_X | MAX9295_VID_TX_EN_Y | MAX9295_VID_TX_EN_Z | MAX9295_VID_TX_EN_U | MAX9295_VID_INIT);
-
- tier4_max9295_write_reg(dev, MAX9295_START_PIPE_ADDR, st_pipe);
- tier4_max9295_write_reg(dev, MAX9295_CSI_PORT_SEL_ADDR, port_sel);
-
- tier4_max9295_write_reg(dev, MAX9295_PIPE_EN_ADDR, pipe_en);
-
- priv->g_client.st_done = true;
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_setup_streaming);
-
-// ------------------------------------------------------------------
-
-int tier4_max9295_control_sensor_power_seq(struct device *dev, __u32 sensor_id, bool power_on)
-{
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- struct tier4_gmsl_link_ctx *g_ctx;
- int err = 0;
-
- g_ctx = priv->g_client.g_ctx;
-
-#if 1
-
- msleep(200);
-
- if (power_on == true)
- { // power up camera sensor
-
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x00);
-
- msleep(100);
-
- if (sensor_id == SENSOR_ID_ISX021)
- {
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_5_ADDR, 0x04);
- msleep(100);
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR, 0x10);
- msleep(100);
- }
- else if (sensor_id == SENSOR_ID_IMX728)
- {
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR, 0x10);
- msleep(100);
- }
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x10);
- }
- else
- { // power down caemra sensor
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x00);
- msleep(100);
- if (sensor_id == SENSOR_ID_ISX021)
- {
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_5_ADDR, 0x04);
- msleep(100);
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR, 0x00);
- msleep(100);
- }
- else if (sensor_id == SENSOR_ID_IMX728)
- {
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR, 0x00);
- msleep(100);
- }
- }
-
- if (err)
- {
- dev_err(dev, "[%s] : Ppower on/off Camera Sensor or ISP failed.\n", __func__);
- }
-
- msleep(50);
-#endif
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_control_sensor_power_seq);
-
-int tier4_max9295_setup_gpo(struct device *dev)
-{
- int err = 0;
-
- dev_info(dev, "[%s] : Set up max9295 for fsync trigger mode \n", __func__);
-
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_CONFIG_MFP3_ADDR, 0x04);
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_GPIO_TX_ID_ADDR, 0x00);
- err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_GPIO_RX_ID_ADDR, 0x06);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_setup_gpo);
-
-int tier4_max9295_setup_control(struct device *dev)
-{
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- int err = 0;
- struct tier4_gmsl_link_ctx *g_ctx;
- u32 offset1 = 0;
- u32 offset2 = 0;
- u32 i;
-
- u8 i2c_ovrd[] = {
- 0x6B, 0x10, 0x73, 0x11, 0x7B, 0x30, 0x83, 0x30, 0x93, 0x30, 0x9B, 0x30, 0xA3, 0x30, 0xAB, 0x30, 0x8B, 0x30,
- };
-
- u8 addr_offset[] = {
- 0x80, 0x00, 0x00, 0x84, 0x00, 0x01, 0xC0, 0x02, 0x02, 0xC4, 0x02, 0x03,
- };
-
- mutex_lock(&priv->lock);
-
- g_ctx = priv->g_client.g_ctx;
-
- if (prim_priv__[g_ctx->reg_mux] == NULL)
- {
- err = -EINVAL;
- goto error;
- }
- /* update address reassingment */
- tier4_max9295_write_reg(&prim_priv__[g_ctx->reg_mux]->i2c_client->dev, MAX9295_DEV_ADDR, (g_ctx->ser_reg << 1));
-
- msleep(100);
-
- if (g_ctx->serdes_csi_link == GMSL_SERDES_CSI_LINK_A)
- {
- err = tier4_max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x21);
- }
- else
- {
- err = tier4_max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x22);
- }
-
- /* check if serializer device exists */
- if (err)
- {
- dev_err(dev, "[%s]: Ser device not found\n", __func__);
- goto error;
- }
- /* delay to settle link */
- msleep(100);
-
- /* Set RCLKOUT soruce to the reference PLL clock*/
- err = tier4_max9295_write_reg(dev, MAX9295_CLK_OUTPUT_ADDR, 0x03);
-
- /* No need?*/
- usleep_range(10000, 11000);
-
- /* PLL setting & Reset PLL */
- err = tier4_max9295_write_reg(dev, MAX9295_REF_VTG0_ADDR, 0x5A);
- usleep_range(10000, 11000);
-// err = tier4_max9295_write_reg(dev, MAX9295_REG570_ADDR, 0x0C);
-
- for (i = 0; i < ARRAY_SIZE(addr_offset); i += 3)
- {
- if ((g_ctx->ser_reg << 1) == addr_offset[i])
- {
- offset1 = addr_offset[i + 1];
- offset2 = addr_offset[i + 2];
- break;
- }
- }
-
- if (i == ARRAY_SIZE(addr_offset))
- {
- dev_err(dev, "[%s] : Invalid ser slave address\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- for (i = 0; i < ARRAY_SIZE(i2c_ovrd); i += 2)
- {
- /* update address overrides */
- i2c_ovrd[i + 1] += (i < 4) ? offset1 : offset2;
-
- /* i2c passthrough2 must be configured once for all devices */
- if ((i2c_ovrd[i] == 0x8B) && prim_priv__[g_ctx->reg_mux]->pst2_ref)
- continue;
-
- tier4_max9295_write_reg(dev, i2c_ovrd[i], i2c_ovrd[i + 1]);
- }
-
- /* dev addr pass-through2 ref */
-
- prim_priv__[g_ctx->reg_mux]->pst2_ref++;
-
- tier4_max9295_write_reg(dev, MAX9295_I2C4_ADDR, (g_ctx->sdev_reg << 1));
- tier4_max9295_write_reg(dev, MAX9295_I2C5_ADDR, (g_ctx->sdev_def << 1));
-
- tier4_max9295_write_reg(dev, MAX9295_SRC_PWDN_ADDR, MAX9295_PWDN_GPIO);
- tier4_max9295_write_reg(dev, MAX9295_SRC_CTRL_ADDR, MAX9295_RESET_SRC);
- tier4_max9295_write_reg(dev, MAX9295_SRC_OUT_RCLK_ADDR, MAX9295_SRC_RCLK);
-
- /* PLL setting & Enable PLL */
- tier4_max9295_write_reg(dev, MAX9295_REF_VTG0_ADDR, 0x59);
-
-
- g_ctx->serdev_found = true;
-
-error:
-
- mutex_unlock(&priv->lock);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_setup_control);
-
-int tier4_max9295_reset_control(struct device *dev)
-{
- struct tier4_max9295 *priv = dev_get_drvdata(dev);
- int err = 0;
-
- mutex_lock(&priv->lock);
- if (!priv->g_client.g_ctx)
- {
- dev_err(dev, "[%s] : No sdev client found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- prim_priv__[priv->g_client.g_ctx->reg_mux]->pst2_ref--;
-
- priv->g_client.st_done = false;
-
- tier4_max9295_write_reg(dev, MAX9295_DEV_ADDR, (prim_priv__[priv->g_client.g_ctx->reg_mux]->def_addr << 1));
-
- tier4_max9295_write_reg(&prim_priv__[priv->g_client.g_ctx->reg_mux]->i2c_client->dev, MAX9295_CTRL0_ADDR,
- MAX9295_RESET_ALL);
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_reset_control);
-
-int tier4_max9295_sdev_pair(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx)
-{
- struct tier4_max9295 *priv;
- int err = 0;
-
- if (!dev || !g_ctx || !g_ctx->s_dev)
- {
- dev_err(dev, "[%s]: Invalid input params\n", __func__);
- return -EINVAL;
- }
-
- priv = dev_get_drvdata(dev);
- mutex_lock(&priv->lock);
- if (priv->g_client.g_ctx)
- {
- dev_err(dev, "[%s] : Device already paired\n", __func__);
- err = -EINVAL;
- goto error;
- }
- priv->g_client.st_done = false;
-
- priv->g_client.g_ctx = g_ctx;
-
-error:
- mutex_unlock(&priv->lock);
- return 0;
-}
-EXPORT_SYMBOL(tier4_max9295_sdev_pair);
-
-int tier4_max9295_sdev_unpair(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9295 *priv = NULL;
- int err = 0;
-
- if (!dev || !s_dev)
- {
- dev_err(dev, "[%s] : Invalid input params\n", __func__);
- return -EINVAL;
- }
-
- priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->lock);
-
- if (!priv->g_client.g_ctx)
- {
- dev_err(dev, "[%s] : Device is not paired\n", __func__);
- err = -ENOMEM;
- goto error;
- }
-
- if (priv->g_client.g_ctx->s_dev != s_dev)
- {
- dev_err(dev, "[%s] : Invalid device\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- priv->g_client.g_ctx = NULL;
- priv->g_client.st_done = false;
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9295_sdev_unpair);
-
-static struct regmap_config tier4_max9295_regmap_config = {
- .reg_bits = 16,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
-};
-
-static int tier4_max9295_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct tier4_max9295 *priv;
- int err = 0;
- struct device_node *node = client->dev.of_node;
-
- dev_info(&client->dev, "[%s] : probing GMSL Serializer\n", __func__);
-
- priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
- priv->i2c_client = client;
- priv->regmap = devm_regmap_init_i2c(priv->i2c_client, &tier4_max9295_regmap_config);
- if (IS_ERR(priv->regmap))
- {
- dev_err(&client->dev, "[%s] : devm_regmap_init() failed: %ld\n", __func__, PTR_ERR(priv->regmap));
- return -ENODEV;
- }
-
- mutex_init(&priv->lock);
-
- if (of_get_property(node, "is-prim-ser", NULL))
- {
- if (prim_priv__[channel_count_isx021] && channel_count_isx021 >= MAX_CHANNEL_NUM)
- {
- dev_err(&client->dev, "[%s] : prim-ser already exists\n", __func__);
- return -EEXIST;
- }
-
- err = of_property_read_u32(node, "reg", &priv->def_addr);
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] : reg not found\n", __func__);
- return -EINVAL;
- }
-
- if (priv == NULL)
- {
- dev_err(&client->dev, "[%s] : priv is NULL\n", __func__);
- return err;
- }
-
- prim_priv__[channel_count_isx021] = priv;
-
- channel_count_isx021++;
- }
-
- dev_set_drvdata(&client->dev, priv);
-
- /* dev communication gets validated when GMSL link setup is done */
- dev_info(&client->dev, "[%s] : Probing succeeded\n", __func__);
-
- return err;
-}
-
-static int tier4_max9295_remove(struct i2c_client *client)
-{
- struct tier4_max9295 *priv;
-
- if (channel_count_isx021 > 0)
- channel_count_isx021--;
-
- if (client != NULL)
- {
- priv = dev_get_drvdata(&client->dev);
- mutex_destroy(&priv->lock);
- }
-
- return 0;
-}
-
-static const struct i2c_device_id tier4_max9295_id[] = {
- { "tier4_max9295", 0 },
- {},
-};
-
-const struct of_device_id tier4_max9295_of_match[] = {
- {
- .compatible = "nvidia,tier4_max9295",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, tier4_max9295_of_match);
-MODULE_DEVICE_TABLE(i2c, tier4_max9295_id);
-
-static struct i2c_driver tier4_max9295_i2c_driver = {
- .driver = {
- .name = "tier4_max9295",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(tier4_max9295_of_match),
- },
- .probe = tier4_max9295_probe,
- .remove = tier4_max9295_remove,
- .id_table = tier4_max9295_id,
-};
-
-static int __init tier4_max9295_init(void)
-{
- printk(KERN_INFO "MAX9295 Driver for TIER4 C1 camera : %s\n", BUILD_STAMP);
-
- return i2c_add_driver(&tier4_max9295_i2c_driver);
-}
-
-static void __exit tier4_max9295_exit(void)
-{
- i2c_del_driver(&tier4_max9295_i2c_driver);
-}
-
-module_init(tier4_max9295_init);
-module_exit(tier4_max9295_exit);
-
-MODULE_DESCRIPTION("GMSL Serializer driver tier4_max9295");
-MODULE_AUTHOR("Originaly NVIDIA Corporation");
-MODULE_AUTHOR("K.Iwasaki");
-MODULE_AUTHOR("Y.Fujii");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-max9296.c b/drivers/src/tier4-max9296.c
deleted file mode 100644
index 29037e1..0000000
--- a/drivers/src/tier4-max9296.c
+++ /dev/null
@@ -1,1228 +0,0 @@
-/*
- * tier4_max9296.c - tier4_max9296 GMSL Deserializer driver
- *
- * Copyright (c) 2022, TIER IV Inc. All rights reserved.
- * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tier4-max9296.h"
-#include "tier4-gmsl-link.h"
-#include "tier4-hw-model.h"
-
-struct tier4_max9296_source_ctx
-{
- struct tier4_gmsl_link_ctx *g_ctx;
- bool st_enabled;
-};
-
-#define _USE_CHECK_LINK_LOCKED_ 1
-
-#define MAX9296_SHOW_I2C_WRITE_MSG 1
-
-/* register specifics */
-
-#define MAX9296_LINK_ADDR 0x0013
-
-#define MAX9296_REG5_ADDR 0x0005
-#define MAX9296_CTRL0_ADDR 0x0010
-
-#define MAX9296_PIPE_X_ST_SEL_ADDR 0x0050
-
-#define MAX9296_GPIO0_CONFIG_MFP0_ADDR 0x02B0
-#define MAX9296_GPIO0_GPIO_TX_ID_ADDR 0x02B1
-#define MAX9296_GPIO0_GPIO_RX_ID_ADDR 0x02B2
-
-#define MAX9296_PHY1_CLK_ADDR 0x0320
-
-#define MAX9296_DST_CSI_MODE_ADDR 0x0330
-#define MAX9296_PWDN_PHYS_ADDR 0x0332
-#define MAX9296_LANE_MAP1_ADDR 0x0333
-#define MAX9296_LANE_MAP2_ADDR 0x0334
-
-#define MAX9296_LANE_CTRL0_ADDR 0x040A
-#define MAX9296_TX11_PIPE_X_EN_ADDR 0x040B
-#define MAX9296_PIPE_X_SRC_0_MAP_ADDR 0x040D
-#define MAX9296_PIPE_X_DST_0_MAP_ADDR 0x040E
-#define MAX9296_PIPE_X_SRC_1_MAP_ADDR 0x040F
-
-#define MAX9296_PIPE_X_DST_1_MAP_ADDR 0x0410
-#define MAX9296_PIPE_X_SRC_2_MAP_ADDR 0x0411
-#define MAX9296_PIPE_X_DST_2_MAP_ADDR 0x0412
-
-#define MAX9296_TX45_PIPE_X_DST_CTRL_ADDR 0x042D
-
-#define MAX9296_LANE_CTRL1_ADDR 0x044A
-#define MAX9296_LANE_CTRL2_ADDR 0x048A
-#define MAX9296_LANE_CTRL3_ADDR 0x04CA
-
-/* data defines */
-
-#define MAX9296_CSI_MODE_4X2 0x1
-#define MAX9296_CSI_MODE_2X4 0x4
-#define MAX9296_LANE_MAP1_4X2 0x44
-#define MAX9296_LANE_MAP2_4X2 0x44
-#define MAX9296_LANE_MAP1_2X4 0x4E
-#define MAX9296_LANE_MAP2_2X4 0xE4
-
-#define MAX9296_LANE_CTRL_MAP(num_lanes) (((num_lanes) << 6) & 0xF0)
-
-#define MAX9296_ALLPHYS_NOSTDBY 0xF0
-#define MAX9296_ST_ID_SEL_INVALID 0xF
-
-//#define MAX9296_PHY1_CLK 0x32
-#define MAX9296_PHY1_CLK_3100MHZ 0x3F
-#define MAX9296_PHY1_CLK_3000MHZ 0x3E
-#define MAX9296_PHY1_CLK_2900MHZ 0x3D
-#define MAX9296_PHY1_CLK_2800MHZ 0x3C
-#define MAX9296_PHY1_CLK_2700MHZ 0x3B
-#define MAX9296_PHY1_CLK_2600MHZ 0x3A
-#define MAX9296_PHY1_CLK_2500MHZ 0x39
-#define MAX9296_PHY1_CLK_2400MHZ 0x38
-#define MAX9296_PHY1_CLK_2300MHZ 0x37
-#define MAX9296_PHY1_CLK_2200MHZ 0x36
-#define MAX9296_PHY1_CLK_2100MHZ 0x35
-#define MAX9296_PHY1_CLK_2000MHZ 0x34
-#define MAX9296_PHY1_CLK_1900MHZ 0x33
-#define MAX9296_PHY1_CLK_1800MHZ 0x32
-#define MAX9296_PHY1_CLK_1700MHZ 0x31
-#define MAX9296_PHY1_CLK_1600MHZ 0x30
-#define MAX9296_PHY1_CLK_1500MHZ 0x2F
-#define MAX9296_PHY1_CLK_1400MHZ 0x2E
-#define MAX9296_PHY1_CLK_1300MHZ 0x2D
-#define MAX9296_PHY1_CLK_1200MHZ 0x2C
-#define MAX9296_PHY1_CLK_1100MHZ 0x2B
-#define MAX9296_PHY1_CLK_1000MHZ 0x2A
-#define MAX9296_PHY1_CLK_900MHZ 0x29
-#define MAX9296_PHY1_CLK_800MHZ 0x28
-#define MAX9296_PHY1_CLK_700MHZ 0x27
-
-#define MAX9296_PHY1_CLK MAX9296_PHY1_CLK_1500MHZ
-
-#define MAX9296_RESET_ALL 0x80
-
-/* Dual GMSL MAX9296A/B */
-
-#define MAX9296_MAX_SOURCES 2
-
-#define MAX9296_MAX_PIPES 4
-
-#define MAX9296_PIPE_X 0
-#define MAX9296_PIPE_Y 1
-#define MAX9296_PIPE_Z 2
-#define MAX9296_PIPE_U 3
-#define MAX9296_PIPE_INVALID 0xF
-
-#define MAX9296_CSI_CTRL_0 0
-#define MAX9296_CSI_CTRL_1 1
-#define MAX9296_CSI_CTRL_2 2
-#define MAX9296_CSI_CTRL_3 3
-
-#define MAX9296_INVAL_ST_ID 0xFF
-
-/* Use reset value as per spec, confirm with vendor */
-
-#define MAX9296_RESET_ST_ID 0x00
-
-struct pipe_ctx
-{
- u32 id;
- u32 dt_type;
- u32 dst_csi_ctrl;
- u32 st_count;
- u32 st_id_sel;
-};
-
-struct tier4_max9296
-{
- struct i2c_client *i2c_client;
- struct regmap *regmap;
- u32 num_src;
- u32 max_src;
- u32 num_src_found;
- u32 src_link;
- bool splitter_enabled;
-
- struct tier4_max9296_source_ctx sources[MAX9296_MAX_SOURCES];
-
- struct mutex lock;
- u32 sdev_ref;
- bool lane_setup;
- bool link_setup;
- struct pipe_ctx pipe[MAX9296_MAX_PIPES];
- u8 csi_mode;
- u8 lane_mp1;
- u8 lane_mp2;
- int reset_gpio;
- int pw_ref;
- struct regulator *vdd_cam_1v2;
-};
-
-static int tier4_max9296_read_reg(struct device *dev, u16 addr, u8 *val)
-{
- int err = 0;
- u32 reg_val = 0;
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- char str_bus_num[4], str_sl_addr[4];
- int len;
-
- memset(str_bus_num, 0, 4);
- memset(str_sl_addr, 0, 4);
-
- err = regmap_read(priv->regmap, addr, ®_val);
- *val = reg_val & 0xFF;
-
- if ((err == 0) && (dev != NULL))
- {
- len = strlen(dev->kobj.name);
-
- if (dev)
- {
- strncpy(str_bus_num, &dev->kobj.name[0], 2);
- strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
- }
- dev_info(dev, "tier4_max9296_read_reg %s 0x%s 0x%x\n", str_bus_num, str_sl_addr, addr);
- }
-
- return err;
-}
-
-static int tier4_max9296_write_reg(struct device *dev, u16 addr, u8 val)
-{
- struct tier4_max9296 *priv;
- int err;
- char str_bus_num[4], str_sl_addr[4];
- int len;
-
- priv = dev_get_drvdata(dev);
-
- memset(str_bus_num, 0, 4);
- memset(str_sl_addr, 0, 4);
-
- len = strlen(dev->kobj.name);
-
- if (dev)
- {
- strncpy(str_bus_num, &dev->kobj.name[0], 2);
- strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
- }
-
- err = regmap_write(priv->regmap, addr, val);
-
- if (err)
- {
- dev_err(dev, "[%s] : Max9296 I2C write failed Reg at 0x%04X:[0x%02X]\n", __func__, addr, val);
- return err;
- }
-#if MAX9296_SHOW_I2C_WRITE_MSG
- else
- {
- dev_info(dev, "[%s] : Max9296 I2C write register at 0x%04X:[0x%02X]\n", __func__, addr, val);
- }
-#endif
- /* delay before next i2c command as required for SERDES link */
-
- usleep_range(100, 110);
-
- return err;
-}
-
-static int tier4_max9296_get_sdev_idx(struct device *dev, struct device *s_dev, int *idx)
-{
- int i;
- int err = 0;
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->lock);
-
- for (i = 0; i < priv->max_src; i++)
- {
- if (priv->sources[i].g_ctx->s_dev == s_dev)
- {
- break;
- }
- }
- if (i == priv->max_src)
- {
- dev_err(dev, "[%s] : No sdev found\n", __func__);
- err = -EINVAL;
- goto ret;
- }
-
- if (idx)
- {
- *idx = i;
- }
-
-ret:
- mutex_unlock(&priv->lock);
- return err;
-}
-
-static void tier4_max9296_pipes_reset(struct tier4_max9296 *priv)
-{
- /*
- * This is default pipes combination. add more mappings
- * for other combinations and requirements.
- */
- struct pipe_ctx pipe_defaults[] = { { MAX9296_PIPE_X, GMSL_CSI_DT_YUV_8, // For YUV8
- MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID },
- { MAX9296_PIPE_Y, GMSL_CSI_DT_YUV_8, // For YUV8
- MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID },
- { MAX9296_PIPE_Z, GMSL_CSI_DT_EMBED, MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID },
- { MAX9296_PIPE_U, GMSL_CSI_DT_EMBED, MAX9296_CSI_CTRL_1, 0,
- MAX9296_INVAL_ST_ID } };
-
- /*
- * Add DT props for num-streams and stream sequence, and based on that
- * set the appropriate pipes defaults.
- * For now default it supports "2 RAW12 and 2 EMBED" 1:1 mappings.
- */
- memcpy(priv->pipe, pipe_defaults, sizeof(pipe_defaults));
-}
-
-static void tier4_max9296_reset_ctx(struct tier4_max9296 *priv)
-{
- int i;
-
- priv->link_setup = false;
- priv->lane_setup = false;
- priv->num_src_found = 0;
- priv->src_link = 0;
- priv->splitter_enabled = false;
-
- tier4_max9296_pipes_reset(priv);
-
- for (i = 0; i < priv->num_src; i++)
- {
- priv->sources[i].st_enabled = false;
- }
-}
-
-int tier4_max9296_power_on(struct device *dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- int i, err = 0;
-
- mutex_lock(&priv->lock);
-
- if (priv->pw_ref == 0)
- {
- usleep_range(1, 2);
-
- for (i = 0; i < priv->max_src; i++)
- {
- if (priv->sources[i].g_ctx)
- {
- break;
- }
- }
-// if (priv->reset_gpio)
- if (gpio_is_valid(priv->reset_gpio))
- {
- gpio_direction_output(priv->reset_gpio, 0);
- }
-
- usleep_range(50, 80);
-
- if (priv->vdd_cam_1v2)
- {
- err = regulator_enable(priv->vdd_cam_1v2);
- if (unlikely(err))
- goto ret;
- }
- usleep_range(50, 80);
-
- /*exit reset mode: XCLR */
-// if (priv->reset_gpio)
- if (gpio_is_valid(priv->reset_gpio))
- {
-
- // gpio_set_value(priv->reset_gpio, 0);
- gpio_direction_output(priv->reset_gpio, 0);
-
- usleep_range(50, 80);
- usleep_range(1000000,1100000);
- // gpio_set_value(priv->reset_gpio, 1);
-
- gpio_direction_output(priv->reset_gpio, 1);
-
- usleep_range(50, 80);
- }
-
- /* delay to settle reset */
- // msleep(1000);
- }
-
- priv->pw_ref++;
-
-ret:
-
- mutex_unlock(&priv->lock);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_power_on);
-
-void tier4_max9296_power_off(struct device *dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->lock);
- priv->pw_ref--;
-
- if (priv->pw_ref == 0)
- {
- /* enter reset mode: XCLR */
- usleep_range(1, 2);
- if (priv->reset_gpio)
- // gpio_set_value(priv->reset_gpio, 0);
- gpio_direction_output(priv->reset_gpio, 0);
-
- if (priv->vdd_cam_1v2)
- regulator_disable(priv->vdd_cam_1v2);
- }
-
- mutex_unlock(&priv->lock);
-}
-EXPORT_SYMBOL(tier4_max9296_power_off);
-
-static int tier4_max9296_write_link(struct device *dev, u32 link)
-{
- int err = 0;
-
- if (link == GMSL_SERDES_CSI_LINK_A)
- {
- err = tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x01);
- err |= tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x21);
- }
- else if (link == GMSL_SERDES_CSI_LINK_B)
- {
- err = tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x02);
- err |= tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x22);
- }
- else
- {
- dev_err(dev, "[%s] : Invalid GMSL link\n", __func__);
- return -EINVAL;
- }
-
- /* delay to settle link */
- msleep(100);
-
- return 0;
-}
-
-int tier4_max9296_setup_link(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- int err = 0;
- int i;
-
- err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx failed.\n", __func__);
- return err;
- }
-
- // max9296_debug_i2c_write = priv->sources[i].g_ctx->debug_i2c_write;
-
- mutex_lock(&priv->lock);
-
- if (!priv->splitter_enabled)
- {
- err = tier4_max9296_write_link(dev, priv->sources[i].g_ctx->serdes_csi_link);
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_write_link failed.\n", __func__);
- goto ret;
- }
- priv->link_setup = true;
- }
-
-ret:
- mutex_unlock(&priv->lock);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_setup_link);
-
-static int tier4_max9296_link_locked(struct device *dev)
-{
- u8 val;
-
- usleep_range(100, 110);
- tier4_max9296_read_reg(dev, MAX9296_LINK_ADDR, &val);
-
- if (0 == (val & 0x08))
- {
- return -EINVAL;
- }
- return 0;
-}
-
-int tier4_max9296_setup_gpi(struct device *dev, int fsync_mfp)
-{
- int err = 0;
- u16 gpio_mfp_base;
-
- dev_info(dev, "[%s] : MFP%d is used for fsync\n", __func__, fsync_mfp);
-
- gpio_mfp_base = (MAX9296_GPIO0_CONFIG_MFP0_ADDR + 3 * fsync_mfp) & 0xFFFF;
-
- err += tier4_max9296_write_reg(dev, gpio_mfp_base, 0x03);
- err += tier4_max9296_write_reg(dev, gpio_mfp_base + 1, 0x06);
- err += tier4_max9296_write_reg(dev, gpio_mfp_base + 2, 0x00);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_setup_gpi);
-
-int tier4_max9296_setup_control(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- int err = 0;
- int i;
-
- err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx() failed.\n", __func__);
- return err;
- }
-
- mutex_lock(&priv->lock);
-
- if (!priv->link_setup)
- {
- dev_err(dev, "[%s] : Invalid state\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- if (priv->sources[i].g_ctx->serdev_found)
- {
- priv->num_src_found++;
- priv->src_link = priv->sources[i].g_ctx->serdes_csi_link;
- }
-
- /* Enable splitter mode */
- if ((priv->max_src > 1U) && (priv->num_src_found > 0U) && (priv->splitter_enabled == false))
- {
- tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x03);
- tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x23);
-
- priv->splitter_enabled = true;
-
- /* delay to settle link */
- msleep(500);
- }
-
-#if _USE_CHECK_LINK_LOCKED_
- // Check GMSL link
- err = tier4_max9296_link_locked(dev);
- if (err)
- {
- // GMSL2 link not locked
- dev_info(dev, "[%s]: max9296 link is not locked.\n", __func__);
- err = tier4_max9296_write_link(dev, priv->src_link);
- if (err)
- {
- dev_err(dev, "[%s]: tier4_max9296_write_link() failed.\n", __func__);
- goto error;
- }
- }
-#endif
-
- if (!priv->splitter_enabled)
- {
- tier4_max9296_write_reg(dev, MAX9296_PWDN_PHYS_ADDR, MAX9296_ALLPHYS_NOSTDBY);
- priv->splitter_enabled = true;
- }
- priv->link_setup = true;
-
- priv->sdev_ref++;
-
- /* Reset splitter mode if all devices are not found */
- if ((priv->sdev_ref == priv->max_src) && (priv->splitter_enabled == true) && (priv->num_src_found > 0U) &&
- (priv->num_src_found < priv->max_src))
- {
- err = tier4_max9296_write_link(dev, priv->src_link);
- if (err)
- goto error;
-
- priv->splitter_enabled = false;
- }
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_setup_control);
-
-int tier4_max9296_reset_control(struct device *dev, struct device *s_dev, bool force_reset)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- int err = 0;
-
- mutex_lock(&priv->lock);
- if (!priv->sdev_ref && force_reset == false)
- {
- dev_info(dev, "[%s] : dev is already in reset state\n", __func__);
- goto ret;
- }
-
- priv->sdev_ref--;
- if (priv->sdev_ref == 0 || force_reset == true)
- {
- tier4_max9296_reset_ctx(priv);
- tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, MAX9296_RESET_ALL);
-
- /* delay to settle reset */
- msleep(100);
- }
-
-ret:
- mutex_unlock(&priv->lock);
-
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_reset_control);
-
-int tier4_max9296_sdev_register(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx)
-{
- struct tier4_max9296 *priv = NULL;
- int i;
- int err = 0;
-
- if (!dev || !g_ctx || !g_ctx->s_dev)
- {
- dev_err(dev, "[%s] : Invalid input params\n", __func__);
- return -EINVAL;
- }
-
- priv = dev_get_drvdata(dev);
-
- mutex_lock(&priv->lock);
-
- if ((g_ctx->hardware_model == HW_MODEL_NVIDIA_ORIN_DEVKIT ) ||
- (g_ctx->hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN ))
- {
- for ( i = 0 ; i < MAX9296_MAX_SOURCES ; i++ )
- {
- if ( priv->sources[i].g_ctx != NULL )
- {
- priv->sources[i].g_ctx->serdes_csi_link = 0;
- }
- }
- }
-
- if (priv->num_src > priv->max_src)
- {
- dev_err(dev, "[%s] : MAX9296 inputs size exhausted\n", __func__);
- err = -ENOMEM;
- goto error;
- }
-
- /* Check csi mode compatibility */
- if (!((priv->csi_mode == MAX9296_CSI_MODE_2X4) ?
- ((g_ctx->csi_mode == GMSL_CSI_1X4_MODE) || (g_ctx->csi_mode == GMSL_CSI_2X4_MODE)) :
- ((g_ctx->csi_mode == GMSL_CSI_2X2_MODE) || (g_ctx->csi_mode == GMSL_CSI_4X2_MODE))))
- {
- dev_err(dev, "[%s] : CSI mode not supported\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
- asm("dsb sy");
-
- for (i = 0; i < priv->num_src; i++)
- {
-// dev_info(dev, "[%s]: g_ctx->serdes_csi_link = %u priv->sources[%d].g_ctx->serdes_csi_link = %u\n"
-// , __func__, g_ctx->serdes_csi_link, i, priv->sources[i].g_ctx->serdes_csi_link );
-
-// usleep_range(1000,1100);
-
- if (g_ctx->serdes_csi_link == priv->sources[i].g_ctx->serdes_csi_link)
- {
-// WARN_ON(1);
- dev_info(dev, "[%s]: g_ctx->serdes_csi_link = %u\n" , __func__, g_ctx->serdes_csi_link );
- dev_err(dev, "[%s] : Serdes CSI link is in use\n", __func__);
- err = -EINVAL;
- goto error;
- }
- /*
- * All sdevs should have same num-csi-lanes regardless of
- * dst csi port selected.
- * Later if there is any usecase which requires each port
- * to be configured with different num-csi-lanes, then this
- * check should be performed per port.
- */
-
- if (g_ctx->num_csi_lanes != priv->sources[i].g_ctx->num_csi_lanes)
- {
- dev_err(dev, "[%s] : CSI num lanes mismatch. %d, %d i=%d\n", __func__, g_ctx->num_csi_lanes,
- priv->sources[i].g_ctx->num_csi_lanes, i);
- err = -EINVAL;
- goto error;
- }
- }
-
- priv->sources[priv->num_src].g_ctx = g_ctx;
- priv->sources[priv->num_src].st_enabled = false;
-
- priv->num_src++;
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_sdev_register);
-
-int tier4_max9296_sdev_unregister(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = NULL;
- int err = 0;
- int i = 0;
-
- if (!dev || !s_dev)
- {
- dev_err(dev, "[%s] : Invalid input params\n", __func__);
- return -EINVAL;
- }
-
- priv = dev_get_drvdata(dev);
- mutex_lock(&priv->lock);
-
- if (priv->num_src == 0)
- {
- dev_err(dev, "[%s] : No source found\n", __func__);
- err = -ENODATA;
- goto error;
- }
-
- for (i = 0; i < priv->num_src; i++)
- {
- if (s_dev == priv->sources[i].g_ctx->s_dev)
- {
- priv->sources[i].g_ctx = NULL;
- priv->num_src--;
- break;
- }
- }
-
- if (i == priv->num_src)
- {
- dev_err(dev, "[%s] : Requested device not found\n", __func__);
- err = -EINVAL;
- goto error;
- }
-
-error:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_sdev_unregister);
-
-static int tier4_max9296_get_available_pipe(struct device *dev, u32 st_data_type, u32 dst_csi_port)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- int i;
-
- for (i = 0; i < MAX9296_MAX_PIPES; i++)
- {
- /*
- * TODO: Enable a pipe for multi stream configuration having
- * similar stream data type. For now use st_count as a flag
- * for 1 to 1 mapping in pipe and stream data type, same can
- * be extended as count for many to 1 mapping. Would also need
- * few more checks such as input stream id select, dst port etc.
- */
- if ((priv->pipe[i].dt_type == st_data_type) &&
- ((dst_csi_port == GMSL_CSI_PORT_A) ?
- (priv->pipe[i].dst_csi_ctrl == MAX9296_CSI_CTRL_0) || (priv->pipe[i].dst_csi_ctrl == MAX9296_CSI_CTRL_1) :
- (priv->pipe[i].dst_csi_ctrl == MAX9296_CSI_CTRL_2) ||
- (priv->pipe[i].dst_csi_ctrl == MAX9296_CSI_CTRL_3)) &&
- (!priv->pipe[i].st_count))
- break;
- }
-
- if (i == MAX9296_MAX_PIPES)
- {
- dev_err(dev, "[%s] : All pipes are busy\n", __func__);
- return -ENOMEM;
- }
-
- return i;
-}
-
-struct reg_pair
-{
- u16 addr;
- u8 val;
-};
-
-static int tier4_max9296_setup_pipeline(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- struct tier4_gmsl_stream *g_stream;
- struct reg_pair *map_list;
- u32 arr_sz = 0;
- int pipe_id = 0;
- u32 i = 0;
- u32 j = 0;
- u32 vc_idx = 0;
-
- for (i = 0; i < g_ctx->num_streams; i++)
- {
- /* Base data type mapping: pipeX/RAW12/CSICNTR1 */
- struct reg_pair map_pipe_yuv8[] = {
- // for YUV8
- /* addr, val */
- { MAX9296_TX11_PIPE_X_EN_ADDR, 0x7 }, { MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15 },
-
- { MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x1E }, // for YUV8
- { MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x1E }, // for YUV8
- { MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00 }, { MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00 },
- { MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01 }, { MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01 },
- };
-
- /* Base data type mapping: pipeX/EMBED/CSICNTR1 */
- struct reg_pair map_pipe_embed[] = {
- /* addr, val */
- { MAX9296_TX11_PIPE_X_EN_ADDR, 0x7 }, { MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15 },
- { MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x12 }, { MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x12 },
- { MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00 }, { MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00 },
- { MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01 }, { MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01 },
- };
-
- g_stream = &g_ctx->streams[i];
- g_stream->des_pipe = MAX9296_PIPE_INVALID;
-
- if (g_stream->st_data_type == GMSL_CSI_DT_YUV_8)
- { // for YUV8
- map_list = map_pipe_yuv8; // for YUV8
- arr_sz = ARRAY_SIZE(map_pipe_yuv8); // for YUV8
- }
- else if (g_stream->st_data_type == GMSL_CSI_DT_EMBED)
- {
- map_list = map_pipe_embed;
- arr_sz = ARRAY_SIZE(map_pipe_embed);
- }
- else if (g_stream->st_data_type == GMSL_CSI_DT_UED_U1)
- {
- continue;
- }
- else
- {
- dev_err(dev, "[%s] : Invalid data type\n", __func__);
- return -EINVAL;
- }
-
- pipe_id = tier4_max9296_get_available_pipe(dev, g_stream->st_data_type, g_ctx->dst_csi_port);
- if (pipe_id < 0)
- return pipe_id;
-
- for (j = 0, vc_idx = 3; j < arr_sz; j++, vc_idx += 2)
- {
- /* update pipe configuration */
- map_list[j].addr += (0x40 * pipe_id);
- /* update vc id configuration */
- if (vc_idx < arr_sz)
- {
- map_list[vc_idx].val |= (g_ctx->dst_vc << 6);
- }
- tier4_max9296_write_reg(dev, map_list[j].addr, map_list[j].val);
- }
-
- /* Set stream id select input */
- if (g_stream->st_id_sel == GMSL_ST_ID_UNUSED)
- {
- dev_err(dev, "[%s] : Invalid stream st_id_sel\n", __func__);
- return -EINVAL;
- }
-
- g_stream->des_pipe = MAX9296_PIPE_X_ST_SEL_ADDR + pipe_id;
-
- /* Update pipe internals */
- priv->pipe[pipe_id].st_count++;
- priv->pipe[pipe_id].st_id_sel = g_stream->st_id_sel;
- }
-
- return 0;
-}
-
-int tier4_max9296_start_streaming(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- struct tier4_gmsl_link_ctx *g_ctx;
- struct tier4_gmsl_stream *g_stream;
- int err = 0;
- int i = 0;
-
- err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx failed.\n", __func__);
- return err;
- }
-
- mutex_lock(&priv->lock);
-
- g_ctx = priv->sources[i].g_ctx;
-
- for (i = 0; i < g_ctx->num_streams; i++)
- {
- g_stream = &g_ctx->streams[i];
-
- if (g_stream->des_pipe != MAX9296_PIPE_INVALID)
- {
- tier4_max9296_write_reg(dev, g_stream->des_pipe, g_stream->st_id_sel);
- }
- }
-
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(tier4_max9296_start_streaming);
-
-int tier4_max9296_stop_streaming(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- struct tier4_gmsl_link_ctx *g_ctx;
- struct tier4_gmsl_stream *g_stream;
- int err = 0;
- int i = 0;
-
- err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
- if (err)
- return err;
-
- mutex_lock(&priv->lock);
- g_ctx = priv->sources[i].g_ctx;
-
- for (i = 0; i < g_ctx->num_streams; i++)
- {
- g_stream = &g_ctx->streams[i];
-
- if (g_stream->des_pipe != MAX9296_PIPE_INVALID)
- {
- tier4_max9296_write_reg(dev, g_stream->des_pipe, MAX9296_RESET_ST_ID);
- }
- }
-
- mutex_unlock(&priv->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(tier4_max9296_stop_streaming);
-
-int tier4_max9296_setup_streaming(struct device *dev, struct device *s_dev)
-{
- struct tier4_max9296 *priv = dev_get_drvdata(dev);
- struct tier4_gmsl_link_ctx *g_ctx;
- int err = 0;
- int i = 0;
- u16 lane_ctrl_addr;
-
- err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx() failed.\n", __func__);
- return err;
- }
-
- mutex_lock(&priv->lock);
- if (priv->sources[i].st_enabled)
- goto ret;
-
- g_ctx = priv->sources[i].g_ctx;
-
- err = tier4_max9296_setup_pipeline(dev, g_ctx);
-
- if (err)
- {
- dev_err(dev, "[%s] : tier4_max9296_setup_pipeline() failed.\n", __func__);
- goto ret;
- }
-
- /* Derive CSI lane map register */
- switch (g_ctx->dst_csi_port)
- {
- case GMSL_CSI_PORT_A:
- case GMSL_CSI_PORT_D:
- lane_ctrl_addr = MAX9296_LANE_CTRL1_ADDR;
- break;
- case GMSL_CSI_PORT_B:
- case GMSL_CSI_PORT_E:
- lane_ctrl_addr = MAX9296_LANE_CTRL2_ADDR;
- break;
- case GMSL_CSI_PORT_C:
- lane_ctrl_addr = MAX9296_LANE_CTRL0_ADDR;
- break;
- case GMSL_CSI_PORT_F:
- lane_ctrl_addr = MAX9296_LANE_CTRL3_ADDR;
- break;
- default:
- dev_err(dev, "[%s] : Invalid GMSL CSI port!\n", __func__);
- err = -EINVAL;
- goto ret;
- };
-
- /*
- * rewrite num_lanes to same dst port should not be an issue,
- * as the device compatibility is already
- * checked during sdev registration against the des properties.
- */
-
- tier4_max9296_write_reg(dev, lane_ctrl_addr, MAX9296_LANE_CTRL_MAP(g_ctx->num_csi_lanes - 1));
-
- if (!priv->lane_setup)
- {
- tier4_max9296_write_reg(dev, MAX9296_DST_CSI_MODE_ADDR, priv->csi_mode);
- tier4_max9296_write_reg(dev, MAX9296_LANE_MAP1_ADDR, priv->lane_mp1);
- tier4_max9296_write_reg(dev, MAX9296_LANE_MAP2_ADDR, priv->lane_mp2);
- if (g_ctx->hardware_model == HW_MODEL_NVIDIA_ORIN_DEVKIT)
- {
- tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK_1400MHZ);
- }
- else if (g_ctx->hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)
- {
- tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK_1500MHZ);
- }
- else if (g_ctx->hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER)
- {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
- // RQX-58G L4T 35.4.1
- tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK_1600MHZ);
-#else // RQX-58G L4T 32.x
- tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK_1800MHZ);
-#endif
- }
- else
- {
- tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR, MAX9296_PHY1_CLK_1400MHZ);
- }
-
- priv->lane_setup = true;
- }
-
-#if 0
- tier4_max9296_write_reg(dev, MAX9296_REG5_ADDR, 0xC0); // informed from Maxim
-#endif
- priv->sources[i].st_enabled = true;
-
-ret:
- mutex_unlock(&priv->lock);
- return err;
-}
-EXPORT_SYMBOL(tier4_max9296_setup_streaming);
-
-const struct of_device_id tier4_max9296_of_match[] = {
- {
- .compatible = "nvidia,tier4_max9296",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, tier4_max9296_of_match);
-
-static int tier4_max9296_parse_dt(struct tier4_max9296 *priv, struct i2c_client *client)
-{
- struct device_node *node = client->dev.of_node;
- int err = 0;
- const char *str_value;
- int value;
- const struct of_device_id *match;
-
- if (!node)
- return -EINVAL;
-
- match = of_match_device(tier4_max9296_of_match, &client->dev);
- if (!match)
- {
- dev_err(&client->dev, "[%s] : Failed to match device with dt id\n", __func__);
- return -EFAULT;
- }
-
- err = of_property_read_string(node, "csi-mode", &str_value);
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] : csi-mode property not found\n", __func__);
- return err;
- }
-
- if (!strcmp(str_value, "2x4"))
- {
- priv->csi_mode = MAX9296_CSI_MODE_2X4;
- priv->lane_mp1 = MAX9296_LANE_MAP1_2X4;
- priv->lane_mp2 = MAX9296_LANE_MAP2_2X4;
- }
- else if (!strcmp(str_value, "4x2"))
- {
- priv->csi_mode = MAX9296_CSI_MODE_4X2;
- priv->lane_mp1 = MAX9296_LANE_MAP1_4X2;
- priv->lane_mp2 = MAX9296_LANE_MAP2_4X2;
- }
- else
- {
- dev_err(&client->dev, "[%s] : Invalid csi mode\n", __func__);
- return -EINVAL;
- }
-
- err = of_property_read_u32(node, "max-src", &value);
- if (err < 0)
- {
- dev_err(&client->dev, "[%s] : No max-src info\n", __func__);
- return err;
- }
-
- priv->max_src = value;
-
- priv->reset_gpio = of_get_named_gpio(node, "reset-gpios", 0);
- if (priv->reset_gpio < 0)
- {
- dev_err(&client->dev, "[%s] : reset-gpios not found %d\n", __func__, err);
- return err;
- }
-
- /* digital 1.2v */
- if (of_get_property(node, "vdd_cam_1v2-supply", NULL))
- {
- priv->vdd_cam_1v2 = regulator_get(&client->dev, "vdd_cam_1v2");
- if (IS_ERR(priv->vdd_cam_1v2))
- {
- dev_err(&client->dev, "[%s] : vdd_cam_1v2 regulator get failed\n", __func__);
- err = PTR_ERR(priv->vdd_cam_1v2);
- priv->vdd_cam_1v2 = NULL;
- return err;
- }
- }
- else
- {
- priv->vdd_cam_1v2 = NULL;
- }
-
- return 0;
-}
-
-static struct regmap_config tier4_max9296_regmap_config = {
- .reg_bits = 16,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
-};
-
-static int tier4_max9296_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct tier4_max9296 *priv;
- int err = 0;
-
- dev_info(&client->dev, "[%s]: Probing GMSL deserializer\n", __func__);
-
- priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
- priv->i2c_client = client;
- priv->regmap = devm_regmap_init_i2c(priv->i2c_client, &tier4_max9296_regmap_config);
- if (IS_ERR(priv->regmap))
- {
- dev_err(&client->dev, "[%s] : devm_regmap_init() failed: %ld\n", __func__, PTR_ERR(priv->regmap));
- return -ENODEV;
- }
-
- err = tier4_max9296_parse_dt(priv, client);
- if (err)
- {
- dev_err(&client->dev, "[%s] : Unable to parse dt\n", __func__);
- return -EFAULT;
- }
-
- tier4_max9296_pipes_reset(priv);
-
- if (priv->max_src > MAX9296_MAX_SOURCES)
- {
- dev_err(&client->dev, "[%s] : Max sources more than currently supported\n", __func__);
- return -EINVAL;
- }
-
- mutex_init(&priv->lock);
-
- dev_set_drvdata(&client->dev, priv);
-
- /* dev communication gets validated when GMSL link setup is done */
- dev_info(&client->dev, "[%s] : Probing GMSL Deserializer is done.\n", __func__);
-
- return err;
-}
-
-static int tier4_max9296_remove(struct i2c_client *client)
-{
- struct tier4_max9296 *priv;
-
- if (client != NULL)
- {
- priv = dev_get_drvdata(&client->dev);
- mutex_destroy(&priv->lock);
- }
-
- return 0;
-}
-
-static const struct i2c_device_id tier4_max9296_id[] = {
- { "tier4_max9296", 0 },
- {},
-};
-
-MODULE_DEVICE_TABLE(i2c, tier4_max9296_id);
-
-static struct i2c_driver tier4_max9296_i2c_driver = {
- .driver = {
- .name = "tier4_max9296",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(tier4_max9296_of_match),
- },
- .probe = tier4_max9296_probe,
- .remove = tier4_max9296_remove,
- .id_table = tier4_max9296_id,
-};
-
-static int __init tier4_max9296_init(void)
-{
- printk(KERN_INFO "MAX9296 Driver for TIERIV Camera : %s\n", BUILD_STAMP);
- return i2c_add_driver(&tier4_max9296_i2c_driver);
-}
-
-static void __exit tier4_max9296_exit(void)
-{
- i2c_del_driver(&tier4_max9296_i2c_driver);
-}
-
-module_init(tier4_max9296_init);
-module_exit(tier4_max9296_exit);
-
-MODULE_DESCRIPTION("Dual GMSL Deserializer driver tier4_max9296");
-MODULE_AUTHOR("Originaly NVIDIA Corporation");
-MODULE_AUTHOR("K.Iwasaki");
-MODULE_AUTHOR("Y.Fujii");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/tools/make_overlay_dtb.py b/drivers/tools/make_overlay_dtb.py
deleted file mode 100755
index 9491478..0000000
--- a/drivers/tools/make_overlay_dtb.py
+++ /dev/null
@@ -1,4363 +0,0 @@
-import sys
-
-str_overlay_header = '''
-/dts-v1/;
-/plugin/;
-
-/ {
- overlay-name = "Tier4 ISX021 IMX490 GMSL2 Camera Device Tree Overlay";
- compatible = "nvidia,p2822-0000+p2888-0001";
- jetson-header-name = "Jetson AGX Xavier CSI Connector";
-
-'''
-
-str_fragment0 = '''
-
- fragment@0 {
-
- target-path = \"/i2c@c240000/tca9546@70/i2c@0\";
-
- __overlay__ {
-
- i2c-mux,deselect-on-exit;
- #address-cells = <1>;
- #size-cells = <0>;
-
-'''
-
-str_ser_isp_i2c0 = '''
-
- ser_prim: max9295_prim@62 {
- compatible = "nvidia,tier4_max9295";
- reg = <0x62>;
- is-prim-ser;
- };
- ser_a: max9295_a@42 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x42>;
- nvidia,gmsl-dser-device = <&dser>;
- };
- ser_b: max9295_b@60 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x60>;
- nvidia,gmsl-dser-device = <&dser>;
- };
- isp_prim: gw5300_prim@6d {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6d>;
- is-prim-isp;
- };
- isp_a: gw5300_a@6e {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6e>;
- };
- isp_b: gw5300_b@6f {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6f>;
- };
-'''
-
-str_imx490_b_2c_i2c0 = '''
-
- imx490_b@2c {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- // clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_b>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_b>;
- nvidia,gmsl-dser-device = <&dser>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2c>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <0>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = "\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
-
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out1: endpoint {
- vc-id = <1>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_in1>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_imx490_a_2b_i2c0 = '''
-
- imx490_a@2b {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- // clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_a>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_a>;
- nvidia,gmsl-dser-device = <&dser>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2b>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <0>;
- sensor_model =\"imx490\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
-
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
-
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out0: endpoint {
- vc-id = <0>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_in0>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\"; /* Port at which sensor is connected to its serializer device. */
- dst-csi-port = \"a\"; /* Destination CSI port on the Jetson side, connected at deserializer. */
- serdes-csi-link = \"a\"; /* GMSL link sensor/serializer connected */
- csi-mode = \"1x4\"; /* to sensor CSI mode. */
- st-vc = <0>; /* Sensor source default VC ID: 0 unless overridden by sensor. */
- vc-id = <0>; /* Destination VC ID, assigned to sensor stream by deserializer. */
- num-lanes = <2>; /* Number of CSI lanes used. */
- streams = \"ued-u1\",\"yuv8\"; /* Types of streams sensor is streaming. */
- };
- };
-'''
-
-str_isx021_b_1c_i2c0 = '''
-
- isx021_b@1c {
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,gmsl-ser-device = <&ser_b>;
- nvidia,gmsl-dser-device = <&dser>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1c>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <0>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"1\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\"; /* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out1: endpoint {
- vc-id = <1>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_in1>;
- };
- };
- };
-
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_a_1b_i2c0 = '''
-
- isx021_a@1b {
-
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,gmsl-ser-device = <&ser_a>;
- nvidia,gmsl-dser-device = <&dser>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1b>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <0>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out0: endpoint {
- vc-id = <0>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_in0>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\"; /* Port at which sensor is connected to its serializer device. */
- dst-csi-port = \"a\"; /* Destination CSI port on the Jetson side, connected at deserializer. */
- serdes-csi-link = \"a\"; /* GMSL link sensor/serializer connected */
- csi-mode = \"1x4\"; /* to sensor CSI mode. */
- st-vc = <0>; /* Sensor source default VC ID: 0 unless overridden by sensor. */
- vc-id = <0>; /* Destination VC ID, assigned to sensor stream by deserializer. */
- num-lanes = <2>; /* Number of CSI lanes used. */
- streams = \"ued-u1\",\"yuv8\"; /* Types of streams sensor is streaming. */
- };
- };
-'''
-
-str_fragment1 = '''
-
- fragment@1 {
-
- target-path = \"/i2c@c240000/tca9546@70/i2c@1\";
-
- __overlay__ {
-
- i2c-mux,deselect-on-exit;
- #address-cells = <1>;
- #size-cells = <0>;
-'''
-
-str_ser_isp_i2c1 = '''
-
- ser_prima: max9295_prim@62 {
- compatible = "nvidia,tier4_max9295\";
- reg = <0x62>;
- is-prim-ser;
- };
- ser_c: max9295_a@42 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x42>;
- nvidia,gmsl-dser-device = <&dsera>;
- };
- ser_d: max9295_b@60 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x60>;
- nvidia,gmsl-dser-device = <&dsera>;
- };
-
- isp_prima: gw5300_prim@6d {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6d>;
- is-prim-isp;
- };
- isp_c: gw5300_a@6e {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6e>;
- };
- isp_d: gw5300_b@6f {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6f>;
- };
-'''
-
-str_imx490_d_2c_i2c1 = '''
-
- imx490_d@2c {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- //clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- //clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_d>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_d>;
- nvidia,gmsl-dser-device = <&dsera>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2c>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <1>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out3: endpoint {
- vc-id = <1>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_in3>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_imx490_c_2b_i2c1 = '''
-
- imx490_c@2b {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- //clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_c>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_c>;
- nvidia,gmsl-dser-device = <&dsera>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2b>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <1>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out2: endpoint {
- vc-id = <0>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_in2>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\"; /* Port at which sensor is connected to its serializer device. */
- dst-csi-port = \"a\"; /* Destination CSI port on the Jetson side, connected at deserializer. */
- serdes-csi-link = \"a\"; /* GMSL link sensor/serializer connected */
- csi-mode = \"1x4\"; /* to sensor CSI mode. */
- st-vc = <0>; /* Sensor source default VC ID: 0 unless overridden by sensor. */
- vc-id = <0>; /* Destination VC ID, assigned to sensor stream by deserializer. */
- num-lanes = <2>; /* Number of CSI lanes used. */
- streams = \"ued-u1\",\"yuv8\"; /* Types of streams sensor is streaming. */
- };
- };
-'''
-
-str_isx021_d_1c_i2c1 = '''
-
- isx021_d@1c {
-
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = "extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_d>;
- nvidia,gmsl-dser-device = <&dsera>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1c>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <1>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_c\";
- vc_id = \"1\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out3: endpoint {
- vc-id = <1>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_in3>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_c_1b_i2c1 = '''
-
- isx021_c@1b {
-
- def-addr = <0x1a>;
-
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_c>;
- nvidia,gmsl-dser-device = <&dsera>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1b>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <1>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_c\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out2: endpoint {
- vc-id = <0>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_in2>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\"; /* Port at which sensor is connected to its serializer device. */
- dst-csi-port = \"a\"; /* Destination CSI port on the Jetson side, connected at deserializer. */
- serdes-csi-link = \"a\"; /* GMSL link sensor/serializer connected */
- csi-mode = \"1x4\"; /* to sensor CSI mode. */
- st-vc = <0>; /* Sensor source default VC ID: 0 unless overridden by sensor. */
- vc-id = <0>; /* Destination VC ID, assigned to sensor stream by deserializer. */
- num-lanes = <2>; /* Number of CSI lanes used. */
- streams = \"ued-u1\",\"yuv8\"; /* Types of streams sensor is streaming. */
- };
- };
-'''
-
-str_fragment2 = '''
-
- fragment@2 {
-
- target-path = \"/i2c@c240000/tca9546@70/i2c@2\";
-
- __overlay__ {
-
- i2c-mux,deselect-on-exit;
- #address-cells = <1>;
- #size-cells = <0>;
-'''
-
-str_ser_isp_i2c2 = '''
-
- ser_primb: max9295_prim@62 {
- compatible = "nvidia,tier4_max9295\";
- reg = <0x62>;
- is-prim-ser;
- };
- ser_e: max9295_a@42 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x42>;
- nvidia,gmsl-dser-device = <&dserb>;
- };
- ser_f: max9295_b@60 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x60>;
- nvidia,gmsl-dser-device = <&dserb>;
- };
-
- isp_primb: gw5300_prim@6d {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6d>;
- is-prim-isp;
- };
- isp_e: gw5300_a@6e {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6e>;
- };
- isp_f: gw5300_b@6f {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6f>;
- };
-'''
-
-str_imx490_f_2c_i2c2 = '''
-
- imx490_f@2c {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- //clocks = <&bpmp_clks 36 >, <&bpmp_clks 36 >;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_f>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_f>;
- nvidia,gmsl-dser-device = <&dserb>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2c>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <2>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out5: endpoint {
- vc-id = <1>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_in5>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_imx490_e_2b_i2c2 = '''
-
- imx490_e@2b {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_e>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_e>;
- nvidia,gmsl-dser-device = <&dserb>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2b>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <2>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out4: endpoint {
- vc-id = <0>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_in4>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"a\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <0>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_f_1c_i2c2 = '''
-
- isx021_f@1c {
-
- def-addr = <0x1a>;
-
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = "extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_f>;
- nvidia,gmsl-dser-device = <&dserb>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1c>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <2>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
-
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_e\";
- vc_id = \"1\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out5: endpoint {
- vc-id = <1>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_in5>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_e_1b_i2c2 = '''
-
- isx021_e@1b {
-
- def-addr = <0x1a>;
-
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_e>;
- nvidia,gmsl-dser-device = <&dserb>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1b>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <2>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
-
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_e\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out4: endpoint {
- vc-id = <0>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_in4>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"a\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <0>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_fragment3 = '''
-
- fragment@3 {
- target-path = \"/i2c@c240000/tca9546@70/i2c@3\";
- __overlay__ {
- i2c-mux,deselect-on-exit;
- #address-cells = <1>;
- #size-cells = <0>;
-'''
-
-str_ser_isp_i2c3 = '''
-
- ser_primc: max9295_prim@62 {
- compatible = "nvidia,tier4_max9295\";
- reg = <0x62>;
- is-prim-ser;
- };
- ser_g: max9295_a@42 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x42>;
- nvidia,gmsl-dser-device = <&dserc>;
- };
- ser_h: max9295_b@60 {
- compatible = \"nvidia,tier4_max9295\";
- reg = <0x60>;
- nvidia,gmsl-dser-device = <&dserc>;
- };
- isp_primc: gw5300_prim@6d {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6d>;
- is-prim-isp;
- };
- isp_g: gw5300_a@6e {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6e>;
- };
- isp_h: gw5300_b@6f {
- compatible = \"nvidia,tier4_gw5300\";
- reg = <0x6f>;
- };
-'''
-
-str_imx490_h_2c_i2c3 = '''
-
- imx490_h@2c {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- //clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_h>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_h>;
- nvidia,gmsl-dser-device = <&dserc>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2c>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <3>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out7: endpoint {
- vc-id = <1>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_in7>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_imx490_g_2b_i2c3 = '''
-
- imx490_g@2b {
- compatible = \"nvidia,tier4_imx490\";
- def-addr = <0x1a>;
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks 36>, <&bpmp_clks 36>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
- nvidia,isp-device = <&isp_g>; // for C2 camera
- nvidia,gmsl-ser-device = <&ser_g>;
- nvidia,gmsl-dser-device = <&dserc>;
- nvidia,fpga-device = <&t4_fpga>;
- reg = <0x2b>;
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <3>;
- sensor_model =\"imx490\";
- fsync-mode = \"false\";
- distortion-correction = \"false\";
- auto-exposure = \"true\";
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
- mode0 {/*mode IMX490_MODE_2880X1860_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_a\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
- active_w = \"2880\";
- active_h = \"1860\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"160704000\";
- serdes_pix_clk_hz = \"1200000000\";
- gain_factor = \"5\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"1\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"0\";
- max_framerate = \"40954095\";
- step_framerate = \"1\";
- default_framerate = \"0\";
- exposure_factor = \"1000000\";
- min_exp_time = \"0\"; /* us 1 line */
- max_exp_time = \"40954095\";
- step_exp_time = \"1\";
- default_exp_time = \"0\"; /* us */
- embedded_metadata_height = \"0\";
- };
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- imx490_out6: endpoint {
- vc-id = <0>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_in6>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"a\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <0>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_h_1c_i2c3 = '''
-
- isx021_h@1c {
-
- def-addr = <0x1a>;
-
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_h>;
- nvidia,gmsl-dser-device = <&dserc>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1c>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <3>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
-
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_g\";
- vc_id = \"1\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /*us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out7: endpoint {
- vc-id = <1>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_in7>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"b\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <1>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_isx021_g_1b_i2c3 = '''
-
- isx021_g@1b {
-
- def-addr = <0x1a>;
-
- /* Define any required hw resources needed by driver */
- /* ie. clocks, io pins, power sources */
- // clocks = <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>,
- // <&bpmp_clks TEGRA194_CLK_EXTPERIPH1>;
- clock-names = \"extperiph1\", \"pllp_grtba\";
- mclk = \"extperiph1\";
-
- nvidia,gmsl-ser-device = <&ser_g>;
- nvidia,gmsl-dser-device = <&dserc>;
- nvidia,fpga-device = <&t4_fpga>;
-
- compatible = \"nvidia,tier4_isx021\";
-
- reg = <0x1b>;
-
- /* Physical dimensions of sensor */
- physical_w = \"15.0\";
- physical_h = \"12.5\";
- reg_mux = <3>;
- sensor_model =\"isx021\";
-
- fsync-mode = \"false\";
-
- distortion-correction = \"false\";
-
- auto-exposure = \"true\";
-
- /* Defines number of frames to be dropped by driver internally after applying */
- /* sensor crop settings. Some sensors send corrupt frames after applying */
- /* crop co-ordinates */
- post_crop_frame_drop = \"0\";
-
- /* Convert Gain to unit of dB (decibel) befor passing to kernel driver */
- use_decibel_gain = \"true\";
-
- /* enable CID_SENSOR_MODE_ID for sensor modes selection */
- use_sensor_mode_id = \"true\";
-
- /**
- * A modeX node is required to support v4l2 driver
- * implementation with NVIDIA camera software stack
- *
- * mclk_khz = \"\";
- * Standard MIPI driving clock, typically 24MHz
- *
- * num_lanes = \"\";
- * Number of lane channels sensor is programmed to output
- *
- * tegra_sinterface = \"\";
- * The base tegra serial interface lanes are connected to
- *
- * vc_id = \"\";
- * The virtual channel id of the sensor.
- *
- * discontinuous_clk = \"\";
- * The sensor is programmed to use a discontinuous clock on MIPI lanes
- *
- * dpcm_enable = \"true\";
- * The sensor is programmed to use a DPCM modes
- *
- * cil_settletime = \"\";
- * MIPI lane settle time value.
- * A \"0\" value attempts to autocalibrate based on mclk_khz and pix_clk_hz
- *
- * active_w = \"\";
- * Pixel active region width
- *
- * active_h = \"\";
- * Pixel active region height
- *
- * dynamic_pixel_bit_depth = \"\";
- * sensor dynamic bit depth for sensor mode
- *
- * csi_pixel_bit_depth = \"\";
- * sensor output bit depth for sensor mode
- *
- * mode_type=\"\";
- * Sensor mode type, For eg: yuv, Rgb, bayer, bayer_wdr_pwl
- *
- * pixel_phase=\"\";
- * Pixel phase for sensor mode, For eg: rggb, vyuy, rgb888
- *
- * readout_orientation = \"0\";
- * Based on camera module orientation.
- * Only change readout_orientation if you specifically
- * Program a different readout order for this mode
- *
- * line_length = \"\";
- * Pixel line length (width) for sensor mode.
- * This is used to calibrate features in our camera stack.
- *
- * pix_clk_hz = \"\";
- * Sensor pixel clock used for calculations like exposure and framerate
- *
- *
- *
- *
- * inherent_gain = \"\";
- * Gain obtained inherently from mode (ie. pixel binning)
- *
- * min_gain_val = \"\"; (floor to 6 decimal places)
- * max_gain_val = \"\"; (floor to 6 decimal places)
- * Gain limits for mode
- * if use_decibel_gain = \"true\", please set the gain as decibel
- *
- * min_exp_time = \"\"; (ceil to integer)
- * max_exp_time = \"\"; (ceil to integer)
- * Exposure Time limits for mode (us)
- *
- *
- * min_hdr_ratio = \"\";
- * max_hdr_ratio = \"\";
- * HDR Ratio limits for mode
- *
- * min_framerate = \"\";
- * max_framerate = \"\";
- * Framerate limits for mode (fps)
- *
- * embedded_metadata_height = \"\";
- * Sensor embedded metadata height in units of rows.
- * If sensor does not support embedded metadata value should be 0.
- */
-
- mode0 {/*mode ISX021_MODE_1920X1280_CROP_30FPS*/
- mclk_khz = \"24000\";
- num_lanes = \"2\";
- tegra_sinterface = \"serial_g\";
- vc_id = \"0\";
- discontinuous_clk = \"no\";
- dpcm_enable = \"false\";
- cil_settletime = \"0\";
- dynamic_pixel_bit_depth = \"16\";
- csi_pixel_bit_depth = \"16\";
- mode_type = \"yuv\";
- pixel_phase = \"uyvy\";
-
- active_w = \"1920\";
- active_h = \"1280\";
- readout_orientation = \"0\";
- line_length = \"2250\";
- inherent_gain = \"1\";
- pix_clk_hz = \"94500000\";
- serdes_pix_clk_hz = \"833333333\";
-
- gain_factor = \"10\";
- min_gain_val = \"0\"; /* dB */
- max_gain_val = \"300\"; /* dB */
- step_gain_val = \"3\"; /* 0.3 */
- default_gain = \"0\";
- min_hdr_ratio = \"1\";
- max_hdr_ratio = \"1\";
- framerate_factor = \"1000000\";
- min_framerate = \"30000000\";
- max_framerate = \"30000000\";
- step_framerate = \"1\";
- default_framerate = \"30000000\";
- exposure_factor = \"1000000\";
- min_exp_time = \"24\"; /* us 1 line */
- max_exp_time = \"33333\";
- step_exp_time = \"1\";
- default_exp_time = \"33333\";/* us */
- embedded_metadata_height = \"0\";
- };
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- isx021_out6: endpoint {
- vc-id = <0>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_in6>;
- };
- };
- };
- gmsl-link {
- src-csi-port = \"b\";
- dst-csi-port = \"a\";
- serdes-csi-link = \"a\";
- csi-mode = \"1x4\";
- st-vc = <0>;
- vc-id = <0>;
- num-lanes = <2>;
- streams = \"ued-u1\",\"yuv8\";
- };
- };
-'''
-
-str_fragment_vi_0 = '''
-
- fragment@4 {
- target = <&vi_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@5 {
- target = <&vi_in0>;
- __overlay__ {
- status = \"okay\";
- vc-id = <0>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_out0>;
- };
- };
-'''
-
-str_fragment_vi_1 = '''
-
- fragment@6 {
- target = <&vi_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@7 {
- target = <&vi_in1>;
- __overlay__ {
- status = \"okay\";
- vc-id = <1>;
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&csi_out1>;
- };
- };
-'''
-
-str_fragment_vi_2 = '''
-
- fragment@8 {
- target = <&vi_port2>;
- __overlay__ {
- reg = <2>;
- status = \"okay\";
- };
- };
-
- fragment@9 {
- target = <&vi_in2>;
- __overlay__ {
- status = \"okay\";
- vc-id = <0>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_out2>;
- };
- };
-'''
-
-str_fragment_vi_3 = '''
-
- fragment@10 {
- target = <&vi_port3>;
- __overlay__ {
- reg = <3>;
- status = \"okay\";
- };
- };
-
- fragment@11 {
- target = <&vi_in3>;
- __overlay__ {
- status = \"okay\";
- vc-id = <1>;
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&csi_out3>;
- };
- };
-'''
-
-str_fragment_vi_4 = '''
-
- fragment@12 {
- target = <&vi_port4>;
- __overlay__ {
- reg = <4>;
- status = \"okay\";
- };
- };
-
- fragment@13 {
- target = <&vi_in4>;
- __overlay__ {
- status = \"okay\";
- vc-id = <0>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_out4>;
- };
- };
-'''
-
-str_fragment_vi_5 = '''
-
- fragment@14 {
- target = <&vi_port5>;
- __overlay__ {
- reg = <5>;
- status = \"okay\";
- };
- };
-
- fragment@15 {
- target = <&vi_in5>;
- __overlay__ {
- status = \"okay\";
- vc-id = <1>;
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&csi_out5>;
- };
- };
-'''
-
-str_fragment_vi_6 = '''
-
- fragment@16 {
- target = <&vi_port6>;
- __overlay__ {
- reg = <6>;
- status = \"okay\";
- };
- };
-
- fragment@17 {
- target = <&vi_in6>;
- __overlay__ {
- status = \"okay\";
- vc-id = <0>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_out6>;
- };
- };
-'''
-
-str_fragment_vi_7 = '''
-
- fragment@18 {
- target = <&vi_port7>;
- __overlay__ {
- reg = <7>;
- status = \"okay\";
- };
- };
-
- fragment@19 {
- target = <&vi_in7>;
- __overlay__ {
- status = \"okay\";
- vc-id = <1>;
- port-index = <5>;
- bus-width = <2>;
- remote-endpoint = <&csi_out7>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch0 = '''
-
- /* channel 0 */
- fragment@20 {
- target = <&csi_chan0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@21 {
- target = <&csi_chan0_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@22 {
- target = <&csi_chan0_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@23 {
- target = <&csi_in0>;
- __overlay__ {
- status = \"okay\";
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out0>;
- };
- };
-
- fragment@24 {
- target = <&csi_out0>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in0>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch1 = '''
-
- /* channel 1 */
- fragment@25 {
- target = <&csi_chan1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@26 {
- target = <&csi_chan1_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@27 {
- target = <&csi_chan1_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@28 {
- target = <&csi_in1>;
- __overlay__ {
- status = \"okay\";
- port-index = <0>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out1>;
- };
- };
-
- fragment@29 {
- target = <&csi_out1>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in1>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch2 = '''
-
- /* channel 2 */
- fragment@30 {
- target = <&csi_chan2>;
- __overlay__ {
- reg = <2>;
- status = \"okay\";
- };
- };
-
- fragment@31 {
- target = <&csi_chan2_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@32 {
- target = <&csi_chan2_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@33 {
- target = <&csi_in2>;
- __overlay__ {
- status = \"okay\";
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out2>;
- };
- };
-
- fragment@34 {
- target = <&csi_out2>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in2>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch3 = '''
-
- /* channel 3 */
- fragment@35 {
- target = <&csi_chan3>;
- __overlay__ {
- reg = <3>;
- status = \"okay\";
- };
- };
-
- fragment@36 {
- target = <&csi_chan3_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@37 {
- target = <&csi_chan3_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@38 {
- target = <&csi_in3>;
- __overlay__ {
- status = \"okay\";
- port-index = <2>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out3>;
- };
- };
-
- fragment@39 {
- target = <&csi_out3>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in3>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch4 = '''
-
- /* channel 4 */
- fragment@40 {
- target = <&csi_chan4>;
- __overlay__ {
- reg = <4>;
- status = \"okay\";
- };
- };
-
- fragment@41 {
- target = <&csi_chan4_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@42 {
- target = <&csi_chan4_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@43 {
- target = <&csi_in4>;
- __overlay__ {
- status = \"okay\";
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out4>;
- };
- };
-
- fragment@44 {
- target = <&csi_out4>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in4>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch5 = '''
-
- /* channel 5 */
- fragment@45 {
- target = <&csi_chan5>;
- __overlay__ {
- reg = <5>;
- status = \"okay\";
- };
- };
-
- fragment@46 {
- target = <&csi_chan5_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@47 {
- target = <&csi_chan5_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@48 {
- target = <&csi_in5>;
- __overlay__ {
- status = \"okay\";
- port-index = <4>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out5>;
- };
- };
-
- fragment@49 {
- target = <&csi_out5>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in5>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch6 = '''
-
- /* channel 6 */
- fragment@50 {
- target = <&csi_chan6>;
- __overlay__ {
- reg = <6>;
- status = \"okay\";
- };
- };
-
- fragment@51 {
- target = <&csi_chan6_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@52 {
- target = <&csi_chan6_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@53 {
- target = <&csi_in6>;
- __overlay__ {
- status = \"okay\";
- port-index = <6>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out6>;
- };
- };
-
- fragment@54 {
- target = <&csi_out6>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in6>;
- };
- };
-'''
-
-str_fragment_nvcsi_ch7 = '''
-
- /* channel 7 */
- fragment@55 {
- target = <&csi_chan7>;
- __overlay__ {
- reg = <7>;
- status = \"okay\";
- };
- };
-
- fragment@56 {
- target = <&csi_chan7_port0>;
- __overlay__ {
- reg = <0>;
- status = \"okay\";
- };
- };
-
- fragment@57 {
- target = <&csi_chan7_port1>;
- __overlay__ {
- reg = <1>;
- status = \"okay\";
- };
- };
-
- fragment@58 {
- target = <&csi_in7>;
- __overlay__ {
- status = \"okay\";
- port-index = <6>;
- bus-width = <2>;
- remote-endpoint = <&imx490_out7>;
- };
- };
-
- fragment@59 {
- target = <&csi_out7>;
- __overlay__ {
- status = \"okay\";
- remote-endpoint = <&vi_in7>;
- };
- };
-'''
-
-str_imx490_cameramodule0 = '''
-
- /* camera 0 */
- fragment@60 {
- target = <&camera_module0>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_rear_liimx490\";
- position = \"rear\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 30-002b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@0/imx490_a@2b\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule1 = '''
-
- fragment@61 {
- target = <&camera_module1>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_front_liimx490\";
- position = \"front\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 30-002c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@0/imx490_b@2c\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule2 = '''
-
- fragment@62 {
- target = <&camera_module2>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_topright_liimx490\";
- position = \"topright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 31-002b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@1/imx490_c@2b\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule3 = '''
-
- fragment@63 {
- target = <&camera_module3>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_bottomright_liimx490\";
- position = \"bottomright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 31-002c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@1/imx490_d@2c\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule4 = '''
-
- fragment@64 {
- target = <&camera_module4>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_topleft_liimx490\";
- position = \"topleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 32-002b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@2/imx490_e@2b\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule5 = '''
-
- fragment@65 {
- target = <&camera_module5>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_centerright_liimx490\";
- position = \"centerright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 32-002c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@2/imx490_f@2c\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule6 = '''
-
- fragment@66 {
- target = <&camera_module6>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_centerleft_liimx490\";
- position = \"centerleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 33-002b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@3/imx490_g@2b\";
- };
- };
- };
-'''
-
-str_imx490_cameramodule7 = '''
-
- fragment@67 {
- target = <&camera_module7>;
- __overlay__ {
- status = \"okay\";
- badge = \"imx490_bottomleft_liimx490\";
- position = \"bottomleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"imx490 33-002c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@3/imx490_h@2c\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule0 = '''
-
- /* camera 0 */
- fragment@60 {
- target = <&camera_module0>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_rear_liisx021\";
- position = \"rear\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 30-001b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@0/isx021_a@1b\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule1 = '''
-
- fragment@61 {
- target = <&camera_module1>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_front_liisx021\";
- position = \"front\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 30-001c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@0/isx021_b@1c\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule2 = '''
-
- fragment@62 {
- target = <&camera_module2>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_topright_liisx021\";
- position = \"topright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 31-001b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@1/isx021_c@1b\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule3 = '''
-
- fragment@63 {
- target = <&camera_module3>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_bottomright_liisx021\";
- position = \"bottomright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 31-001c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@1/isx021_d@1c\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule4 = '''
-
- fragment@64 {
- target = <&camera_module4>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_topleft_liisx021\";
- position = \"topleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 32-001b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@2/isx021_e@1b\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule5 = '''
-
- fragment@65 {
- target = <&camera_module5>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_centerright_liisx021\";
- position = \"centerright\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 32-001c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@2/isx021_f@1c\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule6 = '''
-
- fragment@66 {
- target = <&camera_module6>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_centerleft_liisx021\";
- position = \"centerleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 33-001b\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@3/isx021_g@1b\";
- };
- };
- };
-'''
-
-str_isx021_cameramodule7 = '''
-
- fragment@67 {
- target = <&camera_module7>;
- __overlay__ {
- status = \"okay\";
- badge = \"isx021_bottomleft_liisx021\";
- position = \"bottomleft\";
- orientation = \"1\";
- drivernode0 {
- status = \"okay\";
- pcl_id = \"v4l2_sensor\";
- devname = \"isx021 33-001c\";
- proc-device-tree = \"/proc/device-tree/i2c@c240000/tca9546@70/i2c@3/isx021_h@1c\";
- };
- };
- };
-'''
-
-str_dser_fragment = '''
-
- fragment@68 {
- target = <&dser>;
- __overlay__ {
- compatible = \"nvidia,tier4_max9296\";
- };
- };
-
- fragment@69 {
- target = <&dsera>;
- __overlay__ {
- compatible = \"nvidia,tier4_max9296\";
- };
- };
-
- fragment@70 {
- target = <&dserb>;
- __overlay__ {
- compatible = \"nvidia,tier4_max9296\";
- };
- };
-
- fragment@71 {
- target = <&dserc>;
- __overlay__ {
- compatible = \"nvidia,tier4_max9296\";
- };
- };
-
- fragment@72 {
- target-path = \"/host1x/vi@15c10000\";
- __overlay__ {
- num-channels = <8>;
- };
- };
-
- fragment@73{
- target-path = "/i2c@3180000";
- __overlay__ {
- t4_fpga: tier4_fpga@66 {
- compatible = "nvidia,tier4_fpga";
- reg = <0x66>;
- generate-fsync = "false";
- status = "okay";
- };
- };
- };
-'''
-
-str_block_end = '''
- };
- };
-'''
-
-str_overlay_end = '''
-
-};
-'''
-
-def idenify_camera(cmd_arg):
- upper_arg = cmd_arg.upper()
- if upper_arg == 'C1' :
- return 'C1'
- elif upper_arg == 'C2' :
- return 'C2'
- else :
- return 'NC'
-
-def get_type_of_cameras(l_camera):
-
- l_camera_type = [None] * 4
-
- for i in range(0,4):
- k = 2*i
- if l_camera[k] == 'C1' or l_camera[k+1] == 'C1' :
- l_camera_type[i] = 'c1'
- elif l_camera[k] == 'C2' or l_camera[k+1] == 'C2' :
- l_camera_type[i] = 'c2'
- elif l_camera[k] == 'NC' and l_camera[k+1] == 'NC' :
- l_camera_type[i] = 'nc'
-
- return l_camera_type
-
-def build_symlink_c1c2(dev_num, v_num, camera_type):
-
- video_num = v_num + 1
-
- str_subsys = 'SUBSYSTEM==\"video4linux\", ATTR{name}==\"vi-output, '
- str_symlink = 'SYMLINK+= \"gmsl/tier4-isx021-imx490-cam' + str(video_num) + '\"\n'
-
- if camera_type == 'C1' :
-
- driver_name = [ 'tier4_isx021 30-001b\", ', 'tier4_isx021 30-001c\", ', \
- 'tier4_isx021 31-001b\", ', 'tier4_isx021 31-001c\", ', \
- 'tier4_isx021 32-001b\", ', 'tier4_isx021 32-001c\", ', \
- 'tier4_isx021 33-001b\", ', 'tier4_isx021 33-001c\", ' \
- ]
-
- elif camera_type == 'C2' :
-
- driver_name = [ 'tier4_imx490 30-002b\", ', 'tier4_imx490 30-002c\", ', \
- 'tier4_imx490 31-002b\", ', 'tier4_imx490 31-002c\", ', \
- 'tier4_imx490 32-002b\", ', 'tier4_imx490 32-002c\", ', \
- 'tier4_imx490 33-002b\", ', 'tier4_imx490 33-002c\", ' \
- ]
-
- str_symlink_dev = str_subsys + driver_name[v_num] + str_symlink
-
- return str_symlink_dev
-
-def get_des_number( port_num ): # port_num is 0 to 7
-
- even_port = port_num & 0x6
-
- if even_port == 0 :
- rc = 12 # port 1,2
- elif even_port == 2 :
- rc = 34 # port 3,4
- elif even_port == 4 :
- rc = 56 # port 5,6
- elif even_port == 6 :
- rc = 78 # port 7,8
- return rc
-
-def usage():
- print('************************************************************************')
- print('** **')
- print('** This is the tool to generate overlay dts and udev file. **')
- print('** **')
- print('************************************************************************')
- print('** **')
- print('** Usage : **')
- print('** **')
- print('** $> python3 make_overaly_dtb2.py camera1 camera2 ... camera8 **')
- print('** **')
- print('** camera1 : camera connected to port1 **')
- print('** camera2 : camera connected to port2 **')
- print('** camera3 : camera connected to port3 **')
- print('** . **')
- print('** . **')
- print('** camera8 : camera connected to port8 **')
- print('** **')
- print('** The camerN shoud be c1, c2 or nc(not connected) **')
- print('** **')
- print('** Overlay dts will be output to **')
- print('** \"tier4-isx021-imx490-xx-yy-zz-uu-overlay-device-tree.dts\" **')
- print('** **')
- print('** udev file will be generated as **')
- print('** \"99-tier4-isx021-imx490-gmsl.rules\" **')
- print('** **')
- print('************************************************************************')
-
-def check_last_port(num, camera):
-
- if num & 0x1 :
- if camera[num] == 'C1' :
- if camera[num-1] == 'C1' or camera[num-1] == 'NC':
- return 0
- else:
- return -1
- elif camera[num] == 'C2' :
- if camera[num-1] == 'C2' or camera[num-1] == 'NC':
- return 0
- else:
- return -1
- elif camera[num] == 'NC' :
- if camera[num-1] == 'C2' or camera[num-1] == 'NC' or camera[num-1] == 'C1':
- return 0
- else:
- return -1
- else:
- return 0
-
-def identify_camera(cmd_arg):
- upper_arg = cmd_arg.upper()
- if upper_arg == 'C1' :
- return 'C1'
- elif upper_arg == 'C2' :
- return 'C2'
- else :
- return 'NC'
-
-# ---- main ----------
-
-args = sys.argv
-
-#print( 'argv = ' + str(args) )
-
-#print( 'arg len = ' + str(len(args)))
-
-total_num_args = len(args)
-
-found_camera = 0
-
-camera = [ 'NC', 'NC', 'NC', 'NC',\
- 'NC', 'NC', 'NC', 'NC' ]
-
-temp_cam = [None]*8
-
-if total_num_args != 9 :
-
- print(' ***** Error! : ' + args[0] + ' needs 8 arguments. *****\n')
- usage()
- sys.exit()
-
-with open( '99-tier4-isx021-imx490-gmsl.rules', 'w', encoding='utf-8') as udev_file:
- for i in range(8):
- temp_cam[i] = identify_camera(args[i+1])
- if temp_cam[i] == 'NC' :
- camera[i] = 'C1'
- else :
- camera[i] = temp_cam[i]
- err = check_last_port(i, camera)
- if err == -1 :
- if camera[i] == 'C1' :
- print(' ***** Error! : port[' + str(i-1) + '] should be C1 or NC. *****\n')
- elif camera[i] == 'C2' :
- print(' ***** Error! : port[' + str(i-1) + '] should be C2 or NC. *****\n')
- usage()
- sys.exit()
- else:
- if camera[i] == 'C1' or camera[i] == 'C2' :
- str_line_in_udev = build_symlink_c1c2( i, found_camera, camera[i] )
- udev_file.write(str_line_in_udev)
- found_camera += 1
-
- if i == 0 :
-
- if camera[i] == 'C1' :
- str_camera1 = str_isx021_a_1b_i2c0
- str_fragment_vi0 = str_fragment_vi_0
- str_fragment_nvcsi0 = str_fragment_nvcsi_ch0.replace('imx490_out0', 'isx021_out0')
- str_cameramodule0 = str_isx021_cameramodule0
- elif camera[i] == 'C2' :
- str_camera1 = str_imx490_a_2b_i2c0
- str_fragment_vi0 = str_fragment_vi_0
- str_fragment_nvcsi0 = str_fragment_nvcsi_ch0
- str_cameramodule0 = str_imx490_cameramodule0
- else:
- str_camera1 = ''
- str_fragment_vi0 = ''
- str_fragment_nvcsi0 = ''
- str_cameramodule0 = ''
-
- elif i == 1 :
-
- if camera[i] == 'C1' :
- str_camera2 = str_isx021_b_1c_i2c0
- str_fragment_vi1 = str_fragment_vi_1
- str_fragment_nvcsi1 = str_fragment_nvcsi_ch1.replace('imx490_out1', 'isx021_out1')
- str_cameramodule1 = str_isx021_cameramodule1
- elif camera[i] == 'C2' :
- str_camera2 = str_imx490_b_2c_i2c0
- str_fragment_vi1 = str_fragment_vi_1
- str_fragment_nvcsi1 = str_fragment_nvcsi_ch1
- str_cameramodule1 = str_imx490_cameramodule1
- else:
- str_camera2 = ''
- str_fragment_vi1 = ''
- str_fragment_nvcsi1 = ''
- str_cameramodule1 = ''
-
- elif i == 2 :
-
- if camera[i] == 'C1' :
- str_camera3 = str_isx021_c_1b_i2c1
- str_fragment_vi2 = str_fragment_vi_2
- str_fragment_nvcsi2 = str_fragment_nvcsi_ch2.replace('imx490_out2', 'isx021_out2')
- str_cameramodule2 = str_isx021_cameramodule2
- elif camera[i] == 'C2' :
- str_camera3 = str_imx490_c_2b_i2c1
- str_fragment_vi2 = str_fragment_vi_2
- str_fragment_nvcsi2 = str_fragment_nvcsi_ch2
- str_cameramodule2 = str_imx490_cameramodule2
- else:
- str_camera3 = ''
- str_fragment_vi2 = ''
- str_fragment_nvcsi2 = ''
- str_cameramodule2 = ''
-
-
- elif i == 3 :
-
- if camera[i] == 'C1' :
- str_camera4 = str_isx021_d_1c_i2c1
- str_fragment_vi3 = str_fragment_vi_3
- str_fragment_nvcsi3 = str_fragment_nvcsi_ch3.replace('imx490_out3', 'isx021_out3')
- str_cameramodule3 = str_isx021_cameramodule3
- elif camera[i] == 'C2' :
- str_camera4 = str_imx490_d_2c_i2c1
- str_fragment_vi3 = str_fragment_vi_3
- str_fragment_nvcsi3 = str_fragment_nvcsi_ch3
- str_cameramodule3 = str_imx490_cameramodule3
- else:
- str_camera4 = ''
- str_fragment_vi3 = ''
- str_fragment_nvcsi3 = ''
- str_cameramodule3 = ''
-
- elif i == 4 :
-
- if camera[i] == 'C1' :
- str_camera5 = str_isx021_e_1b_i2c2
- str_fragment_vi4 = str_fragment_vi_4
- str_fragment_nvcsi4 = str_fragment_nvcsi_ch4.replace('imx490_out4', 'isx021_out4')
- str_cameramodule4 = str_isx021_cameramodule4
- elif camera[i] == 'C2' :
- str_camera5 = str_imx490_e_2b_i2c2
- str_fragment_vi4 = str_fragment_vi_4
- str_fragment_nvcsi4 = str_fragment_nvcsi_ch4
- str_cameramodule4 = str_imx490_cameramodule4
- else:
- str_camera5 = ''
- str_fragment_vi4 = ''
- str_fragment_nvcsi4 = ''
- str_cameramodule4 = ''
-
- elif i == 5 :
-
- if camera[i] == 'C1' :
- str_camera6 = str_isx021_f_1c_i2c2
- str_fragment_vi5 = str_fragment_vi_5
- str_fragment_nvcsi5 = str_fragment_nvcsi_ch5.replace('imx490_out5', 'isx021_out5')
- str_cameramodule5 = str_isx021_cameramodule5
- elif camera[i] == 'C2' :
- str_camera6 = str_imx490_f_2c_i2c2
- str_fragment_vi5 = str_fragment_vi_5
- str_fragment_nvcsi5 = str_fragment_nvcsi_ch5
- str_cameramodule5 = str_imx490_cameramodule5
- else:
- str_camera6 = ''
- str_fragment_vi5 = ''
- str_fragment_nvcsi5 = ''
- str_cameramodule5 = ''
-
- elif i == 6 :
-
- if camera[i] == 'C1' :
- str_camera7 = str_isx021_g_1b_i2c3
- str_fragment_vi6 = str_fragment_vi_6
- str_fragment_nvcsi6 = str_fragment_nvcsi_ch6.replace('imx490_out6', 'isx021_out6')
- str_cameramodule6 = str_isx021_cameramodule6
- elif camera[i] == 'C2' :
- str_camera7 = str_imx490_g_2b_i2c3
- str_fragment_vi6 = str_fragment_vi_6
- str_fragment_nvcsi6 = str_fragment_nvcsi_ch6
- str_cameramodule6 = str_imx490_cameramodule6
- else:
- str_camera7 = ''
- str_fragment_vi6 = ''
- str_fragment_nvcsi6 = ''
- str_cameramodule6 = ''
-
- elif i == 7 :
-
- if camera[i] == 'C1' :
- str_camera8 = str_isx021_h_1c_i2c3
- str_fragment_vi7 = str_fragment_vi_7
- str_fragment_nvcsi7 = str_fragment_nvcsi_ch7.replace('imx490_out7', 'isx021_out7')
- str_cameramodule7 = str_isx021_cameramodule7
- elif camera[i] == 'C2' :
- str_camera8 = str_imx490_h_2c_i2c3
- str_fragment_vi7 = str_fragment_vi_7
- str_fragment_nvcsi7 = str_fragment_nvcsi_ch7
- str_cameramodule7 = str_imx490_cameramodule7
- else:
- str_camera8 = ''
- str_fragment_vi7 = ''
- str_fragment_nvcsi7 = ''
- str_cameramodule7 = ''
-
-str_i2c0 = str_fragment0 + str_ser_isp_i2c0 + str_camera2 + str_camera1 + str_block_end
-
-str_i2c1 = str_fragment1 + str_ser_isp_i2c1 + str_camera4 + str_camera3 + str_block_end
-
-str_i2c2 = str_fragment2 + str_ser_isp_i2c2 + str_camera6 + str_camera5 + str_block_end
-
-str_i2c3 = str_fragment3 + str_ser_isp_i2c3 + str_camera8 + str_camera7 + str_block_end
-
-str_whole_i2c = str_i2c0 + str_i2c1 + str_i2c2 + str_i2c3
-
-str_whole_dts = str_overlay_header \
- + str_i2c0 + str_i2c1 + str_i2c2 + str_i2c3 \
- + str_fragment_vi0 + str_fragment_vi1 + str_fragment_vi2 + str_fragment_vi3 \
- + str_fragment_vi4 + str_fragment_vi5 + str_fragment_vi6 + str_fragment_vi7 \
- + str_fragment_nvcsi0 + str_fragment_nvcsi1 + str_fragment_nvcsi2 + str_fragment_nvcsi3 \
- + str_fragment_nvcsi4 + str_fragment_nvcsi5 + str_fragment_nvcsi6 + str_fragment_nvcsi7 \
- + str_cameramodule0 + str_cameramodule1 + str_cameramodule2 + str_cameramodule3 \
- + str_cameramodule4 + str_cameramodule5 + str_cameramodule6 + str_cameramodule7 \
- + str_dser_fragment + str_overlay_end
-
-camera_type = get_type_of_cameras(temp_cam)
-#camera_type = get_type_of_cameras(camera)
-
-overlay_dts_file_name = 'tier4-isx021-imx490-' + str(camera_type[0]) + '-' + str(camera_type[1]) + '-' \
- + str(camera_type[2]) + '-' + str(camera_type[3]) + '-gmsl-device-tree-overlay.dts'
-
-with open( overlay_dts_file_name, 'w', encoding='utf-8') as overlay_dts_file:
- print(str_whole_dts, file=overlay_dts_file )
-
diff --git a/pkg/create_deb_pkg.sh b/pkg/create_deb_pkg.sh
new file mode 100755
index 0000000..e019271
--- /dev/null
+++ b/pkg/create_deb_pkg.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+dpkg-buildpackage -b -rfakeroot -us -uc
diff --git a/drivers/debian/README.Debian b/pkg/debian/README.Debian
similarity index 100%
rename from drivers/debian/README.Debian
rename to pkg/debian/README.Debian
diff --git a/drivers/debian/README.source b/pkg/debian/README.source
similarity index 100%
rename from drivers/debian/README.source
rename to pkg/debian/README.source
diff --git a/drivers/debian/changelog b/pkg/debian/changelog
similarity index 100%
rename from drivers/debian/changelog
rename to pkg/debian/changelog
diff --git a/drivers/debian/compat b/pkg/debian/compat
similarity index 100%
rename from drivers/debian/compat
rename to pkg/debian/compat
diff --git a/drivers/debian/control b/pkg/debian/control
similarity index 58%
rename from drivers/debian/control
rename to pkg/debian/control
index 0aa34d1..cdeaeda 100644
--- a/drivers/debian/control
+++ b/pkg/debian/control
@@ -1,13 +1,13 @@
Source: tier4-camera-gmsl
Section: kernel
Priority: optional
-Maintainer: Yusuke Fujii
+Maintainer: Ryo Munakata
Build-Depends: debhelper (>=9), dkms
Standards-Version: 3.9.6
-Homepage:
+Homepage:
Package: tier4-camera-gmsl
Architecture: arm64
Provides: tier4-camera-gmsl
Depends: ${misc:Depends}
-Description: Tier4 ISX021 GMSL2 Camera Kernel Module.
+Description: V4L2 camera drivers for TIER IV C1/C2/C3 cameras
diff --git a/drivers/debian/copyright b/pkg/debian/copyright
similarity index 100%
rename from drivers/debian/copyright
rename to pkg/debian/copyright
diff --git a/drivers/debian/dkms b/pkg/debian/dkms
similarity index 100%
rename from drivers/debian/dkms
rename to pkg/debian/dkms
diff --git a/drivers/debian/etc/modprobe.d/tier4-imx490.conf b/pkg/debian/etc/modprobe.d/tier4-imx490.conf
old mode 100644
new mode 100755
similarity index 88%
rename from drivers/debian/etc/modprobe.d/tier4-imx490.conf
rename to pkg/debian/etc/modprobe.d/tier4-imx490.conf
index 4361487..ac60d93
--- a/drivers/debian/etc/modprobe.d/tier4-imx490.conf
+++ b/pkg/debian/etc/modprobe.d/tier4-imx490.conf
@@ -23,5 +23,8 @@ options tier4_imx490 trigger_mode=0 enable_auto_exposure=1 enable_distortion_cor
# "generate_fsync=0" External pulse is not automatically genereated by FPGA(Default).
# "generate_fsync=1" External pulse is automatically genereated by FPGA( not supported yet).
#
+# Please refer to the following page.
+# https://adlink-ros.github.io/roscube-doc/roscube-x/gmsl_camera/frame_sync.html#tier-iv-c1-c2-frame-sync
+#
options tier4_fpga generate_fsync=0
diff --git a/pkg/debian/etc/modprobe.d/tier4-imx728.conf b/pkg/debian/etc/modprobe.d/tier4-imx728.conf
new file mode 100755
index 0000000..089e0ed
--- /dev/null
+++ b/pkg/debian/etc/modprobe.d/tier4-imx728.conf
@@ -0,0 +1,30 @@
+# Configurations:
+# "trigger_mode=0" run cameras in master 20fps mode. (Default)
+# "trigger_mode=1" run cameras in slave(External pulse sync) 10fps mode. (Not supported yet)
+# "trigger_mode=2" run cameras in maste 20fps mode.
+# "trigger_mode=3" run cameras in slave(External pulse sync) 20fps mode. (Not supported yet)
+# "trigger_mode=4" run cameras in master 30fps mode. (Not supported)
+# "trigger_mode=5" run cameras in slave(External pulse sync) 30fps mode. (Not supported)
+#
+# "trigger_mode=1,3 and 5" are valid for ADLINK RQX-58G and RQX-59G only.
+#
+# "enable_auto_exposure=0" disable auto-exposure feature.
+# "enable_auto_exposure=1" enable auto-exposure feature. (Default)
+#
+# "enable_distortion_correction=0" disable distortion correction feature.
+# "enable_distortion_correction=1" enable distortion correction feature.(Default)
+#
+
+options tier4_imx728 trigger_mode=0 enable_auto_exposure=1 enable_distortion_correction=1
+
+#
+# The following parameter is valid for ADLINK RQX-58G and RQX-59G only.
+#
+# "generate_fsync=0" External pulse is not automatically genereated by FPGA(Default).
+# "generate_fsync=1" External pulse is automatically genereated by FPGA( not supported yet).
+#
+# Please refer to the following page.
+# https://adlink-ros.github.io/roscube-doc/roscube-x/gmsl_camera/frame_sync.html#tier-iv-c1-c2-frame-sync
+#
+
+options tier4_fpga generate_fsync=0
diff --git a/pkg/debian/etc/modprobe.d/tier4-isx021.conf b/pkg/debian/etc/modprobe.d/tier4-isx021.conf
new file mode 100755
index 0000000..2031410
--- /dev/null
+++ b/pkg/debian/etc/modprobe.d/tier4-isx021.conf
@@ -0,0 +1,26 @@
+# Configurations:
+# "trigger_mode=0" run cameras in master mode. (Default)
+# "trigger_mode=1" run cameras in slave(External pulse sync) mode, and valid for ADLINK RQX-58G/59G only.
+#
+# "enable_auto_exposure=0" disable auto-exposure feature.
+# "enable_auto_exposure=1" enable auto-exposure feature. (Default)
+#
+# "enable_distortion_correction=0" disable distortion correction feature.
+# "enable_distortion_correction=1" enable distortion correction feature. (Default)
+#
+options tier4_isx021 trigger_mode=0 enable_auto_exposure=1 enable_distortion_correction=1
+
+
+# Note:
+# The following parameters are valid for RQX-58G and RQX-59G.
+#
+# "fsync_mode=0" disable FPGA Fsync mode. (Default)
+# "fsync_mode=1" enable FPGA Fsync Auto Trigger mode.
+# "fsync_mode=2" enable FPGA Fsync Manual Trigger mode.
+#
+# "fps_cam1_cam2=10" set 10fps for cam1&2 in Fsync Auto Trigger mode. (FPS 1~30)
+# "fps_cam3_cam4=10" set 10fps for cam3&4 in Fsync Auto Trigger mode. (FPS 1~30)
+# "fps_cam5_cam6=10" set 10fps for cam5&6 in Fsync Auto Trigger mode. (FPS 1~30)
+# "fps_cam7_cam8=10" set 10fps for cam7&8 in Fsync Auto Trigger mode. (FPS 1~30)
+#
+options tier4_fpga fsync_mode=0 fps_cam1_cam2=10 fps_cam3_cam4=10 fps_cam5_cam6=10 fps_cam7_cam8=10
diff --git a/drivers/debian/etc/modules-load.d/tier4-imx490-gmsl.conf b/pkg/debian/etc/modules-load.d/tier4-imx490-gmsl.conf
old mode 100644
new mode 100755
similarity index 100%
rename from drivers/debian/etc/modules-load.d/tier4-imx490-gmsl.conf
rename to pkg/debian/etc/modules-load.d/tier4-imx490-gmsl.conf
diff --git a/pkg/debian/etc/modules-load.d/tier4-imx728-gmsl.conf b/pkg/debian/etc/modules-load.d/tier4-imx728-gmsl.conf
new file mode 100755
index 0000000..19a6fa8
--- /dev/null
+++ b/pkg/debian/etc/modules-load.d/tier4-imx728-gmsl.conf
@@ -0,0 +1,7 @@
+tier4-max9295
+tier4-max9296
+tier4-fpga
+tier4-gw5300
+tier4-isx021
+tier4-imx490
+tier4-imx728
diff --git a/drivers/debian/etc/modules-load.d/tier4-isx021-gmsl.conf b/pkg/debian/etc/modules-load.d/tier4-isx021-gmsl.conf
old mode 100644
new mode 100755
similarity index 100%
rename from drivers/debian/etc/modules-load.d/tier4-isx021-gmsl.conf
rename to pkg/debian/etc/modules-load.d/tier4-isx021-gmsl.conf
diff --git a/drivers/debian/install b/pkg/debian/install
similarity index 100%
rename from drivers/debian/install
rename to pkg/debian/install
diff --git a/drivers/debian/postinst b/pkg/debian/postinst
similarity index 97%
rename from drivers/debian/postinst
rename to pkg/debian/postinst
index c9cc723..c8b2139 100755
--- a/drivers/debian/postinst
+++ b/pkg/debian/postinst
@@ -25,6 +25,7 @@ dkms_configure () {
case "$1" in
configure)
+ udevadm control --reload
dkms_configure
;;
diff --git a/drivers/debian/prerm b/pkg/debian/prerm
similarity index 70%
rename from drivers/debian/prerm
rename to pkg/debian/prerm
index 3fc3a77..235c257 100755
--- a/drivers/debian/prerm
+++ b/pkg/debian/prerm
@@ -5,16 +5,6 @@ NAME=tier4-camera-gmsl
VERSION=1.5.0
KERNEL_REL=$(uname -r)
-ISX021_GMSL_DTBO=$(ls /boot/tier4-isx021-gmsl*)
-ISX021_GMSL_DTBO_EXIST=$?
-
-IMX490_GMSL_DTBO=$(ls /boot/tier4-imx490-gmsl-*)
-ISX490_GMSL_DTBO_EXIST=$?
-
-IMX728_GMSL_DTBO=$(ls /boot/tier4-imx728-gmsl-*)
-IMX728_GMSL_DTBO_EXIST=$?
-
-
set -e
case "$1" in
remove|upgrade|deconfigure)
@@ -36,15 +26,9 @@ case "$1" in
rm -f /etc/modprobe.d/tier4-imx490.conf
rm -f /etc/modprobe.d/tier4-imx728.conf
- if [ $ISX021_GMSL_DTBO_EXIST = 0 ]; then
- rm -f $ISX021_GMSL_DTBO
- fi
- if [ $IMX490_GMSL_DTBO_EXIST = 0 ]; then
- rm -f $IMX490_GMSL_DTBO
- fi
- if [ $IMX728_GMSL_DTBO_EXIST = 0 ]; then
- rm -f $IMX728_GMSL_DTBO
- fi
+ rm -f /boot/tier4-isx021-*
+ rm -f /boot/tier4-imx490-*
+ rm -f /boot/tier4-imx728-*
fi
;;
diff --git a/drivers/debian/rules b/pkg/debian/rules
similarity index 64%
rename from drivers/debian/rules
rename to pkg/debian/rules
index 6f75dce..b2517ec 100755
--- a/drivers/debian/rules
+++ b/pkg/debian/rules
@@ -7,6 +7,16 @@ dkms_version := $(shell cat dkms.conf | grep ^PACKAGE_VERSION= | cut -d '"' -f 2
dkms_src_dir := $(CURDIR)/debian/${package}/usr/src/tier4-camera-gmsl-$(dkms_version)/
kernel_src_dir ?= /lib/modules/$(kernel_release)/build
+UDEV_FILE := ./debian/udev
+
+ROScube_Orin_word := 590
+ROScube_Orin_Model_word := ROScube-Orin
+
+dt_model := $(shell cat /proc/device-tree/model | tr -d "\0" )
+
+ifeq ($(ROScube_Orin_word), $(findstring $(ROScube_Orin_word),$(dt_model)))
+ MODEL := $(ROScube_Orin_Model_word)
+endif
%:
dh $@ --with dkms
@@ -19,11 +29,18 @@ override_dh_auto_install:
# dh_install debian/var ../${package}
dh_install debian/usr ../${package}
mkdir -p $(dkms_src_dir)
- cp -rf $(CURDIR)/src/* $(dkms_src_dir)
+ cp -rf $(CURDIR)/../src/${package}/* $(dkms_src_dir)
+ cp -rf $(CURDIR)/../tools/dts_generator/* $(dkms_src_dir)
override_dh_usrlocal:
override_dh_installudev:
+
+ifeq ($(MODEL),$(ROScube_Orin_Model_word))
+ sed -i -e 's/001b/001d/g' $(UDEV_FILE)
+ sed -i -e 's/001c/001e/g' $(UDEV_FILE)
+endif
+
dh_installudev --priority 99
override_dh_dkms:
diff --git a/drivers/debian/source/format b/pkg/debian/source/format
similarity index 100%
rename from drivers/debian/source/format
rename to pkg/debian/source/format
diff --git a/pkg/debian/udev b/pkg/debian/udev
new file mode 100644
index 0000000..ea7950f
--- /dev/null
+++ b/pkg/debian/udev
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="video4linux", KERNEL=="video*", ATTR{name}=="?*tier4?*", RUN+="/usr/bin/tier4-create-camera-symlink.sh $devnode"
diff --git a/drivers/debian/usr/local/bin/run_tier4_isx021_single.sh b/pkg/debian/usr/bin/run_tier4_isx021_single.sh
similarity index 100%
rename from drivers/debian/usr/local/bin/run_tier4_isx021_single.sh
rename to pkg/debian/usr/bin/run_tier4_isx021_single.sh
diff --git a/pkg/debian/usr/bin/tier4-create-camera-symlink.sh b/pkg/debian/usr/bin/tier4-create-camera-symlink.sh
new file mode 100755
index 0000000..690b160
--- /dev/null
+++ b/pkg/debian/usr/bin/tier4-create-camera-symlink.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -eu
+
+[ $# -eq 1 ] || exit 1
+[ -e $1 ] || exit 1
+
+CAMERA_PATH=$(v4l2-ctl --info -d $1 | grep "Card type" | grep -o "[0-9]\+-[0-9a-f]\+")
+CAMERA_OF_NODE=$(cat $(find /sys/devices/ -name ${CAMERA_PATH})/of_node/name)
+SENSOR=$(echo $CAMERA_OF_NODE | cut -d _ -f1)
+
+INDEX=$(printf '%d' "'$(echo ${CAMERA_OF_NODE} | cut -d _ -f2)")
+INDEX_START=$(printf '%d' "'a")
+NUM_INDEX=$(expr ${INDEX} - ${INDEX_START} + 1)
+
+GMSL_DIR="/dev/gmsl"
+mkdir -p "${GMSL_DIR}"
+ln -s $1 "${GMSL_DIR}/tier4-${SENSOR}-cam${NUM_INDEX}"
diff --git a/drivers/dkms.conf b/pkg/dkms.conf
similarity index 78%
rename from drivers/dkms.conf
rename to pkg/dkms.conf
index 63f166b..766893c 100644
--- a/drivers/dkms.conf
+++ b/pkg/dkms.conf
@@ -1,9 +1,8 @@
PACKAGE_NAME="tier4-camera-gmsl"
PACKAGE_VERSION="1.5.0"
-PROCS_NUM=`nproc`
-[ $PROCS_NUM -gt 16 ] && PROCS_NUM=16
-MAKE="make all -j$PROCS_NUM"
-CLEAN="make clean"
+
+MAKE="make -f Makefile.dkms all KERNEL_SRC_DIR=/lib/modules/$kernelver/build/"
+CLEAN="make -f Makefile.dkms clean KERNEL_SRC_DIR=/lib/modules/$kernelver/build/"
BUILT_MODULE_NAME[0]="tier4-isx021"
DEST_MODULE_LOCATION[0]="/updates"
diff --git a/scripts/c1/reset/READE b/scripts/c1/reset/READE
new file mode 100644
index 0000000..3f19f3c
--- /dev/null
+++ b/scripts/c1/reset/READE
@@ -0,0 +1,37 @@
+- reset_single.sh : port 1 の Deser(max9296),Ser(max9295), Camera SensorISX021をリセットする。
+
+使い方: sudo ./reset_single.sh
+
+他のportのDeser,Ser,Camera Sensorをリセットしたい場合は、reset_single.shに以下の変更が必要である。
+
+port 2 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 30 0x60 に変更する。
+
+port 3 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 31 0x42 に変更する。
+
+port 4 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 31 0x60 に変更する。
+
+port 5 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 32 0x42 に変更する。
+
+port 6 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 32 0x60 に変更する。
+
+port 7 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 33 0x42 に変更する。
+
+port 8 をリセットしたい場合:i2cset -f -y 30 0x42 --> i2cset -f -y 33 0x60 に変更する。
+
+
+- reset_dual.sh : ポート1,2 の Deser and Ser, Camera Sensor をリセットする。
+
+使い方: sudo ./reset_dual.sh
+
+port 1とport 2を個別にリセットはできない。理由:Deserが共有のため。
+
+他のportのDeser,Ser,Camera Sensorをリセットしたい場合は、reset_dual.shに以下の変更が必要である。
+
+port 3,4 をリセットしたい場合:
+ i2cset -f -y 30 --> i2cset -f -y 31 に変更する。
+
+port 5,6 をリセットしたい場合:
+ i2cset -f -y 30 --> i2cset -f -y 32 に変更する。
+
+port 7,8 をリセットしたい場合:
+ i2cset -f -y 30 --> i2cset -f -y 33 に変更する。
diff --git a/scripts/c1/reset/reset_dual.sh b/scripts/c1/reset/reset_dual.sh
new file mode 100755
index 0000000..84439c2
--- /dev/null
+++ b/scripts/c1/reset/reset_dual.sh
@@ -0,0 +1,155 @@
+#!/bin/bash
+
+echo 1 > /sys/kernel/debug/bpmp/debug/clk/i2c2/mrq_rate_locked
+
+echo 400000 > /sys/kernel/debug/bpmp/debug/clk/i2c2/rate
+
+# if you don't want to show i2cset command on your screen
+# comment out the line of "set -x"
+
+set -x
+
+i2cset -f -y 30 0x42 0x00 0x10 0x80 i
+i2cset -f -y 30 0x62 0x00 0x10 0x80 i
+i2cset -f -y 30 0x60 0x00 0x10 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x01 i
+i2cset -f -y 30 0x48 0x00 0x10 0x21 i
+
+i2cset -f -y 30 0x62 0x00 0x00 0x84 i
+
+i2cset -f -y 30 0x42 0x00 0x10 0x21 i
+i2cset -f -y 30 0x42 0x00 0x6B 0x10 i
+i2cset -f -y 30 0x42 0x00 0x73 0x11 i
+i2cset -f -y 30 0x42 0x00 0x7B 0x31 i
+i2cset -f -y 30 0x42 0x00 0x83 0x31 i
+i2cset -f -y 30 0x42 0x00 0x93 0x31 i
+i2cset -f -y 30 0x42 0x00 0x9B 0x31 i
+i2cset -f -y 30 0x42 0x00 0xA3 0x31 i
+i2cset -f -y 30 0x42 0x00 0xAB 0x31 i
+i2cset -f -y 30 0x42 0x00 0x8B 0x31 i
+i2cset -f -y 30 0x42 0x00 0x44 0x36 i
+i2cset -f -y 30 0x42 0x00 0x45 0x34 i
+i2cset -f -y 30 0x42 0x02 0xBE 0x90 i
+i2cset -f -y 30 0x42 0x02 0xBF 0x60 i
+i2cset -f -y 30 0x42 0x03 0xF1 0x89 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x03 i
+i2cset -f -y 30 0x48 0x00 0x10 0x23 i
+
+i2cset -f -y 30 0x62 0x00 0x00 0xC0 i
+
+i2cset -f -y 30 0x60 0x00 0x10 0x22 i
+i2cset -f -y 30 0x60 0x00 0x6B 0x12 i
+i2cset -f -y 30 0x60 0x00 0x73 0x13 i
+i2cset -f -y 30 0x60 0x00 0x7B 0x32 i
+i2cset -f -y 30 0x60 0x00 0x83 0x32 i
+i2cset -f -y 30 0x60 0x00 0x93 0x32 i
+i2cset -f -y 30 0x60 0x00 0x9B 0x32 i
+i2cset -f -y 30 0x60 0x00 0xA3 0x32 i
+i2cset -f -y 30 0x60 0x00 0xAB 0x32 i
+i2cset -f -y 30 0x60 0x00 0x44 0x38 i
+i2cset -f -y 30 0x60 0x00 0x45 0x34 i
+i2cset -f -y 30 0x60 0x02 0xBE 0x90 i
+i2cset -f -y 30 0x60 0x02 0xBF 0x60 i
+i2cset -f -y 30 0x60 0x03 0xF1 0x89 i
+
+
+i2cset -f -y 30 0x60 0x03 0x30 0x00 i
+i2cset -f -y 30 0x60 0x03 0x31 0x30 i
+
+i2cset -f -y 30 0x42 0x03 0x30 0x00 i
+
+i2cset -f -y 30 0x60 0x03 0x32 0xE0 i
+
+i2cset -f -y 30 0x42 0x03 0x31 0x30 i
+
+i2cset -f -y 30 0x60 0x03 0x33 0x04 i
+
+i2cset -f -y 30 0x42 0x03 0x32 0xE0 i
+
+i2cset -f -y 30 0x60 0x03 0x16 0x70 i
+#i2cset -f -y 30 0x60 0x03 0x16 0x5E i
+
+i2cset -f -y 30 0x42 0x03 0x33 0x04 i
+
+i2cset -f -y 30 0x60 0x03 0x1A 0x5E i
+
+i2cset -f -y 30 0x42 0x03 0x14 0xF0 i
+#i2cset -f -y 30 0x42 0x03 0x14 0xDE i
+
+i2cset -f -y 30 0x60 0x03 0x11 0xF0 i
+
+i2cset -f -y 30 0x42 0x03 0x18 0x5E i
+
+i2cset -f -y 30 0x60 0x03 0x08 0x6A i
+
+i2cset -f -y 30 0x42 0x03 0x11 0xF0 i
+
+i2cset -f -y 30 0x60 0x00 0x02 0xF3 i
+
+i2cset -f -y 30 0x42 0x03 0x08 0x65 i
+
+i2cset -f -y 30 0x48 0x04 0x0B 0x07 i
+
+i2cset -f -y 30 0x42 0x00 0x02 0xF3 i
+
+i2cset -f -y 30 0x48 0x04 0x2D 0x15 i
+i2cset -f -y 30 0x48 0x04 0x0D 0x1E i
+i2cset -f -y 30 0x48 0x04 0x0E 0x5E i
+i2cset -f -y 30 0x48 0x04 0x0F 0x00 i
+i2cset -f -y 30 0x48 0x04 0x10 0x40 i
+i2cset -f -y 30 0x48 0x04 0x11 0x01 i
+i2cset -f -y 30 0x48 0x04 0x12 0x41 i
+i2cset -f -y 30 0x48 0x04 0x4A 0x40 i
+i2cset -f -y 30 0x48 0x03 0x30 0x04 i
+i2cset -f -y 30 0x48 0x03 0x33 0x4E i
+i2cset -f -y 30 0x48 0x03 0x34 0xE4 i
+i2cset -f -y 30 0x48 0x03 0x20 0x2F i
+i2cset -f -y 30 0x48 0x00 0x05 0xC0 i
+i2cset -f -y 30 0x48 0x04 0x4B 0x07 i
+i2cset -f -y 30 0x48 0x04 0x6D 0x15 i
+i2cset -f -y 30 0x48 0x04 0x4D 0x1E i
+i2cset -f -y 30 0x48 0x04 0x4E 0x1E i
+i2cset -f -y 30 0x48 0x04 0x4F 0x00 i
+i2cset -f -y 30 0x48 0x04 0x50 0x00 i
+i2cset -f -y 30 0x48 0x04 0x51 0x01 i
+i2cset -f -y 30 0x48 0x04 0x52 0x01 i
+i2cset -f -y 30 0x48 0x04 0x4A 0x40 i
+i2cset -f -y 30 0x48 0x00 0x05 0xC0 i
+
+i2cset -f -y 30 0x60 0x02 0xD6 0x00 i
+
+i2cset -f -y 30 0x42 0x02 0xD6 0x00 i
+
+i2cset -f -y 30 0x60 0x02 0xCD 0x04 i
+
+i2cset -f -y 30 0x42 0x02 0xCD 0x04 i
+
+i2cset -f -y 30 0x60 0x02 0xCA 0x10 i
+
+i2cset -f -y 30 0x42 0x02 0xCA 0x10 i
+
+i2cset -f -y 30 0x60 0x02 0xD6 0x10 i
+
+i2cset -f -y 30 0x42 0x02 0xD6 0x10 i
+
+i2cset -f -y 30 0x1c 0xAB 0xC0 0x00 i
+i2cset -f -y 30 0x1c 0xAC 0x4E 0x03 i
+i2cset -f -y 30 0x1c 0xAC 0x48 0xE8 i
+i2cset -f -y 30 0x1c 0xAC 0x49 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x50 0x03 i
+
+i2cset -f -y 30 0x1b 0xAB 0xC0 0x00 i
+i2cset -f -y 30 0x1b 0xAC 0x4E 0x03 i
+i2cset -f -y 30 0x1b 0xAC 0x48 0xE8 i
+i2cset -f -y 30 0x1b 0xAC 0x49 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x51 0x02 i
+
+echo 136000000 > /sys/kernel/debug/bpmp/debug/clk/i2c2/rate
+
+echo 0 > /sys/kernel/debug/bpmp/debug/clk/i2c2/mrq_rate_locked
diff --git a/scripts/c1/reset/reset_single.sh b/scripts/c1/reset/reset_single.sh
new file mode 100755
index 0000000..8bec026
--- /dev/null
+++ b/scripts/c1/reset/reset_single.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# if you don't want to show i2cset command on your screen
+# comment out the line of "set -x"
+
+set -x
+
+echo 1 > /sys/kernel/debug/bpmp/debug/clk/i2c2/mrq_rate_locked
+
+echo 400000 > /sys/kernel/debug/bpmp/debug/clk/i2c2/rate
+
+i2cset -f -y 30 0x42 0x00 0x10 0x80 i
+i2cset -f -y 30 0x60 0x00 0x10 0x80 i
+i2cset -f -y 30 0x48 0x00 0x10 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x01 i
+i2cset -f -y 30 0x48 0x00 0x10 0x21 i
+
+i2cset -f -y 30 0x62 0x00 0x00 0x84 i
+
+i2cset -f -y 30 0x42 0x00 0x10 0x21 i
+i2cset -f -y 30 0x42 0x00 0x6B 0x10 i
+i2cset -f -y 30 0x42 0x00 0x73 0x11 i
+i2cset -f -y 30 0x42 0x00 0x7B 0x31 i
+i2cset -f -y 30 0x42 0x00 0x83 0x31 i
+i2cset -f -y 30 0x42 0x00 0x93 0x31 i
+i2cset -f -y 30 0x42 0x00 0x9B 0x31 i
+i2cset -f -y 30 0x42 0x00 0xA3 0x31 i
+i2cset -f -y 30 0x42 0x00 0xAB 0x31 i
+i2cset -f -y 30 0x42 0x00 0x8B 0x31 i
+i2cset -f -y 30 0x42 0x00 0x44 0x36 i
+i2cset -f -y 30 0x42 0x00 0x45 0x34 i
+i2cset -f -y 30 0x42 0x02 0xBE 0x90 i
+i2cset -f -y 30 0x42 0x02 0xBF 0x60 i
+i2cset -f -y 30 0x42 0x03 0xF1 0x89 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x03 i
+i2cset -f -y 30 0x48 0x00 0x10 0x23 i
+
+i2cset -f -y 30 0x48 0x00 0x10 0x01 i
+i2cset -f -y 30 0x48 0x00 0x10 0x21 i
+#i2cset -f -y 30 0x62 0x00 0x00 0xC0 i
+
+#i2cset -f -y 30 0x60 0x00 0x10 0x22 i
+
+i2cset -f -y 30 0x42 0x03 0x30 0x00 i
+i2cset -f -y 30 0x42 0x03 0x31 0x30 i
+i2cset -f -y 30 0x42 0x03 0x32 0xE0 i
+i2cset -f -y 30 0x42 0x03 0x33 0x04 i
+i2cset -f -y 30 0x42 0x03 0x14 0xF0 i
+#i2cset -f -y 30 0x42 0x03 0x14 0xDE i
+i2cset -f -y 30 0x42 0x03 0x18 0x5E i
+i2cset -f -y 30 0x42 0x03 0x11 0xF0 i
+i2cset -f -y 30 0x42 0x03 0x08 0x65 i
+i2cset -f -y 30 0x42 0x00 0x02 0xF3 i
+i2cset -f -y 30 0x48 0x04 0x0B 0x07 i
+i2cset -f -y 30 0x48 0x04 0x2D 0x15 i
+i2cset -f -y 30 0x48 0x04 0x0D 0x1E i
+i2cset -f -y 30 0x48 0x04 0x0E 0x1E i
+i2cset -f -y 30 0x48 0x04 0x0F 0x00 i
+i2cset -f -y 30 0x48 0x04 0x10 0x00 i
+i2cset -f -y 30 0x48 0x04 0x11 0x01 i
+i2cset -f -y 30 0x48 0x04 0x12 0x01 i
+i2cset -f -y 30 0x48 0x04 0x4A 0x40 i
+i2cset -f -y 30 0x48 0x03 0x30 0x04 i
+i2cset -f -y 30 0x48 0x03 0x33 0x4E i
+i2cset -f -y 30 0x48 0x03 0x34 0xE4 i
+i2cset -f -y 30 0x48 0x03 0x20 0x2F i
+i2cset -f -y 30 0x48 0x00 0x05 0xC0 i
+i2cset -f -y 30 0x42 0x02 0xD6 0x00 i
+i2cset -f -y 30 0x42 0x02 0xCD 0x04 i
+i2cset -f -y 30 0x42 0x02 0xCA 0x10 i
+i2cset -f -y 30 0x42 0x02 0xD6 0x10 i
+
+i2cset -f -y 30 0x1b 0xAB 0xC0 0x00 i
+i2cset -f -y 30 0x1b 0xAC 0x4E 0x03 i
+i2cset -f -y 30 0x1b 0xAC 0x48 0xE8 i
+i2cset -f -y 30 0x1b 0xAC 0x49 0x80 i
+
+i2cset -f -y 30 0x48 0x00 0x50 0x02 i
+
+echo 136000000 > /sys/kernel/debug/bpmp/debug/clk/i2c2/rate
+
+echo 0 > /sys/kernel/debug/bpmp/debug/clk/i2c2/mrq_rate_locked
+
diff --git a/scripts/c2/.integration.sh.swp b/scripts/c2/.integration.sh.swp
new file mode 100644
index 0000000..e3d2313
Binary files /dev/null and b/scripts/c2/.integration.sh.swp differ
diff --git a/scripts/common/hotplug/camera-hotplug.sh b/scripts/common/hotplug/camera-hotplug.sh
index 3918de2..c5fad64 100755
--- a/scripts/common/hotplug/camera-hotplug.sh
+++ b/scripts/common/hotplug/camera-hotplug.sh
@@ -16,15 +16,14 @@ set -eux
mkdir -p overlay
cd overlay
rm -f *.dts *.dtbo
-"../../../../drivers/src/make_overlay_dts_$BOARD.py" "$L4T_REVISION" ${@:3}
+"../../../../tools/dts_generator/make_overlay_dts_$BOARD.py" "$L4T_REVISION" ${@:3}
dtc -O dtb -o target.dtbo -@ $(ls *.dts)
-sudo modprobe -r tier4-isx021 || true
-sudo modprobe -r tier4-imx490 || true
+sudo modprobe -r tier4_imx728 || true
sudo rmdir /sys/kernel/config/device-tree/overlays/camera/ || true
sudo mkdir -p /sys/kernel/config/device-tree/overlays/camera/
sudo cp target.dtbo /sys/kernel/config/device-tree/overlays/camera/dtbo
echo 1 | sudo tee /sys/kernel/config/device-tree/overlays/camera/status
-sudo modprobe tier4-imx490
+sudo modprobe tier4-imx728
diff --git a/scripts/common/hotplug/dtbocfg b/scripts/common/hotplug/dtbocfg
index d3cea0f..06207c6 160000
--- a/scripts/common/hotplug/dtbocfg
+++ b/scripts/common/hotplug/dtbocfg
@@ -1 +1 @@
-Subproject commit d3cea0fea5a59e2b0805f3d17cf33e83dac2c00f
+Subproject commit 06207c67bac6978a997b37d6e8843504d6f70a4b
diff --git a/scripts/common/trigger/rqx59g/camera_trigger.sh b/scripts/common/trigger/rqx59g/camera_trigger.sh
deleted file mode 100755
index 2cdba94..0000000
--- a/scripts/common/trigger/rqx59g/camera_trigger.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/bash -e
-help()
-{
- echo "Run GPIO triggering on all four deserializers on ROScube X."
- echo
- echo "Syntax: scriptTemplate [-r|h]"
- echo "Options:"
- echo "r Set the frame rate. Default is 10Hz. Maximum is 25Hz, minimum is 1Hz"
- echo "h Print this Help."
- echo
-}
-cleanup()
-{
- echo "Cleaning up before exit..."
- echo 440 > /sys/class/gpio/unexport
- echo 397 > /sys/class/gpio/unexport
- echo 487 > /sys/class/gpio/unexport
- echo 486 > /sys/class/gpio/unexport
-}
-trap cleanup EXIT
-fps=10
-while getopts ":hr:" option; do
- case $option in
- h) # Display help
- help
- exit;;
- r) # Get frame rate
- fps=$OPTARG
- if [ $fps -gt 25 ]
- then
- echo "Frame rate must be less than 25Hz"
- exit
- fi
- if [ $fps -lt 1 ]
- then
- echo "Frame rate must be more than 1Hz"
- exit
- fi;;
- \?) # Invalid option
- echo "Error: Invalid option"
- exit;;
- esac
-done
-on_time_milli=10
-let "off_time_milli = 1000 / $fps - $on_time_milli"
-echo 440 > /sys/class/gpio/export
-sleep $(echo "scale=10; 0.5" | bc)
-echo out > /sys/class/gpio/gpio440/direction
-sleep $(echo "scale=10; 0.5" | bc)
-echo 397 > /sys/class/gpio/export
-sleep $(echo "scale=10; 0.5" | bc)
-echo out > /sys/class/gpio/gpio397/direction
-sleep $(echo "scale=10; 0.5" | bc)
-echo 487 > /sys/class/gpio/export
-sleep $(echo "scale=10; 0.5" | bc)
-echo out > /sys/class/gpio/gpio487/direction
-sleep $(echo "scale=10; 0.5" | bc)
-echo 486 > /sys/class/gpio/export
-sleep $(echo "scale=10; 0.5" | bc)
-echo out > /sys/class/gpio/gpio486/direction
-sleep $(echo "scale=10; 0.5" | bc)
-
-while true
-do
- echo 1 > /sys/class/gpio/gpio440/value
- echo 1 > /sys/class/gpio/gpio397/value
- echo 1 > /sys/class/gpio/gpio486/value
- echo 1 > /sys/class/gpio/gpio487/value
- sleep $(echo "scale=10; $on_time_milli/1000" | bc)
- echo 0 > /sys/class/gpio/gpio440/value
- echo 0 > /sys/class/gpio/gpio397/value
- echo 0 > /sys/class/gpio/gpio487/value
- echo 0 > /sys/class/gpio/gpio486/value
- sleep $(echo "scale=10; $off_time_milli/1000" | bc)
-done
diff --git a/src/tier4-camera-gmsl/.clang-format b/src/tier4-camera-gmsl/.clang-format
new file mode 100755
index 0000000..ccc9b93
--- /dev/null
+++ b/src/tier4-camera-gmsl/.clang-format
@@ -0,0 +1,743 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# clang-format configuration file. Intended for clang-format >= 11.
+#
+# For more information, see:
+#
+# Documentation/process/clang-format.rst
+# https://clang.llvm.org/docs/ClangFormat.html
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Left
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: false
+
+# Taken from:
+# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
+# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
+# | LC_ALL=C sort -u
+ForEachMacros:
+ - '__ata_qc_for_each'
+ - '__bio_for_each_bvec'
+ - '__bio_for_each_segment'
+ - '__evlist__for_each_entry'
+ - '__evlist__for_each_entry_continue'
+ - '__evlist__for_each_entry_from'
+ - '__evlist__for_each_entry_reverse'
+ - '__evlist__for_each_entry_safe'
+ - '__for_each_mem_range'
+ - '__for_each_mem_range_rev'
+ - '__for_each_thread'
+ - '__hlist_for_each_rcu'
+ - '__map__for_each_symbol_by_name'
+ - '__pci_bus_for_each_res0'
+ - '__pci_bus_for_each_res1'
+ - '__pci_dev_for_each_res0'
+ - '__pci_dev_for_each_res1'
+ - '__perf_evlist__for_each_entry'
+ - '__perf_evlist__for_each_entry_reverse'
+ - '__perf_evlist__for_each_entry_safe'
+ - '__rq_for_each_bio'
+ - '__shost_for_each_device'
+ - '__sym_for_each'
+ - 'apei_estatus_for_each_section'
+ - 'ata_for_each_dev'
+ - 'ata_for_each_link'
+ - 'ata_qc_for_each'
+ - 'ata_qc_for_each_raw'
+ - 'ata_qc_for_each_with_internal'
+ - 'ax25_for_each'
+ - 'ax25_uid_for_each'
+ - 'bio_for_each_bvec'
+ - 'bio_for_each_bvec_all'
+ - 'bio_for_each_folio_all'
+ - 'bio_for_each_integrity_vec'
+ - 'bio_for_each_segment'
+ - 'bio_for_each_segment_all'
+ - 'bio_list_for_each'
+ - 'bip_for_each_vec'
+ - 'bond_for_each_slave'
+ - 'bond_for_each_slave_rcu'
+ - 'bpf_for_each'
+ - 'bpf_for_each_reg_in_vstate'
+ - 'bpf_for_each_reg_in_vstate_mask'
+ - 'bpf_for_each_spilled_reg'
+ - 'bpf_object__for_each_map'
+ - 'bpf_object__for_each_program'
+ - 'btree_for_each_safe128'
+ - 'btree_for_each_safe32'
+ - 'btree_for_each_safe64'
+ - 'btree_for_each_safel'
+ - 'card_for_each_dev'
+ - 'cgroup_taskset_for_each'
+ - 'cgroup_taskset_for_each_leader'
+ - 'cpu_aggr_map__for_each_idx'
+ - 'cpufreq_for_each_efficient_entry_idx'
+ - 'cpufreq_for_each_entry'
+ - 'cpufreq_for_each_entry_idx'
+ - 'cpufreq_for_each_valid_entry'
+ - 'cpufreq_for_each_valid_entry_idx'
+ - 'css_for_each_child'
+ - 'css_for_each_descendant_post'
+ - 'css_for_each_descendant_pre'
+ - 'damon_for_each_region'
+ - 'damon_for_each_region_from'
+ - 'damon_for_each_region_safe'
+ - 'damon_for_each_scheme'
+ - 'damon_for_each_scheme_safe'
+ - 'damon_for_each_target'
+ - 'damon_for_each_target_safe'
+ - 'damos_for_each_filter'
+ - 'damos_for_each_filter_safe'
+ - 'data__for_each_file'
+ - 'data__for_each_file_new'
+ - 'data__for_each_file_start'
+ - 'device_for_each_child_node'
+ - 'displayid_iter_for_each'
+ - 'dma_fence_array_for_each'
+ - 'dma_fence_chain_for_each'
+ - 'dma_fence_unwrap_for_each'
+ - 'dma_resv_for_each_fence'
+ - 'dma_resv_for_each_fence_unlocked'
+ - 'do_for_each_ftrace_op'
+ - 'drm_atomic_crtc_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane_state'
+ - 'drm_atomic_for_each_plane_damage'
+ - 'drm_client_for_each_connector_iter'
+ - 'drm_client_for_each_modeset'
+ - 'drm_connector_for_each_possible_encoder'
+ - 'drm_exec_for_each_locked_object'
+ - 'drm_exec_for_each_locked_object_reverse'
+ - 'drm_for_each_bridge_in_chain'
+ - 'drm_for_each_connector_iter'
+ - 'drm_for_each_crtc'
+ - 'drm_for_each_crtc_reverse'
+ - 'drm_for_each_encoder'
+ - 'drm_for_each_encoder_mask'
+ - 'drm_for_each_fb'
+ - 'drm_for_each_legacy_plane'
+ - 'drm_for_each_plane'
+ - 'drm_for_each_plane_mask'
+ - 'drm_for_each_privobj'
+ - 'drm_gem_for_each_gpuva'
+ - 'drm_gem_for_each_gpuva_safe'
+ - 'drm_gpuva_for_each_op'
+ - 'drm_gpuva_for_each_op_from_reverse'
+ - 'drm_gpuva_for_each_op_safe'
+ - 'drm_gpuvm_for_each_va'
+ - 'drm_gpuvm_for_each_va_range'
+ - 'drm_gpuvm_for_each_va_range_safe'
+ - 'drm_gpuvm_for_each_va_safe'
+ - 'drm_mm_for_each_hole'
+ - 'drm_mm_for_each_node'
+ - 'drm_mm_for_each_node_in_range'
+ - 'drm_mm_for_each_node_safe'
+ - 'dsa_switch_for_each_available_port'
+ - 'dsa_switch_for_each_cpu_port'
+ - 'dsa_switch_for_each_cpu_port_continue_reverse'
+ - 'dsa_switch_for_each_port'
+ - 'dsa_switch_for_each_port_continue_reverse'
+ - 'dsa_switch_for_each_port_safe'
+ - 'dsa_switch_for_each_user_port'
+ - 'dsa_tree_for_each_cpu_port'
+ - 'dsa_tree_for_each_user_port'
+ - 'dsa_tree_for_each_user_port_continue_reverse'
+ - 'dso__for_each_symbol'
+ - 'dsos__for_each_with_build_id'
+ - 'elf_hash_for_each_possible'
+ - 'elf_symtab__for_each_symbol'
+ - 'evlist__for_each_cpu'
+ - 'evlist__for_each_entry'
+ - 'evlist__for_each_entry_continue'
+ - 'evlist__for_each_entry_from'
+ - 'evlist__for_each_entry_reverse'
+ - 'evlist__for_each_entry_safe'
+ - 'flow_action_for_each'
+ - 'for_each_acpi_consumer_dev'
+ - 'for_each_acpi_dev_match'
+ - 'for_each_active_dev_scope'
+ - 'for_each_active_drhd_unit'
+ - 'for_each_active_iommu'
+ - 'for_each_active_route'
+ - 'for_each_aggr_pgid'
+ - 'for_each_and_bit'
+ - 'for_each_andnot_bit'
+ - 'for_each_available_child_of_node'
+ - 'for_each_bench'
+ - 'for_each_bio'
+ - 'for_each_board_func_rsrc'
+ - 'for_each_btf_ext_rec'
+ - 'for_each_btf_ext_sec'
+ - 'for_each_bvec'
+ - 'for_each_card_auxs'
+ - 'for_each_card_auxs_safe'
+ - 'for_each_card_components'
+ - 'for_each_card_dapms'
+ - 'for_each_card_pre_auxs'
+ - 'for_each_card_prelinks'
+ - 'for_each_card_rtds'
+ - 'for_each_card_rtds_safe'
+ - 'for_each_card_widgets'
+ - 'for_each_card_widgets_safe'
+ - 'for_each_cgroup_storage_type'
+ - 'for_each_child_of_node'
+ - 'for_each_clear_bit'
+ - 'for_each_clear_bit_from'
+ - 'for_each_clear_bitrange'
+ - 'for_each_clear_bitrange_from'
+ - 'for_each_cmd'
+ - 'for_each_cmsghdr'
+ - 'for_each_collection'
+ - 'for_each_comp_order'
+ - 'for_each_compatible_node'
+ - 'for_each_component_dais'
+ - 'for_each_component_dais_safe'
+ - 'for_each_conduit'
+ - 'for_each_console'
+ - 'for_each_console_srcu'
+ - 'for_each_cpu'
+ - 'for_each_cpu_and'
+ - 'for_each_cpu_andnot'
+ - 'for_each_cpu_or'
+ - 'for_each_cpu_wrap'
+ - 'for_each_dapm_widgets'
+ - 'for_each_dedup_cand'
+ - 'for_each_dev_addr'
+ - 'for_each_dev_scope'
+ - 'for_each_dma_cap_mask'
+ - 'for_each_dpcm_be'
+ - 'for_each_dpcm_be_rollback'
+ - 'for_each_dpcm_be_safe'
+ - 'for_each_dpcm_fe'
+ - 'for_each_drhd_unit'
+ - 'for_each_dss_dev'
+ - 'for_each_efi_memory_desc'
+ - 'for_each_efi_memory_desc_in_map'
+ - 'for_each_element'
+ - 'for_each_element_extid'
+ - 'for_each_element_id'
+ - 'for_each_endpoint_of_node'
+ - 'for_each_event'
+ - 'for_each_event_tps'
+ - 'for_each_evictable_lru'
+ - 'for_each_fib6_node_rt_rcu'
+ - 'for_each_fib6_walker_rt'
+ - 'for_each_free_mem_pfn_range_in_zone'
+ - 'for_each_free_mem_pfn_range_in_zone_from'
+ - 'for_each_free_mem_range'
+ - 'for_each_free_mem_range_reverse'
+ - 'for_each_func_rsrc'
+ - 'for_each_gpiochip_node'
+ - 'for_each_group_evsel'
+ - 'for_each_group_evsel_head'
+ - 'for_each_group_member'
+ - 'for_each_group_member_head'
+ - 'for_each_hstate'
+ - 'for_each_if'
+ - 'for_each_inject_fn'
+ - 'for_each_insn'
+ - 'for_each_insn_prefix'
+ - 'for_each_intid'
+ - 'for_each_iommu'
+ - 'for_each_ip_tunnel_rcu'
+ - 'for_each_irq_nr'
+ - 'for_each_lang'
+ - 'for_each_link_codecs'
+ - 'for_each_link_cpus'
+ - 'for_each_link_platforms'
+ - 'for_each_lru'
+ - 'for_each_matching_node'
+ - 'for_each_matching_node_and_match'
+ - 'for_each_media_entity_data_link'
+ - 'for_each_mem_pfn_range'
+ - 'for_each_mem_range'
+ - 'for_each_mem_range_rev'
+ - 'for_each_mem_region'
+ - 'for_each_member'
+ - 'for_each_memory'
+ - 'for_each_migratetype_order'
+ - 'for_each_missing_reg'
+ - 'for_each_mle_subelement'
+ - 'for_each_mod_mem_type'
+ - 'for_each_net'
+ - 'for_each_net_continue_reverse'
+ - 'for_each_net_rcu'
+ - 'for_each_netdev'
+ - 'for_each_netdev_continue'
+ - 'for_each_netdev_continue_rcu'
+ - 'for_each_netdev_continue_reverse'
+ - 'for_each_netdev_dump'
+ - 'for_each_netdev_feature'
+ - 'for_each_netdev_in_bond_rcu'
+ - 'for_each_netdev_rcu'
+ - 'for_each_netdev_reverse'
+ - 'for_each_netdev_safe'
+ - 'for_each_new_connector_in_state'
+ - 'for_each_new_crtc_in_state'
+ - 'for_each_new_mst_mgr_in_state'
+ - 'for_each_new_plane_in_state'
+ - 'for_each_new_plane_in_state_reverse'
+ - 'for_each_new_private_obj_in_state'
+ - 'for_each_new_reg'
+ - 'for_each_node'
+ - 'for_each_node_by_name'
+ - 'for_each_node_by_type'
+ - 'for_each_node_mask'
+ - 'for_each_node_state'
+ - 'for_each_node_with_cpus'
+ - 'for_each_node_with_property'
+ - 'for_each_nonreserved_multicast_dest_pgid'
+ - 'for_each_numa_hop_mask'
+ - 'for_each_of_allnodes'
+ - 'for_each_of_allnodes_from'
+ - 'for_each_of_cpu_node'
+ - 'for_each_of_pci_range'
+ - 'for_each_old_connector_in_state'
+ - 'for_each_old_crtc_in_state'
+ - 'for_each_old_mst_mgr_in_state'
+ - 'for_each_old_plane_in_state'
+ - 'for_each_old_private_obj_in_state'
+ - 'for_each_oldnew_connector_in_state'
+ - 'for_each_oldnew_crtc_in_state'
+ - 'for_each_oldnew_mst_mgr_in_state'
+ - 'for_each_oldnew_plane_in_state'
+ - 'for_each_oldnew_plane_in_state_reverse'
+ - 'for_each_oldnew_private_obj_in_state'
+ - 'for_each_online_cpu'
+ - 'for_each_online_node'
+ - 'for_each_online_pgdat'
+ - 'for_each_or_bit'
+ - 'for_each_path'
+ - 'for_each_pci_bridge'
+ - 'for_each_pci_dev'
+ - 'for_each_pcm_streams'
+ - 'for_each_physmem_range'
+ - 'for_each_populated_zone'
+ - 'for_each_possible_cpu'
+ - 'for_each_present_blessed_reg'
+ - 'for_each_present_cpu'
+ - 'for_each_prime_number'
+ - 'for_each_prime_number_from'
+ - 'for_each_probe_cache_entry'
+ - 'for_each_process'
+ - 'for_each_process_thread'
+ - 'for_each_prop_codec_conf'
+ - 'for_each_prop_dai_codec'
+ - 'for_each_prop_dai_cpu'
+ - 'for_each_prop_dlc_codecs'
+ - 'for_each_prop_dlc_cpus'
+ - 'for_each_prop_dlc_platforms'
+ - 'for_each_property_of_node'
+ - 'for_each_reg'
+ - 'for_each_reg_filtered'
+ - 'for_each_reloc'
+ - 'for_each_reloc_from'
+ - 'for_each_requested_gpio'
+ - 'for_each_requested_gpio_in_range'
+ - 'for_each_reserved_mem_range'
+ - 'for_each_reserved_mem_region'
+ - 'for_each_rtd_codec_dais'
+ - 'for_each_rtd_components'
+ - 'for_each_rtd_cpu_dais'
+ - 'for_each_rtd_dais'
+ - 'for_each_sband_iftype_data'
+ - 'for_each_script'
+ - 'for_each_sec'
+ - 'for_each_set_bit'
+ - 'for_each_set_bit_from'
+ - 'for_each_set_bit_wrap'
+ - 'for_each_set_bitrange'
+ - 'for_each_set_bitrange_from'
+ - 'for_each_set_clump8'
+ - 'for_each_sg'
+ - 'for_each_sg_dma_page'
+ - 'for_each_sg_page'
+ - 'for_each_sgtable_dma_page'
+ - 'for_each_sgtable_dma_sg'
+ - 'for_each_sgtable_page'
+ - 'for_each_sgtable_sg'
+ - 'for_each_sibling_event'
+ - 'for_each_sta_active_link'
+ - 'for_each_subelement'
+ - 'for_each_subelement_extid'
+ - 'for_each_subelement_id'
+ - 'for_each_sublist'
+ - 'for_each_subsystem'
+ - 'for_each_supported_activate_fn'
+ - 'for_each_supported_inject_fn'
+ - 'for_each_sym'
+ - 'for_each_test'
+ - 'for_each_thread'
+ - 'for_each_token'
+ - 'for_each_unicast_dest_pgid'
+ - 'for_each_valid_link'
+ - 'for_each_vif_active_link'
+ - 'for_each_vma'
+ - 'for_each_vma_range'
+ - 'for_each_vsi'
+ - 'for_each_wakeup_source'
+ - 'for_each_zone'
+ - 'for_each_zone_zonelist'
+ - 'for_each_zone_zonelist_nodemask'
+ - 'func_for_each_insn'
+ - 'fwnode_for_each_available_child_node'
+ - 'fwnode_for_each_child_node'
+ - 'fwnode_for_each_parent_node'
+ - 'fwnode_graph_for_each_endpoint'
+ - 'gadget_for_each_ep'
+ - 'genradix_for_each'
+ - 'genradix_for_each_from'
+ - 'genradix_for_each_reverse'
+ - 'hash_for_each'
+ - 'hash_for_each_possible'
+ - 'hash_for_each_possible_rcu'
+ - 'hash_for_each_possible_rcu_notrace'
+ - 'hash_for_each_possible_safe'
+ - 'hash_for_each_rcu'
+ - 'hash_for_each_safe'
+ - 'hashmap__for_each_entry'
+ - 'hashmap__for_each_entry_safe'
+ - 'hashmap__for_each_key_entry'
+ - 'hashmap__for_each_key_entry_safe'
+ - 'hctx_for_each_ctx'
+ - 'hists__for_each_format'
+ - 'hists__for_each_sort_list'
+ - 'hlist_bl_for_each_entry'
+ - 'hlist_bl_for_each_entry_rcu'
+ - 'hlist_bl_for_each_entry_safe'
+ - 'hlist_for_each'
+ - 'hlist_for_each_entry'
+ - 'hlist_for_each_entry_continue'
+ - 'hlist_for_each_entry_continue_rcu'
+ - 'hlist_for_each_entry_continue_rcu_bh'
+ - 'hlist_for_each_entry_from'
+ - 'hlist_for_each_entry_from_rcu'
+ - 'hlist_for_each_entry_rcu'
+ - 'hlist_for_each_entry_rcu_bh'
+ - 'hlist_for_each_entry_rcu_notrace'
+ - 'hlist_for_each_entry_safe'
+ - 'hlist_for_each_entry_srcu'
+ - 'hlist_for_each_safe'
+ - 'hlist_nulls_for_each_entry'
+ - 'hlist_nulls_for_each_entry_from'
+ - 'hlist_nulls_for_each_entry_rcu'
+ - 'hlist_nulls_for_each_entry_safe'
+ - 'i3c_bus_for_each_i2cdev'
+ - 'i3c_bus_for_each_i3cdev'
+ - 'idr_for_each_entry'
+ - 'idr_for_each_entry_continue'
+ - 'idr_for_each_entry_continue_ul'
+ - 'idr_for_each_entry_ul'
+ - 'in_dev_for_each_ifa_rcu'
+ - 'in_dev_for_each_ifa_rtnl'
+ - 'inet_bind_bucket_for_each'
+ - 'interval_tree_for_each_span'
+ - 'intlist__for_each_entry'
+ - 'intlist__for_each_entry_safe'
+ - 'kcore_copy__for_each_phdr'
+ - 'key_for_each'
+ - 'key_for_each_safe'
+ - 'klp_for_each_func'
+ - 'klp_for_each_func_safe'
+ - 'klp_for_each_func_static'
+ - 'klp_for_each_object'
+ - 'klp_for_each_object_safe'
+ - 'klp_for_each_object_static'
+ - 'kunit_suite_for_each_test_case'
+ - 'kvm_for_each_memslot'
+ - 'kvm_for_each_memslot_in_gfn_range'
+ - 'kvm_for_each_vcpu'
+ - 'libbpf_nla_for_each_attr'
+ - 'list_for_each'
+ - 'list_for_each_codec'
+ - 'list_for_each_codec_safe'
+ - 'list_for_each_continue'
+ - 'list_for_each_entry'
+ - 'list_for_each_entry_continue'
+ - 'list_for_each_entry_continue_rcu'
+ - 'list_for_each_entry_continue_reverse'
+ - 'list_for_each_entry_from'
+ - 'list_for_each_entry_from_rcu'
+ - 'list_for_each_entry_from_reverse'
+ - 'list_for_each_entry_lockless'
+ - 'list_for_each_entry_rcu'
+ - 'list_for_each_entry_reverse'
+ - 'list_for_each_entry_safe'
+ - 'list_for_each_entry_safe_continue'
+ - 'list_for_each_entry_safe_from'
+ - 'list_for_each_entry_safe_reverse'
+ - 'list_for_each_entry_srcu'
+ - 'list_for_each_from'
+ - 'list_for_each_prev'
+ - 'list_for_each_prev_safe'
+ - 'list_for_each_rcu'
+ - 'list_for_each_reverse'
+ - 'list_for_each_safe'
+ - 'llist_for_each'
+ - 'llist_for_each_entry'
+ - 'llist_for_each_entry_safe'
+ - 'llist_for_each_safe'
+ - 'lwq_for_each_safe'
+ - 'map__for_each_symbol'
+ - 'map__for_each_symbol_by_name'
+ - 'maps__for_each_entry'
+ - 'maps__for_each_entry_safe'
+ - 'mas_for_each'
+ - 'mci_for_each_dimm'
+ - 'media_device_for_each_entity'
+ - 'media_device_for_each_intf'
+ - 'media_device_for_each_link'
+ - 'media_device_for_each_pad'
+ - 'media_entity_for_each_pad'
+ - 'media_pipeline_for_each_entity'
+ - 'media_pipeline_for_each_pad'
+ - 'mlx5_lag_for_each_peer_mdev'
+ - 'msi_domain_for_each_desc'
+ - 'msi_for_each_desc'
+ - 'mt_for_each'
+ - 'nanddev_io_for_each_page'
+ - 'netdev_for_each_lower_dev'
+ - 'netdev_for_each_lower_private'
+ - 'netdev_for_each_lower_private_rcu'
+ - 'netdev_for_each_mc_addr'
+ - 'netdev_for_each_synced_mc_addr'
+ - 'netdev_for_each_synced_uc_addr'
+ - 'netdev_for_each_uc_addr'
+ - 'netdev_for_each_upper_dev_rcu'
+ - 'netdev_hw_addr_list_for_each'
+ - 'nft_rule_for_each_expr'
+ - 'nla_for_each_attr'
+ - 'nla_for_each_nested'
+ - 'nlmsg_for_each_attr'
+ - 'nlmsg_for_each_msg'
+ - 'nr_neigh_for_each'
+ - 'nr_neigh_for_each_safe'
+ - 'nr_node_for_each'
+ - 'nr_node_for_each_safe'
+ - 'of_for_each_phandle'
+ - 'of_property_for_each_string'
+ - 'of_property_for_each_u32'
+ - 'pci_bus_for_each_resource'
+ - 'pci_dev_for_each_resource'
+ - 'pcl_for_each_chunk'
+ - 'pcl_for_each_segment'
+ - 'pcm_for_each_format'
+ - 'perf_config_items__for_each_entry'
+ - 'perf_config_sections__for_each_entry'
+ - 'perf_config_set__for_each_entry'
+ - 'perf_cpu_map__for_each_cpu'
+ - 'perf_cpu_map__for_each_idx'
+ - 'perf_evlist__for_each_entry'
+ - 'perf_evlist__for_each_entry_reverse'
+ - 'perf_evlist__for_each_entry_safe'
+ - 'perf_evlist__for_each_evsel'
+ - 'perf_evlist__for_each_mmap'
+ - 'perf_hpp_list__for_each_format'
+ - 'perf_hpp_list__for_each_format_safe'
+ - 'perf_hpp_list__for_each_sort_list'
+ - 'perf_hpp_list__for_each_sort_list_safe'
+ - 'perf_tool_event__for_each_event'
+ - 'plist_for_each'
+ - 'plist_for_each_continue'
+ - 'plist_for_each_entry'
+ - 'plist_for_each_entry_continue'
+ - 'plist_for_each_entry_safe'
+ - 'plist_for_each_safe'
+ - 'pnp_for_each_card'
+ - 'pnp_for_each_dev'
+ - 'protocol_for_each_card'
+ - 'protocol_for_each_dev'
+ - 'queue_for_each_hw_ctx'
+ - 'radix_tree_for_each_slot'
+ - 'radix_tree_for_each_tagged'
+ - 'rb_for_each'
+ - 'rbtree_postorder_for_each_entry_safe'
+ - 'rdma_for_each_block'
+ - 'rdma_for_each_port'
+ - 'rdma_umem_for_each_dma_block'
+ - 'resort_rb__for_each_entry'
+ - 'resource_list_for_each_entry'
+ - 'resource_list_for_each_entry_safe'
+ - 'rhl_for_each_entry_rcu'
+ - 'rhl_for_each_rcu'
+ - 'rht_for_each'
+ - 'rht_for_each_entry'
+ - 'rht_for_each_entry_from'
+ - 'rht_for_each_entry_rcu'
+ - 'rht_for_each_entry_rcu_from'
+ - 'rht_for_each_entry_safe'
+ - 'rht_for_each_from'
+ - 'rht_for_each_rcu'
+ - 'rht_for_each_rcu_from'
+ - 'rq_for_each_bvec'
+ - 'rq_for_each_segment'
+ - 'rq_list_for_each'
+ - 'rq_list_for_each_safe'
+ - 'sample_read_group__for_each'
+ - 'scsi_for_each_prot_sg'
+ - 'scsi_for_each_sg'
+ - 'sctp_for_each_hentry'
+ - 'sctp_skb_for_each'
+ - 'sec_for_each_insn'
+ - 'sec_for_each_insn_continue'
+ - 'sec_for_each_insn_from'
+ - 'sec_for_each_sym'
+ - 'shdma_for_each_chan'
+ - 'shost_for_each_device'
+ - 'sk_for_each'
+ - 'sk_for_each_bound'
+ - 'sk_for_each_bound_bhash2'
+ - 'sk_for_each_entry_offset_rcu'
+ - 'sk_for_each_from'
+ - 'sk_for_each_rcu'
+ - 'sk_for_each_safe'
+ - 'sk_nulls_for_each'
+ - 'sk_nulls_for_each_from'
+ - 'sk_nulls_for_each_rcu'
+ - 'snd_array_for_each'
+ - 'snd_pcm_group_for_each_entry'
+ - 'snd_soc_dapm_widget_for_each_path'
+ - 'snd_soc_dapm_widget_for_each_path_safe'
+ - 'snd_soc_dapm_widget_for_each_sink_path'
+ - 'snd_soc_dapm_widget_for_each_source_path'
+ - 'strlist__for_each_entry'
+ - 'strlist__for_each_entry_safe'
+ - 'sym_for_each_insn'
+ - 'sym_for_each_insn_continue_reverse'
+ - 'symbols__for_each_entry'
+ - 'tb_property_for_each'
+ - 'tcf_act_for_each_action'
+ - 'tcf_exts_for_each_action'
+ - 'ttm_resource_manager_for_each_res'
+ - 'twsk_for_each_bound_bhash2'
+ - 'udp_portaddr_for_each_entry'
+ - 'udp_portaddr_for_each_entry_rcu'
+ - 'usb_hub_for_each_child'
+ - 'v4l2_device_for_each_subdev'
+ - 'v4l2_m2m_for_each_dst_buf'
+ - 'v4l2_m2m_for_each_dst_buf_safe'
+ - 'v4l2_m2m_for_each_src_buf'
+ - 'v4l2_m2m_for_each_src_buf_safe'
+ - 'virtio_device_for_each_vq'
+ - 'while_for_each_ftrace_op'
+ - 'xa_for_each'
+ - 'xa_for_each_marked'
+ - 'xa_for_each_range'
+ - 'xa_for_each_start'
+ - 'xas_for_each'
+ - 'xas_for_each_conflict'
+ - 'xas_for_each_marked'
+ - 'xbc_array_for_each_value'
+ - 'xbc_for_each_key_value'
+ - 'xbc_node_for_each_array_value'
+ - 'xbc_node_for_each_child'
+ - 'xbc_node_for_each_key_value'
+ - 'xbc_node_for_each_subkey'
+ - 'zorro_for_each_dev'
+
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '.*'
+ Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentGotoLabels: false
+IndentPPDirectives: None
+IndentWidth: 8
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 8
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+
+# Taken from git's rules
+PenaltyBreakAssignment: 10
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: false
+SortUsingDeclarations: false
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatementsExceptForEachMacros
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
+...
diff --git a/src/tier4-camera-gmsl/Makefile b/src/tier4-camera-gmsl/Makefile
new file mode 100644
index 0000000..69dace0
--- /dev/null
+++ b/src/tier4-camera-gmsl/Makefile
@@ -0,0 +1,35 @@
+ARCH = arm64
+KDIR = /lib/modules/$(shell uname -r)/build/
+CROSS_COMPILE =
+
+ccflags-y += -DBUILD_STAMP="\"`date +'%Y-%m-%d %H:%M:%S'`\""
+
+obj-m := tier4-fpga.o tier4-gw5300.o tier4-imx490.o tier4-imx728.o tier4-isx021.o tier4-max9295.o tier4-max9296.o
+
+all: modules
+
+modules:
+ $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
+
+clean:
+ $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) clean
+
+load: modules unload
+ sudo insmod drivers/src/tier4-fpga.ko
+ sudo insmod drivers/src/tier4-max9295.ko
+ sudo insmod drivers/src/tier4-max9296.ko
+ sudo insmod drivers/src/tier4-gw5300.ko
+ sudo insmod drivers/src/tier4-isx021.ko
+ sudo insmod drivers/src/tier4-imx490.ko
+ sudo insmod drivers/src/tier4-imx728.ko
+
+unload:
+ sudo rmmod tier4-imx728 || true
+ sudo rmmod tier4-imx490 || true
+ sudo rmmod tier4-isx021 || true
+ sudo rmmod tier4-gw5300 || true
+ sudo rmmod tier4-max9296 || true
+ sudo rmmod tier4-max9295 || true
+ sudo rmmod tier4-fpga || true
+
+.PHONY: all modules clean load unload
diff --git a/drivers/src/Makefile b/src/tier4-camera-gmsl/Makefile.dkms
similarity index 91%
rename from drivers/src/Makefile
rename to src/tier4-camera-gmsl/Makefile.dkms
index f74d4ce..fd6e1cf 100644
--- a/drivers/src/Makefile
+++ b/src/tier4-camera-gmsl/Makefile.dkms
@@ -3,11 +3,13 @@ ARCH ?= $(shell uname -m | sed -e s/arm.*/arm/ -e s/aarch64.*/arm64/)
PWD ?= ${shell pwd}
BUILD_DIR ?= $(shell pwd)
_BUILD_DIR ?= $(shell readlink -f $(BUILD_DIR))
+EXTRA_MAKE_FLAGS =
Xavier_word := Xavier
Xavier_other_word_1 := Jetson-AGX
Orin_word := Orin
Orin_Compatible_word := p3737-0000+p3701-0000nvidia
+AGX_Orin_devkit := NVIDIA Jetson AGX Orin Developer Kit
ROScube_Xavier_word := 58G
ROScube_Xavier_Model_word := ROScube-Xavier
ROScube_Orin_word := 590
@@ -67,7 +69,22 @@ endif
$(warning MODEL = $(MODEL))
-ifeq ($(L4T_RELEASE_MAIN), R32)
+ifeq ($(L4T_RELEASE_MAIN), R36)
+ EXTRA_CFLAGS += -I /usr/src/nvidia/nvidia-oot/include/
+ KBUILD_EXTRA_SYMBOLS += /usr/src/nvidia/nvidia-oot/Module.symvers
+ EXTRA_MAKE_FLAGS += EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(KBUILD_EXTRA_SYMBOLS)"
+endif
+
+ifeq ($(MODEL),$(Anvil_Model_word))
+ KERNELRELEASE := $(shell uname -r)
+ L4T_RELEASE_MAIN_LOWER = $(shell echo $(L4T_RELEASE_MAIN) | tr A-Z a-z)
+ TARGET_ISX021_DTS := tier4-isx021-gmsl-device-tree-overlay-anvil-$(L4T_RELEASE_MAIN_LOWER)
+ TARGET_IMX490_DTS := tier4-imx490-gmsl-device-tree-overlay-anvil-$(L4T_RELEASE_MAIN_LOWER)
+ TARGET_IMX728_DTS := tier4-imx728-gmsl-device-tree-overlay-anvil-$(L4T_RELEASE_MAIN_LOWER)
+ TARGET_ISX021_IMX490_DTS := tier4-isx021-imx490-gmsl-device-tree-overlay-anvil-$(L4T_RELEASE_MAIN_LOWER)
+ TARGET_ISX021_IMX490_IMX728_DTS := tier4-isx021-imx490-imx728-gmsl-device-tree-overlay-anvil-$(L4T_RELEASE_MAIN_LOWER)
+ MAKE_OVERLAY_DTS_CMD := make_overlay_dts_anvil.py $(L4T_RELEASE_MAIN)
+else ifeq ($(L4T_RELEASE_MAIN), R32)
ifeq ($(L4T_RELEASE_MAJOR), 5)
ifeq ($(MODEL), $(ROScube_Xavier_Model_word))
KERNELRELEASE := 4.9.201-rqx58g
@@ -249,14 +266,6 @@ else ifeq ($(L4T_RELEASE_MAIN), R35)
TARGET_ISX021_IMX490_DTS := tier4-isx021-imx490-gmsl-device-tree-overlay-eac-5000-r3531
TARGET_ISX021_IMX490_IMX728_DTS := tier4-isx021-imx490-imx728-gmsl-device-tree-overlay-eac-5000-r3531
MAKE_OVERLAY_DTS_CMD := make_overlay_dts_eac-5000.py r35.3.1
- else ifeq ($(MODEL),$(Anvil_Model_word))
- KERNELRELEASE := 5.10.104-tegra
- TARGET_ISX021_DTS := tier4-isx021-gmsl-device-tree-overlay-anvil-r35
- TARGET_IMX490_DTS := tier4-imx490-gmsl-device-tree-overlay-anvil-r35
- TARGET_IMX728_DTS := tier4-imx728-gmsl-device-tree-overlay-anvil-r35
- TARGET_ISX021_IMX490_DTS := tier4-isx021-imx490-gmsl-device-tree-overlay-anvil-r35
- TARGET_ISX021_IMX490_IMX728_DTS := tier4-isx021-imx490-imx728-gmsl-device-tree-overlay-anvil-r35
- MAKE_OVERLAY_DTS_CMD := make_overlay_dts_anvil.py r35
else
KERNELRELEASE := 5.1.104-unknown
TARGET_ISX021_DTS := Unknown
@@ -265,6 +274,16 @@ else ifeq ($(L4T_RELEASE_MAIN), R35)
TARGET_ISX021_IMX490_DTS := Unknown
TARGET_ISX021_IMX490_IMX728_DTS := Unknown
endif
+else ifeq ($(L4T_RELEASE_MAIN), R36)
+ ifeq ($(dt_model),$(AGX_Orin_devkit))
+ KERNELRELEASE := 5.15.148-tegra
+ TARGET_ISX021_DTS := tier4-isx021-gmsl-device-tree-overlay-orin-devkit-r36
+ TARGET_IMX490_DTS := tier4-imx490-gmsl-device-tree-overlay-orin-devkit-r36
+ TARGET_IMX728_DTS := tier4-imx728-gmsl-device-tree-overlay-orin-devkit-r36
+ TARGET_ISX021_IMX490_DTS := tier4-isx021-imx490-gmsl-device-tree-overlay-orin-devkit-r36
+ TARGET_ISX021_IMX490_IMX728_DTS := tier4-isx021-imx490-imx728-gmsl-device-tree-overlay-orin-devkit-r36
+ MAKE_OVERLAY_DTS_CMD := make_overlay_dts_orin-devkit-r36.py r36
+ endif
else
KERNELRELEASE := Unknown
TARGET_ISX021_DTS := Unknown
@@ -315,7 +334,7 @@ obj-m := tier4-max9295.o tier4-max9296.o tier4-isx021.o tier4-imx490.o tier4-imx
all: binary_module modules dtbo
modules:
- $(MAKE) -C $(KERNEL_SRC_DIR) ARCH=$(ARCH) M=$(BUILD_DIR) src=$(PWD) modules
+ $(MAKE) -C $(KERNEL_SRC_DIR) ARCH=$(ARCH) M=$(BUILD_DIR) src=$(PWD) $(EXTRA_MAKE_FLAGS) modules
binary_module:
install -d $(DEST_FIRMWARE_DIR)
diff --git a/src/tier4-camera-gmsl/Makefile.r36 b/src/tier4-camera-gmsl/Makefile.r36
new file mode 100644
index 0000000..51af318
--- /dev/null
+++ b/src/tier4-camera-gmsl/Makefile.r36
@@ -0,0 +1,37 @@
+ARCH = arm64
+KDIR = /lib/modules/$(shell uname -r)/build/
+CROSS_COMPILE =
+EXTRA_CFLAGS = -I /usr/src/nvidia/nvidia-oot/include/
+KBUILD_EXTRA_SYMBOLS = /usr/src/nvidia/nvidia-oot/Module.symvers
+
+ccflags-y += -DBUILD_STAMP="\"`date +'%Y-%m-%d %H:%M:%S'`\""
+
+obj-m := tier4-fpga.o tier4-gw5300.o tier4-imx490.o tier4-imx728.o tier4-isx021.o tier4-max9295.o tier4-max9296.o
+
+all: modules
+
+modules:
+ $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(KBUILD_EXTRA_SYMBOLS)" modules
+
+clean:
+ $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) clean
+
+load: modules unload
+ sudo insmod drivers/src/tier4-fpga.ko
+ sudo insmod drivers/src/tier4-max9295.ko
+ sudo insmod drivers/src/tier4-max9296.ko
+ sudo insmod drivers/src/tier4-gw5300.ko
+ sudo insmod drivers/src/tier4-isx021.ko
+ sudo insmod drivers/src/tier4-imx490.ko
+ sudo insmod drivers/src/tier4-imx728.ko
+
+unload:
+ sudo rmmod tier4-imx728 || true
+ sudo rmmod tier4-imx490 || true
+ sudo rmmod tier4-isx021 || true
+ sudo rmmod tier4-gw5300 || true
+ sudo rmmod tier4-max9296 || true
+ sudo rmmod tier4-max9295 || true
+ sudo rmmod tier4-fpga || true
+
+.PHONY: all modules clean load unload
diff --git a/src/tier4-camera-gmsl/tier4-fpga.c b/src/tier4-camera-gmsl/tier4-fpga.c
new file mode 100644
index 0000000..8d47e46
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-fpga.c
@@ -0,0 +1,555 @@
+/*
+ * tier4_fpga.c - tier4_fpga driver
+ *
+ * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tier4-gmsl-link.h"
+#include "tier4-fpga.h"
+
+//#define DEBUG_INFO
+
+#define FPGA_ENABLED 0xF0
+#define FPGA_DISABLED 0xFF
+#define NO_ERROR 0
+
+#define FPGA_REG_VERSION_ADDR 0x1
+#define FPGA_REG_ENABLE_ADDR 0x4
+//#define FPGA_REG_FREQ_BASE_ADDR 0x8
+
+#define FREQ_10HZ 10
+#define FREQ_20HZ 20
+#define FREQ_30HZ 30
+
+static int fsync_mode; // 0: disabled, 1: enable auto mode, 2: enable manual mode
+
+module_param(fsync_mode, int, S_IRUGO | S_IWUSR);
+
+static int fps_cam1_cam2 = 0xCAFE;
+static int fps_cam3_cam4 = 0xCAFE;
+static int fps_cam5_cam6 = 0xCAFE;
+static int fps_cam7_cam8 = 0xCAFE;
+
+module_param(fps_cam1_cam2, int, S_IRUGO | S_IWUSR);
+module_param(fps_cam3_cam4, int, S_IRUGO | S_IWUSR);
+module_param(fps_cam5_cam6, int, S_IRUGO | S_IWUSR);
+module_param(fps_cam7_cam8, int, S_IRUGO | S_IWUSR);
+
+struct tier4_fpga {
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ struct tier4_gmsl_link_ctx g_ctx;
+ struct mutex lock;
+ /* FPGA slave address */
+ __u32 reg_addr;
+ // bool generate_fsync;
+};
+
+//static int generate_fsync;
+//module_param(generate_fsync, int, S_IRUGO | S_IWUSR);
+
+static struct regmap_config tier4_fpga_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+/* count channel */
+static __u32 channel_count_fpga; /* should be 1 */
+
+#if 1
+static int tier4_fpga_read_reg(struct device *dev, u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+ struct tier4_fpga *priv = dev_get_drvdata(dev);
+
+ err = regmap_read(priv->regmap, addr, ®_val);
+
+ *val = reg_val & 0xFF;
+
+ return err;
+}
+#endif
+
+static int tier4_fpga_write_reg(struct device *dev, u16 addr, u8 val)
+{
+ struct tier4_fpga *priv = dev_get_drvdata(dev);
+ int err = 0;
+
+ err = regmap_write(priv->regmap, addr, val);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] FPGA I2C write Reg at 0x%04X:[0x%02X] failed.\n",
+ __func__, addr, val);
+ }
+#ifdef DEBUG_INFO
+ else {
+ dev_info(dev, "[%s] FPGA I2C write Reg at 0x%04X:[0x%02X].\n",
+ __func__, addr, val);
+ }
+#endif
+
+ /* delay before next i2c command as required for SERDES link */
+ usleep_range(200, 220);
+ // tier4_fpga_read_reg(dev, addr, &e);
+ // usleep_range(100, 110);
+
+ return err;
+}
+
+int tier4_fpga_get_fsync_mode(void)
+{
+ return fsync_mode; // 0: disabled, 1: enable auto mode, 2: enable manual mode
+}
+EXPORT_SYMBOL(tier4_fpga_get_fsync_mode);
+
+int tier4_fpga_enable_fsync_mode(struct device *dev)
+{
+ int err = 0;
+ // u8 val = 0;
+
+ // err = tier4_fpga_read_reg(dev, FPGA_REG_MODE_ADDR, &val);
+ // if ((val & 0xFF) == FPGA_MODE_FSYNC) {
+ // // skip writing the same value to reg in order to save the flash write cycles
+ // dev_info(dev, "[%s] : Keep FSYNC mode enabled.\n", __func__);
+ // return err;
+ // }
+
+ err = tier4_fpga_write_reg(dev, FPGA_REG_MODE_ADDR, FPGA_MODE_FSYNC);
+ if (err) {
+ dev_err(dev, "[%s] Enabling FSYNC mode failed.\n", __func__);
+ }
+#ifdef DEBUG_INFO
+ else {
+ dev_info(dev, "[%s] Enabling FSYNC mode.\n", __func__);
+ }
+#endif
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_fpga_enable_fsync_mode);
+
+int tier4_fpga_disable_fsync_mode(struct device *dev)
+{
+ int err = 0;
+ // u8 val = 0;
+
+ // err = tier4_fpga_read_reg(dev, FPGA_REG_MODE_ADDR, &val);
+ // if ((val & 0xFF) == FPGA_MODE_FREE_RUN) {
+ // // skip writing the same value to reg in order to save the flash write cycles
+ // dev_info(dev, "[%s] : Keep FSYNC mode disabled.\n", __func__);
+ // return err;
+ // }
+
+ err = tier4_fpga_write_reg(dev, FPGA_REG_MODE_ADDR, FPGA_MODE_FREE_RUN);
+ if (err) {
+ dev_err(dev, "[%s] Disabling FSYNC mode failed.\n", __func__);
+ }
+#ifdef DEBUG_INFO
+ else {
+ dev_info(dev, "[%s] Disabling FSYNC mode.\n", __func__);
+ }
+#endif
+ return err;
+}
+EXPORT_SYMBOL(tier4_fpga_disable_fsync_mode);
+
+int tier4_fpga_set_fsync_auto_trigger(struct device *dev)
+{
+ int err = 0;
+ // u8 val = 0;
+
+ // err = tier4_fpga_read_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, &val);
+ // if ((val & 0xFF) == FPGA_FSYNC_AUTO) {
+ // // skip writing the same value to reg in order to save the flash write cycles
+ // dev_info(dev, "[%s] : Keep FSYNC Auto Trigger mode.\n", __func__);
+ // return err;
+ // }
+
+ err = tier4_fpga_write_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR,
+ FPGA_FSYNC_AUTO);
+ if (err) {
+ dev_err(dev, "[%s] Enabling FSYNC Auto Trigger mode failed.\n",
+ __func__);
+ }
+#ifdef DEBUG_INFO
+ else {
+ dev_info(dev, "[%s] Enabling FSYNC Auto Trigger mode.\n",
+ __func__);
+ }
+#endif
+ return err;
+}
+EXPORT_SYMBOL(tier4_fpga_set_fsync_auto_trigger);
+
+int tier4_fpga_set_fsync_manual_trigger(struct device *dev)
+{
+ int err = 0;
+ // u8 val = 0;
+
+ // err = tier4_fpga_read_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR, &val);
+ // if ((val & 0xFF) == FPGA_FSYNC_MANUAL) {
+ // // skip writing the same value to reg in order to save the flash write cycles
+ // dev_info(dev, "[%s] : Keep FSYNC Auto Trigger mode.\n", __func__);
+ // return err;
+ // }
+
+ err = tier4_fpga_write_reg(dev, FPGA_REG_FSYNC_TRIG_ADDR,
+ FPGA_FSYNC_MANUAL);
+ if (err) {
+ dev_err(dev,
+ "[%s] Enabling FSYNC Manual Trigger mode failed.\n",
+ __func__);
+ }
+#ifdef DEBUG_INFO
+ else {
+ dev_info(dev,
+ "[%s] Enabling FSYNC Manual Trigger mode failed.\n",
+ __func__);
+ }
+#endif
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_fpga_set_fsync_manual_trigger);
+
+// ***************
+
+int tier4_fpga_check_access(struct device *dev)
+{
+ int err = 0;
+ int i;
+ u8 dummy8 = 0;
+
+ for (i = 0; i < 5; i++) {
+ err = tier4_fpga_read_reg(dev, FPGA_REG_VERSION_ADDR, &dummy8);
+ if (!err) {
+ break;
+ }
+ usleep_range(10000, 11000); // sleep 10 msec
+ }
+
+ if (err) {
+ dev_err(dev, "[%s] Accessing FPGA failed.\n", __func__);
+ return err;
+ }
+ return NO_ERROR;
+}
+EXPORT_SYMBOL(tier4_fpga_check_access);
+
+static int tier4_fpga_get_fps_camx_camy(struct device *dev, int des_number,
+ int fps, int trigger_mode)
+{
+ int freq;
+ char str_fps_camx_camy[15] = "\0";
+
+#ifdef DEBUG_INFO
+ dev_info(dev, "[%s] dns_number=%d trigger_mode=%de.\n", __func__,
+ des_number, trigger_mode);
+#endif
+
+ switch (des_number) {
+ case 0:
+ strcpy(str_fps_camx_camy, "fps_cam1_cam2");
+ break;
+ case 1:
+ strcpy(str_fps_camx_camy, "fps_cam3_cam4");
+ break;
+ case 2:
+ strcpy(str_fps_camx_camy, "fps_cam5_cam6");
+ break;
+ case 3:
+ strcpy(str_fps_camx_camy, "fps_cam7_cam8");
+ break;
+ default:
+ strcpy(str_fps_camx_camy, "fps_cam?_cam?");
+ break;
+ }
+
+ if (trigger_mode == 1) {
+ if ((fps > 5) && (fps <= 10)) {
+ freq = fps;
+ } else {
+ freq = FREQ_10HZ;
+ dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.",
+ __func__, str_fps_camx_camy, fps,
+ str_fps_camx_camy, freq);
+ }
+ } else if (trigger_mode == 3) {
+ if ((fps > 10) && (fps <= 20)) {
+ freq = fps;
+ } else {
+ freq = FREQ_20HZ;
+ dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.",
+ __func__, str_fps_camx_camy, fps,
+ str_fps_camx_camy, freq);
+ }
+ } else if (trigger_mode == 5) {
+ if ((fps > 20) && (fps <= 30)) {
+ freq = fps;
+ } else {
+ freq = FREQ_30HZ;
+ dev_info(dev, "[%s] Invalid %s:%d, Set %s to %d.",
+ __func__, str_fps_camx_camy, fps,
+ str_fps_camx_camy, freq);
+ }
+ }
+
+#ifdef DEBUG_INFO
+ dev_info(dev, "[%s] freq=%d.\n", __func__, freq);
+#endif
+
+ return freq;
+}
+
+// --------------------------------------------
+
+int tier4_fpga_set_fsync_signal_frequency(struct device *dev, int des_number,
+ int trigger_mode)
+{
+ int err = 0;
+ u8 val8, addr8;
+ int freq = 0;
+ // u8 read_val = 0;
+ u8 freq_bitmask = 0x3F; // bit[0:5]
+
+ switch (des_number) {
+ case 0:
+ freq = tier4_fpga_get_fps_camx_camy(
+ dev, des_number, fps_cam1_cam2, trigger_mode);
+ break;
+ case 1:
+ freq = tier4_fpga_get_fps_camx_camy(
+ dev, des_number, fps_cam3_cam4, trigger_mode);
+ break;
+ case 2:
+ freq = tier4_fpga_get_fps_camx_camy(
+ dev, des_number, fps_cam5_cam6, trigger_mode);
+ break;
+ case 3:
+ freq = tier4_fpga_get_fps_camx_camy(
+ dev, des_number, fps_cam7_cam8, trigger_mode);
+ break;
+ default:
+ dev_err(dev, "[%s] Invalid des_number(%d)\n", __func__,
+ des_number);
+ break;
+ }
+
+ addr8 = (u8)(FPGA_REG_FREQ_BASE_ADDR + 12 * (des_number));
+ val8 = (u8)(freq & freq_bitmask);
+
+#ifdef DEBUG_INFO
+ dev_info(dev, "[%s] freq=%d.\n", __func__, freq);
+#endif
+
+ // err = tier4_fpga_read_reg(dev, addr8, &read_val);
+ // if ((read_val & freq_bitmask) == val8) {
+ // // skip writing the same value to reg in order to save the flash write cycles
+ // dev_info(dev, "[%s] : Keep the frequency of fsync trigger to %d\n", __func__, val8);
+ // return err;
+ // }
+
+ err = tier4_fpga_write_reg(dev, addr8, val8);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] Setting the frequency of fsync trigger failed.\n",
+ __func__);
+ return err;
+ } else {
+ dev_info(dev,
+ "[%s] Setting the frequency of fsync trigger to %d.\n",
+ __func__, val8);
+ }
+
+ return NO_ERROR;
+}
+EXPORT_SYMBOL(tier4_fpga_set_fsync_signal_frequency);
+
+int tier4_fpga_get_slave_addr(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx)
+{
+ struct tier4_fpga *priv = dev_get_drvdata(dev);
+
+ if (!g_ctx) {
+ dev_err(dev, "[%s] g_ctx is null\n", __func__);
+ return -1;
+ }
+
+ g_ctx->sdev_fpga_reg = priv->reg_addr;
+
+ return 0;
+}
+EXPORT_SYMBOL(tier4_fpga_get_slave_addr);
+
+const struct of_device_id tier4_fpga_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_fpga",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tier4_fpga_of_match);
+
+// -----------------------------------------------------
+
+static int tier4_fpga_parse_dt(struct tier4_fpga *priv,
+ struct i2c_client *client)
+{
+ struct device_node *node = client->dev.of_node;
+ int err = 0;
+
+ if (!node)
+ return -EINVAL;
+
+ err = of_property_read_u32(node, "reg", &priv->reg_addr);
+ if (err < 0) {
+ dev_err(&client->dev, "[%s] fpga reg not found\n", __func__);
+ return -EINVAL;
+ }
+
+ priv->g_ctx.sdev_fpga_reg = priv->reg_addr;
+
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------
+
+static int tier4_fpga_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tier4_fpga *priv;
+ int err = 0;
+ int inhibit_fpga_access = 0;
+
+ dev_info(&client->dev, "[%s] probing FPGA\n", __func__);
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ priv->i2c_client = client;
+
+ priv->regmap = devm_regmap_init_i2c(priv->i2c_client,
+ &tier4_fpga_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&client->dev, "[%s] devm_regmap_init() failed: %ld\n",
+ __func__, PTR_ERR(priv->regmap));
+ return -ENODEV;
+ }
+
+ err = tier4_fpga_parse_dt(priv, client);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] Unable to parse fpga dt\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ mutex_init(&priv->lock);
+
+ dev_set_drvdata(&client->dev, priv);
+
+ err = tier4_fpga_check_access(&client->dev);
+
+ if (err) {
+ inhibit_fpga_access = 1;
+ }
+
+ // default mode is disabling gnereation of fsync
+
+ err = tier4_fpga_disable_fsync_mode(&client->dev);
+
+ if (err < 0) {
+ dev_err(&client->dev,
+ "[%s] Unable to disable generation of fsync.\n",
+ __func__);
+ if (inhibit_fpga_access) {
+ return NO_ERROR;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ channel_count_fpga++;
+
+ dev_info(&client->dev, "[%s] Probing FPGA succeeded.\n", __func__);
+
+ return err;
+}
+
+static int tier4_fpga_remove(struct i2c_client *client)
+{
+ struct tier4_fpga *priv;
+
+ if (channel_count_fpga > 0)
+ channel_count_fpga--;
+
+ if (client != NULL) {
+ priv = dev_get_drvdata(&client->dev);
+ mutex_destroy(&priv->lock);
+ }
+
+ return 0;
+}
+
+// ----------------------------------------------
+
+static const struct i2c_device_id tier4_fpga_id[] = {
+ { "tier4_fpga", 0 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tier4_fpga_id);
+
+static struct i2c_driver tier4_fpga_i2c_driver = {
+ .driver = {
+ .name = "tier4_fpga",
+ .owner = THIS_MODULE,
+ },
+ .probe = tier4_fpga_probe,
+ .remove = tier4_fpga_remove,
+ .id_table = tier4_fpga_id,
+};
+
+static int __init tier4_fpga_init(void)
+{
+ printk("FPGA Driver for Tier4 Cameras.\n");
+
+ return i2c_add_driver(&tier4_fpga_i2c_driver);
+}
+
+static void __exit tier4_fpga_exit(void)
+{
+ i2c_del_driver(&tier4_fpga_i2c_driver);
+}
+
+module_init(tier4_fpga_init);
+module_exit(tier4_fpga_exit);
+
+MODULE_DESCRIPTION("FPGA driver tier4_fpga");
+MODULE_AUTHOR("Kohji Iwasaki");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-fpga.h b/src/tier4-camera-gmsl/tier4-fpga.h
similarity index 83%
rename from drivers/src/tier4-fpga.h
rename to src/tier4-camera-gmsl/tier4-fpga.h
index dc65fab..a34cef0 100644
--- a/drivers/src/tier4-fpga.h
+++ b/src/tier4-camera-gmsl/tier4-fpga.h
@@ -23,21 +23,21 @@
#define __TIER4_FPGA_H__
-#define FPGA_REG_MODE_ADDR 0x04
-#define FPGA_MODE_FREE_RUN 0xF0 // camera master mode, default 30 FPS
-#define FPGA_MODE_FSYNC 0xFF // camera slave mode, triggered by FSYNC signal
+#define FPGA_REG_MODE_ADDR 0x04
+#define FPGA_MODE_FREE_RUN 0xF0 // camera master mode, default 30 FPS
+#define FPGA_MODE_FSYNC 0xFF // camera slave mode, triggered by FSYNC signal
-#define FPGA_REG_FSYNC_TRIG_ADDR 0x05
-#define FPGA_FSYNC_MANUAL 0x00 // manually triggered by external GPIO
-#define FPGA_FSYNC_AUTO 0xF0 // automatically triggered by FPGA itself
+#define FPGA_REG_FSYNC_TRIG_ADDR 0x05
+#define FPGA_FSYNC_MANUAL 0x00 // manually triggered by external GPIO
+#define FPGA_FSYNC_AUTO 0xF0 // automatically triggered by FPGA itself
#define FPGA_FSYNC_MODE_DISABLE 0
-#define FPGA_FSYNC_MODE_AUTO 1
-#define FPGA_FSYNC_MODE_MANUAL 2
+#define FPGA_FSYNC_MODE_AUTO 1
+#define FPGA_FSYNC_MODE_MANUAL 2
#define NO_ERROR 0
-#define FPGA_REG_FREQ_BASE_ADDR 0x08
+#define FPGA_REG_FREQ_BASE_ADDR 0x08
#define FPGA_SLAVE_MODE_10FPS 10
#define FPGA_SLAVE_MODE_30FPS 30
@@ -130,7 +130,8 @@ int tier4_fpga_set_fsync_manual_trigger(struct device *dev);
* @return 0 for success, or -1 otherwise.
*/
-int tier4_fpga_set_fsync_signal_frequency(struct device *dev, int des_number, int trigger_mode);
+int tier4_fpga_set_fsync_signal_frequency(struct device *dev, int des_number,
+ int trigger_mode);
/**
* check access to FPGA.
@@ -151,6 +152,7 @@ int tier4_fpga_check_access(struct device *dev);
* @return 0 for success, or -1 otherwise.
*/
-int tier4_fpga_get_slave_addr(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx);
+int tier4_fpga_get_slave_addr(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx);
#endif /* __TIER4_FPGA_H__ */
diff --git a/drivers/src/tier4-gmsl-link.h b/src/tier4-camera-gmsl/tier4-gmsl-link.h
similarity index 61%
rename from drivers/src/tier4-gmsl-link.h
rename to src/tier4-camera-gmsl/tier4-gmsl-link.h
index 8059589..7b297ed 100644
--- a/drivers/src/tier4-gmsl-link.h
+++ b/src/tier4-camera-gmsl/tier4-gmsl-link.h
@@ -71,48 +71,46 @@
/**
* Holds information about a data stream in a GMSL link (\ref tier4_gmsl_link_ctx).
*/
-struct tier4_gmsl_stream
-{
- __u32 st_id_sel;
- __u32 st_data_type;
- __u32 des_pipe;
+struct tier4_gmsl_stream {
+ __u32 st_id_sel;
+ __u32 st_data_type;
+ __u32 des_pipe;
};
/**
* Holds the configuration of the GMSL links from a sensor to its serializer to
* its deserializer.
*/
-struct tier4_gmsl_link_ctx
-{
- __u32 st_vc; /**< Default sensor virtual channel. */
- __u32 dst_vc; /**< Destination virtual channel (user-defined). */
- __u32 src_csi_port; /**< Sensor to serializer CSI port connection. */
- __u32 dst_csi_port; /**< Deserializer to Jetson CSI port connection. */
- __u32 serdes_csi_link; /**< GMSL link between serializer and deserializer
+struct tier4_gmsl_link_ctx {
+ __u32 st_vc; /**< Default sensor virtual channel. */
+ __u32 dst_vc; /**< Destination virtual channel (user-defined). */
+ __u32 src_csi_port; /**< Sensor to serializer CSI port connection. */
+ __u32 dst_csi_port; /**< Deserializer to Jetson CSI port connection. */
+ __u32 serdes_csi_link; /**< GMSL link between serializer and deserializer
devices. */
- __u32 num_streams; /**< Number of active streams to be mapped
+ __u32 num_streams; /**< Number of active streams to be mapped
from sensor. */
- __u32 num_csi_lanes; /**< Sensor's CSI lane configuration. */
- __u32 csi_mode; /**< Deserializer CSI mode. */
- __u32 ser_reg; /**< Serializer slave address. */
- __u32 sdev_reg; /**< Sensor proxy slave address. */
- __u32 sdev_def; /**< Sensor default slave address. */
- __u32 reg_mux;
- bool serdev_found; /**< Indicates whether the serializer device for
+ __u32 num_csi_lanes; /**< Sensor's CSI lane configuration. */
+ __u32 csi_mode; /**< Deserializer CSI mode. */
+ __u32 ser_reg; /**< Serializer slave address. */
+ __u32 sdev_reg; /**< Sensor proxy slave address. */
+ __u32 sdev_def; /**< Sensor default slave address. */
+ __u32 reg_mux;
+ bool serdev_found; /**< Indicates whether the serializer device for
the specified sensor source was found. Set by
the serializer driver during setup; used by
the deserializer driver to choose certain
configuration settings during setup. */
- struct tier4_gmsl_stream streams[GMSL_DEV_MAX_NUM_DATA_STREAMS];
- /*< An array of information about the data streams in the link. */
- __u32 sensor_id; /**< Sensor ID 21:isx021 or 490:imx490 */
- __u32 sdev_isp_reg; /**< Sensor or ISP proxy slave address. */
- __u32 sdev_isp_def; /**< Sensor or ISP default slave address. */
- __u32 sdev_fpga_reg; /**< FPGA default slave address. */
- struct device *s_dev; /**< Sensor device handle. */
- __u32 hardware_model; /**< ROScube, Xavier or Orin . */
-// bool fpga_generate_fsync; /**< Indicates whther FPGA generate fsync or not . */
-// int debug_i2c_write; /**< Debug flag for i2c write */
+ struct tier4_gmsl_stream streams[GMSL_DEV_MAX_NUM_DATA_STREAMS];
+ /*< An array of information about the data streams in the link. */
+ __u32 sensor_id; /**< Sensor ID 21:isx021 or 490:imx490 */
+ __u32 sdev_isp_reg; /**< Sensor or ISP proxy slave address. */
+ __u32 sdev_isp_def; /**< Sensor or ISP default slave address. */
+ __u32 sdev_fpga_reg; /**< FPGA default slave address. */
+ struct device *s_dev; /**< Sensor device handle. */
+ __u32 hardware_model; /**< ROScube, Xavier or Orin . */
+ // bool fpga_generate_fsync; /**< Indicates whther FPGA generate fsync or not . */
+ // int debug_i2c_write; /**< Debug flag for i2c write */
};
/** @} */
diff --git a/src/tier4-camera-gmsl/tier4-gw5300.c b/src/tier4-camera-gmsl/tier4-gw5300.c
new file mode 100644
index 0000000..c28d743
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-gw5300.c
@@ -0,0 +1,933 @@
+/*
+ * tier4_gw5300.c - tier4_gw5300 ISP driver
+ *
+ * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+
+#include "tier4-gmsl-link.h"
+#include "tier4-gw5300.h"
+
+struct tier4_gw5300 {
+ struct i2c_client *i2c_client;
+ struct tier4_gmsl_link_ctx g_client;
+ struct mutex lock;
+ /* primary ISP properties */
+ __u32 def_addr;
+};
+
+#define MAX_CHANNEL_NUM 8
+
+#define NO_ERROR 0
+
+/* count channel,the max MAX_CHANNEL_NUM*/
+static __u32 channel_count_gw5300;
+
+static struct tier4_gw5300 *prim_priv__[MAX_CHANNEL_NUM];
+
+static u8 master_30fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x00, 0x00, 0x6A };
+
+static u8 master_10fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x1E, 0x00, 0x00, 0x00, 0x38 };
+
+static u8 slave_10fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x42 };
+
+static u8 master_20fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x5A, 0x00, 0x00, 0x00, 0x74 };
+
+static u8 slave_20fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x5F, 0x00, 0x00, 0x00, 0x79 };
+
+static u8 slave_30fps[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x55, 0x00, 0x00, 0x00, 0x6F };
+
+static u8 master_10fps_slow[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x17 };
+
+static u8 slave_10fps_slow[] = { 0x33, 0x47, 0x0B, 0x00, 0x00, 0x00,
+ 0x12, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x4B, 0x00, 0x00, 0x00, 0x65 };
+
+/*
+ * C3 camera mode support
+ */
+struct mode_command {
+ u8 *command;
+ size_t len;
+ unsigned int delay_ms;
+};
+
+#define MODE_CMD(cmd, delay) \
+ { \
+ .command = (cmd), .len = sizeof(cmd), .delay_ms = delay, \
+ }
+
+#define NUM_VA_ARGS(type, ...) (sizeof((type[]){ __VA_ARGS__ }) / sizeof(type))
+
+#define MODE_SEQ(h_line_time_ns, ...) \
+ { \
+ .commands = (struct mode_command[]){ __VA_ARGS__ }, \
+ .len = NUM_VA_ARGS(struct mode_command, __VA_ARGS__), \
+ .h_line_ns = (h_line_time_ns) \
+ }
+
+struct mode_sequence {
+ struct mode_command *commands;
+ size_t len;
+ u32 h_line_ns;
+};
+
+/*
+ * C3 preset modes
+ */
+
+static u8 c3_master_5fps_cmd[] = { 0x33, 0x47, 0xb, 0x0, 0x0, 0x0,
+ 0x12, 0x0, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x17 };
+
+/* mode 0 */
+static struct mode_sequence c3_master_5fps_seq =
+ MODE_SEQ(40000, MODE_CMD(c3_master_5fps_cmd, 0), );
+
+/* mode 4 */
+static u8 c3_master_20fps_cmd[] = { 0x33, 0x47, 0xb, 0x0, 0x0, 0x0,
+ 0x12, 0x0, 0x80, 0x3, 0x0, 0x0,
+ 0x0, 0x4b, 0x0, 0x0, 0x0, 0x65 };
+static struct mode_sequence c3_master_20fps_seq =
+ MODE_SEQ(20000, MODE_CMD(c3_master_20fps_cmd, 0));
+
+static u8 c3_master_20fps_ebd_cmd[] = { 0x33, 0x47, 0xb, 0x0, 0x0, 0x0,
+ 0x12, 0x0, 0x80, 0x3, 0x0, 0x0,
+ 0x0, 0x50, 0x0, 0x0, 0x0, 0x6a };
+
+/* mode 10 */
+static struct mode_sequence c3_master_20fps_ebd_seq =
+ MODE_SEQ(20000, MODE_CMD(c3_master_20fps_ebd_cmd, 0));
+
+static u8 c3_master_30fps_cmd[] = { 0x33, 0x47, 0xb, 0x0, 0x0, 0x0,
+ 0x12, 0x0, 0x80, 0x3, 0x0, 0x0,
+ 0x0, 0x1e, 0x0, 0x0, 0x0, 0x38 };
+
+/* mode 6 */
+static struct mode_sequence c3_master_30fps_seq =
+ MODE_SEQ(13890, MODE_CMD(c3_master_30fps_cmd, 0));
+
+static u8 c3_master_30fps_ebd_cmd[] = { 0x33, 0x47, 0xb, 0x0, 0x0, 0x0,
+ 0x12, 0x0, 0x80, 0x3, 0x0, 0x0,
+ 0x0, 0x28, 0x0, 0x0, 0x0, 0x42 };
+
+/* mode 12 */
+static struct mode_sequence c3_master_30fps_ebd_seq =
+ MODE_SEQ(13890, MODE_CMD(c3_master_30fps_ebd_cmd, 0));
+
+/*
+ * C3 derived modes
+ */
+static u8 c3_regmap_ffff[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x25 };
+
+static u8 c3_standby_mode[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0x4, 0x1b, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x2, 0x1, 0x45 };
+
+static u8 c3_drive_mode_sel[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0,
+ 0x1, 0x0, 0x0, 0x0, 0x2, 0x1, 0x68 };
+
+static u8 c3_master_sync_mode[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0x41, 0x0, 0x0, 0x0,
+ 0x5, 0x0, 0x0, 0x0, 0x2, 0x1, 0x6d };
+
+static u8 c3_sensor_streaming[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0x4, 0x1b, 0x0, 0x0,
+ 0x5c, 0x0, 0x0, 0x0, 0x2, 0x1, 0xa2 };
+
+static u8 c3_master_sync_mode_2[] = { 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0,
+ 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x34,
+ 0x0, 0x0, 0x0, 0x4, 0x1b, 0x0, 0x0,
+ 0xa3, 0x0, 0x0, 0x0, 0x2, 0x1, 0xe9 };
+
+/* mode 1 */
+static struct mode_sequence c3_slave_5fps_seq = MODE_SEQ(
+ 40000, MODE_CMD(c3_master_5fps_cmd, 5000),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+static u8 c3_20_to_10fps_cmd_1[] = {
+ 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1,
+ 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x50, 0x97, 0x0,
+ 0x0, 0xc4, 0x0, 0x0, 0x0, 0x2, 0x1, 0xd2,
+};
+
+static u8 c3_20_to_10fps_cmd_2[] = {
+ 0x33, 0x47, 0x15, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x80, 0x1,
+ 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x51, 0x97, 0x0,
+ 0x0, 0x09, 0x0, 0x0, 0x0, 0x2, 0x1, 0x18,
+};
+
+/* mode 2 */
+static struct mode_sequence c3_master_10fps_seq =
+ MODE_SEQ(20000, MODE_CMD(c3_master_20fps_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500), );
+
+/* mode 3 */
+static struct mode_sequence c3_slave_10fps_seq = MODE_SEQ(
+ 20000, MODE_CMD(c3_master_20fps_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+/* mode 5 */
+static struct mode_sequence c3_slave_20fps_seq = MODE_SEQ(
+ 20000, MODE_CMD(c3_master_20fps_cmd, 5000),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+/* mode 7 */
+static struct mode_sequence c3_slave_30fps_seq = MODE_SEQ(
+ 13890, MODE_CMD(c3_master_30fps_cmd, 5000),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+/* mode 8 */
+static struct mode_sequence c3_master_10fps_ebd_seq =
+ MODE_SEQ(20000, MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500), );
+
+/* mode 9 */
+static struct mode_sequence c3_slave_10fps_ebd_seq = MODE_SEQ(
+ 20000, MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+/* mode 11 */
+static struct mode_sequence c3_slave_20fps_ebd_seq = MODE_SEQ(
+ 20000, MODE_CMD(c3_master_20fps_ebd_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+/* mode 13 */
+static struct mode_sequence c3_slave_30fps_ebd_seq = MODE_SEQ(
+ 13890, MODE_CMD(c3_master_30fps_ebd_cmd, 5000),
+
+ MODE_CMD(c3_20_to_10fps_cmd_1, 2000),
+ MODE_CMD(c3_20_to_10fps_cmd_2, 500),
+
+ MODE_CMD(c3_regmap_ffff, 500), MODE_CMD(c3_standby_mode, 500),
+ MODE_CMD(c3_drive_mode_sel, 500), MODE_CMD(c3_master_sync_mode, 500),
+ MODE_CMD(c3_sensor_streaming, 500),
+ MODE_CMD(c3_master_sync_mode_2, 500), );
+
+static struct mode_sequence c3_mode_seqs[GW5300_MODE_MAX];
+
+struct map_ctx {
+ u8 dt;
+ u16 addr;
+ u8 val;
+ u8 st_id;
+};
+
+#if 0
+static int tier4_gw5300_receive_msg(struct device *dev, u8 *data, int data_size )
+{
+ int err = 0;
+ struct i2c_msg msg;
+ struct tier4_gw5300 *priv = dev_get_drvdata(dev);
+
+ msg.addr = priv->i2c_client->addr;
+ msg.flags = I2C_M_RD; // I2C Read
+ msg.len = data_size;
+ msg.buf = data;
+
+ err = i2c_transfer(priv->i2c_client->adapter, &msg, 1);
+
+ if (err <= 0 ) {
+ dev_err(dev, "[%s] : i2c_transer receive message failed : slave addr = 0x%x\n", __func__, msg.addr );
+ }
+
+ return err;
+}
+#endif
+
+// -------------------------------------------------------------------
+
+static int tier4_gw5300_send_and_recv_msg(struct device *dev, u8 *wdata,
+ int wdata_size, u8 *rdata,
+ int rdata_size)
+{
+ int err = 0;
+ struct i2c_msg msg[2];
+ struct tier4_gw5300 *priv = dev_get_drvdata(dev);
+
+ msg[0].addr = priv->i2c_client->addr;
+ msg[0].flags = 0; // I2C Write
+ msg[0].len = wdata_size;
+ msg[0].buf = wdata;
+
+ msg[1].addr = priv->i2c_client->addr;
+ msg[1].flags = I2C_M_RD; // I2C Read
+ msg[1].len = rdata_size;
+ msg[1].buf = rdata;
+
+ err = i2c_transfer(priv->i2c_client->adapter, msg, 2);
+
+ if (err <= 0) {
+ dev_err(dev,
+ "[%s] : i2c_transer send message failed. %d: slave addr = 0x%x\n",
+ __func__, err, msg[0].addr);
+ }
+
+ return err; // the total number of bytes to have been sent or recived
+}
+
+// -------------------------------------------------------------------
+
+static int tier4_gw5300_c3_send_and_recv_msg(struct device *dev, u8 *wdata,
+ int wdata_size, u8 *rdata,
+ int rdata_size)
+{
+ return tier4_gw5300_send_and_recv_msg(dev, wdata, wdata_size, rdata,
+ rdata_size);
+}
+
+static int
+tier4_gw5300_mode_seq_send_and_recv_msg(struct device *dev,
+ struct mode_sequence *mode_seq,
+ u8 *rdata, int rdata_size)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < mode_seq->len; ++i) {
+ struct mode_command *cmd = &mode_seq->commands[i];
+
+ err = tier4_gw5300_send_and_recv_msg(
+ dev, cmd->command, cmd->len, rdata, rdata_size);
+ msleep(cmd->delay_ms);
+ if (err < 0) {
+ dev_err(dev, "%s: Failed to send a command[%d]: %d\n",
+ __func__, i, err);
+ break;
+ }
+ }
+
+ return err;
+}
+
+// -------------------------------------------------------------------
+
+uint8_t calcCheckSum(const uint8_t *data, size_t size)
+{
+ uint8_t result = 0;
+ size_t i = 0;
+ for (i = 0; i < size; i++) {
+ result += data[i];
+ }
+ return result;
+}
+
+int tier4_gw5300_set_integration_time_on_aemode(struct device *dev,
+ u32 h_line_ns,
+ u32 max_integration_time,
+ u32 min_integration_time)
+{
+ u8 buf[6];
+ int ret = 0;
+
+ u8 cmd_integration_max[22] = {
+ 0x33, 0x47, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x00,
+ 0x80, 0x05, 0x00, 0x15, 0x00, 0x01, 0x00, 0x04,
+ 0x00, 0x70, 0x03, 0x00, 0x00, 0x00
+ }; // val = 0x70, 0x03, 0x00, 0x00
+ u8 cmd_integration_min[20] = {
+ 0x33, 0x47, 0x0d, 0x00, 0x00, 0x00, 0x55, 0x00, 0x80, 0x05,
+ 0x00, 0x21, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x03, 0x00
+ }; //val = 0x70, 0x03
+
+ const size_t max_val_pos = 17;
+ const size_t min_val_pos = 17;
+ uint32_t min_line =
+ DIV_ROUND_CLOSEST(min_integration_time * 1000, h_line_ns);
+ uint32_t max_line =
+ DIV_ROUND_CLOSEST(max_integration_time * 1000, h_line_ns);
+ uint8_t b1 = max_line & 0xFF;
+ uint8_t b2 = (max_line >> 8) & 0xFF;
+ uint8_t b3 = 0;
+ uint8_t b4 = 0;
+
+ dev_info(
+ dev,
+ "%s: integration time(%u[ns/H line]): max=(%d[us], %d[line]) min=(%d[us], %d[line])\n",
+ __func__, h_line_ns, max_integration_time, max_line,
+ min_integration_time, min_line);
+
+ cmd_integration_max[max_val_pos] = b1;
+ cmd_integration_max[max_val_pos + 1] = b2;
+ cmd_integration_max[max_val_pos + 2] = b3;
+ cmd_integration_max[max_val_pos + 3] = b4;
+ cmd_integration_max[sizeof(cmd_integration_max) - 1] =
+ calcCheckSum(cmd_integration_max, sizeof(cmd_integration_max));
+
+ b1 = min_line & 0xFF;
+ b2 = (min_line >> 8) & 0xFF;
+
+ cmd_integration_min[min_val_pos] = b1;
+ cmd_integration_min[min_val_pos + 1] = b2;
+
+ cmd_integration_min[sizeof(cmd_integration_min) - 1] =
+ calcCheckSum(cmd_integration_min, sizeof(cmd_integration_min));
+
+ msleep(20);
+ ret += tier4_gw5300_send_and_recv_msg(dev, cmd_integration_max,
+ sizeof(cmd_integration_max), buf,
+ sizeof(buf));
+ msleep(20);
+ ret += tier4_gw5300_send_and_recv_msg(dev, cmd_integration_min,
+ sizeof(cmd_integration_min), buf,
+ sizeof(buf));
+
+ return ret;
+}
+
+int tier4_gw5300_c2_set_integration_time_on_aemode(struct device *dev,
+ int trigger_mode,
+ u32 max_integration_time,
+ u32 min_integration_time)
+{
+ size_t h_line_ns = 12500;
+
+ if (trigger_mode == GW5300_MASTER_MODE_10FPS_SLOW ||
+ trigger_mode == GW5300_SLAVE_MODE_10FPS_SLOW)
+ h_line_ns = 50000;
+
+ return tier4_gw5300_set_integration_time_on_aemode(
+ dev, h_line_ns, max_integration_time, min_integration_time);
+}
+EXPORT_SYMBOL(tier4_gw5300_c2_set_integration_time_on_aemode);
+
+int tier4_gw5300_c3_set_integration_time_on_aemode(struct device *dev,
+ int trigger_mode,
+ u32 max_integration_time,
+ u32 min_integration_time)
+{
+ return tier4_gw5300_set_integration_time_on_aemode(
+ dev, c3_mode_seqs[trigger_mode].h_line_ns, max_integration_time,
+ min_integration_time);
+}
+EXPORT_SYMBOL(tier4_gw5300_c3_set_integration_time_on_aemode);
+
+// ------------------------------------------------------------------
+
+int tier4_gw5300_set_distortion_correction(struct device *dev, bool val)
+{
+ int ret = 0;
+ u8 buf[6];
+ u8 cmd_dwp_on[] = { 0x33, 0x47, 0x06, 0x00, 0x00, 0x00, 0x4d,
+ 0x00, 0x80, 0x04, 0x00, 0x01, 0x52 };
+ u8 cmd_dwp_off[] = { 0x33, 0x47, 0x03, 0x00, 0x00,
+ 0x00, 0x45, 0x00, 0x80, 0x42 };
+
+ if (val) {
+ ret += tier4_gw5300_send_and_recv_msg(
+ dev, cmd_dwp_on, sizeof(cmd_dwp_on), buf, sizeof(buf));
+ } else {
+ ret += tier4_gw5300_send_and_recv_msg(dev, cmd_dwp_off,
+ sizeof(cmd_dwp_off), buf,
+ sizeof(buf));
+ }
+ return ret;
+}
+EXPORT_SYMBOL(tier4_gw5300_set_distortion_correction);
+
+// ------------------------------------------------------------------
+
+int tier4_gw5300_c3_set_distortion_correction(struct device *dev, bool val)
+{
+ int ret = 0;
+ u8 buf[6];
+ u8 cmd_dwp_on[] = { 0x33, 0x47, 0x6, 0x00, 0x00, 0x00, 0x4d,
+ 0x00, 0x80, 0x04, 0x00, 0x01, 0x52 };
+ u8 cmd_dwp_off[] = { 0x33, 0x47, 0x3, 0x00, 0x00,
+ 0x00, 0x45, 0x00, 0x80, 0x042 };
+
+ if (val) {
+ ret += tier4_gw5300_c3_send_and_recv_msg(
+ dev, cmd_dwp_on, sizeof(cmd_dwp_on), buf, sizeof(buf));
+ } else {
+ ret += tier4_gw5300_c3_send_and_recv_msg(dev, cmd_dwp_off,
+ sizeof(cmd_dwp_off),
+ buf, sizeof(buf));
+ }
+ return ret;
+}
+EXPORT_SYMBOL(tier4_gw5300_c3_set_distortion_correction);
+
+// ------------------------------------------------------------------
+
+int tier4_gw5300_c3_set_auto_exposure(struct device *dev, bool val)
+{
+ int ret = 0;
+ u8 buf[6];
+ u8 cmd_auto_exp_on[] = { 0x33, 0x47, 0x0C, 0x00, 0x00, 0x00, 0x55,
+ 0x00, 0x80, 0x05, 0x00, 0x07, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x69 };
+ u8 cmd_auto_exp_off[] = { 0x33, 0x47, 0x0C, 0x00, 0x00, 0x00, 0x55,
+ 0x00, 0x80, 0x05, 0x00, 0x07, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x01, 0x6A };
+
+ dev_info(dev, "%s: auto exposure is %s\n", __func__,
+ val ? "on" : "off");
+
+ if (val) {
+ ret += tier4_gw5300_c3_send_and_recv_msg(
+ dev, cmd_auto_exp_on, sizeof(cmd_auto_exp_on), buf,
+ sizeof(buf));
+ } else {
+ ret += tier4_gw5300_c3_send_and_recv_msg(
+ dev, cmd_auto_exp_off, sizeof(cmd_auto_exp_off), buf,
+ sizeof(buf));
+ }
+ return ret;
+}
+EXPORT_SYMBOL(tier4_gw5300_c3_set_auto_exposure);
+
+// ------------------------------------------------------------------
+
+int tier4_gw5300_check_device(struct device *dev, u8 *rdata, int rdata_size)
+{
+ int err = 0;
+ struct i2c_msg msg[2];
+ struct tier4_gw5300 *priv = dev_get_drvdata(dev);
+
+ msg[0].addr = priv->i2c_client->addr;
+ msg[0].flags = I2C_M_RD; // I2C Read
+ msg[0].len = rdata_size;
+ msg[0].buf = rdata;
+
+ err = i2c_transfer(priv->i2c_client->adapter, msg, 1);
+
+ if (err <= 0) {
+ dev_err(dev,
+ "[%s] : i2c_transer send message failed. : slave addr = 0x%x\n",
+ __func__, msg[0].addr);
+ } else {
+ err = NO_ERROR;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_gw5300_check_device);
+
+int tier4_gw5300_prim_slave_addr(struct tier4_gmsl_link_ctx *g_ctx)
+{
+ if (!g_ctx) {
+ dev_err(&prim_priv__[channel_count_gw5300 - 1]->i2c_client->dev,
+ "[%s] : Failed. g_ctx is null\n", __func__);
+ return -1;
+ }
+
+ g_ctx->sdev_isp_def = prim_priv__[channel_count_gw5300 - 1]->def_addr;
+
+ return 0;
+}
+EXPORT_SYMBOL(tier4_gw5300_prim_slave_addr);
+
+int tier4_gw5300_setup_sensor_mode(struct device *dev, int sensor_mode)
+{
+ int err = 0;
+ u8 buf[6];
+
+ memset(buf, 0x00, 6);
+
+ switch (sensor_mode) {
+ case GW5300_MASTER_MODE_10FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, master_10fps,
+ sizeof(master_10fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Master mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Master mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+
+ case GW5300_SLAVE_MODE_10FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, slave_10fps,
+ sizeof(slave_10fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ case GW5300_MASTER_MODE_20FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, master_20fps,
+ sizeof(master_20fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Master mode 20fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Master mode 20fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ case GW5300_SLAVE_MODE_20FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, slave_20fps,
+ sizeof(slave_20fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 20fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 20fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ case GW5300_MASTER_MODE_30FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, master_30fps,
+ sizeof(master_30fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Master mode 30fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Master mode 30fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+
+ case GW5300_SLAVE_MODE_30FPS:
+ err = tier4_gw5300_send_and_recv_msg(dev, slave_30fps,
+ sizeof(slave_30fps), buf,
+ sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 30fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Slave mode 30fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ case GW5300_MASTER_MODE_10FPS_SLOW:
+ err = tier4_gw5300_send_and_recv_msg(dev, master_10fps_slow,
+ sizeof(master_10fps_slow),
+ buf, sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Slow clock Master mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Slow clock Master mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ case GW5300_SLAVE_MODE_10FPS_SLOW:
+ err = tier4_gw5300_send_and_recv_msg(dev, slave_10fps_slow,
+ sizeof(slave_10fps_slow),
+ buf, sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up Slow clock Slave mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up Slow clock Slave mode 10fps failed. %d message has been sent to gw5300.\n",
+ __func__, err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+error:
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_gw5300_setup_sensor_mode);
+
+// ----------- for C3 camera ----------
+
+int tier4_gw5300_c3_setup_sensor_mode(struct device *dev, int sensor_mode)
+{
+ int err = 0;
+ u8 buf[6];
+
+ memset(buf, 0x00, 6);
+
+ switch (sensor_mode) {
+ case GW5300_MASTER_MODE_10FPS:
+ case GW5300_SLAVE_MODE_10FPS:
+ case GW5300_MASTER_MODE_20FPS:
+ case GW5300_SLAVE_MODE_20FPS:
+ case GW5300_MASTER_MODE_30FPS:
+ case GW5300_SLAVE_MODE_30FPS:
+ case GW5300_MASTER_MODE_5FPS:
+ case GW5300_SLAVE_MODE_5FPS:
+ case GW5300_MASTER_MODE_10FPS_EBD:
+ case GW5300_SLAVE_MODE_10FPS_EBD:
+ case GW5300_MASTER_MODE_20FPS_EBD:
+ case GW5300_SLAVE_MODE_20FPS_EBD:
+ case GW5300_MASTER_MODE_30FPS_EBD:
+ case GW5300_SLAVE_MODE_30FPS_EBD:
+ err = tier4_gw5300_mode_seq_send_and_recv_msg(
+ dev, &c3_mode_seqs[sensor_mode], buf, sizeof(buf));
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : Setting up %s failed. %d message has been sent to gw5300.\n",
+ __func__, gw5300_mode_name[sensor_mode], err);
+ goto error;
+ } else if (err == 0) { // it means that 0 message has been sent.
+ dev_err(dev,
+ "[%s] : Setting up %s failed. %d message has been sent to gw5300.\n",
+ __func__, gw5300_mode_name[sensor_mode], err);
+ err = -999;
+ goto error;
+ } else {
+ err = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+error:
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_gw5300_c3_setup_sensor_mode);
+
+static int tier4_gw5300_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tier4_gw5300 *priv;
+ int err = 0;
+ struct device_node *node = client->dev.of_node;
+
+ dev_info(&client->dev, "[%s] : probing GW5300 ISP\n", __func__);
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ priv->i2c_client = client;
+
+ mutex_init(&priv->lock);
+
+ if (of_get_property(node, "is-prim-isp", NULL)) {
+ if (prim_priv__[channel_count_gw5300] &&
+ channel_count_gw5300 >= MAX_CHANNEL_NUM) {
+ dev_err(&client->dev,
+ "[%s] : prim-isp already exists\n", __func__);
+ return -EEXIST;
+ }
+
+ err = of_property_read_u32(node, "reg", &priv->def_addr);
+ if (err < 0) {
+ dev_err(&client->dev, "[%s] : reg not found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ prim_priv__[channel_count_gw5300] = priv;
+ channel_count_gw5300++;
+ }
+
+ dev_set_drvdata(&client->dev, priv);
+
+ /* dev communication gets validated when GMSL link setup is done */
+ dev_info(&client->dev, "[%s] : Probing succeeded\n", __func__);
+
+ return err;
+}
+
+static int tier4_gw5300_remove(struct i2c_client *client)
+{
+ struct tier4_gw5300 *priv;
+
+ if (channel_count_gw5300 > 0)
+ channel_count_gw5300--;
+
+ if (client != NULL) {
+ priv = dev_get_drvdata(&client->dev);
+ mutex_destroy(&priv->lock);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id tier4_gw5300_id[] = {
+ { "tier4_gw5300", 0 },
+ {},
+};
+
+const struct of_device_id tier4_gw5300_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_gw5300",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tier4_gw5300_of_match);
+MODULE_DEVICE_TABLE(i2c, tier4_gw5300_id);
+
+static struct i2c_driver tier4_gw5300_i2c_driver = {
+ .driver = {
+ .name = "tier4_gw5300",
+ .owner = THIS_MODULE,
+ },
+ .probe = tier4_gw5300_probe,
+ .remove = tier4_gw5300_remove,
+ .id_table = tier4_gw5300_id,
+};
+
+static int __init tier4_gw5300_init(void)
+{
+ printk(KERN_INFO "ISP Driver for TIERIV Camera.\n");
+
+ c3_mode_seqs[GW5300_MASTER_MODE_5FPS] = c3_master_5fps_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_5FPS] = c3_slave_5fps_seq;
+
+ c3_mode_seqs[GW5300_MASTER_MODE_10FPS] = c3_master_10fps_seq;
+ c3_mode_seqs[GW5300_MASTER_MODE_10FPS_EBD] = c3_master_10fps_ebd_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_10FPS] = c3_slave_10fps_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_10FPS_EBD] = c3_slave_10fps_ebd_seq;
+
+ c3_mode_seqs[GW5300_MASTER_MODE_20FPS] = c3_master_20fps_seq;
+ c3_mode_seqs[GW5300_MASTER_MODE_20FPS_EBD] = c3_master_20fps_ebd_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_20FPS] = c3_slave_20fps_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_20FPS_EBD] = c3_slave_20fps_ebd_seq;
+
+ c3_mode_seqs[GW5300_MASTER_MODE_30FPS] = c3_master_30fps_seq;
+ c3_mode_seqs[GW5300_MASTER_MODE_30FPS_EBD] = c3_master_30fps_ebd_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_30FPS] = c3_slave_30fps_seq;
+ c3_mode_seqs[GW5300_SLAVE_MODE_30FPS_EBD] = c3_slave_30fps_ebd_seq;
+
+ return i2c_add_driver(&tier4_gw5300_i2c_driver);
+}
+
+static void __exit tier4_gw5300_exit(void)
+{
+ i2c_del_driver(&tier4_gw5300_i2c_driver);
+}
+
+module_init(tier4_gw5300_init);
+module_exit(tier4_gw5300_exit);
+
+MODULE_DESCRIPTION("GW5300 ISP driver tier4_gw5300");
+MODULE_AUTHOR("Kohji Iwasaki");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-gw5300.h b/src/tier4-camera-gmsl/tier4-gw5300.h
similarity index 61%
rename from drivers/src/tier4-gw5300.h
rename to src/tier4-camera-gmsl/tier4-gw5300.h
index 10ebec9..4fb7353 100644
--- a/drivers/src/tier4-gw5300.h
+++ b/src/tier4-camera-gmsl/tier4-gw5300.h
@@ -22,40 +22,40 @@
#define __TIER4_GW5300_H__
#define GW5300_MASTER_MODE_10FPS 0
-#define GW5300_SLAVE_MODE_10FPS 1
+#define GW5300_SLAVE_MODE_10FPS 1
#define GW5300_MASTER_MODE_20FPS 2
-#define GW5300_SLAVE_MODE_20FPS 3
+#define GW5300_SLAVE_MODE_20FPS 3
#define GW5300_MASTER_MODE_30FPS 4
-#define GW5300_SLAVE_MODE_30FPS 5
-#define GW5300_SLAVE_MODE_10FPS_SLOW 6
+#define GW5300_SLAVE_MODE_30FPS 5
+#define GW5300_SLAVE_MODE_10FPS_SLOW 6
#define GW5300_MASTER_MODE_10FPS_SLOW 7
#define GW5300_MASTER_MODE_5FPS 8
#define GW5300_SLAVE_MODE_5FPS 9
#define GW5300_MASTER_MODE_10FPS_EBD 10
-#define GW5300_SLAVE_MODE_10FPS_EBD 11
+#define GW5300_SLAVE_MODE_10FPS_EBD 11
#define GW5300_MASTER_MODE_20FPS_EBD 12
-#define GW5300_SLAVE_MODE_20FPS_EBD 13
+#define GW5300_SLAVE_MODE_20FPS_EBD 13
#define GW5300_MASTER_MODE_30FPS_EBD 14
-#define GW5300_SLAVE_MODE_30FPS_EBD 15
+#define GW5300_SLAVE_MODE_30FPS_EBD 15
#define GW5300_MODE_MAX 16
-const char * const gw5300_mode_name[] = {
- [GW5300_MASTER_MODE_10FPS] = "Master mode 10FPS",
- [GW5300_SLAVE_MODE_10FPS] = "Slave mode 10FPS",
- [GW5300_MASTER_MODE_20FPS] = "Master mode 20FPS",
- [GW5300_SLAVE_MODE_20FPS] = "Slave mode 20FPS",
- [GW5300_MASTER_MODE_30FPS] = "Master mode 30FPS",
- [GW5300_SLAVE_MODE_30FPS] = "Slave mode 30FPS",
- [GW5300_MASTER_MODE_10FPS_SLOW] = "Master mode 10FPS Slow",
- [GW5300_SLAVE_MODE_10FPS_SLOW] = "Slave mode 10FPS Slow",
- [GW5300_MASTER_MODE_5FPS] = "Master mode 5FPS",
- [GW5300_SLAVE_MODE_5FPS] = "Slave mode 5FPS",
- [GW5300_MASTER_MODE_10FPS_EBD] = "Master mode 10FPS with EBD",
- [GW5300_SLAVE_MODE_10FPS_EBD] = "Slave mode 10FPS with EBD",
- [GW5300_MASTER_MODE_20FPS_EBD] = "Master mode 20FPS with EBD",
- [GW5300_SLAVE_MODE_20FPS_EBD] = "Slave mode 20FPS with EBD",
- [GW5300_MASTER_MODE_30FPS_EBD] = "Master mode 30FPS with EBD",
- [GW5300_SLAVE_MODE_30FPS_EBD] = "Slave mode 30FPS with EBD",
+const char *const gw5300_mode_name[] = {
+ [GW5300_MASTER_MODE_10FPS] = "Master mode 10FPS",
+ [GW5300_SLAVE_MODE_10FPS] = "Slave mode 10FPS",
+ [GW5300_MASTER_MODE_20FPS] = "Master mode 20FPS",
+ [GW5300_SLAVE_MODE_20FPS] = "Slave mode 20FPS",
+ [GW5300_MASTER_MODE_30FPS] = "Master mode 30FPS",
+ [GW5300_SLAVE_MODE_30FPS] = "Slave mode 30FPS",
+ [GW5300_MASTER_MODE_10FPS_SLOW] = "Master mode 10FPS Slow",
+ [GW5300_SLAVE_MODE_10FPS_SLOW] = "Slave mode 10FPS Slow",
+ [GW5300_MASTER_MODE_5FPS] = "Master mode 5FPS",
+ [GW5300_SLAVE_MODE_5FPS] = "Slave mode 5FPS",
+ [GW5300_MASTER_MODE_10FPS_EBD] = "Master mode 10FPS with EBD",
+ [GW5300_SLAVE_MODE_10FPS_EBD] = "Slave mode 10FPS with EBD",
+ [GW5300_MASTER_MODE_20FPS_EBD] = "Master mode 20FPS with EBD",
+ [GW5300_SLAVE_MODE_20FPS_EBD] = "Slave mode 20FPS with EBD",
+ [GW5300_MASTER_MODE_30FPS_EBD] = "Master mode 30FPS with EBD",
+ [GW5300_SLAVE_MODE_30FPS_EBD] = "Slave mode 30FPS with EBD",
};
/**
@@ -100,9 +100,15 @@ int tier4_gw5300_c3_setup_sensor_mode(struct device *dev, int sensor_mode);
* @return 0 for success, or -1 otherwise.
*/
-int tier4_gw5300_c2_set_integration_time_on_aemode(struct device *dev, int trigger_mode, u32 max_integration_time, u32 min_integration_time);
+int tier4_gw5300_c2_set_integration_time_on_aemode(struct device *dev,
+ int trigger_mode,
+ u32 max_integration_time,
+ u32 min_integration_time);
-int tier4_gw5300_c3_set_integration_time_on_aemode(struct device *dev, int trigger_mode, u32 max_integration_time, u32 min_integration_time);
+int tier4_gw5300_c3_set_integration_time_on_aemode(struct device *dev,
+ int trigger_mode,
+ u32 max_integration_time,
+ u32 min_integration_time);
int tier4_gw5300_set_distortion_correction(struct device *dev, bool val);
diff --git a/drivers/src/tier4-hw-model.h b/src/tier4-camera-gmsl/tier4-hw-model.h
similarity index 97%
rename from drivers/src/tier4-hw-model.h
rename to src/tier4-camera-gmsl/tier4-hw-model.h
index 4149c2c..6a3fa91 100644
--- a/drivers/src/tier4-hw-model.h
+++ b/src/tier4-camera-gmsl/tier4-hw-model.h
@@ -35,4 +35,4 @@
#define HW_MODEL_ADLINK_ROSCUBE_ORIN 4
#define HW_MODEL_UNKNOWN 0
-#endif // __TIER4_HW_MODEL_H__
+#endif // __TIER4_HW_MODEL_H__
diff --git a/src/tier4-camera-gmsl/tier4-imx490.c b/src/tier4-camera-gmsl/tier4-imx490.c
new file mode 100644
index 0000000..c19f30e
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-imx490.c
@@ -0,0 +1,1984 @@
+/*
+ * tier4_imsx490.c - imx490 sensor driver
+ *
+ * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
+ * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tier4-fpga.h"
+#include "tier4-gmsl-link.h"
+#include "tier4-gw5300.h"
+#include "tier4-hw-model.h"
+#include "tier4-isx021-extern.h"
+#include "tier4-max9295.h"
+#include "tier4-max9296.h"
+
+MODULE_SOFTDEP("pre: tier4_max9296");
+MODULE_SOFTDEP("pre: tier4_max9295");
+MODULE_SOFTDEP("pre: tier4_gw5300");
+MODULE_SOFTDEP("pre: tier4_fpga");
+MODULE_SOFTDEP("pre: tier4_isx021");
+
+#define USE_DISTORTION_CORRECTION 1
+
+// Register Address
+
+#define IMX490_DEFAULT_FRAME_LENGTH (2000)
+
+#define BIT_SHIFT_8 8
+#define BIT_SHIFT_16 16
+#define MASK_1_BIT 0x1
+#define MASK_4_BIT 0xF
+#define MASK_8_BIT 0xFF
+
+#define NO_ERROR 0
+#define NO_C2_CAMERA (-490)
+
+#define TIME_120_MILISEC 120000
+#define TIME_121_MILISEC 121000
+
+#define ISP_PRIM_SLAVE_ADDR 0x6D
+
+#define TIER4_C2_CAMERA 1
+
+#define SENSOR_ID_IMX490 490
+
+#define MAX_NUM_CAMERA 8
+
+#define FSYNC_FREQ_HZ 10
+
+enum {
+ IMX490_MODE_2880x1860_CROP_30FPS,
+ IMX490_MODE_START_STREAM,
+ IMX490_MODE_STOP_STREAM,
+};
+
+static const int tier4_imx490_30fps[] = {
+ 30,
+};
+static const struct camera_common_frmfmt tier4_imx490_frmfmt[] = {
+ { { 2880, 1860 },
+ tier4_imx490_30fps,
+ 1,
+ 0,
+ IMX490_MODE_2880x1860_CROP_30FPS },
+};
+
+const struct of_device_id tier4_imx490_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_imx490",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, tier4_imx490_of_match);
+
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
+// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
+
+static const u32 ctrl_cid_list[] = {
+ TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE,
+ TEGRA_CAMERA_CID_EXPOSURE_SHORT, TEGRA_CAMERA_CID_FRAME_RATE,
+ TEGRA_CAMERA_CID_HDR_EN,
+ // TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
+};
+
+struct tier4_imx490 {
+ struct i2c_client *i2c_client;
+ const struct i2c_device_id *id;
+ struct v4l2_subdev *subdev;
+ struct device *ser_dev;
+ struct device *dser_dev;
+ struct device *isp_dev;
+ struct tier4_gmsl_link_ctx g_ctx;
+ u32 frame_length;
+ struct camera_common_data *s_data;
+ struct tegracam_device *tc_dev;
+ int trigger_mode;
+ bool distortion_correction;
+ bool last_distortion_correction;
+ bool auto_exposure;
+ bool inhibit_fpga_access;
+ struct device *fpga_dev;
+};
+
+static const struct regmap_config tier4_sensor_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+struct st_priv {
+ struct i2c_client *p_client;
+ struct tier4_imx490 *p_priv;
+ struct tegracam_device *p_tc_dev;
+ bool isp_ser_shutdown;
+ bool des_shutdown;
+ bool running;
+};
+
+static struct st_priv wst_priv[MAX_NUM_CAMERA];
+
+static struct mutex tier4_imx490_lock;
+
+static int camera_channel_count = 0;
+
+// --- module parameter ---
+
+static int trigger_mode;
+static int fsync_mfp = 0;
+static int enable_distortion_correction = 1;
+
+#define IMX490_MIN_EXPOSURE_TIME 11000 // 11 milisecond
+#define IMX490_MAX_EXPOSURE_TIME 33000 // 33 milisecond
+
+static int shutter_time_min = IMX490_MIN_EXPOSURE_TIME;
+static int shutter_time_max = IMX490_MAX_EXPOSURE_TIME;
+
+module_param(trigger_mode, int, 0644);
+module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
+module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
+
+module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
+module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
+
+// ------------------------
+static char upper(char c)
+{
+ if ('a' <= c && c <= 'z') {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+static void to_upper_string(char *out, const char *in)
+{
+ int i;
+
+ i = 0;
+ while (in[i] != '\0') {
+ out[i] = upper(in[i]);
+ i++;
+ }
+}
+
+static inline int tier4_imx490_read_reg(struct camera_common_data *s_data,
+ u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+
+ err = regmap_read(s_data->regmap, addr, ®_val);
+
+ if (err) {
+ dev_err(s_data->dev, "[%s] : I2C read failed, address=0x%x\n",
+ __func__, addr);
+ } else {
+ *val = reg_val & 0xFF;
+ }
+ return err;
+}
+
+static int tier4_imx490_write_reg(struct camera_common_data *s_data, u16 addr,
+ u8 val)
+{
+ int err = 0;
+
+ err = regmap_write(s_data->regmap, addr, val);
+
+ if (err) {
+ dev_err(s_data->dev, "[%s] : I2C write failed at x%x=[0x%x]\n",
+ __func__, addr, val);
+ }
+
+ return err;
+}
+
+// ------------------------------------------------
+
+static int tier4_imx490_set_fsync_trigger_mode(struct tier4_imx490 *priv,
+ int mode)
+{
+ int err = 0;
+ struct device *dev = priv->s_data->dev;
+ int des_num = 0;
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ priv->inhibit_fpga_access = false;
+
+ dev_info(dev, "[%s] : Set fsync trigger mode.\n", __func__);
+
+ err = tier4_fpga_check_access(priv->fpga_dev);
+ if (err) {
+ priv->inhibit_fpga_access = true;
+ }
+
+ if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE) {
+ dev_info(dev, "[%s] : Disabling FPGA fsync.\n",
+ __func__);
+
+ err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Disabling FPGA fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else {
+ err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA generate fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+
+ if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_AUTO) {
+ // Auto Trigger Mode
+ err = tier4_fpga_set_fsync_auto_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ des_num = priv->g_ctx.reg_mux;
+ err = tier4_fpga_set_fsync_signal_frequency(
+ priv->fpga_dev, des_num,
+ priv->trigger_mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_MANUAL) {
+ // Manual Trigger Mode
+ dev_info(
+ dev,
+ "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n",
+ __func__);
+
+ err = tier4_fpga_set_fsync_manual_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ }
+ }
+ }
+
+ err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
+
+ if (err) {
+ dev_err(dev, "[%s] :tier4_max9296_setup_gpi() failed\n",
+ __func__);
+ return err;
+ }
+
+ err = tier4_max9295_setup_gpo(priv->ser_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9295_setup_gpo() failed\n",
+ __func__);
+ return err;
+ }
+
+ err = tier4_gw5300_setup_sensor_mode(priv->isp_dev, mode);
+ if (err) {
+ dev_err(dev, "[%s] : tier4_gw5300_setup_sensor_mode() failed\n",
+ __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static struct mutex serdes_lock__;
+
+static int tier4_imx490_gmsl_serdes_setup(struct tier4_imx490 *priv)
+{
+ int err = 0;
+ int des_err = 0;
+ struct device *dev;
+
+ if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client) {
+ return -EINVAL;
+ }
+
+ dev = &priv->i2c_client->dev;
+
+ mutex_lock(&serdes_lock__);
+
+ /* For now no separate power on required for serializer device */
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_on(priv->dser_dev);
+ }
+
+ /* setup serdes addressing and control pipeline */
+
+ err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : GMSL deserializer link config failed\n",
+ __func__);
+ goto error;
+ }
+
+ err = tier4_max9295_setup_control(priv->ser_dev);
+
+ /* proceed even if ser setup failed, to setup deser correctly */
+ if (err) {
+ dev_err(dev, "[%s] : GMSL serializer setup failed\n", __func__);
+ goto error;
+ }
+
+ des_err = tier4_max9296_setup_control(priv->dser_dev,
+ &priv->i2c_client->dev);
+
+ if (des_err) {
+ dev_err(dev, "[%s] : GMSL deserializer : setup failed\n",
+ __func__);
+ err = des_err;
+ }
+
+error:
+ mutex_unlock(&serdes_lock__);
+ return err;
+}
+
+static void tier4_imx490_gmsl_serdes_reset(struct tier4_imx490 *priv)
+{
+ mutex_lock(&serdes_lock__);
+
+ /* reset serdes addressing and control pipeline */
+ tier4_max9295_reset_control(priv->ser_dev);
+
+ tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev,
+ true);
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_off(priv->dser_dev);
+ }
+
+ mutex_unlock(&serdes_lock__);
+}
+
+static int tier4_imx490_power_on(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_on) {
+ err = pdata->power_on(pw);
+
+ if (err) {
+ dev_err(dev, "[%s] : failed.\n", __func__);
+ } else {
+ pw->state = SWITCH_ON;
+ }
+ return err;
+ }
+
+ pw->state = SWITCH_ON;
+
+ return err;
+}
+
+static int tier4_imx490_power_off(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_off) {
+ err = pdata->power_off(pw);
+
+ if (!err) {
+ goto power_off_done;
+ } else {
+ dev_err(dev, "[%s] : power off failed.\n", __func__);
+ }
+ return err;
+ }
+
+power_off_done:
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+static int tier4_imx490_power_get(struct tegracam_device *tc_dev)
+{
+ struct camera_common_power_rail *pw = tc_dev->s_data->power;
+ int err = 0;
+
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+static int tier4_imx490_power_put(struct tegracam_device *tc_dev)
+{
+ if (unlikely(!tc_dev->s_data->power)) {
+ return -EFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+static int tier4_imx490_set_group_hold(struct tegracam_device *tc_dev, bool val)
+{
+ volatile int err = 0;
+
+ return err;
+}
+
+static int tier4_imx490_set_gain(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ // struct camera_common_data *s_data = tc_dev->s_data;
+
+ // struct device *dev = tc_dev->dev;
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_imx490_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+ // struct device dev = tc_dev->dev;
+
+ /* fixed 30fps */
+ priv->frame_length = IMX490_DEFAULT_FRAME_LENGTH;
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_imx490_set_auto_exposure(struct tegracam_device *tc_dev)
+{
+ int err = 0;
+ //struct tier4_imx490 *priv = (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_imx490_set_exposure(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+ tier4_gw5300_c2_set_integration_time_on_aemode(
+ priv->isp_dev, priv->trigger_mode, val, val);
+
+ return err;
+}
+// --------------------------------------------------------------------------------------
+// Enable Distortion Coreection
+// --------------------------------------------------------------------------------------
+#if USE_DISTORTION_CORRECTION
+
+static int
+tier4_imx490_set_distortion_correction(struct tegracam_device *tc_dev, bool val)
+{
+ int err = 0;
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+
+ if (priv->last_distortion_correction != val) {
+ dev_info(&priv->i2c_client->dev,
+ "[%s] : Setting distortion correction mode :%s.\n",
+ __func__, val ? "True" : "False");
+
+ err = tier4_gw5300_set_distortion_correction(priv->isp_dev,
+ val);
+ if (err <= 0) {
+ dev_info(
+ &priv->i2c_client->dev,
+ "[%s] : Setting distortion correction mode failed.\n",
+ __func__);
+ } else {
+ err = 0;
+ priv->last_distortion_correction = val;
+ }
+ }
+
+ return err;
+}
+#endif
+
+// --------------------------------------------------------------------------------------
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
+// please add the new memeber and the function at the following table.
+
+static struct tegracam_ctrl_ops tier4_imx490_ctrl_ops = {
+ .numctrls = ARRAY_SIZE(ctrl_cid_list),
+ .ctrl_cid_list = ctrl_cid_list,
+ .set_gain = tier4_imx490_set_gain,
+ .set_exposure = tier4_imx490_set_exposure,
+ .set_exposure_short = tier4_imx490_set_exposure,
+ .set_frame_rate = tier4_imx490_set_frame_rate,
+ .set_group_hold = tier4_imx490_set_group_hold,
+ // .set_distortion_correction = tier4_imx490_set_distortion_correction,
+};
+
+// --------------------------------------------------------------------------------------
+
+static struct camera_common_pdata *
+tier4_imx490_parse_dt(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct camera_common_pdata *board_priv_pdata;
+ const struct of_device_id *match;
+ int err;
+
+ if (!node) {
+ return NULL;
+ }
+
+ match = of_match_device(tier4_imx490_of_match, dev);
+
+ if (!match) {
+ dev_err(dev, "[%s] : Failed to find matching dt id\n",
+ __func__);
+ return NULL;
+ }
+
+ board_priv_pdata =
+ devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
+
+ err = of_property_read_string(node, "mclk",
+ &board_priv_pdata->mclk_name);
+
+ if (err) {
+ dev_err(dev, "[%s] : mclk not in DT\n", __func__);
+ }
+
+ return board_priv_pdata;
+}
+
+/* tier4_imx490_set_mode() can not be needed. But it remains for compatiblity */
+
+static int tier4_imx490_set_mode(struct tegracam_device *tc_dev)
+{
+ volatile int err = 0;
+
+ return err;
+}
+
+static int tier4_imx490_start_one_streaming(struct tegracam_device *tc_dev)
+{
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+ int err;
+
+ /* enable serdes streaming */
+
+ err = tier4_max9295_setup_streaming(priv->ser_dev);
+
+ if (err) {
+ goto exit;
+ }
+
+ err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : Setup Streaming failed\n", __func__);
+ goto exit;
+ }
+
+ if (priv->auto_exposure == true) {
+ err = tier4_imx490_set_auto_exposure(tc_dev);
+ }
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setting Digital Gain to default value failed\n",
+ __func__);
+ goto exit;
+ }
+
+ dev_info(dev, "[%s] : trigger_mode = %d\n", __func__, trigger_mode);
+
+ priv->trigger_mode = trigger_mode;
+
+ switch (priv->trigger_mode) {
+ case GW5300_MASTER_MODE_10FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to Master mode 10fps\n",
+ __func__);
+
+ err = tier4_gw5300_setup_sensor_mode(priv->isp_dev,
+ GW5300_MASTER_MODE_10FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Master mode 10fps failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ break;
+
+ case GW5300_SLAVE_MODE_10FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to Slave mode 10fps\n",
+ __func__);
+
+ err = tier4_imx490_set_fsync_trigger_mode(
+ priv, GW5300_SLAVE_MODE_10FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Slave mode 10fps failed\n",
+ __func__);
+ goto exit;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ msleep(20);
+
+ break;
+
+ case GW5300_MASTER_MODE_20FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to Master mode 20fps\n",
+ __func__);
+
+ err = tier4_gw5300_setup_sensor_mode(priv->isp_dev,
+ GW5300_MASTER_MODE_20FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Master mode 20fps failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ break;
+
+ case GW5300_SLAVE_MODE_20FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to Slave mode 20fps\n",
+ __func__);
+
+ err = tier4_imx490_set_fsync_trigger_mode(
+ priv, GW5300_SLAVE_MODE_20FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Slave mode 20fps failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ break;
+
+ case GW5300_MASTER_MODE_30FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to Master mode 30fps\n",
+ __func__);
+
+ err = tier4_gw5300_setup_sensor_mode(priv->isp_dev,
+ GW5300_MASTER_MODE_30FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Master mode 30fps failed\n",
+ __func__);
+ return err;
+ }
+
+ break;
+
+ case GW5300_SLAVE_MODE_30FPS:
+
+ dev_info(dev,
+ "[%s] : Setting camera sensor to slave mode 30fps\n",
+ __func__);
+
+ err = tier4_imx490_set_fsync_trigger_mode(
+ priv, GW5300_SLAVE_MODE_30FPS);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Slave mode 30fps failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ break;
+
+ case GW5300_SLAVE_MODE_10FPS_SLOW:
+
+ err = tier4_imx490_set_fsync_trigger_mode(
+ priv, GW5300_SLAVE_MODE_10FPS_SLOW);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Slow clock Slave mode 10fps failed\n",
+ __func__);
+ goto exit;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ msleep(20);
+
+ break;
+
+ case GW5300_MASTER_MODE_10FPS_SLOW:
+
+ err = tier4_gw5300_setup_sensor_mode(
+ priv->isp_dev, GW5300_MASTER_MODE_10FPS_SLOW);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to Slow clock Master mode 10fps failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+
+ break;
+
+ default: // case of trigger_mode < 0
+
+ dev_err(dev,
+ "[%s] : The camera sensor mode(fsync mode) is invalid.\n",
+ __func__);
+
+ return err;
+ }
+
+#if USE_DISTORTION_CORRECTION
+
+ if (priv->last_distortion_correction != enable_distortion_correction) {
+ usleep_range(900000, 910000);
+ //msleep(900);
+ }
+
+ if (enable_distortion_correction == 0xCAFE) {
+ // if not set kernel param, read device tree param
+ if (priv->distortion_correction == false) {
+ err = tier4_imx490_set_distortion_correction(
+ tc_dev, priv->distortion_correction);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Disabling Distortion Correction failed\n",
+ __func__);
+ goto exit;
+ }
+ msleep(20);
+ }
+ } else {
+ err = tier4_imx490_set_distortion_correction(
+ tc_dev, enable_distortion_correction == 1);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setup Distortion Correction failed\n",
+ __func__);
+ goto exit;
+ }
+ msleep(20);
+ }
+
+#endif
+
+ err = tier4_max9296_start_streaming(priv->dser_dev, dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_start_stream() failed\n",
+ __func__);
+ return err;
+ }
+
+ msleep(200);
+
+ //#if 0
+ msleep(1000);
+ tier4_gw5300_c2_set_integration_time_on_aemode(priv->isp_dev,
+ priv->trigger_mode,
+ shutter_time_max,
+ shutter_time_min);
+ //#endif
+
+ dev_info(dev, "[%s] : Camera has started streaming\n", __func__);
+
+ return NO_ERROR;
+
+exit:
+
+ dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
+
+ return err;
+}
+
+static bool tier4_imx490_is_camera_connected_to_port(int nport)
+{
+ if (wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx490_check_null_tc_dev_for_port(int nport)
+{
+ if (wst_priv[nport].p_tc_dev == NULL) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx490_is_camera_running_on_port(int nport)
+{
+ if (wst_priv[nport].running) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx490_is_current_port(struct tier4_imx490 *priv, int nport)
+{
+ if (priv->i2c_client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_imx490_set_running_flag(int nport, bool flag)
+{
+ wst_priv[nport].running = flag;
+}
+
+static int tier4_imx490_stop_streaming(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+ int i, err = 0;
+
+ mutex_lock(&tier4_imx490_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_imx490_is_camera_connected_to_port(i)) {
+ if (tier4_imx490_is_current_port(priv, i) &&
+ tier4_imx490_is_camera_running_on_port(i)) {
+ /* disable serdes streaming */
+ err = tier4_max9296_stop_streaming(
+ priv->dser_dev, dev);
+ if (err) {
+ return err;
+ }
+ tier4_imx490_set_running_flag(i, false);
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&tier4_imx490_lock);
+
+ return NO_ERROR;
+}
+
+/* *************************************************************************** */
+/* 1. In the case where a camera is connected to GMSL A port on a Des. */
+/* */
+/* a > Check if another camera is connected to GMSL B port */
+/* a-1) Connected: */
+/* b > Check if another camera on GMSL B port is running */
+/* b-1) Running: */
+/* c > Check if the camera on GMSL A port is running */
+/* c-1) Running : */
+/* Do nothing and return */
+/* c-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* b-2) Not Running: */
+/* Start the camera on GMSL B port. */
+/* a-2) Not connected : */
+/* b > Check if the camera on GMSL A port is running */
+/* b-1) Running : */
+/* Do nothing and return */
+/* b-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* */
+/* 2. In the case where a camera is connected to GMSL B port on a Des. */
+/* */
+/* a > Check if the camera on GMSL B port is running */
+/* a-1) Running : */
+/* Do nothing and return */
+/* a-2) Not running : */
+/* Start the camera on GMSL B port. */
+/* *************************************************************************** */
+
+static int tier4_imx490_start_streaming(struct tegracam_device *tc_dev)
+{
+ int i, err = 0;
+ // struct tier4_imx490 *next_client_priv;
+ struct tier4_imx490 *priv =
+ (struct tier4_imx490 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+
+ mutex_lock(&tier4_imx490_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (i & 0x1) { // if i = 1,3,5,7 ( GMSL B port of a Des )
+
+ if (tier4_imx490_is_camera_connected_to_port(
+ i)) { // a camera is connected to GMSL B portL
+
+ if ((tier4_imx490_is_current_port(priv, i) ==
+ true) &&
+ (tier4_imx490_is_camera_running_on_port(
+ i) == false)) {
+ err = tier4_imx490_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming.\n",
+ __func__);
+ goto error_exit;
+ }
+ // wst_priv[i].running = true;
+ tier4_imx490_set_running_flag(i, true);
+ break;
+ }
+ }
+ } else { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
+
+ if ((tier4_imx490_is_camera_connected_to_port(i) ==
+ true) &&
+ (tier4_imx490_is_current_port(priv, i) == true)) {
+ if (tier4_imx490_is_camera_connected_to_port(
+ i + 1) ==
+ false) { // if another one camera( GMSL B port) is not
+ // connected to Des.
+ if (tier4_imx490_is_camera_running_on_port(
+ i) ==
+ false) { // and if the camera is not running.
+
+ err = tier4_imx490_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for next imx490 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx490_set_running_flag(
+ i, true);
+ }
+ break;
+ }
+
+ // two cameras are connected to one Des.
+
+ if (tier4_imx490_check_null_tc_dev_for_port(
+ i + 1)) { // check if tc_dev is null
+ dev_err(dev,
+ "[%s] : wst_priv[%d].p_tc_dev is NULL.\n",
+ __func__, i + 1);
+ err = -EINVAL;
+ goto error_exit;
+ }
+
+ if (tier4_imx490_is_camera_running_on_port(
+ i + 1) == false) {
+ err = tier4_imx490_start_one_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for the next imx490 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx490_set_running_flag(i + 1,
+ true);
+ usleep_range(200000, 220000);
+ //msleep(200);
+ mutex_unlock(&tier4_imx490_lock);
+ tier4_imx490_stop_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ mutex_lock(&tier4_imx490_lock);
+ tier4_imx490_set_running_flag(i + 1,
+ false);
+ }
+
+ if (tier4_imx490_is_camera_running_on_port(i) ==
+ false) {
+ err = tier4_imx490_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for current imx490 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx490_set_running_flag(i, true);
+ }
+ }
+ }
+ } // for loop
+
+ err = NO_ERROR;
+
+error_exit:
+
+ mutex_unlock(&tier4_imx490_lock);
+
+ // tier4_imx490_sensor_mutex_unlock();
+
+ return err;
+}
+
+static struct camera_common_sensor_ops tier4_imx490_common_ops = {
+ .numfrmfmts = ARRAY_SIZE(tier4_imx490_frmfmt),
+ .frmfmt_table = tier4_imx490_frmfmt,
+ .power_on = tier4_imx490_power_on,
+ .power_off = tier4_imx490_power_off,
+ .write_reg = tier4_imx490_write_reg,
+ .read_reg = tier4_imx490_read_reg,
+ .parse_dt = tier4_imx490_parse_dt,
+ .power_get = tier4_imx490_power_get,
+ .power_put = tier4_imx490_power_put,
+ .set_mode = tier4_imx490_set_mode,
+ .start_streaming = tier4_imx490_start_streaming,
+ .stop_streaming = tier4_imx490_stop_streaming,
+};
+
+static int tier4_imx490_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ //struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ return NO_ERROR;
+}
+
+static const struct v4l2_subdev_internal_ops tier4_imx490_subdev_internal_ops = {
+ .open = tier4_imx490_open,
+};
+
+static const char *of_stdout_options;
+
+static int tier4_imx490_board_setup(struct tier4_imx490 *priv)
+{
+ struct tegracam_device *tc_dev = priv->tc_dev;
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *ser_node;
+ struct i2c_client *ser_i2c = NULL;
+ struct device_node *dser_node;
+ struct i2c_client *dser_i2c = NULL;
+ struct device_node *isp_node;
+ struct i2c_client *isp_i2c = NULL;
+ struct device_node *fpga_node = NULL;
+ struct i2c_client *fpga_i2c = NULL;
+ struct device_node *gmsl;
+ struct device_node *root_node;
+ int value = 0xFFFF;
+ const char *str_value;
+ const char *str_value1[2];
+ int i;
+ int err;
+ const char *str_model;
+ char upper_str_model[64];
+ char *str_err;
+ char *sub_str_err;
+
+ root_node = of_find_node_opts_by_path("/", &of_stdout_options);
+
+ err = of_property_read_string(root_node, "model", &str_model);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : model not found\n", __func__);
+ goto error;
+ }
+
+ memset(upper_str_model, 0, 64);
+
+ to_upper_string(upper_str_model, str_model);
+
+ priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
+
+ if (str_err) {
+ sub_str_err = strstr(upper_str_model,
+ STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
+
+ if (sub_str_err) {
+ priv->g_ctx.hardware_model =
+ HW_MODEL_ADLINK_ROSCUBE_ORIN;
+ } else {
+ priv->g_ctx.hardware_model =
+ HW_MODEL_NVIDIA_ORIN_DEVKIT;
+ }
+ }
+
+ dev_info(dev, "[%s] : model=%s\n", __func__, str_model);
+ dev_info(dev, "[%s] : hardware_model=%d\n", __func__,
+ priv->g_ctx.hardware_model);
+
+ if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN) {
+ dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_isp_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : def-addr not found\n", __func__);
+ goto error;
+ }
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_isp_def);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : def-addr not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg_mux not found\n", __func__);
+ goto error;
+ }
+
+ // err = of_property_read_string(node, "fsync-mode", &str_value);
+ //
+ // if (err < 0)
+ // {
+ // dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
+ // goto error;
+ // }
+ //
+ // if (!strcmp(str_value, "true"))
+ // {
+ // priv->fsync_mode = true;
+ // }
+ // else
+ // {
+ // priv->fsync_mode = false;
+ // }
+
+ err = of_property_read_string(node, "distortion-correction",
+ &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No distortion-correction found\n",
+ __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "true")) {
+ priv->distortion_correction = true;
+ } else {
+ priv->distortion_correction = false;
+ }
+
+ err = of_property_read_string(node, "auto-exposure", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : Inavlid Exposure mode.\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "true")) {
+ priv->auto_exposure = true;
+ } else {
+ priv->auto_exposure = false;
+ }
+
+#if 0
+ priv->g_ctx.fpga_generate_fsync = false;
+
+ if (( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER ) ||
+ ( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN )) {
+
+ err = of_property_read_string(node, "fpga-generate-fsync", &str_value);
+
+ if ( err < 0) {
+ if ( err == -EINVAL ) {
+ dev_info(dev, "[%s] : Parameter of fpga-generate-fsync does not exist.\n", __func__);
+ } else {
+ dev_err(dev, "[%s] : Parameter of fpga-generate-fsync is invalid .\n", __func__);
+ goto error;
+ }
+ } else {
+ if (!strcmp(str_value, "true")) {
+ priv->g_ctx.fpga_generate_fsync = true;
+ }
+ }
+ }
+#endif
+
+ // For Ser node
+ ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
+
+ if (ser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-ser-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
+ goto error;
+ }
+
+ ser_i2c = of_find_i2c_device_by_node(ser_node);
+
+ of_node_put(ser_node);
+
+ if (ser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing Serializer Dev Handle\n",
+ __func__);
+ goto error;
+ }
+ if (ser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->ser_dev = &ser_i2c->dev;
+
+ // For ISP node
+
+ isp_node = of_parse_phandle(node, "nvidia,isp-device", 0);
+
+ if (isp_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,isp-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(isp_node, "reg", &priv->g_ctx.sdev_isp_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : ISP reg not found\n", __func__);
+ goto error;
+ }
+
+ isp_i2c = of_find_i2c_device_by_node(isp_node);
+
+ of_node_put(isp_node);
+
+ if (isp_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing ISP Dev Handle\n", __func__);
+ goto error;
+ }
+ if (isp_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing ISP driver\n", __func__);
+ goto error;
+ }
+
+ priv->isp_dev = &isp_i2c->dev;
+
+ err = tier4_gw5300_prim_slave_addr(&priv->g_ctx);
+ if (err) {
+ dev_err(dev,
+ "[%s] : ISP Prim slave address is unavailable, the default address(0x6D) is applied.\n",
+ __func__);
+ priv->g_ctx.sdev_isp_def = ISP_PRIM_SLAVE_ADDR;
+ }
+
+ priv->g_ctx.sdev_reg = priv->g_ctx.sdev_isp_reg;
+ priv->g_ctx.sdev_def = priv->g_ctx.sdev_isp_def;
+
+ // For Dser node
+
+ dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
+
+ if (dser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-dser-device");
+ goto error;
+ }
+
+ dser_i2c = of_find_i2c_device_by_node(dser_node);
+
+ of_node_put(dser_node);
+
+ if (dser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer dev handle\n",
+ __func__);
+ goto error;
+ }
+
+ if (dser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->dser_dev = &dser_i2c->dev;
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ // for FPGA node
+
+ fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
+
+ if (fpga_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,fpga-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(fpga_node, "reg",
+ &priv->g_ctx.sdev_fpga_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
+ goto error;
+ }
+
+ fpga_i2c = of_find_i2c_device_by_node(fpga_node);
+
+ of_node_put(fpga_node);
+
+ if (fpga_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA Dev Handle\n",
+ __func__);
+ goto error;
+ }
+ if (fpga_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
+ goto error;
+ }
+
+ priv->fpga_dev = &fpga_i2c->dev;
+ }
+
+ /* populate g_ctx from DT */
+
+ gmsl = of_get_child_by_name(node, "gmsl-link");
+
+ if (gmsl == NULL) {
+ dev_err(dev, "[%s] : Missing GMSL-Link device node\n",
+ __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "src-csi-port", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "csi-mode", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No csi-mode found\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "1x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
+ } else if (!strcmp(str_value, "2x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
+ } else if (!strcmp(str_value, "4x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
+ } else if (!strcmp(str_value, "2x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
+ } else {
+ dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ?
+ GMSL_SERDES_CSI_LINK_A :
+ GMSL_SERDES_CSI_LINK_B;
+
+ err = of_property_read_u32(gmsl, "st-vc", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No st-vc info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.st_vc = value;
+
+ err = of_property_read_u32(gmsl, "vc-id", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No vc-id info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_vc = value;
+
+ err = of_property_read_u32(gmsl, "num-lanes", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No num-lanes info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.num_csi_lanes = value;
+
+ priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
+
+ if (priv->g_ctx.num_streams <= 0) {
+ dev_err(dev, "[%s] : No streams found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < priv->g_ctx.num_streams; i++) {
+ of_property_read_string_index(gmsl, "streams", i,
+ &str_value1[i]);
+
+ if (!str_value1[i]) {
+ dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value1[i], "raw12")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_RAW_12;
+ } else if (!strcmp(str_value1[i], "yuv8")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
+ } else if (!strcmp(str_value1[i], "embed")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
+ } else if (!strcmp(str_value1[i], "ued-u1")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_UED_U1;
+ } else {
+ dev_err(dev, "[%s] : Invalid stream data type\n",
+ __func__);
+ goto error;
+ }
+ }
+
+ priv->g_ctx.s_dev = dev;
+
+ return NO_ERROR;
+
+error:
+ dev_err(dev, "[%s] : Board Setup failed\n", __func__);
+ return err;
+}
+
+static int tier4_imx490_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct device_node *node = dev->of_node;
+ struct tegracam_device *tc_dev;
+ struct tier4_imx490 *priv;
+ int err = 0;
+
+ dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
+
+ if (!IS_ENABLED(CONFIG_OF) || !node) {
+ return -EINVAL;
+ }
+
+ wst_priv[camera_channel_count].p_client = NULL;
+ wst_priv[camera_channel_count].p_priv = NULL;
+ wst_priv[camera_channel_count].p_tc_dev = NULL;
+
+ wst_priv[camera_channel_count].isp_ser_shutdown = false;
+ wst_priv[camera_channel_count].des_shutdown = false;
+ wst_priv[camera_channel_count].running = false;
+
+ priv = devm_kzalloc(dev, sizeof(struct tier4_imx490), GFP_KERNEL);
+
+ if (!priv) {
+ dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
+
+ if (!tc_dev) {
+ return -ENOMEM;
+ }
+
+ priv->i2c_client = tc_dev->client = client;
+
+ tc_dev->dev = dev;
+
+ strncpy(tc_dev->name, "imx490", sizeof(tc_dev->name));
+
+ tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
+ tc_dev->sensor_ops = &tier4_imx490_common_ops;
+ tc_dev->v4l2sd_internal_ops = &tier4_imx490_subdev_internal_ops;
+ tc_dev->tcctrl_ops = &tier4_imx490_ctrl_ops;
+
+ err = tegracam_device_register(tc_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : Tegra Camera Driver Registration failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->tc_dev = tc_dev;
+ priv->s_data = tc_dev->s_data;
+ priv->subdev = &tc_dev->s_data->subdev;
+
+ tegracam_set_privdata(tc_dev, (void *)priv);
+
+ priv->g_ctx.sensor_id = SENSOR_ID_IMX490;
+
+ tier4_isx021_sensor_mutex_lock();
+
+ err = tier4_imx490_board_setup(priv);
+
+ if (err) {
+ dev_err(dev, "[%s] : Board Setup failed\n", __func__);
+ goto err_tegracam_unreg;
+ }
+
+ /* Pair sensor to serializer dev */
+
+ err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed\n",
+ __func__);
+ goto err_tegracam_unreg;
+ }
+ /* Register sensor to deserializer dev */
+
+ err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev,
+ "[%s] : GMSL Deserializer Register failed\n", __func__);
+ goto err_max9295_unpair;
+ }
+
+ /*
+ * gmsl serdes setup
+ *
+ * Sensor power on/off should be the right place for serdes
+ * setup/reset. But the problem is, the total required delay
+ * in serdes setup/reset exceeds the frame wait timeout, looks to
+ * be related to multiple channel open and close sequence
+ * issue (#BUG 200477330).
+ * Once this bug is fixed, these may be moved to power on/off.
+ * The delays in serdes is as per guidelines and can't be reduced,
+ * so it is placed in probe/remove, though for that, deserializer
+ * would be powered on always post boot, until 1.2v is supplied
+ * to deserializer from CVB.
+ */
+
+ err = tier4_imx490_gmsl_serdes_setup(priv);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] : GMSL Serdes setup failed\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ err = tegracam_v4l2subdev_register(tc_dev, true);
+
+ if (err) {
+ dev_err(dev, "[%s] : Tegra Camera Subdev Registration failed\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ wst_priv[camera_channel_count].p_client = client;
+ wst_priv[camera_channel_count].p_priv = priv;
+ wst_priv[camera_channel_count].p_tc_dev = tc_dev;
+
+ camera_channel_count++;
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ return NO_ERROR;
+
+ // tier4_isx021_sensor_mutex_unlock();
+
+ // dev_info(&client->dev, "Detected Tier4 IMX490 sensor\n");
+
+err_max9296_unreg:
+ tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
+err_max9295_unpair:
+ tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
+err_tegracam_unreg:
+ tegracam_device_unregister(priv->tc_dev);
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ // dev_info(dev, "[%s] :camera_channel_count = %d p_client = %p \n", __func__, camera_channel_count,
+ // wst_priv[camera_channel_count].p_client);
+
+ return err;
+ //return NO_ERROR; // err;
+}
+
+static void tier4_imx490_shutdown(struct i2c_client *client);
+
+static int tier4_imx490_remove(struct i2c_client *client)
+{
+ struct camera_common_data *s_data = to_camera_common_data(&client->dev);
+ struct tier4_imx490 *priv = (struct tier4_imx490 *)s_data->priv;
+
+ tier4_imx490_shutdown(client);
+
+ tier4_imx490_gmsl_serdes_reset(priv);
+
+ tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
+ tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
+
+ tegracam_v4l2subdev_unregister(priv->tc_dev);
+
+ tegracam_device_unregister(priv->tc_dev);
+
+ return NO_ERROR;
+}
+
+static struct mutex tier4_imx490_lock;
+
+static bool tier4_imx490_is_isp_ser_shutdown(int nport)
+{
+ if (wst_priv[nport].isp_ser_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx490_is_des_shutdown(int nport)
+{
+ if (wst_priv[nport].des_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_imx490_set_isp_ser_shutdown(int nport, bool val)
+{
+ wst_priv[nport].isp_ser_shutdown = val;
+}
+
+static void tier4_imx490_set_des_shutdown(int nport, bool val)
+{
+ wst_priv[nport].des_shutdown = val;
+}
+
+static bool tier4_imx490_is_current_i2c_client(struct i2c_client *client,
+ int nport)
+{
+ if (client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+static void tier4_imx490_shutdown(struct i2c_client *client)
+{
+ struct tier4_imx490 *priv = NULL;
+ int i;
+
+ tier4_isx021_sensor_mutex_lock();
+
+ mutex_lock(&tier4_imx490_lock);
+
+ if (!client) {
+ goto error_exit;
+ }
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_imx490_is_current_i2c_client(client, i)) {
+ priv = wst_priv[i].p_priv;
+
+ if (i &
+ 0x1) { // Even port number( GMSL B port on a Des : i = port_number -1 )
+
+ if (tier4_imx490_is_camera_connected_to_port(
+ i -
+ 1)) { // if a camera connected to another(GMSL A)port on a Des.
+ // a camera is connected to each port of the Des.
+ if (tier4_imx490_is_isp_ser_shutdown(
+ i -
+ 1)) { // ISP and Ser on another(GMSL A) port have been already shut down ?
+
+ if (tier4_imx490_is_des_shutdown(
+ i - 1) ==
+ false) { // if Des on another(GMSL A)port is not shutdown yet
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ true); // Des will be shut down
+ } else { // if Des on the another port is already shut down. This is Error case.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // Des will not be shutdown
+ }
+ } else { // The camera ISP and Ser on another(GMSL A) port are not shut down yet.
+
+ if (tier4_imx490_is_des_shutdown(
+ i - 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // The Des won't be shut down.
+ } else { // Only Des on another port is already shut down. This is Error case.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // Des will not be shut down.
+ }
+ } // a camera is connected to only (GMSL B) port on Des.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ true); // The Des won't be shut down.
+ }
+ } else { // if ( i & 0x1 ) == 0
+
+ if (tier4_imx490_is_camera_connected_to_port(
+ i +
+ 1)) { // Another camera is connected to another(GMSL B) port on the Des
+
+ if (tier4_imx490_is_isp_ser_shutdown(
+ i +
+ 1)) { // if the ISP and Ser on another port are already shut down
+
+ if (tier4_imx490_is_des_shutdown(
+ i + 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // The Des will be shut down.
+ } else { // Des is already shut down. This is Error case.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ } else { // The ISP and Ser on another(GMSL B) port are not shut down yet.
+
+ if (tier4_imx490_is_des_shutdown(
+ i + 1) ==
+ false) { // if Des on another(GMSL B) port is not shut down yet.
+
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ } else { // Only Des on another(GMSL B) port is already shut down.
+ // This is Error case.
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ }
+ } else {
+ tier4_imx490_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx490_set_des_shutdown(
+ i,
+ true); // The Des will be shut down.
+ }
+ } // if ( i & 0x1 )
+ // break;
+
+ if (tier4_imx490_is_isp_ser_shutdown(i)) {
+ // Reset camera sensor
+ tier4_max9295_control_sensor_power_seq(
+ priv->ser_dev, SENSOR_ID_IMX490, false);
+ // S/W Reset max9295
+ tier4_max9295_reset_control(priv->ser_dev);
+ }
+
+ if (tier4_imx490_is_des_shutdown(i)) {
+ // S/W Reset max9296
+ tier4_max9296_reset_control(priv->dser_dev,
+ &client->dev, true);
+ }
+
+ if (priv == NULL || i >= camera_channel_count) {
+ mutex_unlock(&tier4_imx490_lock);
+ tier4_isx021_sensor_mutex_unlock();
+ return;
+ }
+ }
+
+ } // for loop
+
+error_exit:
+
+ mutex_unlock(&tier4_imx490_lock);
+
+ tier4_isx021_sensor_mutex_unlock();
+}
+static const struct i2c_device_id tier4_imx490_id[] = { { "tier4_imx490", 0 },
+ {} };
+
+MODULE_DEVICE_TABLE(i2c, tier4_imx490_id);
+
+static struct i2c_driver tier4_imx490_i2c_driver = {
+ .driver = {
+ .name = "tier4_imx490",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tier4_imx490_of_match),
+ },
+ .probe = tier4_imx490_probe,
+ .remove = tier4_imx490_remove,
+ .shutdown = tier4_imx490_shutdown,
+ .id_table = tier4_imx490_id,
+};
+
+static int __init tier4_imx490_init(void)
+{
+ mutex_init(&serdes_lock__);
+ mutex_init(&tier4_imx490_lock);
+
+ printk(KERN_INFO "TIERIV Automotive HDR Camera driver.\n");
+
+ return i2c_add_driver(&tier4_imx490_i2c_driver);
+}
+
+static void __exit tier4_imx490_exit(void)
+{
+ mutex_destroy(&serdes_lock__);
+ mutex_destroy(&tier4_imx490_lock);
+
+ i2c_del_driver(&tier4_imx490_i2c_driver);
+}
+
+module_init(tier4_imx490_init);
+module_exit(tier4_imx490_exit);
+
+MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
+MODULE_AUTHOR("Originaly NVIDIA Corporation");
+MODULE_AUTHOR("K.Iwasaki");
+MODULE_AUTHOR("Y.Fujii");
+MODULE_LICENSE("GPL v2");
diff --git a/src/tier4-camera-gmsl/tier4-imx728.c b/src/tier4-camera-gmsl/tier4-imx728.c
new file mode 100644
index 0000000..f60a028
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-imx728.c
@@ -0,0 +1,1895 @@
+/*
+ * tier4_imx728.c - imx728 sensor driver
+ *
+ * Copyright (c) 2022-2023, TIER IV Inc. All rights reserved.
+ * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tier4-fpga.h"
+#include "tier4-gmsl-link.h"
+#include "tier4-gw5300.h"
+#include "tier4-hw-model.h"
+#include "tier4-isx021-extern.h"
+#include "tier4-max9295.h"
+#include "tier4-max9296.h"
+
+MODULE_SOFTDEP("pre: tier4_max9296");
+MODULE_SOFTDEP("pre: tier4_max9295");
+MODULE_SOFTDEP("pre: tier4_gw5300");
+MODULE_SOFTDEP("pre: tier4_fpga");
+MODULE_SOFTDEP("pre: tier4_isx021");
+MODULE_SOFTDEP("pre: tier4_imx490");
+
+#define USE_DISTORTION_CORRECTION 1
+
+// Register Address
+
+#define IMX728_DEFAULT_FRAME_LENGTH (2350)
+
+#define BIT_SHIFT_8 8
+#define BIT_SHIFT_16 16
+#define MASK_1_BIT 0x1
+#define MASK_4_BIT 0xF
+#define MASK_8_BIT 0xFF
+
+#define POWER_ON 1
+#define POWER_OFF 0
+
+#define NO_ERROR 0
+//#define NO_C3_CAMERA (-728)
+
+//#define TIME_120_MILISEC 120000
+//#define TIME_121_MILISEC 121000
+
+#define ISP_PRIM_SLAVE_ADDR 0x6D
+
+//#define TIER4_C3_CAMERA 1
+
+#define MAX_NUM_CAMERA 8
+
+//#define FSYNC_FREQ_HZ 10
+
+enum {
+ IMX728_MODE_3840x2160_CROP_20FPS,
+ IMX728_MODE_START_STREAM,
+ IMX728_MODE_STOP_STREAM,
+};
+
+static const int tier4_imx728_20fps[] = {
+ 20,
+};
+static const struct camera_common_frmfmt tier4_imx728_frmfmt[] = {
+ { { 3840, 2160 },
+ tier4_imx728_20fps,
+ 1,
+ 0,
+ IMX728_MODE_3840x2160_CROP_20FPS },
+ // { { 3840, 2163 }, tier4_imx728_20fps, 1, 0, IMX728_MODE_3840x2160_CROP_20FPS },
+};
+
+const struct of_device_id tier4_imx728_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_imx728",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, tier4_imx728_of_match);
+
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
+// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
+
+static const u32 ctrl_cid_list[] = {
+ TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE,
+ TEGRA_CAMERA_CID_EXPOSURE_SHORT, TEGRA_CAMERA_CID_FRAME_RATE,
+ TEGRA_CAMERA_CID_HDR_EN,
+ // TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
+};
+
+struct tier4_imx728 {
+ struct i2c_client *i2c_client;
+ const struct i2c_device_id *id;
+ struct v4l2_subdev *subdev;
+ struct device *ser_dev;
+ struct device *dser_dev;
+ struct device *isp_dev;
+ struct tier4_gmsl_link_ctx g_ctx;
+ u32 frame_length;
+ struct camera_common_data *s_data;
+ struct tegracam_device *tc_dev;
+ int trigger_mode;
+ bool distortion_correction;
+ bool last_distortion_correction;
+ bool inhibit_fpga_access;
+ struct device *fpga_dev;
+};
+
+static const struct regmap_config tier4_sensor_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+struct st_priv {
+ struct i2c_client *p_client;
+ struct tier4_imx728 *p_priv;
+ struct tegracam_device *p_tc_dev;
+ bool isp_ser_shutdown;
+ bool des_shutdown;
+ bool running;
+};
+
+static struct st_priv wst_priv[MAX_NUM_CAMERA];
+
+static struct mutex tier4_imx728_lock;
+
+static int camera_channel_count = 0;
+
+// --- module parameter ---
+
+static int trigger_mode;
+static int fsync_mfp = 0;
+static int enable_distortion_correction = 1;
+static int enable_auto_exposure = 0xCAFE;
+
+#define IMX728_MIN_EXPOSURE_TIME 11000 // 11 milisecond
+#define IMX728_MAX_EXPOSURE_TIME 33000 // 33 milisecond
+
+static int shutter_time_min = IMX728_MIN_EXPOSURE_TIME;
+static int shutter_time_max = IMX728_MAX_EXPOSURE_TIME;
+
+module_param(trigger_mode, int, 0644);
+module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
+module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
+
+module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
+module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
+module_param(enable_auto_exposure, int, S_IRUGO | S_IWUSR);
+
+// ------------------------
+static char upper(char c)
+{
+ if ('a' <= c && c <= 'z') {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+static void to_upper_string(char *out, const char *in)
+{
+ int i;
+
+ i = 0;
+ while (in[i] != '\0') {
+ out[i] = upper(in[i]);
+ i++;
+ }
+}
+
+static inline int tier4_imx728_read_reg(struct camera_common_data *s_data,
+ u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+
+ err = regmap_read(s_data->regmap, addr, ®_val);
+
+ if (err) {
+ dev_err(s_data->dev, "[%s] : I2C read failed, address=0x%x\n",
+ __func__, addr);
+ } else {
+ *val = reg_val & 0xFF;
+ }
+ return err;
+}
+
+static int tier4_imx728_write_reg(struct camera_common_data *s_data, u16 addr,
+ u8 val)
+{
+ int err = 0;
+
+ err = regmap_write(s_data->regmap, addr, val);
+
+ if (err) {
+ dev_err(s_data->dev, "[%s] : I2C write failed at x%x=[0x%x]\n",
+ __func__, addr, val);
+ }
+
+ return err;
+}
+
+// ------------------------------------------------
+
+static int tier4_imx728_set_fsync_trigger_mode(struct tier4_imx728 *priv,
+ int mode)
+{
+ int err = 0;
+ struct device *dev = priv->s_data->dev;
+ int des_num = 0;
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ priv->inhibit_fpga_access = false;
+
+ dev_info(dev, "[%s] : Set fsync trigger mode.\n", __func__);
+
+ err = tier4_fpga_check_access(priv->fpga_dev);
+ if (err) {
+ priv->inhibit_fpga_access = true;
+ }
+
+ if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE) {
+ dev_info(dev, "[%s] : Disabling FPGA fsync.\n",
+ __func__);
+
+ err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Disabling FPGA fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else {
+ err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA generate fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+
+ if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_AUTO) {
+ // Auto Trigger Mode
+ err = tier4_fpga_set_fsync_auto_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ des_num = priv->g_ctx.reg_mux;
+ err = tier4_fpga_set_fsync_signal_frequency(
+ priv->fpga_dev, des_num,
+ priv->trigger_mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_MANUAL) {
+ // Manual Trigger Mode
+ dev_info(
+ dev,
+ "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n",
+ __func__);
+
+ err = tier4_fpga_set_fsync_manual_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ }
+ }
+ }
+
+ err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
+
+ if (err) {
+ dev_err(dev, "[%s] :tier4_max9296_setup_gpi() failed\n",
+ __func__);
+ return err;
+ }
+
+ err = tier4_max9295_setup_gpo(priv->ser_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9295_setup_gpo() failed\n",
+ __func__);
+ return err;
+ }
+
+ // Power on GW5300 via Max9295 in C3 camera
+ // err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
+ // if (err)
+ // {
+ // dev_err(dev, "[%s] : Power on gw5300 in C3 camaera failed.\n", __func__);
+ // return err;
+ // }
+
+ err = tier4_gw5300_c3_setup_sensor_mode(priv->isp_dev, mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : tier4_gw5300_c3_setup_sensor_mode() failed\n",
+ __func__);
+ return err;
+ }
+
+ return err;
+}
+
+static struct mutex serdes_lock__;
+
+static int tier4_imx728_gmsl_serdes_setup(struct tier4_imx728 *priv)
+{
+ int err = 0;
+ int des_err = 0;
+ struct device *dev;
+
+ if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client) {
+ return -EINVAL;
+ }
+
+ dev = &priv->i2c_client->dev;
+
+ mutex_lock(&serdes_lock__);
+
+ /* For now no separate power on required for serializer device */
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_on(priv->dser_dev);
+ }
+
+ /* setup serdes addressing and control pipeline */
+
+ err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : GMSL deserializer link config failed\n",
+ __func__);
+ goto error;
+ }
+
+ err = tier4_max9295_setup_control(priv->ser_dev);
+
+ /* proceed even if ser setup failed, to setup deser correctly */
+ if (err) {
+ dev_err(dev, "[%s] : GMSL serializer setup failed\n", __func__);
+ goto error;
+ }
+
+ des_err = tier4_max9296_setup_control(priv->dser_dev,
+ &priv->i2c_client->dev);
+
+ if (des_err) {
+ dev_err(dev, "[%s] : GMSL deserializer : setup failed\n",
+ __func__);
+ err = des_err;
+ }
+
+error:
+ mutex_unlock(&serdes_lock__);
+ return err;
+}
+
+static void tier4_imx728_gmsl_serdes_reset(struct tier4_imx728 *priv)
+{
+ mutex_lock(&serdes_lock__);
+
+ /* reset serdes addressing and control pipeline */
+ tier4_max9295_reset_control(priv->ser_dev);
+
+ tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev,
+ true);
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_off(priv->dser_dev);
+ }
+
+ mutex_unlock(&serdes_lock__);
+}
+
+static int tier4_imx728_power_on(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_on) {
+ err = pdata->power_on(pw);
+
+ if (err) {
+ dev_err(dev, "[%s] : failed.\n", __func__);
+ } else {
+ pw->state = SWITCH_ON;
+ }
+ return err;
+ }
+
+ pw->state = SWITCH_ON;
+
+ return err;
+}
+
+static int tier4_imx728_power_off(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_off) {
+ err = pdata->power_off(pw);
+
+ if (!err) {
+ goto power_off_done;
+ } else {
+ dev_err(dev, "[%s] : power off failed.\n", __func__);
+ }
+ return err;
+ }
+
+power_off_done:
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+static int tier4_imx728_power_get(struct tegracam_device *tc_dev)
+{
+ struct camera_common_power_rail *pw = tc_dev->s_data->power;
+ int err = 0;
+
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+static int tier4_imx728_power_put(struct tegracam_device *tc_dev)
+{
+ if (unlikely(!tc_dev->s_data->power)) {
+ return -EFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+static int tier4_imx728_set_group_hold(struct tegracam_device *tc_dev, bool val)
+{
+ volatile int err = 0;
+
+ return err;
+}
+
+static int tier4_imx728_set_gain(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ // struct camera_common_data *s_data = tc_dev->s_data;
+
+ // struct device *dev = tc_dev->dev;
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_imx728_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+ // struct device dev = tc_dev->dev;
+
+ /* fixed 20fps */
+ priv->frame_length = IMX728_DEFAULT_FRAME_LENGTH;
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_imx728_set_exposure(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+ tier4_gw5300_c3_set_integration_time_on_aemode(
+ priv->isp_dev, priv->trigger_mode, val, val);
+
+ return err;
+}
+// --------------------------------------------------------------------------------------
+// Enable Distortion Coreection
+// --------------------------------------------------------------------------------------
+#if USE_DISTORTION_CORRECTION
+
+static int
+tier4_imx728_set_distortion_correction(struct tegracam_device *tc_dev, bool val)
+{
+ int err = 0;
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+
+ if (priv->last_distortion_correction != val) {
+ dev_info(&priv->i2c_client->dev,
+ "[%s] : Setting distortion correction mode :%s.\n",
+ __func__, val ? "True" : "False");
+
+ err = tier4_gw5300_c3_set_distortion_correction(priv->isp_dev,
+ val);
+ if (err <= 0) {
+ dev_info(
+ &priv->i2c_client->dev,
+ "[%s] : Setting distortion correction mode failed.\n",
+ __func__);
+ } else {
+ err = 0;
+ priv->last_distortion_correction = val;
+ }
+ }
+
+ return err;
+}
+#endif
+
+// --------------------------------------------------------------------------------------
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
+// please add the new memeber and the function at the following table.
+
+static struct tegracam_ctrl_ops tier4_imx728_ctrl_ops = {
+ .numctrls = ARRAY_SIZE(ctrl_cid_list),
+ .ctrl_cid_list = ctrl_cid_list,
+ .set_gain = tier4_imx728_set_gain,
+ .set_exposure = tier4_imx728_set_exposure,
+ .set_exposure_short = tier4_imx728_set_exposure,
+ .set_frame_rate = tier4_imx728_set_frame_rate,
+ .set_group_hold = tier4_imx728_set_group_hold,
+ // .set_distortion_correction = tier4_imx728_set_distortion_correction,
+};
+
+// --------------------------------------------------------------------------------------
+
+static struct camera_common_pdata *
+tier4_imx728_parse_dt(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct camera_common_pdata *board_priv_pdata;
+ const struct of_device_id *match;
+ int err;
+
+ if (!node) {
+ return NULL;
+ }
+
+ match = of_match_device(tier4_imx728_of_match, dev);
+
+ if (!match) {
+ dev_err(dev, "[%s] : Failed to find matching dt id\n",
+ __func__);
+ return NULL;
+ }
+
+ board_priv_pdata =
+ devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
+
+ err = of_property_read_string(node, "mclk",
+ &board_priv_pdata->mclk_name);
+
+ if (err) {
+ dev_err(dev, "[%s] : mclk not in DT\n", __func__);
+ }
+
+ return board_priv_pdata;
+}
+
+/* tier4_imx728_set_mode() can not be needed. But it remains for compatiblity */
+
+static int tier4_imx728_set_mode(struct tegracam_device *tc_dev)
+{
+ volatile int err = 0;
+
+ return err;
+}
+
+static int tier4_imx728_start_one_streaming(struct tegracam_device *tc_dev)
+{
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+ int err;
+
+ /* enable serdes streaming */
+
+ err = tier4_max9295_setup_streaming(priv->ser_dev);
+
+ if (err) {
+ goto exit;
+ }
+
+ err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : Setup Streaming failed\n", __func__);
+ goto exit;
+ }
+
+ dev_info(dev, "[%s] : trigger_mode = %d\n", __func__, trigger_mode);
+
+ priv->trigger_mode = trigger_mode;
+
+ switch (priv->trigger_mode) {
+ case GW5300_MASTER_MODE_5FPS:
+ case GW5300_MASTER_MODE_10FPS:
+ case GW5300_MASTER_MODE_10FPS_EBD:
+ case GW5300_MASTER_MODE_20FPS:
+ case GW5300_MASTER_MODE_20FPS_EBD:
+ case GW5300_MASTER_MODE_30FPS:
+ case GW5300_MASTER_MODE_30FPS_EBD:
+ dev_info(dev, "[%s] : Setting camera sensor to %s\n", __func__,
+ gw5300_mode_name[priv->trigger_mode]);
+
+ err = tier4_gw5300_c3_setup_sensor_mode(priv->isp_dev,
+ priv->trigger_mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to %s failed\n",
+ __func__, gw5300_mode_name[priv->trigger_mode]);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+ break;
+
+ case GW5300_SLAVE_MODE_5FPS:
+ case GW5300_SLAVE_MODE_10FPS:
+ case GW5300_SLAVE_MODE_10FPS_EBD:
+ case GW5300_SLAVE_MODE_20FPS:
+ case GW5300_SLAVE_MODE_20FPS_EBD:
+ case GW5300_SLAVE_MODE_30FPS:
+ case GW5300_SLAVE_MODE_30FPS_EBD:
+ dev_info(dev, "[%s] : Setting camera sensor to %s\n", __func__,
+ gw5300_mode_name[priv->trigger_mode]);
+
+ err = tier4_imx728_set_fsync_trigger_mode(priv,
+ priv->trigger_mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : setting camera sensor to %s failed\n",
+ __func__, gw5300_mode_name[priv->trigger_mode]);
+ return err;
+ }
+
+ priv->last_distortion_correction = 1;
+ break;
+
+ default: // case of trigger_mode < 0
+ dev_err(dev,
+ "[%s] : The camera sensor mode(trigger mode)=%d is invalid.\n",
+ __func__, priv->trigger_mode);
+
+ return err;
+ }
+
+ usleep_range(500000, 510000);
+ err = tier4_gw5300_c3_set_auto_exposure(priv->isp_dev,
+ enable_auto_exposure);
+ if (err <= 0) {
+ dev_err(dev,
+ "[%s] : Setting Digital Gain to default value failed\n",
+ __func__);
+ goto exit;
+ } else {
+ err = 0;
+ }
+
+#if USE_DISTORTION_CORRECTION
+
+ if (priv->last_distortion_correction != enable_distortion_correction) {
+ usleep_range(500000, 510000);
+ //msleep(900);
+ }
+
+ if (enable_distortion_correction == 0xCAFE) {
+ // if not set kernel param, read device tree param
+ if (priv->distortion_correction == false) {
+ err = tier4_imx728_set_distortion_correction(
+ tc_dev, priv->distortion_correction);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Disabling Distortion Correction failed\n",
+ __func__);
+ goto exit;
+ }
+ msleep(20);
+ }
+ } else {
+ err = tier4_imx728_set_distortion_correction(
+ tc_dev, enable_distortion_correction == 1);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setup Distortion Correction failed\n",
+ __func__);
+ goto exit;
+ }
+ msleep(20);
+ }
+
+#endif
+
+ // Reset GW5300 via Max9295 in C3 camera
+ // err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
+ // if (err)
+ // {
+ // dev_err(dev, "[%s] : Reset gw5300 in C3 camaera failed.\n", __func__);
+ // goto exit;
+ // }
+ //
+ // usleep_range(500000, 510000);
+
+ err = tier4_max9296_start_streaming(priv->dser_dev, dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_start_stream() failed\n",
+ __func__);
+ return err;
+ }
+
+ msleep(1000);
+ tier4_gw5300_c3_set_integration_time_on_aemode(priv->isp_dev,
+ priv->trigger_mode,
+ shutter_time_max,
+ shutter_time_min);
+
+ // Reset GW5300 via Max9295 in C3 camera
+ // err = tier4_max9295_control_sensor_power_seq(priv->ser_dev, SENSOR_ID_IMX728, POWER_ON );
+ // if (err)
+ // {
+ // dev_err(dev, "[%s] : Reset gw5300 in C3 camaera failed.\n", __func__);
+ // goto exit;
+ // }
+
+ dev_info(dev, "[%s] : Camera has started streaming\n", __func__);
+
+ return NO_ERROR;
+
+exit:
+
+ dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
+
+ return err;
+}
+
+static bool tier4_imx728_is_camera_connected_to_port(int nport)
+{
+ if (wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx728_check_null_tc_dev_for_port(int nport)
+{
+ if (wst_priv[nport].p_tc_dev == NULL) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx728_is_camera_running_on_port(int nport)
+{
+ if (wst_priv[nport].running) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx728_is_current_port(struct tier4_imx728 *priv, int nport)
+{
+ if (priv->i2c_client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_imx728_set_running_flag(int nport, bool flag)
+{
+ wst_priv[nport].running = flag;
+}
+
+static int tier4_imx728_stop_streaming(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+ int i, err = 0;
+
+ mutex_lock(&tier4_imx728_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_imx728_is_camera_connected_to_port(i)) {
+ if (tier4_imx728_is_current_port(priv, i) &&
+ tier4_imx728_is_camera_running_on_port(i)) {
+ /* disable serdes streaming */
+ err = tier4_max9296_stop_streaming(
+ priv->dser_dev, dev);
+ if (err) {
+ return err;
+ }
+ tier4_imx728_set_running_flag(i, false);
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&tier4_imx728_lock);
+
+ return NO_ERROR;
+}
+
+/* *************************************************************************** */
+/* 1. In the case where a camera is connected to GMSL A port on a Des. */
+/* */
+/* a > Check if another camera is connected to GMSL B port */
+/* a-1) Connected: */
+/* b > Check if another camera on GMSL B port is running */
+/* b-1) Running: */
+/* c > Check if the camera on GMSL A port is running */
+/* c-1) Running : */
+/* Do nothing and return */
+/* c-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* b-2) Not Running: */
+/* Start the camera on GMSL B port. */
+/* a-2) Not connected : */
+/* b > Check if the camera on GMSL A port is running */
+/* b-1) Running : */
+/* Do nothing and return */
+/* b-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* */
+/* 2. In the case where a camera is connected to GMSL B port on a Des. */
+/* */
+/* a > Check if the camera on GMSL B port is running */
+/* a-1) Running : */
+/* Do nothing and return */
+/* a-2) Not running : */
+/* Start the camera on GMSL B port. */
+/* *************************************************************************** */
+
+static int tier4_imx728_start_streaming(struct tegracam_device *tc_dev)
+{
+ int i, err = 0;
+ // struct tier4_imx728 *next_client_priv;
+ struct tier4_imx728 *priv =
+ (struct tier4_imx728 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+
+ mutex_lock(&tier4_imx728_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (i & 0x1) { // if i = 1,3,5,7 ( GMSL B port of a Des )
+
+ if (tier4_imx728_is_camera_connected_to_port(
+ i)) { // a camera is connected to GMSL B portL
+
+ if ((tier4_imx728_is_current_port(priv, i) ==
+ true) &&
+ (tier4_imx728_is_camera_running_on_port(
+ i) == false)) {
+ err = tier4_imx728_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming.\n",
+ __func__);
+ goto error_exit;
+ }
+ // wst_priv[i].running = true;
+ tier4_imx728_set_running_flag(i, true);
+ break;
+ }
+ }
+ } else { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
+
+ if ((tier4_imx728_is_camera_connected_to_port(i) ==
+ true) &&
+ (tier4_imx728_is_current_port(priv, i) == true)) {
+ if (tier4_imx728_is_camera_connected_to_port(
+ i + 1) ==
+ false) { // if another one camera( GMSL B port) is not
+ // connected to Des.
+ if (tier4_imx728_is_camera_running_on_port(
+ i) ==
+ false) { // and if the camera is not running.
+
+ err = tier4_imx728_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for next imx728 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx728_set_running_flag(
+ i, true);
+ }
+ break;
+ }
+
+ // two cameras are connected to one Des.
+
+ if (tier4_imx728_check_null_tc_dev_for_port(
+ i + 1)) { // check if tc_dev is null
+ dev_err(dev,
+ "[%s] : wst_priv[%d].p_tc_dev is NULL.\n",
+ __func__, i + 1);
+ err = -EINVAL;
+ goto error_exit;
+ }
+
+ if (tier4_imx728_is_camera_running_on_port(
+ i + 1) == false) {
+ err = tier4_imx728_start_one_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for the next imx728 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx728_set_running_flag(i + 1,
+ true);
+ usleep_range(200000, 220000);
+ //msleep(200);
+ mutex_unlock(&tier4_imx728_lock);
+ tier4_imx728_stop_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ mutex_lock(&tier4_imx728_lock);
+ tier4_imx728_set_running_flag(i + 1,
+ false);
+ }
+
+ if (tier4_imx728_is_camera_running_on_port(i) ==
+ false) {
+ err = tier4_imx728_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Failed to start one streaming for current imx728 client.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_imx728_set_running_flag(i, true);
+ }
+ }
+ }
+ } // for loop
+
+ err = NO_ERROR;
+
+error_exit:
+
+ mutex_unlock(&tier4_imx728_lock);
+
+ // tier4_imx728_sensor_mutex_unlock();
+
+ return err;
+}
+
+static struct camera_common_sensor_ops tier4_imx728_common_ops = {
+ .numfrmfmts = ARRAY_SIZE(tier4_imx728_frmfmt),
+ .frmfmt_table = tier4_imx728_frmfmt,
+ .power_on = tier4_imx728_power_on,
+ .power_off = tier4_imx728_power_off,
+ .write_reg = tier4_imx728_write_reg,
+ .read_reg = tier4_imx728_read_reg,
+ .parse_dt = tier4_imx728_parse_dt,
+ .power_get = tier4_imx728_power_get,
+ .power_put = tier4_imx728_power_put,
+ .set_mode = tier4_imx728_set_mode,
+ .start_streaming = tier4_imx728_start_streaming,
+ .stop_streaming = tier4_imx728_stop_streaming,
+};
+
+static int tier4_imx728_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ //struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ return NO_ERROR;
+}
+
+static const struct v4l2_subdev_internal_ops tier4_imx728_subdev_internal_ops = {
+ .open = tier4_imx728_open,
+};
+
+static const char *of_stdout_options;
+
+static int tier4_imx728_board_setup(struct tier4_imx728 *priv)
+{
+ struct tegracam_device *tc_dev = priv->tc_dev;
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *ser_node;
+ struct i2c_client *ser_i2c = NULL;
+ struct device_node *dser_node;
+ struct i2c_client *dser_i2c = NULL;
+ struct device_node *isp_node;
+ struct i2c_client *isp_i2c = NULL;
+ struct device_node *fpga_node = NULL;
+ struct i2c_client *fpga_i2c = NULL;
+ struct device_node *gmsl;
+ struct device_node *root_node;
+ int value = 0xFFFF;
+ const char *str_value;
+ const char *str_value1[2];
+ int i;
+ int err;
+ const char *str_model;
+ char upper_str_model[64];
+ char *str_err;
+ char *sub_str_err;
+
+ root_node = of_find_node_opts_by_path("/", &of_stdout_options);
+
+ err = of_property_read_string(root_node, "model", &str_model);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : model not found\n", __func__);
+ goto error;
+ }
+
+ memset(upper_str_model, 0, 64);
+
+ to_upper_string(upper_str_model, str_model);
+
+ priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
+
+ if (str_err) {
+ sub_str_err = strstr(upper_str_model,
+ STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
+
+ if (sub_str_err) {
+ priv->g_ctx.hardware_model =
+ HW_MODEL_ADLINK_ROSCUBE_ORIN;
+ } else {
+ priv->g_ctx.hardware_model =
+ HW_MODEL_NVIDIA_ORIN_DEVKIT;
+ }
+ }
+
+ dev_info(dev, "[%s] : model=%s\n", __func__, str_model);
+ dev_info(dev, "[%s] : hardware_model=%d\n", __func__,
+ priv->g_ctx.hardware_model);
+
+ if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN) {
+ dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_isp_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : def-addr not found\n", __func__);
+ goto error;
+ }
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_isp_def);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : def-addr not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg_mux not found\n", __func__);
+ goto error;
+ }
+
+ // err = of_property_read_string(node, "fsync-mode", &str_value);
+ //
+ // if (err < 0)
+ // {
+ // dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
+ // goto error;
+ // }
+ //
+ // if (!strcmp(str_value, "true"))
+ // {
+ // priv->fsync_mode = true;
+ // }
+ // else
+ // {
+ // priv->fsync_mode = false;
+ // }
+
+ err = of_property_read_string(node, "distortion-correction",
+ &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No distortion-correction found\n",
+ __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "true")) {
+ priv->distortion_correction = true;
+ } else {
+ priv->distortion_correction = false;
+ }
+
+ if (enable_auto_exposure == 0xCAFE) {
+ err = of_property_read_string(node, "auto-exposure",
+ &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : Inavlid Exposure mode.\n",
+ __func__);
+ goto error;
+ }
+
+ enable_auto_exposure = !strcmp(str_value, "true");
+ } else {
+ dev_info(dev, "[%s] : Parameter[enable_auto_exposure] = %d.\n",
+ __func__, enable_auto_exposure);
+ }
+
+#if 0
+ priv->g_ctx.fpga_generate_fsync = false;
+
+ if (( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER ) ||
+ ( priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN )) {
+
+ err = of_property_read_string(node, "fpga-generate-fsync", &str_value);
+
+ if ( err < 0) {
+ if ( err == -EINVAL ) {
+ dev_info(dev, "[%s] : Parameter of fpga-generate-fsync does not exist.\n", __func__);
+ } else {
+ dev_err(dev, "[%s] : Parameter of fpga-generate-fsync is invalid .\n", __func__);
+ goto error;
+ }
+ } else {
+ if (!strcmp(str_value, "true")) {
+ priv->g_ctx.fpga_generate_fsync = true;
+ }
+ }
+ }
+#endif
+
+ // For Ser node
+ ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
+
+ if (ser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-ser-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
+ goto error;
+ }
+
+ ser_i2c = of_find_i2c_device_by_node(ser_node);
+
+ of_node_put(ser_node);
+
+ if (ser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing Serializer Dev Handle\n",
+ __func__);
+ goto error;
+ }
+ if (ser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->ser_dev = &ser_i2c->dev;
+
+ // For ISP node
+
+ isp_node = of_parse_phandle(node, "nvidia,isp-device", 0);
+
+ if (isp_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,isp-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(isp_node, "reg", &priv->g_ctx.sdev_isp_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : ISP reg not found\n", __func__);
+ goto error;
+ }
+
+ isp_i2c = of_find_i2c_device_by_node(isp_node);
+
+ of_node_put(isp_node);
+
+ if (isp_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing ISP Dev Handle\n", __func__);
+ goto error;
+ }
+ if (isp_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing ISP driver\n", __func__);
+ goto error;
+ }
+
+ priv->isp_dev = &isp_i2c->dev;
+
+ err = tier4_gw5300_prim_slave_addr(&priv->g_ctx);
+ if (err) {
+ dev_err(dev,
+ "[%s] : ISP Prim slave address is unavailable, the default address(0x6D) is applied.\n",
+ __func__);
+ priv->g_ctx.sdev_isp_def = ISP_PRIM_SLAVE_ADDR;
+ }
+
+ priv->g_ctx.sdev_reg = priv->g_ctx.sdev_isp_reg;
+ priv->g_ctx.sdev_def = priv->g_ctx.sdev_isp_def;
+
+ // For Dser node
+
+ dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
+
+ if (dser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-dser-device");
+ goto error;
+ }
+
+ dser_i2c = of_find_i2c_device_by_node(dser_node);
+
+ of_node_put(dser_node);
+
+ if (dser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer dev handle\n",
+ __func__);
+ goto error;
+ }
+
+ if (dser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->dser_dev = &dser_i2c->dev;
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ // for FPGA node
+
+ fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
+
+ if (fpga_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,fpga-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(fpga_node, "reg",
+ &priv->g_ctx.sdev_fpga_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
+ goto error;
+ }
+
+ fpga_i2c = of_find_i2c_device_by_node(fpga_node);
+
+ of_node_put(fpga_node);
+
+ if (fpga_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA Dev Handle\n",
+ __func__);
+ goto error;
+ }
+ if (fpga_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
+ goto error;
+ }
+
+ priv->fpga_dev = &fpga_i2c->dev;
+ }
+
+ /* populate g_ctx from DT */
+
+ gmsl = of_get_child_by_name(node, "gmsl-link");
+
+ if (gmsl == NULL) {
+ dev_err(dev, "[%s] : Missing GMSL-Link device node\n",
+ __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "src-csi-port", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "csi-mode", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No csi-mode found\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "1x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
+ } else if (!strcmp(str_value, "2x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
+ } else if (!strcmp(str_value, "4x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
+ } else if (!strcmp(str_value, "2x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
+ } else {
+ dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ?
+ GMSL_SERDES_CSI_LINK_A :
+ GMSL_SERDES_CSI_LINK_B;
+
+ err = of_property_read_u32(gmsl, "st-vc", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No st-vc info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.st_vc = value;
+
+ err = of_property_read_u32(gmsl, "vc-id", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No vc-id info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_vc = value;
+
+ err = of_property_read_u32(gmsl, "num-lanes", &value);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : No num-lanes info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.num_csi_lanes = value;
+
+ priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
+
+ if (priv->g_ctx.num_streams <= 0) {
+ dev_err(dev, "[%s] : No streams found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < priv->g_ctx.num_streams; i++) {
+ of_property_read_string_index(gmsl, "streams", i,
+ &str_value1[i]);
+
+ if (!str_value1[i]) {
+ dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value1[i], "raw12")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_RAW_12;
+ } else if (!strcmp(str_value1[i], "yuv8")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
+ } else if (!strcmp(str_value1[i], "embed")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
+ } else if (!strcmp(str_value1[i], "ued-u1")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_UED_U1;
+ } else {
+ dev_err(dev, "[%s] : Invalid stream data type\n",
+ __func__);
+ goto error;
+ }
+ }
+
+ priv->g_ctx.s_dev = dev;
+
+ return NO_ERROR;
+
+error:
+ dev_err(dev, "[%s] : Board Setup failed\n", __func__);
+ return err;
+}
+
+static int tier4_imx728_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct device_node *node = dev->of_node;
+ struct tegracam_device *tc_dev;
+ struct tier4_imx728 *priv;
+ int err = 0;
+
+ dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
+
+ if (!IS_ENABLED(CONFIG_OF) || !node) {
+ return -EINVAL;
+ }
+
+ wst_priv[camera_channel_count].p_client = NULL;
+ wst_priv[camera_channel_count].p_priv = NULL;
+ wst_priv[camera_channel_count].p_tc_dev = NULL;
+
+ wst_priv[camera_channel_count].isp_ser_shutdown = false;
+ wst_priv[camera_channel_count].des_shutdown = false;
+ wst_priv[camera_channel_count].running = false;
+
+ priv = devm_kzalloc(dev, sizeof(struct tier4_imx728), GFP_KERNEL);
+
+ if (!priv) {
+ dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
+
+ if (!tc_dev) {
+ return -ENOMEM;
+ }
+
+ priv->i2c_client = tc_dev->client = client;
+
+ tc_dev->dev = dev;
+
+ strncpy(tc_dev->name, "imx728", sizeof(tc_dev->name));
+
+ tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
+ tc_dev->sensor_ops = &tier4_imx728_common_ops;
+ tc_dev->v4l2sd_internal_ops = &tier4_imx728_subdev_internal_ops;
+ tc_dev->tcctrl_ops = &tier4_imx728_ctrl_ops;
+
+ err = tegracam_device_register(tc_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : Tegra Camera Driver Registration failed\n",
+ __func__);
+ return err;
+ }
+
+ priv->tc_dev = tc_dev;
+ priv->s_data = tc_dev->s_data;
+ priv->subdev = &tc_dev->s_data->subdev;
+
+ tegracam_set_privdata(tc_dev, (void *)priv);
+
+ priv->g_ctx.sensor_id = SENSOR_ID_IMX728;
+
+ tier4_isx021_sensor_mutex_lock();
+
+ err = tier4_imx728_board_setup(priv);
+
+ if (err) {
+ dev_err(dev, "[%s] : Board Setup failed\n", __func__);
+ goto err_tegracam_unreg;
+ }
+
+ /* Pair sensor to serializer dev */
+
+ err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed\n",
+ __func__);
+ goto err_tegracam_unreg;
+ }
+ /* Register sensor to deserializer dev */
+
+ err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev,
+ "[%s] : GMSL Deserializer Register failed\n", __func__);
+ goto err_max9295_unpair;
+ }
+
+ /*
+ * gmsl serdes setup
+ *
+ * Sensor power on/off should be the right place for serdes
+ * setup/reset. But the problem is, the total required delay
+ * in serdes setup/reset exceeds the frame wait timeout, looks to
+ * be related to multiple channel open and close sequence
+ * issue (#BUG 200477330).
+ * Once this bug is fixed, these may be moved to power on/off.
+ * The delays in serdes is as per guidelines and can't be reduced,
+ * so it is placed in probe/remove, though for that, deserializer
+ * would be powered on always post boot, until 1.2v is supplied
+ * to deserializer from CVB.
+ */
+
+ err = tier4_imx728_gmsl_serdes_setup(priv);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] : GMSL Serdes setup failed\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ err = tegracam_v4l2subdev_register(tc_dev, true);
+
+ if (err) {
+ dev_err(dev, "[%s] : Tegra Camera Subdev Registration failed\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ wst_priv[camera_channel_count].p_client = client;
+ wst_priv[camera_channel_count].p_priv = priv;
+ wst_priv[camera_channel_count].p_tc_dev = tc_dev;
+
+ camera_channel_count++;
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ return NO_ERROR;
+
+ // tier4_isx021_sensor_mutex_unlock();
+
+ // dev_info(&client->dev, "Detected Tier4 IMX490 sensor\n");
+
+err_max9296_unreg:
+ tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
+err_max9295_unpair:
+ tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
+err_tegracam_unreg:
+ tegracam_device_unregister(priv->tc_dev);
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ // dev_info(dev, "[%s] :camera_channel_count = %d p_client = %p \n", __func__, camera_channel_count,
+ // wst_priv[camera_channel_count].p_client);
+
+ return err;
+ //return NO_ERROR; // err;
+}
+
+static int tier4_imx728_remove(struct i2c_client *client)
+{
+ struct camera_common_data *s_data = to_camera_common_data(&client->dev);
+ struct tier4_imx728 *priv = (struct tier4_imx728 *)s_data->priv;
+
+ tier4_imx728_gmsl_serdes_reset(priv);
+
+ tegracam_v4l2subdev_unregister(priv->tc_dev);
+
+ tegracam_device_unregister(priv->tc_dev);
+
+ return NO_ERROR;
+}
+
+static struct mutex tier4_imx728_lock;
+
+static bool tier4_imx728_is_isp_ser_shutdown(int nport)
+{
+ if (wst_priv[nport].isp_ser_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_imx728_is_des_shutdown(int nport)
+{
+ if (wst_priv[nport].des_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_imx728_set_isp_ser_shutdown(int nport, bool val)
+{
+ wst_priv[nport].isp_ser_shutdown = val;
+}
+
+static void tier4_imx728_set_des_shutdown(int nport, bool val)
+{
+ wst_priv[nport].des_shutdown = val;
+}
+
+static bool tier4_imx728_is_current_i2c_client(struct i2c_client *client,
+ int nport)
+{
+ if (client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+static void tier4_imx728_shutdown(struct i2c_client *client)
+{
+ struct tier4_imx728 *priv = NULL;
+ int i;
+
+ tier4_isx021_sensor_mutex_lock();
+
+ mutex_lock(&tier4_imx728_lock);
+
+ if (!client) {
+ goto error_exit;
+ }
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_imx728_is_current_i2c_client(client, i)) {
+ priv = wst_priv[i].p_priv;
+
+ if (i &
+ 0x1) { // Even port number( GMSL B port on a Des : i = port_number -1 )
+
+ if (tier4_imx728_is_camera_connected_to_port(
+ i -
+ 1)) { // if a camera connected to another(GMSL A)port on a Des.
+ // a camera is connected to each port of the Des.
+ if (tier4_imx728_is_isp_ser_shutdown(
+ i -
+ 1)) { // ISP and Ser on another(GMSL A) port have been already shut down ?
+
+ if (tier4_imx728_is_des_shutdown(
+ i - 1) ==
+ false) { // if Des on another(GMSL A)port is not shutdown yet
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ true); // Des will be shut down
+ } else { // if Des on the another port is already shut down. This is Error case.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // Des will not be shutdown
+ }
+ } else { // The camera ISP and Ser on another(GMSL A) port are not shut down yet.
+
+ if (tier4_imx728_is_des_shutdown(
+ i - 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // The Des won't be shut down.
+ } else { // Only Des on another port is already shut down. This is Error case.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // Des will not be shut down.
+ }
+ } // a camera is connected to only (GMSL B) port on Des.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ true); // The Des won't be shut down.
+ }
+ } else { // if ( i & 0x1 ) == 0
+
+ if (tier4_imx728_is_camera_connected_to_port(
+ i +
+ 1)) { // Another camera is connected to another(GMSL B) port on the Des
+
+ if (tier4_imx728_is_isp_ser_shutdown(
+ i +
+ 1)) { // if the ISP and Ser on another port are already shut down
+
+ if (tier4_imx728_is_des_shutdown(
+ i + 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // The Des will be shut down.
+ } else { // Des is already shut down. This is Error case.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ } else { // The ISP and Ser on another(GMSL B) port are not shut down yet.
+
+ if (tier4_imx728_is_des_shutdown(
+ i + 1) ==
+ false) { // if Des on another(GMSL B) port is not shut down yet.
+
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ } else { // Only Des on another(GMSL B) port is already shut down.
+ // This is Error case.
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ }
+ } else {
+ tier4_imx728_set_isp_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_imx728_set_des_shutdown(
+ i,
+ true); // The Des will be shut down.
+ }
+ } // if ( i & 0x1 )
+ // break;
+
+ if (tier4_imx728_is_isp_ser_shutdown(i)) {
+ // Reset camera sensor
+ tier4_max9295_control_sensor_power_seq(
+ priv->ser_dev, SENSOR_ID_IMX728, false);
+ // S/W Reset max9295
+ tier4_max9295_reset_control(priv->ser_dev);
+ }
+
+ if (tier4_imx728_is_des_shutdown(i)) {
+ // S/W Reset max9296
+ tier4_max9296_reset_control(priv->dser_dev,
+ &client->dev, true);
+ }
+
+ if (priv == NULL || i >= camera_channel_count) {
+ mutex_unlock(&tier4_imx728_lock);
+ tier4_isx021_sensor_mutex_unlock();
+ return;
+ }
+ }
+
+ } // for loop
+
+error_exit:
+
+ mutex_unlock(&tier4_imx728_lock);
+
+ tier4_isx021_sensor_mutex_unlock();
+}
+static const struct i2c_device_id tier4_imx728_id[] = { { "tier4_imx728", 0 },
+ {} };
+
+MODULE_DEVICE_TABLE(i2c, tier4_imx728_id);
+
+static struct i2c_driver tier4_imx728_i2c_driver = {
+ .driver = {
+ .name = "tier4_imx728",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tier4_imx728_of_match),
+ },
+ .probe = tier4_imx728_probe,
+ .remove = tier4_imx728_remove,
+ .shutdown = tier4_imx728_shutdown,
+ .id_table = tier4_imx728_id,
+};
+
+static int __init tier4_imx728_init(void)
+{
+ mutex_init(&serdes_lock__);
+ mutex_init(&tier4_imx728_lock);
+
+ printk(KERN_INFO "TIERIV Automotive HDR Camera driver.\n");
+
+ return i2c_add_driver(&tier4_imx728_i2c_driver);
+}
+
+static void __exit tier4_imx728_exit(void)
+{
+ mutex_destroy(&serdes_lock__);
+ mutex_destroy(&tier4_imx728_lock);
+
+ i2c_del_driver(&tier4_imx728_i2c_driver);
+}
+
+module_init(tier4_imx728_init);
+module_exit(tier4_imx728_exit);
+
+MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
+MODULE_AUTHOR("Originaly NVIDIA Corporation");
+MODULE_AUTHOR("K.Iwasaki");
+MODULE_AUTHOR("Y.Fujii");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-isx021-extern.h b/src/tier4-camera-gmsl/tier4-isx021-extern.h
similarity index 100%
rename from drivers/src/tier4-isx021-extern.h
rename to src/tier4-camera-gmsl/tier4-isx021-extern.h
diff --git a/drivers/src/tier4-isx021.bin b/src/tier4-camera-gmsl/tier4-isx021.bin
similarity index 100%
rename from drivers/src/tier4-isx021.bin
rename to src/tier4-camera-gmsl/tier4-isx021.bin
diff --git a/src/tier4-camera-gmsl/tier4-isx021.c b/src/tier4-camera-gmsl/tier4-isx021.c
new file mode 100644
index 0000000..1ae1bb9
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-isx021.c
@@ -0,0 +1,3195 @@
+/*
+ * isx021.c - isx021 sensor driver
+ *
+ * Copyright (c) 2022-2023, TIERIV INC. All rights reserved.
+ * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// ---------------------------------------------------------------
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
+#include
+#endif
+
+#include
+
+#include "tier4-fpga.h"
+#include "tier4-gmsl-link.h"
+#include "tier4-hw-model.h"
+#include "tier4-max9295.h"
+#include "tier4-max9296.h"
+
+#define USE_FIRMWARE
+
+//#define USE_I2C_TRANSFER
+#define USE_I2C_READ_REG
+
+#undef SHOW_I2C_READ_MSG
+
+#define SHOW_I2C_WRITE_MSG
+//#undef SHOW_I2C_WRITE_MSG
+
+#undef USE_CHECK_MODE_SEL
+
+#undef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
+
+MODULE_SOFTDEP("pre: tier4_max9296");
+MODULE_SOFTDEP("pre: tier4_max9295");
+MODULE_SOFTDEP("pre: tier4_fpga");
+
+// Register Address
+
+#define ISX021_SG_MODE_INTERNAL_SYNC 0
+
+#define ISX021_SG_MODE_INTERNAL_SYNC 0
+
+#define ISX021_MIN_GAIN 0
+#define ISX021_MAX_GAIN 48
+
+#define ISX021_MIN_EXPOSURE_TIME 0
+#define ISX021_MID_EXPOSURE_TIME 11010 // 11 milisecond
+#define ISX021_MAX_EXPOSURE_TIME 33000 // 33 milisecond
+
+#define ISX021_GAIN_DEFAULT_VALUE 6
+
+#define ISX021_DEFAULT_FRAME_LENGTH (1125)
+
+// --- Start of Register definition ------------------
+
+#define TIER4_ISX021_REG_0_ADDR 0
+#define TIER4_ISX021_REG_1_ADDR 1
+#define TIER4_ISX021_REG_2_ADDR 2
+#define TIER4_ISX021_REG_3_ADDR 3
+#define TIER4_ISX021_REG_4_ADDR 4
+#define TIER4_ISX021_REG_5_ADDR 5
+#define TIER4_ISX021_REG_6_ADDR 6
+#define TIER4_ISX021_REG_7_ADDR 7
+#define TIER4_ISX021_REG_8_ADDR 8
+#define TIER4_ISX021_REG_9_ADDR 9
+#define TIER4_ISX021_REG_10_ADDR 10
+#define TIER4_ISX021_REG_11_ADDR 11
+#define TIER4_ISX021_REG_12_ADDR 12
+#define TIER4_ISX021_REG_13_ADDR 13
+
+#define TIER4_ISX021_REG_14_ADDR 14
+
+// AE mode
+
+#define TIER4_ISX021_REG_15_ADDR 15
+#define TIER4_ISX021_REG_16_ADDR 16
+#define TIER4_ISX021_REG_17_ADDR 17
+#define TIER4_ISX021_REG_18_ADDR 18
+
+#define TIER4_ISX021_REG_19_ADDR 19
+#define TIER4_ISX021_REG_20_ADDR 20
+#define TIER4_ISX021_REG_21_ADDR 21
+#define TIER4_ISX021_REG_22_ADDR 22
+
+// ME mode
+
+#define TIER4_ISX021_REG_23_ADDR 23
+#define TIER4_ISX021_REG_24_ADDR 24
+#define TIER4_ISX021_REG_25_ADDR 25
+#define TIER4_ISX021_REG_26_ADDR 26
+
+#define TIER4_ISX021_REG_27_ADDR 27
+#define TIER4_ISX021_REG_28_ADDR 28
+#define TIER4_ISX021_REG_29_ADDR 29
+#define TIER4_ISX021_REG_30_ADDR 30
+
+// Analog Gain
+
+#define TIER4_ISX021_REG_31_ADDR 31
+#define TIER4_ISX021_REG_32_ADDR 32
+
+#define TIER4_ISX021_REG_33_ADDR 33
+#define TIER4_ISX021_REG_34_ADDR 34
+
+#define TIER4_ISX021_REG_35_ADDR 35
+#define TIER4_ISX021_REG_36_ADDR 36
+
+#define TIER4_ISX021_REG_37_ADDR 37
+#define TIER4_ISX021_REG_38_ADDR 38
+
+#define TIER4_ISX021_REG_39_ADDR 39
+#define TIER4_ISX021_REG_40_ADDR 40
+
+#define TIER4_ISX021_REG_41_ADDR 41
+#define TIER4_ISX021_REG_42_ADDR 42
+
+#define TIER4_ISX021_REG_43_ADDR 43
+#define TIER4_ISX021_REG_44_ADDR 44
+
+#define TIER4_ISX021_REG_45_ADDR 45
+#define TIER4_ISX021_REG_46_ADDR 46
+
+// Exposure
+
+#define TIER4_ISX021_REG_47_ADDR 47
+#define TIER4_ISX021_REG_48_ADDR 48
+#define TIER4_ISX021_REG_49_ADDR 49
+
+#define TIER4_ISX021_REG_50_ADDR 50
+#define TIER4_ISX021_REG_51_ADDR 51
+#define TIER4_ISX021_REG_52_ADDR 52
+#define TIER4_ISX021_REG_53_ADDR 53
+
+#define TIER4_ISX021_REG_54_ADDR 54
+#define TIER4_ISX021_REG_55_ADDR 55
+#define TIER4_ISX021_REG_56_ADDR 56
+#define TIER4_ISX021_REG_57_ADDR 57
+
+#define TIER4_ISX021_REG_58_ADDR 58
+#define TIER4_ISX021_REG_59_ADDR 59
+#define TIER4_ISX021_REG_60_ADDR 60
+#define TIER4_ISX021_REG_61_ADDR 61
+
+#define TIER4_ISX021_REG_62_ADDR 62
+
+#define TIER4_ISX021_REG_63_ADDR 63
+#define TIER4_ISX021_REG_64_ADDR 64
+#define TIER4_ISX021_REG_65_ADDR 65
+
+#define TIER4_ISX021_REG_66_ADDR 66
+
+// AE mode
+
+#define TIER4_ISX021_REG_67_ADDR 67
+
+#define TIER4_ISX021_REG_68_ADDR 68
+#define TIER4_ISX021_REG_69_ADDR 69
+
+#define TIER4_ISX021_REG_70_ADDR 70
+
+// Digital Gain
+
+#define TIER4_ISX021_REG_71_ADDR 71
+#define TIER4_ISX021_REG_72_ADDR 72
+
+// Distortion Corretion
+
+#define TIER4_ISX021_REG_73_ADDR 73
+#define TIER4_ISX021_REG_74_ADDR 74
+#define TIER4_ISX021_REG_75_ADDR 75
+#define TIER4_ISX021_REG_76_ADDR 76
+
+// Mode change
+
+#define TIER4_ISX021_REG_77_ADDR 77
+
+#define TIER4_ISX021_REG_78_ADDR 78
+
+#define TIER4_ISX021_REG_79_ADDR 79
+
+// Embedded data
+
+#define TIER4_ISX021_REG_80_ADDR 80
+#define TIER4_ISX021_REG_81_ADDR 81
+
+#define TIER4_ISX021_REG_82_ADDR 82
+
+#define TIER4_ISX021_REG_83_ADDR 83
+#define TIER4_ISX021_REG_84_ADDR 84
+#define TIER4_ISX021_REG_85_ADDR 85
+#define TIER4_ISX021_REG_86_ADDR 86
+#define TIER4_ISX021_REG_87_ADDR 87
+#define TIER4_ISX021_REG_88_ADDR 88
+#define TIER4_ISX021_REG_89_ADDR 89
+
+#define TIER4_ISX021_REG_90_ADDR 90
+#define TIER4_ISX021_REG_91_ADDR 91
+
+#define TIER4_ISX021_REG_92_ADDR 92
+#define TIER4_ISX021_REG_93_ADDR 93
+
+// --- End of Register definition ------------------------
+
+#define MAX_NUM_OF_REG (100)
+
+#define ISX021_AUTO_EXPOSURE_MODE 0x00
+#define ISX021_AE_TIME_UNIT_MICRO_SECOND 0x03
+
+#define BIT_SHIFT_8 8
+#define BIT_SHIFT_16 16
+#define MASK_1_BIT 0x1
+#define MASK_4_BIT 0xF
+#define MASK_8_BIT 0xFF
+
+#define NO_ERROR 0
+
+#define TIME_1_MS 1000
+#define TIME_2_MS 2000
+#define TIME_5_MS 5000
+#define TIME_10_MS 10000
+#define TIME_20_MS 20000
+#define TIME_30_MS 30000
+#define TIME_35_MS 35000
+#define TIME_40_MS 40000
+#define TIME_50_MS 50000
+#define TIME_60_MS 60000
+#define TIME_70_MS 70000
+#define TIME_80_MS 80000
+#define TIME_100_MS 100000
+#define TIME_120_MS 120000
+#define TIME_121_MS 121000
+#define TIME_200_MS 200000
+#define TIME_250_MS 250000
+#define TIME_300_MS 300000
+#define TIME_500_MS 500000
+#define TIME_800_MS 800000
+#define TIME_1000_MS 1000000
+
+#define PLUS_10(x) ((x) + (x) / 10)
+
+#define MAX_NUM_CAMERA 8
+
+#define FIRMWARE_BIN_FILE "/lib/firmware/tier4-isx021.bin"
+
+#define FSYNC_FREQ_HZ 10
+
+#define DISABLE_BOTH_EMBEDDED_DATA 0x0
+#define ENABLE_FRONT_EMBEDDED_DATA 0x1
+#define ENABLE_REAR_EMBEDDED_DATA 0x2
+#define ENABLE_BOTH_EMBEDDED_DATA \
+ ((ENABLE_FRONT_EMBEDDED_DATA) | (ENABLE_REAR_EMBEDDED_DATA))
+
+enum {
+ ISX021_MODE_1920X1280_CROP_30FPS,
+ ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA,
+ ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA,
+ ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA,
+ ISX021_MODE_START_STREAM,
+ ISX021_MODE_STOP_STREAM
+};
+
+static const int tier4_isx021_30fps[] = {
+ 30,
+};
+static const struct camera_common_frmfmt tier4_isx021_frmfmt[] = {
+ { { 1920, 1280 },
+ tier4_isx021_30fps,
+ 1,
+ 0,
+ ISX021_MODE_1920X1280_CROP_30FPS },
+ { { 1920, 1281 },
+ tier4_isx021_30fps,
+ 1,
+ 0,
+ ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA }, // added 1 lines of embedded data
+ { { 1920, 1294 },
+ tier4_isx021_30fps,
+ 1,
+ 0,
+ ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA }, // added 14 lines of embedded data
+ { { 1920, 1295 },
+ tier4_isx021_30fps,
+ 1,
+ 0,
+ ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA }, // added 15 lines of embedded data
+};
+
+const struct of_device_id tier4_isx021_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_isx021",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, tier4_isx021_of_match);
+
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function, please add new CID to the following table.
+// and define the CID number in nvidia/include/media/tegra-v4l2-camera.h
+
+static const u32 ctrl_cid_list[] = {
+ TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_EXPOSURE,
+ TEGRA_CAMERA_CID_EXPOSURE_SHORT, TEGRA_CAMERA_CID_FRAME_RATE,
+ TEGRA_CAMERA_CID_HDR_EN,
+ //TEGRA_CAMERA_CID_DISTORTION_CORRECTION,
+};
+
+struct tier4_isx021 {
+ struct i2c_client *i2c_client;
+ const struct i2c_device_id *id;
+ struct v4l2_subdev *subdev;
+ struct device *ser_dev;
+ struct device *dser_dev;
+ struct tier4_gmsl_link_ctx g_ctx;
+ u32 frame_length;
+ struct camera_common_data *s_data;
+ struct tegracam_device *tc_dev;
+ // bool fsync_mode;
+ bool distortion_correction;
+ bool auto_exposure;
+ u16 *firmware_buffer;
+ int es_number;
+ struct device *fpga_dev;
+ int trigger_mode;
+ bool inhibit_fpga_access;
+ int enable_embedded_data; // 0:disable all embedded data 1: enable front embedded data 2:enable rear embedded data 3: enable front and rear embedded data
+};
+
+static const struct regmap_config tier4_sensor_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ //.cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_NONE,
+};
+
+struct st_priv {
+ struct i2c_client *p_client;
+ struct tier4_isx021 *p_priv;
+ struct tegracam_device *p_tc_dev;
+ bool sensor_ser_shutdown;
+ bool des_shutdown;
+ bool running;
+};
+
+static struct st_priv wst_priv[MAX_NUM_CAMERA];
+
+static int camera_channel_count = 0;
+
+static int trigger_mode = 0xCAFE;
+static int enable_auto_exposure = 0xCAFE;
+static int enable_distortion_correction = 0xCAFE;
+static int shutter_time_min = ISX021_MIN_EXPOSURE_TIME;
+static int shutter_time_mid = ISX021_MID_EXPOSURE_TIME;
+static int shutter_time_max = ISX021_MAX_EXPOSURE_TIME;
+static int fsync_mfp = 0;
+// static int debug_i2c_write = 0;
+
+module_param(trigger_mode, int, S_IRUGO | S_IWUSR);
+module_param(enable_auto_exposure, int, S_IRUGO | S_IWUSR);
+module_param(enable_distortion_correction, int, S_IRUGO | S_IWUSR);
+module_param(shutter_time_min, int, S_IRUGO | S_IWUSR);
+module_param(shutter_time_mid, int, S_IRUGO | S_IWUSR);
+module_param(shutter_time_max, int, S_IRUGO | S_IWUSR);
+
+module_param(fsync_mfp, int, S_IRUGO | S_IWUSR);
+// module_param(debug_i2c_write, int, S_IRUGO | S_IWUSR);
+
+static struct mutex tier4_sensor_lock__;
+
+static struct mutex tier4_isx021_lock;
+
+void tier4_isx021_sensor_mutex_lock(void)
+{
+ mutex_lock(&tier4_sensor_lock__);
+}
+EXPORT_SYMBOL(tier4_isx021_sensor_mutex_lock);
+
+void tier4_isx021_sensor_mutex_unlock(void)
+{
+ mutex_unlock(&tier4_sensor_lock__);
+}
+EXPORT_SYMBOL(tier4_isx021_sensor_mutex_unlock);
+
+// -------------------------------
+
+static char upper(char c)
+{
+ if ('a' <= c && c <= 'z') {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+static void to_upper_string(char *out, const char *in)
+{
+ int i;
+
+ i = 0;
+ while (in[i] != '\0') {
+ out[i] = upper(in[i]);
+ i++;
+ }
+}
+
+#ifndef USE_I2C_TRANSFER // with regmap functions
+
+static inline int tier4_isx021_read_reg(struct camera_common_data *s_data,
+ u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+ u16 reg_addr = 0;
+
+#ifdef USE_FIRMWARE
+ reg_addr = priv->firmware_buffer[addr];
+#else
+ reg_addr = addr;
+#endif
+ usleep_range(TIME_1_MS * 50, PLUS_10(TIME_1_MS * 50));
+
+ err = regmap_read(s_data->regmap, reg_addr, ®_val);
+
+ *val = reg_val & 0xFF;
+
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s ] : I2C Read register failed at 0x%04X\n",
+ __func__, reg_addr);
+ }
+#ifdef SHOW_I2C_READ_MSG
+ else {
+ dev_info(s_data->dev,
+ "[%s] : I2C Read regiser at %d(0x%04X)=[0x%02X]\n",
+ __func__, addr, reg_addr, reg_val);
+ }
+#endif
+
+ return err;
+}
+
+static int tier4_isx021_write_reg(struct camera_common_data *s_data, u16 addr,
+ u8 val)
+{
+ int err = 0;
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+ u16 reg_addr = 0;
+
+#ifdef USE_FIRMWARE
+ reg_addr = priv->firmware_buffer[addr];
+#else
+ reg_addr = addr;
+#endif
+
+ usleep_range(TIME_1_MS * 50, PLUS_10(TIME_1_MS * 50));
+
+ err = regmap_write(s_data->regmap, reg_addr, val);
+
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n",
+ __func__, addr, reg_addr, val);
+ }
+#ifdef SHOW_I2C_WRITE_MSG
+ else {
+ dev_info(s_data->dev,
+ "[%s] : I2C write register at %d(0x%04X)=[0x%02X]\n",
+ __func__, addr, reg_addr, val);
+ }
+#endif
+
+ return err;
+}
+
+#ifdef USE_WRITE_AND_VEIFY
+
+static int tier4_isx021_write_reg_and_verify(struct camera_common_data *s_data,
+ u16 addr, u8 val8)
+{
+ u32 r_val32;
+ u8 r_val8;
+ int err = 0;
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+ u16 reg_addr = 0;
+
+#ifdef USE_FIRMWARE
+ reg_addr = priv->firmware_buffer[addr];
+#else
+ reg_addr = addr;
+#endif
+
+ err = regmap_write(s_data->regmap, reg_addr, val8);
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n",
+ __func__, addr, reg_addr, val8);
+ }
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = regmap_read(s_data->regmap, reg_addr, &r_val32);
+
+ r_val8 = r_val32 & 0xFF;
+
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s] : I2C Read register failed at 0x%04X=[0x%02X]\n",
+ __func__, reg_addr, r_val8);
+ }
+
+ return err;
+}
+
+#endif // ifdef USE_WRITE_AND_VEIFY
+
+#else // ifndef USE_I2C_TRANSFER ( with i2c_transfer function )
+
+#ifdef USE_I2C_READ_REG
+
+static int tier4_isx021_read_reg(struct camera_common_data *s_data, u16 addr,
+ u8 *val8) // with i2c_tranfer
+{
+ int err = 0;
+ u16 reg_addr = 0;
+ struct i2c_msg msg[2];
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+ u8 w_buf[5];
+
+#ifdef USE_FIRMWARE
+ reg_addr = priv->firmware_buffer[addr];
+#else
+ reg_addr = addr;
+#endif
+
+ w_buf[0] = (reg_addr >> 8) & 0xFF;
+ w_buf[1] = reg_addr & 0xFF;
+
+ msg[0].addr = priv->i2c_client->addr;
+ msg[0].flags = 0; // I2C Write
+ msg[0].len = 2;
+ msg[0].buf = w_buf;
+
+ msg[1].addr = priv->i2c_client->addr;
+ msg[1].flags = I2C_M_RD; // I2C Read
+ msg[1].len = 1;
+ msg[1].buf = val8;
+
+ err = i2c_transfer(priv->i2c_client->adapter, msg, 2);
+
+ if (err < 0) {
+ dev_err(s_data->dev,
+ "[%s ] : I2C Read register failed at 0x%04X\n",
+ __func__, reg_addr);
+ } else {
+ err = 0;
+ }
+
+ usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
+
+ return err;
+}
+
+#endif // ifdef USE_I2C_READ_REG
+
+// -------------------------------------------------------------------
+
+static int tier4_isx021_write_reg(struct camera_common_data *s_data, u16 addr,
+ u8 val8) // with i2c_tranfer
+{
+ int err = 0;
+ u16 reg_addr = 0;
+ struct i2c_msg msg[2];
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+ u8 w_buf[5];
+
+#ifdef USE_FIRMWARE
+ reg_addr = priv->firmware_buffer[addr];
+#else
+ reg_addr = addr;
+#endif
+
+ w_buf[0] = (reg_addr >> 8) & 0xFF;
+ w_buf[1] = reg_addr & 0xFF;
+ w_buf[2] = val8 & 0xFF;
+
+ msg[0].addr = priv->i2c_client->addr;
+ msg[0].flags = 0; // I2C Write
+ msg[0].len = 3;
+ msg[0].buf = w_buf;
+
+ err = i2c_transfer(priv->i2c_client->adapter, msg, 1);
+
+ if (err < 0) {
+ dev_err(s_data->dev,
+ "[%s] : I2C write register failed at %d(0x%04X)=[0x%02X]\n",
+ __func__, addr, reg_addr, val8);
+ } else {
+ err = 0;
+ }
+
+ usleep_range(TIME_1_MS, PLUS_10(TIME_1_MS));
+
+ return err;
+}
+
+#endif // ifndef USE_I2C_TRANSFER
+
+// ------------------------------------------------------------------
+
+static int
+tier4_isx021_write_mode_set_f_lock_register(struct camera_common_data *s_data,
+ u8 val8)
+{
+ int err = 0;
+
+ usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR,
+ 0x06); // ACK Response mode
+
+ usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_77_ADDR, val8);
+
+ usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR,
+ 0x02); // NAK Response mode
+
+ return 0;
+}
+// ------------------------------------------------------------------
+
+#ifdef USE_REMAP_REGISTER
+
+static int tier4_isx021_write_remap_register(struct camera_common_data *s_data,
+ u8 val8)
+{
+ int err = 0;
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR,
+ 0x06); // ACK Response mode
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_73_ADDR, val8);
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_90_ADDR,
+ 0x02); // NAK Response mode
+
+ return 0;
+}
+#endif
+
+// -------------------------------------------------------------------
+
+static int
+tier4_isx021_transit_to_streaming_state(struct tegracam_device *tc_dev)
+{
+ struct camera_common_data *s_data = tc_dev->s_data;
+ struct device *dev = tc_dev->dev;
+ int err = 0;
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR,
+ 0x80); // transit to Streaming state
+ if (err) {
+ dev_err(dev, "[%s] : Write to MODE_SET_F register failed.\n",
+ __func__);
+ }
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+ //msleep(120);
+
+ return err;
+}
+
+// -------------------------------------------------------------------
+
+static int tier4_isx021_transit_to_startup_state(struct tegracam_device *tc_dev)
+{
+ struct camera_common_data *s_data = tc_dev->s_data;
+ struct device *dev = tc_dev->dev;
+ int err = 0;
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR,
+ 0x00); // transit to Startup state
+
+ if (err) {
+ dev_err(dev, "[%s] : Write to MODE_SET_F register failed.\n",
+ __func__);
+ }
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+ //msleep(120);
+
+ return err;
+}
+
+// ------------------------------------------------------------------
+
+#ifdef USE_CHECK_MODE_SEL
+
+static int tier4_isx021_check_mode_sel(struct camera_common_data *s_data,
+ u8 *val8)
+{
+ //int mode_size = sizeof(remap_mode);
+ u8 rval8 = 0;
+ int err = 0;
+ struct device *dev = s_data->dev;
+
+ err = tier4_isx021_read_reg(s_data, TIER4_ISX021_REG_89_ADDR, &rval8);
+ if (err) {
+ dev_err(dev, "[%s] : Write to MODE_SEL register failed.\n",
+ __func__);
+ return err;
+ }
+
+ *val8 = rval8;
+
+ return err;
+}
+#endif // ifdef USE_CHECK_MODE_SEL
+
+// ------------------------------------------------------------------
+
+static int tier4_isx021_set_fsync_trigger_mode(struct tier4_isx021 *priv)
+{
+ int err = 0;
+ struct camera_common_data *s_data = priv->s_data;
+ struct device *dev = s_data->dev;
+ int des_num = 0;
+
+ dev_info(dev, "[%s] : hardware_model=%d.\n", __func__,
+ priv->g_ctx.hardware_model);
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ priv->inhibit_fpga_access = false;
+
+ err = tier4_fpga_check_access(priv->fpga_dev);
+ if (err) {
+ priv->inhibit_fpga_access = true;
+ }
+
+ if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_DISABLE) {
+ dev_info(dev, "[%s] : Disabling FPGA fsync.\n",
+ __func__);
+
+ err = tier4_fpga_disable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Disabling FPGA generate fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else {
+ err = tier4_fpga_enable_fsync_mode(priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA generate fsync failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+
+ if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_AUTO) {
+ // Auto Trigger Mode
+ dev_info(
+ dev,
+ "[%s] : Enabling FPGA Fsync Auto Trigger mode.\n",
+ __func__);
+
+ err = tier4_fpga_set_fsync_auto_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Auto Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+
+ des_num = priv->g_ctx.reg_mux;
+ err = tier4_fpga_set_fsync_signal_frequency(
+ priv->fpga_dev, des_num,
+ priv->trigger_mode);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setting the frequency of fsync genrated by FPGA failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } else if (tier4_fpga_get_fsync_mode() ==
+ FPGA_FSYNC_MODE_MANUAL) {
+ // Manual Trigger Mode
+ dev_info(
+ dev,
+ "[%s] : Enabling FPGA Fsync Manual Trigger mode.\n",
+ __func__);
+
+ err = tier4_fpga_set_fsync_manual_trigger(
+ priv->fpga_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Enabling FPGA Fsync Maunal Trigger mode failed.\n",
+ __func__);
+ if (!priv->inhibit_fpga_access) {
+ return err;
+ }
+ }
+ } // if (tier4_fpga_get_fsync_mode() == FPGA_FSYNC_MODE_MANUAL)
+ } // else (tier4_fpga_get_fsync_mode() != FPGA_FSYNC_MODE_DISABLE)
+ } // if (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER)
+
+ err = tier4_max9296_setup_gpi(priv->dser_dev, fsync_mfp);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_setup_gpi failed.\n",
+ __func__);
+ return err;
+ }
+
+ err = tier4_max9295_setup_gpo(priv->ser_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9295_setup_gpo failed.\n",
+ __func__);
+ return err;
+ }
+
+ // transit to Startup state
+
+ err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Time out Error occurred in tier4_isx021_write_register_mode_set_f_lock.\n",
+ __func__);
+ return err;
+ }
+
+ usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_62_ADDR, 0x00);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_isx021_write_reg failed.\n",
+ __func__);
+ return err;
+ }
+
+ usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
+
+ // set FSYNC_FUNCSEL to 0 for FSYNC triggered mode
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_92_ADDR, 0x00);
+
+ if (err) {
+ goto error_exit;
+ }
+
+ usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
+
+ // set FSYNC_DRVABTY to 3 for FSYNC triggered mode
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_93_ADDR, 0xFF);
+
+ if (err) {
+ goto error_exit;
+ }
+
+ usleep_range(TIME_50_MS, PLUS_10(TIME_50_MS));
+
+ // set SG_MODE_CTL to 0 for transition to FSYNC mode
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_63_ADDR,
+ 0x02); // set FSYNC mode
+
+ if (err) {
+ goto error_exit;
+ }
+
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+
+ // set SG_MODE_APL to 0 for transition to FSYNC mode
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_78_ADDR, 0x02);
+
+ if (err) {
+ goto error_exit;
+ }
+
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+
+error_exit:
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_set_response_mode(struct tier4_isx021 *priv)
+{
+ int err = 0;
+ struct tegracam_device *tc_dev = priv->tc_dev;
+ struct camera_common_data *s_data = priv->s_data;
+ struct device *dev = s_data->dev;
+ u8 r_val;
+
+ err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to MODE_SET_F_LOCK register caused Time out.\n",
+ __func__);
+ return err;
+ }
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = tier4_isx021_transit_to_startup_state(tc_dev);
+ if (err) {
+ dev_err(dev, "[%s] : Transition to Startup state failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS)); // For ES3 and MP
+
+ err = tier4_isx021_read_reg(s_data, TIER4_ISX021_REG_66_ADDR, &r_val);
+
+ if (r_val == 0x04) {
+ priv->es_number = 2;
+ } else {
+ priv->es_number = 3;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_66_ADDR, 0x06);
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS)); // For ES3 and MP
+
+error_exit:
+
+ return err;
+}
+
+static int tier4_isx021_gmsl_serdes_setup(struct tier4_isx021 *priv)
+{
+ int err = 0;
+ int des_err = 0;
+ struct device *dev;
+
+ if (!priv || !priv->ser_dev || !priv->dser_dev || !priv->i2c_client) {
+ return -EINVAL;
+ }
+
+ dev = &priv->i2c_client->dev;
+
+ /* For now no separate power on required for serializer device */
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_on(priv->dser_dev);
+ }
+ /* setup serdes addressing and control pipeline */
+
+ err = tier4_max9296_setup_link(priv->dser_dev, &priv->i2c_client->dev);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Configuration of GMSL Deserializer link failed.\n",
+ __func__);
+ goto error;
+ }
+
+ err = tier4_max9295_setup_control(priv->ser_dev);
+
+ /* proceed even if ser setup failed, to setup deser correctly */
+ if (err) {
+ dev_err(dev, "[%s] : Setup for GMSL Serializer failed.\n",
+ __func__);
+ goto error;
+ }
+
+ des_err = tier4_max9296_setup_control(priv->dser_dev,
+ &priv->i2c_client->dev);
+
+ if (des_err) {
+ dev_err(dev, "[%s] : Setup for GMSL Deserializer failed.\n",
+ __func__);
+ err = des_err;
+ }
+error:
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void tier4_isx021_gmsl_serdes_reset(struct tier4_isx021 *priv)
+{
+ /* reset serdes addressing and control pipeline */
+ tier4_max9295_reset_control(priv->ser_dev);
+
+ tier4_max9296_reset_control(priv->dser_dev, &priv->i2c_client->dev,
+ false);
+
+ if ((priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_XAVIER) &&
+ (priv->g_ctx.hardware_model != HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ tier4_max9296_power_off(priv->dser_dev);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_power_on(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_on) {
+ err = pdata->power_on(pw);
+
+ if (err) {
+ dev_err(dev, "[%s] : Turning on the power failed.\n",
+ __func__);
+ } else {
+ pw->state = SWITCH_ON;
+ }
+ return err;
+ }
+
+ pw->state = SWITCH_ON;
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_power_off(struct camera_common_data *s_data)
+{
+ int err = 0;
+ struct camera_common_power_rail *pw = s_data->power;
+ struct camera_common_pdata *pdata = s_data->pdata;
+ struct device *dev = s_data->dev;
+
+ if (pdata && pdata->power_off) {
+ err = pdata->power_off(pw);
+
+ if (!err) {
+ goto power_off_done;
+ } else {
+ dev_err(dev, "[%s] : Turning off the power failed.\n",
+ __func__);
+ }
+ return err;
+ }
+
+power_off_done:
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_power_get(struct tegracam_device *tc_dev)
+{
+ struct camera_common_power_rail *pw = tc_dev->s_data->power;
+ int err = 0;
+
+ pw->state = SWITCH_OFF;
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_power_put(struct tegracam_device *tc_dev)
+{
+ if (unlikely(!tc_dev->s_data->power)) {
+ return -EFAULT;
+ }
+
+ return NO_ERROR;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_set_group_hold(struct tegracam_device *tc_dev, bool val)
+{
+ volatile int err = 0;
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_copy_reg_value(struct camera_common_data *s_data, u16 ae_addr,
+ u16 me_addr)
+{
+ int err = 0;
+ u8 val8 = 0;
+
+ err = tier4_isx021_read_reg(s_data, ae_addr, &val8);
+
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s] : I2C Read Register failed at 0x%x\n", __func__,
+ ae_addr);
+ }
+
+ err = tier4_isx021_write_reg(s_data, me_addr, val8);
+
+ if (err) {
+ dev_err(s_data->dev,
+ "[%s] : I2C write Register failed at 0x%x =[ 0x%x]\n",
+ __func__, me_addr, val8);
+ }
+
+ return err;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tier4_isx021_set_gain(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ s64 gain;
+ u8 digital_gain_low_byte;
+ u8 digital_gain_high_byte;
+
+ struct camera_common_data *s_data = tc_dev->s_data;
+ struct device *dev = tc_dev->dev;
+
+ if (val > ISX021_MAX_GAIN) {
+ val = ISX021_MAX_GAIN;
+ } else if (val < ISX021_MIN_GAIN) {
+ val = ISX021_MIN_GAIN;
+ }
+
+ dev_info(dev, "[%s] :Gain is set to %lld\n", __func__, val);
+
+ gain = 10 * val;
+
+ digital_gain_low_byte = gain & 0xFF;
+
+ digital_gain_high_byte = (gain >> 8) & 0xFF;
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_68_ADDR, 0x01);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_69_ADDR, 0x01);
+
+ if (err) {
+ goto fail;
+ }
+
+ // Shutter 0 value
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_15_ADDR,
+ TIER4_ISX021_REG_23_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_16_ADDR,
+ TIER4_ISX021_REG_24_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_17_ADDR,
+ TIER4_ISX021_REG_25_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_18_ADDR,
+ TIER4_ISX021_REG_26_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ // Shutter 1 value
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_19_ADDR,
+ TIER4_ISX021_REG_27_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_20_ADDR,
+ TIER4_ISX021_REG_28_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_21_ADDR,
+ TIER4_ISX021_REG_29_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_22_ADDR,
+ TIER4_ISX021_REG_30_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ // Set Analog Gain for shutter 0
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_31_ADDR,
+ digital_gain_low_byte);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_32_ADDR,
+ digital_gain_high_byte);
+
+ if (err) {
+ goto fail;
+ }
+
+ // copy AE Analog gain value to ME analog gain registers for shutter 1 to 3
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_35_ADDR,
+ TIER4_ISX021_REG_37_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_36_ADDR,
+ TIER4_ISX021_REG_38_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_39_ADDR,
+ TIER4_ISX021_REG_41_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_40_ADDR,
+ TIER4_ISX021_REG_42_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_43_ADDR,
+ TIER4_ISX021_REG_45_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_copy_reg_value(s_data, TIER4_ISX021_REG_44_ADDR,
+ TIER4_ISX021_REG_46_ADDR);
+
+ if (err) {
+ goto fail;
+ }
+
+ msleep(100); // For ES3
+
+ // Change AE mode
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_67_ADDR, 0x03);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_71_ADDR,
+ digital_gain_low_byte);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_72_ADDR,
+ digital_gain_high_byte);
+
+ if (err) {
+ goto fail;
+ }
+
+ return NO_ERROR;
+
+fail:
+ dev_err(dev, "[%s] : Gain control Error\n", __func__);
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_isx021_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
+{
+ struct tier4_isx021 *priv =
+ (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+
+ /* fixed 10fps */
+ priv->frame_length = ISX021_DEFAULT_FRAME_LENGTH;
+
+ return NO_ERROR;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_isx021_set_auto_exposure(struct tegracam_device *tc_dev)
+{
+ int err = 0;
+ struct camera_common_data *s_data = tc_dev->s_data;
+
+ // Change to Auto exposure mode
+
+ msleep(100); // For ES3
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_67_ADDR,
+ ISX021_AUTO_EXPOSURE_MODE);
+
+ // Set min exposure time unit
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_47_ADDR,
+ ISX021_AE_TIME_UNIT_MICRO_SECOND);
+ if (err) {
+ goto fail;
+ }
+
+ // Set mid exposure time unit
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_48_ADDR,
+ ISX021_AE_TIME_UNIT_MICRO_SECOND);
+ if (err) {
+ goto fail;
+ }
+
+ // Set max exposure time unit
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_49_ADDR,
+ ISX021_AE_TIME_UNIT_MICRO_SECOND);
+ if (err) {
+ goto fail;
+ }
+
+ // Set min exposure time
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_50_ADDR,
+ shutter_time_min & 0xFF);
+ if (err) {
+ goto fail;
+ }
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_51_ADDR,
+ (shutter_time_min >> 8) & 0xFF);
+ if (err) {
+ goto fail;
+ }
+
+ // Set mid exposure time
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_54_ADDR,
+ shutter_time_mid & 0xFF);
+ if (err) {
+ goto fail;
+ }
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_55_ADDR,
+ (shutter_time_mid >> 8) & 0xFF);
+ if (err) {
+ goto fail;
+ }
+
+ // Set max exposure time
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_58_ADDR,
+ shutter_time_max & 0xFF);
+ if (err) {
+ goto fail;
+ }
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_59_ADDR,
+ (shutter_time_max >> 8) & 0xFF);
+ if (err) {
+ goto fail;
+ }
+
+fail:
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int tier4_isx021_set_exposure(struct tegracam_device *tc_dev, s64 val)
+{
+ int err = 0;
+
+ u8 exp_time_byte0;
+ u8 exp_time_byte1;
+ u8 exp_time_byte2;
+ u8 exp_time_byte3;
+ // struct tier4_isx021 *priv = (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+ struct camera_common_data *s_data = tc_dev->s_data;
+
+ // unit for val is micro-second
+
+ if (val > ISX021_MAX_EXPOSURE_TIME) {
+ val = ISX021_MAX_EXPOSURE_TIME;
+ } else if (val < ISX021_MIN_EXPOSURE_TIME) {
+ val = ISX021_MIN_EXPOSURE_TIME;
+ }
+
+ exp_time_byte0 = val & 0xFF;
+
+ exp_time_byte1 = (val >> 8) & 0xFF;
+
+ exp_time_byte2 = (val >> 16) & 0xFF;
+
+ exp_time_byte3 = (val >> 24) & 0xFF;
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_48_ADDR, 0x03);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_49_ADDR, 0x03);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_54_ADDR,
+ exp_time_byte0);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_55_ADDR,
+ exp_time_byte1);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_56_ADDR,
+ exp_time_byte2);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_57_ADDR,
+ exp_time_byte3);
+
+ if (err) {
+ goto fail;
+ }
+
+ // Shutter2
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_58_ADDR,
+ exp_time_byte0);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_59_ADDR,
+ exp_time_byte1);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_60_ADDR,
+ exp_time_byte2);
+
+ if (err) {
+ goto fail;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_61_ADDR,
+ exp_time_byte3);
+
+ if (err) {
+ goto fail;
+ }
+
+ return NO_ERROR;
+
+fail:
+
+ return err;
+}
+// --------------------------------------------------------------------------------------
+// Enable Distortion Coreection
+// --------------------------------------------------------------------------------------
+static int
+tier4_isx021_enable_distortion_correction(struct tegracam_device *tc_dev,
+ bool is_enabled)
+{
+ int err = 0;
+ struct device *dev = tc_dev->dev;
+ struct camera_common_data *s_data = tc_dev->s_data;
+
+ err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to MODE_SET_F_LOCK register caused Time out.\n",
+ __func__);
+ return err;
+ }
+
+ usleep_range(TIME_10_MS, PLUS_10(TIME_10_MS));
+
+ err = tier4_isx021_transit_to_startup_state(tc_dev);
+
+ if (err) {
+ dev_err(dev, "[%s] : Transition to Startup state failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
+ //msleep(35);
+
+ if (is_enabled) {
+ err = tier4_isx021_write_reg(tc_dev->s_data,
+ TIER4_ISX021_REG_74_ADDR, 0x01);
+
+ usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
+ //msleep(35);
+
+ err = tier4_isx021_write_reg(tc_dev->s_data,
+ TIER4_ISX021_REG_75_ADDR, 0x01);
+ if (err) {
+ goto error_exit;
+ }
+ } else {
+ dev_info(tc_dev->dev, "[%s] : Disabled Distortion Correction.",
+ __func__);
+
+ err = tier4_isx021_write_reg(tc_dev->s_data,
+ TIER4_ISX021_REG_74_ADDR, 0x00);
+
+ usleep_range(TIME_35_MS, PLUS_10(TIME_35_MS));
+ //msleep(35);
+
+ err = tier4_isx021_write_reg(tc_dev->s_data,
+ TIER4_ISX021_REG_75_ADDR, 0x00);
+ if (err) {
+ goto error_exit;
+ }
+ }
+
+error_exit:
+
+ if (err && !is_enabled) {
+ dev_err(tc_dev->dev,
+ "[%s] : Disabling Distortion Correction failed.",
+ __func__);
+ } else if (err && is_enabled) {
+ dev_err(tc_dev->dev,
+ "[%s] : Enabling Distortion Correction failed.",
+ __func__);
+ }
+
+ return err;
+}
+
+// Please refer to the section for embedded data in ISX021 application note
+
+static int tier4_isx021_setup_embedded_data(struct tegracam_device *tc_dev,
+ int enable_embedded_data)
+{
+ struct camera_common_data *s_data = tc_dev->s_data;
+ struct device *dev = s_data->dev;
+ int err = 0;
+ int rc = 0;
+
+ dev_dbg(dev, "[%s] : Setup for Embedded data.\n", __func__);
+
+ err = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to MODE_SET_F_LOCK Register failed\n",
+ __func__);
+ //goto error_exit;
+ }
+
+ usleep_range(TIME_100_MS, PLUS_10(TIME_100_MS));
+ //msleep(100);
+
+ err = tier4_isx021_transit_to_startup_state(tc_dev);
+ if (err) {
+ dev_err(dev, "[%s] : Transition to Startup state failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ usleep_range(TIME_120_MS, PLUS_10(TIME_120_MS));
+ //msleep(120);
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_91_ADDR,
+ 0x00); // DCROP_ON_APL Regsiter
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to ISX021_DCROP_ON Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_82_ADDR,
+ 0x00); // DCROP_ON register : Enable 0 Padding after Embedded data
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to ISX021_DCROP_ON Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ dev_dbg(dev, "[%s] : enable_embedded_data = %d\n", __func__,
+ enable_embedded_data);
+
+ // Enable Front Embedded data
+
+ if (enable_embedded_data & ENABLE_FRONT_EMBEDDED_DATA) {
+ dev_info(dev, "[%s] : Enabling Front Embedded.\n", __func__);
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_80_ADDR,
+ 0x1); // Enable outputting Front Embedded Data
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IR_DR_I2I_FEBD_EN Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_83_ADDR,
+ 0x1);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_FEBD_SEL Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_85_ADDR,
+ 0x1E); // EBD data are encoded as YcbCr(YUV422: applied in this driver )
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_FEBD Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ } else { // Diable Front Embedded data
+
+ dev_info(dev, "[%s] : Disabling Front Embedded.\n", __func__);
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_80_ADDR,
+ 0x0); // Disable outputting Front Embedded Data
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IR_DR_I2I_FEBD_EN Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_83_ADDR,
+ 0x0); // Front Embedded data type is not selected by IR_DR_I2I_FEBD
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_FEBD_SEL Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_85_ADDR,
+ 0x12); // Default data type for Front Embedded
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IR_DR_I2I_FEBD Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ }
+
+ if (enable_embedded_data &
+ ENABLE_REAR_EMBEDDED_DATA) { // Enable Rear Embedded data
+
+ dev_info(dev, "[%s] : Enabling Rear Embedded.\n", __func__);
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_81_ADDR,
+ 0x1); // Enable outputting Rear Embedded Data
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IR_DR_I2I_REBD_EN Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_84_ADDR,
+ 0x0D);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_REBD_SEL Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_86_ADDR,
+ 0x1E);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_REBD Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ } else { // Diabled Rear Embedded data
+
+ dev_info(dev, "[%s] : Disabling Rear Embedded.\n", __func__);
+
+ err = tier4_isx021_write_reg(
+ s_data, TIER4_ISX021_REG_81_ADDR,
+ 0x0); // Disable outputting Rear Embedded Data
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IR_DR_I2I_REBD_EN Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_84_ADDR,
+ 0x0C);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_REBD_SEL Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_86_ADDR,
+ 0x35);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_REBD Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ }
+
+ err = tier4_isx021_write_reg(s_data, TIER4_ISX021_REG_87_ADDR, 0x1E);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Write to IFD_DATATYPE_VISIBLE Register failed.\n",
+ __func__);
+ goto error_exit;
+ }
+
+error_exit:
+
+#if 1
+
+ rc = tier4_isx021_write_mode_set_f_lock_register(s_data, 0x53);
+ if (rc) {
+ dev_err(dev,
+ "[%s] : Write to MODE_SET_F_LOCK Register failed.\n",
+ __func__);
+ }
+#endif
+
+ return (err | rc);
+}
+
+// --------------------------------------------------------------------------------------
+// If you add new ioctl VIDIOC_S_EXT_CTRLS function,
+// please add the new memeber and the function at the following table.
+
+static struct tegracam_ctrl_ops tier4_isx021_ctrl_ops = {
+ .numctrls = ARRAY_SIZE(ctrl_cid_list),
+ .ctrl_cid_list = ctrl_cid_list,
+ .set_gain = tier4_isx021_set_gain,
+ .set_exposure = tier4_isx021_set_exposure,
+ .set_exposure_short = tier4_isx021_set_exposure,
+ .set_frame_rate = tier4_isx021_set_frame_rate,
+ .set_group_hold = tier4_isx021_set_group_hold,
+ // .set_distortion_correction = tier4_isx021_set_distortion_correction,
+};
+
+// --------------------------------------------------------------------------------------
+
+static struct camera_common_pdata *
+tier4_isx021_parse_dt(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct camera_common_pdata *board_priv_pdata;
+ const struct of_device_id *match;
+ int err;
+
+ if (!node) {
+ return NULL;
+ }
+
+ match = of_match_device(tier4_isx021_of_match, dev);
+
+ if (!match) {
+ dev_err(dev, "[%s] : Finding matching dt id failed.\n",
+ __func__);
+ return NULL;
+ }
+
+ board_priv_pdata =
+ devm_kzalloc(dev, sizeof(*board_priv_pdata), GFP_KERNEL);
+
+ err = of_property_read_string(node, "mclk",
+ &board_priv_pdata->mclk_name);
+
+ if (err) {
+ dev_err(dev, "[%s] : mclk not in DT.\n", __func__);
+ }
+
+ return board_priv_pdata;
+}
+
+/* tier4_isx021_set_mode() can not be needed. But it remains for compatiblity */
+
+static int tier4_isx021_set_mode(struct tegracam_device *tc_dev)
+{
+ struct tier4_isx021 *priv =
+ (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+ struct camera_common_data *s_data = tc_dev->s_data;
+ struct device *dev = tc_dev->dev;
+
+ int err = 0;
+
+ switch (s_data->mode) {
+ case ISX021_MODE_1920X1280_CROP_30FPS:
+ priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
+ break;
+ case ISX021_MODE_1920X1281_CROP_30FPS_FRONT_EMBEDDED_DATA:
+ priv->enable_embedded_data = ENABLE_FRONT_EMBEDDED_DATA;
+ break;
+ case ISX021_MODE_1920X1294_CROP_30FPS_REAR_EMBEDDED_DATA:
+ priv->enable_embedded_data = ENABLE_REAR_EMBEDDED_DATA;
+ break;
+ case ISX021_MODE_1920X1295_CROP_30FPS_BOTH_EMBEDDED_DATA:
+ priv->enable_embedded_data = ENABLE_BOTH_EMBEDDED_DATA;
+ break;
+ default:
+ priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
+ break;
+ }
+
+ dev_dbg(dev, "[%s]: priv->enable_embedded_data = %d \n", __func__,
+ priv->enable_embedded_data);
+
+ return err;
+}
+
+// -------------------------------------------------------------------
+
+static int tier4_isx021_start_one_streaming(struct tegracam_device *tc_dev)
+{
+ struct tier4_isx021 *priv =
+ (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+ int err;
+
+ /* enable serdes streaming */
+
+ err = tier4_max9295_setup_streaming(priv->ser_dev);
+ if (err) {
+ goto exit;
+ }
+
+ err = tier4_max9296_setup_streaming(priv->dser_dev, dev);
+ if (err) {
+ dev_err(dev, "[%s] : Setup for Streaming failed.\n", __func__);
+ goto exit;
+ }
+
+ err = tier4_max9295_control_sensor_power_seq(priv->ser_dev,
+ SENSOR_ID_ISX021, true);
+ if (err) {
+ dev_err(dev, "[%s] : Power on Camera Sensor failed.\n",
+ __func__);
+ goto exit;
+ }
+ if (enable_auto_exposure == 1) {
+ priv->auto_exposure = true;
+ dev_info(dev, "[%s] : Parameter[enable_auto_exposure] = 1.\n",
+ __func__);
+ }
+
+ if (priv->auto_exposure == true) {
+ err = tier4_isx021_set_auto_exposure(tc_dev);
+ if (err) {
+ dev_err(dev, "[%s] : Enabling Auto Exposure failed.\n",
+ __func__);
+ goto exit;
+ } else {
+ dev_info(dev, "[%s] : Enabled Auto Exposure.\n",
+ __func__);
+ }
+ } else {
+ dev_info(dev, "[%s] : Disabled Auto Exposure.\n", __func__);
+ }
+ if (err) {
+ dev_err(dev,
+ "[%s] : Setting digital gain to the default value failed.\n",
+ __func__);
+ }
+
+ dev_info(dev, "[%s] : trigger_mode = %d.\n", __func__, trigger_mode);
+
+ priv->trigger_mode = trigger_mode;
+
+ if (priv->trigger_mode == 1) {
+ // priv->fsync_mode = true;
+ dev_info(dev, "[%s] : Enabled Slave(fsync triggered) mode.\n",
+ __func__);
+ }
+
+ // if (priv->fsync_mode == true)
+ if (priv->trigger_mode == 1) {
+ err = tier4_isx021_set_fsync_trigger_mode(priv);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Camera sensor is unable to work with Slave(fsync triggered) mode.\n",
+ __func__);
+ // goto exit;
+ }
+ }
+
+ usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
+
+ if (enable_distortion_correction == 1) {
+ priv->distortion_correction = true;
+ dev_info(
+ dev,
+ "[%s] : Prameter[enable_distortion_correction] = 1 .\n",
+ __func__);
+ }
+ err = tier4_isx021_enable_distortion_correction(
+ tc_dev, priv->distortion_correction);
+ if (err) {
+ dev_err(dev, "[%s] : Enabling Distortion Correction failed.\n",
+ __func__);
+ goto exit;
+ }
+
+ err = tier4_isx021_setup_embedded_data(tc_dev,
+ priv->enable_embedded_data);
+ if (err) {
+ dev_err(dev, "[%s] : Setup for Embedded data failed.\n",
+ __func__);
+ goto exit;
+ }
+
+ err = tier4_isx021_transit_to_streaming_state(tc_dev);
+ if (err) {
+ dev_err(dev, "[%s] : Transition to Streaming state failed.\n",
+ __func__);
+ return err;
+ }
+
+ usleep_range(TIME_20_MS, PLUS_10(TIME_20_MS));
+
+ err = tier4_max9296_start_streaming(priv->dser_dev, dev);
+ if (err) {
+ dev_err(dev, "[%s] : Des(Max9296) failed to start streaming.\n",
+ __func__);
+ return err;
+ }
+
+ dev_info(dev, "[%s] : Camera has started streaming.\n", __func__);
+
+ return NO_ERROR;
+
+exit:
+
+ dev_err(dev, "[%s] : Camera failed to start streaming.\n", __func__);
+
+ return err;
+}
+
+//-------------------------------------------------------------------
+
+static bool tier4_isx021_is_camera_connected_to_port(int nport)
+{
+ if (wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_isx021_check_null_tc_dev_for_port(int nport)
+{
+ if (wst_priv[nport].p_tc_dev == NULL) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_isx021_is_camera_running_on_port(int nport)
+{
+ if (wst_priv[nport].running) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_isx021_is_current_port(struct tier4_isx021 *priv, int nport)
+{
+ if (priv->i2c_client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_isx021_set_running_flag(int nport, bool flag)
+{
+ wst_priv[nport].running = flag;
+}
+
+// static void tier4_isx021_reset_running_flag(int nport)
+//{
+// wst_priv[nport].running = false;
+//}
+
+static int tier4_isx021_stop_streaming(struct tegracam_device *tc_dev)
+{
+ struct device *dev = tc_dev->dev;
+ struct tier4_isx021 *priv =
+ (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+ int i, err = 0;
+
+ mutex_lock(&tier4_isx021_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_isx021_is_camera_connected_to_port(i)) {
+ if (tier4_isx021_is_current_port(priv, i) &&
+ tier4_isx021_is_camera_running_on_port(i)) {
+ /* disable serdes streaming */
+ err = tier4_max9296_stop_streaming(
+ priv->dser_dev, dev);
+ if (err) {
+ return err;
+ }
+ tier4_isx021_set_running_flag(i, false);
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&tier4_isx021_lock);
+
+ return NO_ERROR;
+}
+
+/* *************************************************************************** */
+/* 1. In the case where a camera is connected to GMSL A port on a Des. */
+/* */
+/* a > Check if another camera is connected to GMSL B port */
+/* a-1) Connected: */
+/* b > Check if another camera on GMSL B port is running */
+/* b-1) Running: */
+/* c > Check if the camera on GMSL A port is running */
+/* c-1) Running : */
+/* Do nothing and return */
+/* c-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* b-2) Not Running: */
+/* Start the camera on GMSL B port. */
+/* a-2) Not connected : */
+/* b > Check if the camera on GMSL A port is running */
+/* b-1) Running : */
+/* Do nothing and return */
+/* b-2) Not running : */
+/* Start the camera on GMSL A port. */
+/* */
+/* 2. In the case where a camera is connected to GMSL B port on a Des. */
+/* */
+/* a > Check if the camera on GMSL B port is running */
+/* a-1) Running : */
+/* Do nothing and return */
+/* a-2) Not running : */
+/* Start the camera on GMSL B port. */
+/* *************************************************************************** */
+
+static int tier4_isx021_start_streaming(struct tegracam_device *tc_dev)
+{
+ int i, err = 0;
+ // struct tier4_isx021 *next_client_priv;
+ struct tier4_isx021 *priv =
+ (struct tier4_isx021 *)tegracam_get_privdata(tc_dev);
+ struct device *dev = tc_dev->dev;
+
+ mutex_lock(&tier4_isx021_lock);
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (i & 0x1) { // if i = 1,3,5,7 ( GMSL B port of a Des )
+
+ if (tier4_isx021_is_camera_connected_to_port(
+ i)) { // a camera is connected to GMSL B portL
+
+ if ((tier4_isx021_is_current_port(priv, i) ==
+ true) &&
+ (tier4_isx021_is_camera_running_on_port(
+ i) == false)) {
+ // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
+ err = tier4_isx021_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Starting one streaming on Camera sensor failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ wst_priv[i].running = true;
+ break;
+ }
+ }
+ } else { // if i = 0,2,4,6 ( GMSL A side port of a Des0,Des1,Des2 or Des3 )
+
+ if ((tier4_isx021_is_camera_connected_to_port(i) ==
+ true) &&
+ (tier4_isx021_is_current_port(priv, i) == true)) {
+ if (tier4_isx021_is_camera_connected_to_port(
+ i + 1) ==
+ false) { // if another one camera( GMSL B port)
+ // is not connected to Des
+ if (tier4_isx021_is_camera_running_on_port(
+ i) ==
+ false) { // and if the camera is not running.
+
+ // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
+ err = tier4_isx021_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Starting one streaming for next isx021 client failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_isx021_set_running_flag(
+ i, true);
+ }
+ break;
+ }
+
+ // two cameras are connected to one Des.
+
+ if (tier4_isx021_check_null_tc_dev_for_port(
+ i + 1)) { // check if tc_dev is null
+ dev_err(dev,
+ "[%s] : wst_priv[%d].p_tc_dev is NULL.\n",
+ __func__, i + 1);
+ err = -EINVAL;
+ goto error_exit;
+ }
+
+ if (tier4_isx021_is_camera_running_on_port(
+ i + 1) == false) {
+ // err = tier4_isx021_start_one_streaming(wst_priv[i+1].p_tc_dev, wst_priv[i+1].p_priv);
+ err = tier4_isx021_start_one_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Start one streaming for the next isx021 client failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_isx021_set_running_flag(i + 1,
+ true);
+ usleep_range(TIME_200_MS,
+ PLUS_10(TIME_200_MS));
+ //msleep(200);
+ mutex_unlock(
+ &tier4_isx021_lock); // stop streaming on GMSL B port
+ tier4_isx021_stop_streaming(
+ wst_priv[i + 1].p_tc_dev);
+ mutex_lock(&tier4_isx021_lock);
+ }
+
+ if (tier4_isx021_is_camera_running_on_port(i) ==
+ false) {
+ // err = tier4_isx021_start_one_streaming(wst_priv[i].p_tc_dev, wst_priv[i].p_priv);
+ err = tier4_isx021_start_one_streaming(
+ wst_priv[i].p_tc_dev);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Starting one streaming for current isx021 client failed.\n",
+ __func__);
+ goto error_exit;
+ }
+ tier4_isx021_set_running_flag(i, true);
+ }
+ }
+ }
+ } // for loop
+
+ err = NO_ERROR;
+
+error_exit:
+
+ mutex_unlock(&tier4_isx021_lock);
+
+ // tier4_isx021_sensor_mutex_unlock();
+
+ return err;
+}
+
+static struct camera_common_sensor_ops tier4_isx021_common_ops = {
+ .numfrmfmts = ARRAY_SIZE(tier4_isx021_frmfmt),
+ .frmfmt_table = tier4_isx021_frmfmt,
+ .power_on = tier4_isx021_power_on,
+ .power_off = tier4_isx021_power_off,
+ .write_reg = tier4_isx021_write_reg,
+ .read_reg = tier4_isx021_read_reg,
+ .parse_dt = tier4_isx021_parse_dt,
+ .power_get = tier4_isx021_power_get,
+ .power_put = tier4_isx021_power_put,
+ .set_mode = tier4_isx021_set_mode,
+ .start_streaming = tier4_isx021_start_streaming,
+ .stop_streaming = tier4_isx021_stop_streaming,
+};
+
+static int tier4_isx021_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ // struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ return NO_ERROR;
+}
+
+static const struct v4l2_subdev_internal_ops tier4_isx021_subdev_internal_ops = {
+ .open = tier4_isx021_open,
+};
+
+static const char *of_stdout_options;
+
+static int tier4_isx021_board_setup(struct tier4_isx021 *priv)
+{
+ struct tegracam_device *tc_dev = priv->tc_dev;
+ struct device *dev = tc_dev->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *mode_node;
+ struct device_node *ser_node;
+ struct device_node *root_node;
+ struct i2c_client *ser_i2c = NULL;
+ struct device_node *dser_node;
+ struct i2c_client *dser_i2c = NULL;
+ struct device_node *fpga_node = NULL;
+ struct i2c_client *fpga_i2c = NULL;
+ struct device_node *gmsl;
+ int value = 0xFFFF;
+ const char *str_value;
+ const char *str_value1[2];
+ int i;
+ int err;
+ const char *str_model;
+ char upper_str_model[64];
+ char *str_err;
+ //char *sub_str_err;
+
+ root_node = of_find_node_opts_by_path("/", &of_stdout_options);
+ err = of_property_read_string(root_node, "model", &str_model);
+ if (err < 0) {
+ dev_err(dev, "[%s] : model not found\n", __func__);
+ goto error;
+ }
+
+ memset(upper_str_model, 0, 64);
+ to_upper_string(upper_str_model, str_model);
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ORIN);
+ priv->g_ctx.hardware_model = HW_MODEL_UNKNOWN;
+
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_ORIN_DEVKIT;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_NVIDIA_XAVIER_DEVKIT;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_XAVIER);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_XAVIER;
+ }
+
+ str_err = strstr(upper_str_model, STR_DTB_MODEL_NAME_ROSCUBE_ORIN);
+ if (str_err) {
+ priv->g_ctx.hardware_model = HW_MODEL_ADLINK_ROSCUBE_ORIN;
+ }
+
+ dev_info(dev, "[%s] : hardware_model=%d\n", __func__,
+ priv->g_ctx.hardware_model);
+ dev_info(dev, "[%s] : model string=%s\n", __func__, str_model);
+
+ // priv->g_ctx.debug_i2c_write = debug_i2c_write;
+
+ if (priv->g_ctx.hardware_model == HW_MODEL_UNKNOWN) {
+ dev_err(dev, "[%s] : Unknown Hardware Sysytem !\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg", &priv->g_ctx.sdev_reg);
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "def-addr", &priv->g_ctx.sdev_def);
+ if (err < 0) {
+ dev_err(dev, "[%s] : def-addr not found\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_u32(node, "reg_mux", &priv->g_ctx.reg_mux);
+ if (err < 0) {
+ dev_err(dev, "[%s] : reg_mux not found\n", __func__);
+ goto error;
+ }
+
+#if 0
+ err = of_property_read_string(node, "fsync-mode", &str_value);
+ if (err < 0)
+ {
+ dev_err(dev, "[%s] : No fsync-mode found\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "true"))
+ {
+ priv->fsync_mode = true;
+ }
+ else
+ {
+ priv->fsync_mode = false;
+ }
+#endif
+
+ if (enable_distortion_correction == 0xCAFE) {
+ // if not set kernel param, read device tree param
+ err = of_property_read_string(node, "distortion-correction",
+ &str_value);
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : No distortion-correction found. set enable_distortion-correction = true\n",
+ __func__);
+ } else {
+ if (!strcmp(str_value, "true")) {
+ enable_distortion_correction = 1;
+ } else {
+ enable_distortion_correction = 0;
+ }
+ }
+ }
+
+ priv->distortion_correction = enable_distortion_correction != 0 ? true :
+ false;
+
+ if (enable_auto_exposure == 0xCAFE) {
+ // if not set kernel param, read device tree param
+ err = of_property_read_string(node, "auto-exposure",
+ &str_value);
+ if (err < 0) {
+ dev_err(dev,
+ "[%s] : No auto-exposure mode found. set enable_auto_exposure = true\n",
+ __func__);
+ } else {
+ if (!strcmp(str_value, "true")) {
+ enable_auto_exposure = 1;
+ } else {
+ enable_auto_exposure = 0;
+ }
+ }
+ }
+
+ priv->auto_exposure = enable_auto_exposure != 0 ? true : false;
+
+ mode_node = of_get_child_by_name(node, "mode0");
+
+ dev_dbg(dev,
+ "[%s] : node->full_name = %s, mode_node->full_name = %s.\n",
+ __func__, node->full_name, mode_node->full_name);
+
+#ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
+ /* check embedded_metadata_height */
+
+ err = of_property_read_string(mode_node, "embedded_metadata_height",
+ &str_value);
+ dev_info(dev, "[%s] : err = %d, embedded_metadata_height = %s\n",
+ __func__, err, str_value);
+
+ err = kstrtoul(str_value, 10, &u_value);
+ embedded_metadata_height = u_value;
+ if (err) {
+ embedded_metadata_height = 0;
+ } else {
+ embedded_metadata_height = u_value;
+ }
+
+ switch (embedded_metadata_height) {
+ case 0:
+ priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
+ break;
+ case 1:
+ priv->enable_embedded_data = ENABLE_FRONT_EMBEDDED_DATA;
+ break;
+ case 14:
+ priv->enable_embedded_data = ENABLE_REAR_EMBEDDED_DATA;
+ break;
+ case 15:
+ priv->enable_embedded_data = ENABLE_BOTH_EMBEDDED_DATA;
+ break;
+ default:
+ priv->enable_embedded_data = DISABLE_BOTH_EMBEDDED_DATA;
+ }
+#else // ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
+
+ priv->enable_embedded_data =
+ DISABLE_BOTH_EMBEDDED_DATA; // priv->enable_embedded_data is defined by camera sensor image mode
+
+#endif // ifdef USE_EMBEDDED_METADAT_HEIGHT_IN_DTB
+
+ // for Ser node
+
+ ser_node = of_parse_phandle(node, "nvidia,gmsl-ser-device", 0);
+
+ if (ser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-ser-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(ser_node, "reg", &priv->g_ctx.ser_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : Serializer reg not found\n", __func__);
+ goto error;
+ }
+
+ ser_i2c = of_find_i2c_device_by_node(ser_node);
+
+ of_node_put(ser_node);
+
+ if (ser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing Serializer Dev Handle\n",
+ __func__);
+ goto error;
+ }
+
+ if (ser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing serializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->ser_dev = &ser_i2c->dev;
+
+ // for Dser node
+
+ dser_node = of_parse_phandle(node, "nvidia,gmsl-dser-device", 0);
+ if (dser_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,gmsl-dser-device");
+ goto error;
+ }
+
+ dser_i2c = of_find_i2c_device_by_node(dser_node);
+ of_node_put(dser_node);
+ if (dser_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer dev handle\n",
+ __func__);
+ goto error;
+ }
+
+ if (dser_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing deserializer driver\n", __func__);
+ goto error;
+ }
+
+ priv->dser_dev = &dser_i2c->dev;
+
+ if ((priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_XAVIER) ||
+ (priv->g_ctx.hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ // for FPGA node
+
+ fpga_node = of_parse_phandle(node, "nvidia,fpga-device", 0);
+
+ if (fpga_node == NULL) {
+ dev_err(dev, "[%s] : Missing %s handle\n", __func__,
+ "nvidia,fpga-device");
+ goto error;
+ }
+
+ err = of_property_read_u32(fpga_node, "reg",
+ &priv->g_ctx.sdev_fpga_reg);
+
+ if (err < 0) {
+ dev_err(dev, "[%s] : FPGA reg not found\n", __func__);
+ goto error;
+ }
+
+ fpga_i2c = of_find_i2c_device_by_node(fpga_node);
+
+ of_node_put(fpga_node);
+
+ if (fpga_i2c == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA Dev Handle\n",
+ __func__);
+ goto error;
+ }
+
+ if (fpga_i2c->dev.driver == NULL) {
+ dev_err(dev, "[%s] : Missing FPGA driver\n", __func__);
+ goto error;
+ }
+
+ priv->fpga_dev = &fpga_i2c->dev;
+ }
+
+ /* populate g_ctx from DT */
+
+ gmsl = of_get_child_by_name(node, "gmsl-link");
+
+ if (gmsl == NULL) {
+ dev_err(dev, "[%s] : Missing GMSL-Link device node\n",
+ __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "dst-csi-port", &str_value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No dst-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "src-csi-port", &str_value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No src-csi-port found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.src_csi_port = (!strcmp(str_value, "a")) ? GMSL_CSI_PORT_A :
+ GMSL_CSI_PORT_B;
+
+ err = of_property_read_string(gmsl, "csi-mode", &str_value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No csi-mode found\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value, "1x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_1X4_MODE;
+ } else if (!strcmp(str_value, "2x4")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X4_MODE;
+ } else if (!strcmp(str_value, "4x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_4X2_MODE;
+ } else if (!strcmp(str_value, "2x2")) {
+ priv->g_ctx.csi_mode = GMSL_CSI_2X2_MODE;
+ } else {
+ dev_err(dev, "[%s] :Invalid csi-mode\n", __func__);
+ goto error;
+ }
+
+ err = of_property_read_string(gmsl, "serdes-csi-link", &str_value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No serdes-csi-link found\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.serdes_csi_link = (!strcmp(str_value, "a")) ?
+ GMSL_SERDES_CSI_LINK_A :
+ GMSL_SERDES_CSI_LINK_B;
+
+ err = of_property_read_u32(gmsl, "st-vc", &value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No st-vc info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.st_vc = value;
+
+ err = of_property_read_u32(gmsl, "vc-id", &value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No vc-id info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.dst_vc = value;
+
+ err = of_property_read_u32(gmsl, "num-lanes", &value);
+ if (err < 0) {
+ dev_err(dev, "[%s] : No num-lanes info\n", __func__);
+ goto error;
+ }
+
+ priv->g_ctx.num_csi_lanes = value;
+
+ priv->g_ctx.num_streams = of_property_count_strings(gmsl, "streams");
+ if (priv->g_ctx.num_streams <= 0) {
+ dev_err(dev, "[%s] : No streams found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < priv->g_ctx.num_streams; i++) {
+ of_property_read_string_index(gmsl, "streams", i,
+ &str_value1[i]);
+ if (!str_value1[i]) {
+ dev_err(dev, "[%s] : Invalid Stream Info\n", __func__);
+ goto error;
+ }
+
+ if (!strcmp(str_value1[i], "raw12")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_RAW_12;
+ } else if (!strcmp(str_value1[i], "yuv8")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_YUV_8;
+ } else if (!strcmp(str_value1[i], "embed")) {
+ priv->g_ctx.streams[i].st_data_type = GMSL_CSI_DT_EMBED;
+ } else if (!strcmp(str_value1[i], "ued-u1")) {
+ priv->g_ctx.streams[i].st_data_type =
+ GMSL_CSI_DT_UED_U1;
+ } else {
+ dev_err(dev, "[%s] : Invalid stream data type.\n",
+ __func__);
+ goto error;
+ }
+ }
+
+ priv->g_ctx.s_dev = dev;
+
+ return NO_ERROR;
+
+error:
+ dev_err(dev, "[%s] : Board Setup failed.\n", __func__);
+ return err;
+}
+
+static int tier4_isx021_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ char *path = FIRMWARE_BIN_FILE;
+ void *firmware_buffer;
+
+ struct device *dev = &client->dev;
+ struct device_node *node = dev->of_node;
+ struct tegracam_device *tc_dev;
+ struct tier4_isx021 *priv;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 65)
+ loff_t size;
+#endif
+
+ tier4_isx021_sensor_mutex_lock();
+
+ // dev_info(dev, "[%s] : Probing V4L2 Sensor.\n", __func__);
+
+ if (!IS_ENABLED(CONFIG_OF) || !node) {
+ err = -EINVAL;
+ goto errret;
+ }
+
+ wst_priv[camera_channel_count].p_client = NULL;
+ wst_priv[camera_channel_count].p_priv = NULL;
+ wst_priv[camera_channel_count].p_tc_dev = NULL;
+ wst_priv[camera_channel_count].sensor_ser_shutdown = false;
+ wst_priv[camera_channel_count].des_shutdown = false;
+ wst_priv[camera_channel_count].running = false;
+
+ priv = devm_kzalloc(dev, sizeof(struct tier4_isx021), GFP_KERNEL);
+
+ if (!priv) {
+ dev_err(dev, "[%s] : Unable to allocate Memory!\n", __func__);
+ err = -ENOMEM;
+ goto errret;
+ }
+
+ tc_dev = devm_kzalloc(dev, sizeof(struct tegracam_device), GFP_KERNEL);
+
+ if (!tc_dev) {
+ err = -ENOMEM;
+ goto errret;
+ }
+
+ priv->i2c_client = tc_dev->client = client;
+
+ tc_dev->dev = dev;
+
+ strncpy(tc_dev->name, "isx021", sizeof(tc_dev->name));
+
+ tc_dev->dev_regmap_config = &tier4_sensor_regmap_config;
+ tc_dev->sensor_ops = &tier4_isx021_common_ops;
+ tc_dev->v4l2sd_internal_ops = &tier4_isx021_subdev_internal_ops;
+ tc_dev->tcctrl_ops = &tier4_isx021_ctrl_ops;
+
+ firmware_buffer =
+ devm_kzalloc(dev, sizeof(u16) * MAX_NUM_OF_REG, GFP_KERNEL);
+
+ if (!firmware_buffer) {
+ dev_err(dev, "[%s] : Allocating firmware buffer failed.\n",
+ __func__);
+ err = -ENOMEM;
+ goto errret;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
+ err = kernel_read_file_from_path(
+ path, 0, &firmware_buffer, INT_MAX, NULL,
+ READING_POLICY); // err is errono and number of bytes actually read
+ if (!err) {
+ dev_err(dev, "Loading %s failed with error %d\n", path, err);
+#ifdef USE_FIRMWARE
+ goto errret;
+#endif
+ }
+#else
+ err = kernel_read_file_from_path(
+ path, &firmware_buffer, &size, INT_MAX,
+ READING_FIRMWARE); // size : number of bytes actually read
+ if (err) {
+ dev_err(dev, "Loading %s failed with error %d\n", path, err);
+#ifdef USE_FIRMWARE
+ goto errret;
+#endif
+ }
+#endif
+
+ priv->firmware_buffer = (u16 *)firmware_buffer;
+
+ err = tegracam_device_register(tc_dev);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Tegra Camera Driver Registration failed.\n",
+ __func__);
+ goto errret;
+ }
+
+ priv->tc_dev = tc_dev;
+ priv->s_data = tc_dev->s_data;
+ priv->subdev = &tc_dev->s_data->subdev;
+
+ tegracam_set_privdata(tc_dev, (void *)priv);
+
+ err = tier4_isx021_board_setup(priv);
+
+ if (err) {
+ dev_err(dev, "[%s] : Board Setup failed.\n", __func__);
+ goto err_tegracam_unreg;
+ }
+
+ priv->trigger_mode = trigger_mode; // trigger_mode per camaera
+
+ /* Pair sensor to serializer dev */
+ err = tier4_max9295_sdev_pair(priv->ser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev, "[%s] : GMSL Ser Pairing failed.\n",
+ __func__);
+ goto err_tegracam_unreg;
+ }
+
+ /* Register sensor to deserializer dev */
+
+ //dev_info(dev, "[%s]: Before tier4_max9296_sdev_register() : priv->g_ctx.serdes_csi_link = %u\n" , __func__, priv->g_ctx.serdes_csi_link );
+
+ //asm("dmb sy");
+
+ err = tier4_max9296_sdev_register(priv->dser_dev, &priv->g_ctx);
+
+ if (err) {
+ dev_err(&client->dev,
+ "[%s] : Failed to register GMSL Deserializer.\n",
+ __func__);
+ goto err_max9295_unpair;
+ }
+
+ /*
+ * gmsl serdes setup
+ *
+ * Sensor power on/off should be the right place for serdes
+ * setup/reset. But the problem is, the total required delay
+ * in serdes setup/reset exceeds the frame wait timeout, looks to
+ * be related to multiple channel open and close sequence
+ * issue (#BUG 200477330).
+ * Once this bug is fixed, these may be moved to power on/off.
+ * The delays in serdes is as per guidelines and can't be reduced,
+ * so it is placed in probe/remove, though for that, deserializer
+ * would be powered on always post boot, until 1.2v is supplied
+ * to deserializer from CVB.
+ */
+
+ err = tier4_isx021_gmsl_serdes_setup(priv);
+ if (err) {
+ dev_err(&client->dev, "[%s] : Setup for GMSL Serdes failed.\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ err = tegracam_v4l2subdev_register(tc_dev, true);
+ if (err) {
+ dev_err(dev,
+ "[%s] : Tegra Camera Subdev Registration failed.\n",
+ __func__);
+ goto err_max9296_unreg;
+ }
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ err = tier4_isx021_write_reg(tc_dev->s_data, TIER4_ISX021_REG_90_ADDR,
+ 0x06);
+
+ err = tier4_isx021_set_response_mode(priv);
+ if (err) {
+ dev_warn(dev, "[%s] : Transition to response mode failed.\n",
+ __func__);
+ goto err_tegracam_v4l2_unreg;
+ }
+
+ dev_info(&client->dev, "Detected ISX021 sensor.\n");
+
+ wst_priv[camera_channel_count].p_client = client;
+ wst_priv[camera_channel_count].p_priv = priv;
+ wst_priv[camera_channel_count].p_tc_dev = tc_dev;
+
+ camera_channel_count++;
+
+ tier4_isx021_sensor_mutex_unlock();
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)) & 0
+
+ dev_info(&client->dev, "Detected ISX021 sensor\n");
+ return NO_ERROR;
+#else
+ return err;
+#endif
+
+err_tegracam_v4l2_unreg:
+ tegracam_v4l2subdev_unregister(priv->tc_dev);
+err_max9296_unreg:
+ tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
+err_max9295_unpair:
+ tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
+err_tegracam_unreg:
+ tegracam_device_unregister(priv->tc_dev);
+errret:
+ tier4_isx021_sensor_mutex_unlock();
+
+ dev_err(&client->dev, "Detection for ISX021 sensor failed.\n");
+
+ return err;
+}
+
+static void tier4_isx021_shutdown(struct i2c_client *client);
+
+static int tier4_isx021_remove(struct i2c_client *client)
+{
+ struct camera_common_data *s_data = to_camera_common_data(&client->dev);
+ struct tier4_isx021 *priv = (struct tier4_isx021 *)s_data->priv;
+
+ tier4_isx021_shutdown(client);
+
+ tier4_isx021_gmsl_serdes_reset(priv);
+
+ tier4_max9296_sdev_unregister(priv->dser_dev, &client->dev);
+ tier4_max9295_sdev_unpair(priv->ser_dev, &client->dev);
+
+ tegracam_v4l2subdev_unregister(priv->tc_dev);
+
+ tegracam_device_unregister(priv->tc_dev);
+
+ return NO_ERROR;
+}
+
+static bool tier4_isx021_is_sensor_ser_shutdown(int nport)
+{
+ if (wst_priv[nport].sensor_ser_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static bool tier4_isx021_is_des_shut_down(int nport)
+{
+ if (wst_priv[nport].des_shutdown) {
+ return true;
+ }
+ return false;
+}
+
+static void tier4_isx021_set_sensor_ser_shutdown(int nport, bool val)
+{
+ wst_priv[nport].sensor_ser_shutdown = val;
+}
+
+static void tier4_isx021_set_des_shutdown(int nport, bool val)
+{
+ wst_priv[nport].des_shutdown = val;
+}
+
+static bool tier4_isx021_is_current_i2c_client(struct i2c_client *client,
+ int nport)
+{
+ if (client == wst_priv[nport].p_client) {
+ return true;
+ }
+ return false;
+}
+
+/**
+* The shutdown routine is needed only when you use ROcube and you would like to reboot command on Linux *
+* if not so, you don't need shutdown function *
+*/
+
+static void tier4_isx021_shutdown(struct i2c_client *client)
+{
+ struct tier4_isx021 *priv = NULL;
+ int i;
+
+ tier4_isx021_sensor_mutex_unlock();
+
+ mutex_lock(&tier4_isx021_lock);
+
+ if (!client) {
+ goto error_exit;
+ }
+
+ for (i = 0; i < camera_channel_count; i++) {
+ if (tier4_isx021_is_current_i2c_client(client, i)) {
+ priv = wst_priv[i].p_priv;
+
+ if (i &
+ 0x1) { // Even port number( GMSL B port on a Des : i = port_number -1 )
+
+ if (tier4_isx021_is_camera_connected_to_port(
+ i -
+ 1)) { // if a camera connected to another(GMSL A)port on a Des.
+
+ if (tier4_isx021_is_sensor_ser_shutdown(
+ i -
+ 1)) { // ISP and Ser on another(GMSL A) port have been
+
+ if (tier4_isx021_is_des_shut_down(
+ i - 1) ==
+ false) { // if Des on another(GMSL A)port is not shutdown yet
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ true); // Des will be shut down
+ } else { // if Des on the another port is already shut down.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // Des will not be shutdown
+ }
+ } else { // The camera ISP and Ser on another(GMSL A) port
+ if (tier4_isx021_is_des_shut_down(
+ i - 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // The Des won't be shut down.
+ } else { // Only Des on another port is already shut down.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // Des will not be shut down.
+ }
+ }
+ } else { // a camera is connected to only (GMSL B) port on Des.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ true); // The Des won't be shut down.
+ }
+ } else { // if ( i & 0x1 ) == 0 : Camera is connected to Odd port number. ( GMSL A potr on a Des : i = port_number -1
+ // )
+
+ if (tier4_isx021_is_camera_connected_to_port(
+ i +
+ 1)) { // Another camera is connected to
+ // another(GMSL B) port on the Des
+ if (tier4_isx021_is_sensor_ser_shutdown(
+ i +
+ 1)) { // if the ISP and Ser on another port
+ // are already shut down
+ if (tier4_isx021_is_des_shut_down(
+ i + 1) ==
+ false) { // if Des is not shut down yet.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ } else { // Des is already shut down. This is Error case.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ } else { // The ISP and Ser on another(GMSL B) port
+ // are not shut down yet.
+ if (tier4_isx021_is_des_shut_down(
+ i + 1) ==
+ false) { // if Des on another(GMSL B) port is not shut down yet.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ } else { // Only Des on another(GMSL B) port is already shut down.
+ // This is Error case.
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ false); // ISP and Ser will not be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ false); // The Des will not be shut down.
+ }
+ }
+ } else {
+ tier4_isx021_set_sensor_ser_shutdown(
+ i,
+ true); // ISP and Ser will be shut down
+ tier4_isx021_set_des_shutdown(
+ i,
+ true); // The Des will be shut down.
+ }
+ } // if ( i & 0x1 )
+ // break;
+
+ if (tier4_isx021_is_sensor_ser_shutdown(i)) {
+ // Reset camera sensor
+ tier4_max9295_control_sensor_power_seq(
+ priv->ser_dev, SENSOR_ID_ISX021, false);
+ // S/W Reset max9295
+ tier4_max9295_reset_control(priv->ser_dev);
+ }
+
+ if (tier4_isx021_is_des_shut_down(i)) {
+ // S/W Reset max9296
+ tier4_max9296_reset_control(priv->dser_dev,
+ &client->dev, true);
+ }
+
+ if (priv == NULL || i >= camera_channel_count) {
+ mutex_unlock(&tier4_isx021_lock);
+ tier4_isx021_sensor_mutex_unlock();
+ return;
+ }
+ }
+ } // for loop
+
+error_exit:
+
+ mutex_unlock(&tier4_isx021_lock);
+
+ tier4_isx021_sensor_mutex_unlock();
+}
+
+static const struct i2c_device_id tier4_isx021_id[] = { { "tier4_isx021", 0 },
+ {} };
+
+MODULE_DEVICE_TABLE(i2c, tier4_isx021_id);
+
+static struct i2c_driver tier4_isx021_i2c_driver = {
+ .driver = {
+ .name = "tier4_isx021",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tier4_isx021_of_match),
+ },
+ .probe = tier4_isx021_probe,
+ .remove = tier4_isx021_remove,
+ .shutdown = tier4_isx021_shutdown,
+ .id_table = tier4_isx021_id,
+};
+
+static int __init tier4_isx021_init(void)
+{
+ mutex_init(&tier4_sensor_lock__);
+ mutex_init(&tier4_isx021_lock);
+
+ // printk(KERN_INFO "TIERIV Automotive HDR Camera driver : %s\n", BUILD_STAMP);
+
+ return i2c_add_driver(&tier4_isx021_i2c_driver);
+}
+
+static void __exit tier4_isx021_exit(void)
+{
+ mutex_destroy(&tier4_sensor_lock__);
+ mutex_destroy(&tier4_isx021_lock);
+
+ printk(KERN_INFO "[%s]: Exit TIERIV Automotive HDR Camera driver.\n",
+ __func__);
+
+ i2c_del_driver(&tier4_isx021_i2c_driver);
+}
+
+module_init(tier4_isx021_init);
+module_exit(tier4_isx021_exit);
+
+MODULE_DESCRIPTION("TIERIV Automotive HDR Camera driver");
+MODULE_AUTHOR("K.Iwasaki");
+MODULE_AUTHOR("Y.Fujii");
+MODULE_LICENSE("GPL v2");
diff --git a/src/tier4-camera-gmsl/tier4-max9295.c b/src/tier4-camera-gmsl/tier4-max9295.c
new file mode 100644
index 0000000..e5f9bfa
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-max9295.c
@@ -0,0 +1,780 @@
+/*
+ * tier4_max9295.c - tier4_max9295 GMSL Serializer driver
+ *
+ * Copyright (c) 2022-2023, TIERIV Inc. All rights reserved.
+ * Copyright (c) 2020, Leopard Imaging Inc. All rights reserved.
+ * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include "tier4-max9295.h"
+#include "tier4-gmsl-link.h"
+
+#define MAX9295_SHOW_I2C_WRITE_MSG 1
+
+/* register specifics */
+
+#define MAX9295_DEV_ADDR 0x0000
+#define MAX9295_PIPE_EN_ADDR 0x0002
+#define MAX9295_CLK_OUTPUT_ADDR 0x0003
+#define MAX9295_CTRL0_ADDR 0x0010
+
+#define MAX9295_I2C4_ADDR 0x0044
+#define MAX9295_I2C5_ADDR 0x0045
+
+#define MAX9295_CFGV_VIDEO_Y_ADDR 0x0057
+#define MAX9295_CFGV_VIDEO_Z_ADDR 0x005B
+
+#define MAX9295_VIDEO_TX0_ADDR 0x0110
+#define MAX9295_VIDEO_TX1_ADDR 0x0111
+#define MAX9295_VIDEO_TX2_ADDR 0x0112
+#define MAX9295_SRC_CTRL_ADDR 0x02BF
+#define MAX9295_SRC_PWDN_ADDR 0x02BE
+
+#define MAX9295_GPIO_3_CONFIG_MFP3_ADDR 0x02C7
+#define MAX9295_GPIO_3_GPIO_TX_ID_ADDR 0x02C8
+#define MAX9295_GPIO_3_GPIO_RX_ID_ADDR 0x02C9
+#define MAX9295_GPIO_4_ADDR 0x02CA
+#define MAX9295_GPIO_5_ADDR 0x02CD
+
+#define MAX9295_GPIO_8_ADDR 0x02D6
+
+#define MAX9295_CSI_PORT_SEL_ADDR 0x0308
+
+#define MAX9295_START_PIPE_ADDR 0x0311
+#define MAX9295_SEND_Z_PIPE_ADDR 0x0312
+#define MAX9295_PIPE_X_DT_ADDR 0x0314
+#define MAX9295_PIPE_Y_DT_ADDR 0x0316
+#define MAX9295_PIPE_Z_DT_ADDR 0x0318
+#define MAX9295_PIPE_U_DT_ADDR 0x031A
+#define MAX9295_OVERRIDE_Z_PIPE_ADDR 0x031E
+
+#define MAX9295_MIPI_RX0_ADDR 0x0330
+#define MAX9295_MIPI_RX1_ADDR 0x0331
+#define MAX9295_MIPI_RX2_ADDR 0x0332
+#define MAX9295_MIPI_RX3_ADDR 0x0333
+
+#define MAX9295_REF_VTG0_ADDR 0x03F0
+#define MAX9295_SRC_OUT_RCLK_ADDR 0x03F1
+
+#define MAX9295_REG570_ADDR 0x0570
+
+#define MAX9295_STREAM_PIPE_UNUSED 0x22
+#define MAX9295_CSI_MODE_1X4 0x00
+#define MAX9295_CSI_MODE_2X2 0x03
+#define MAX9295_CSI_MODE_2X4 0x06
+
+#define MAX9295_CSI_PORT_B(num_lanes) (((num_lanes) << 4) & 0xF0)
+#define MAX9295_CSI_PORT_A(num_lanes) ((num_lanes)&0x0F)
+
+#define MAX9295_CSI_1X4_MODE_LANE_MAP1 0xE0
+#define MAX9295_CSI_1X4_MODE_LANE_MAP2 0x04
+
+#define MAX9295_CSI_2X4_MODE_LANE_MAP1 0xEE
+#define MAX9295_CSI_2X4_MODE_LANE_MAP2 0xE4
+
+#define MAX9295_CSI_2X2_MODE_LANE_MAP1 MAX9295_CSI_2X4_MODE_LANE_MAP1
+#define MAX9295_CSI_2X2_MODE_LANE_MAP2 MAX9295_CSI_2X4_MODE_LANE_MAP2
+
+#define MAX9295_ST_ID_0 0x0
+#define MAX9295_ST_ID_1 0x1
+#define MAX9295_ST_ID_2 0x2
+#define MAX9295_ST_ID_3 0x3
+
+#define MAX9295_PIPE_X_START_B 0x80
+#define MAX9295_PIPE_Y_START_B 0x40
+#define MAX9295_PIPE_Z_START_B 0x20
+#define MAX9295_PIPE_U_START_B 0x10
+
+#define MAX9295_PIPE_X_START_A 0x1
+#define MAX9295_PIPE_Y_START_A 0x2
+#define MAX9295_PIPE_Z_START_A 0x4
+#define MAX9295_PIPE_U_START_A 0x8
+
+#define MAX9295_START_PORT_A 0x10
+#define MAX9295_START_PORT_B 0x20
+
+#define MAX9295_CSI_LN2 0x1
+#define MAX9295_CSI_LN4 0x3
+
+#define MAX9295_EN_LINE_INFO 0x40
+
+#define MAX9295_VID_TX_EN_X 0x10
+#define MAX9295_VID_TX_EN_Y 0x20
+#define MAX9295_VID_TX_EN_Z 0x40
+#define MAX9295_VID_TX_EN_U 0x80
+
+#define MAX9295_VID_INIT 0x3
+#define MAX9295_SRC_RCLK 0x89
+
+#define MAX9295_RESET_ALL 0x80
+#define MAX9295_RESET_SRC 0x60
+#define MAX9295_PWDN_GPIO 0x90
+
+#define MAX9295_MAX_PIPES 0x4
+
+struct tier4_max9295_client_ctx {
+ struct tier4_gmsl_link_ctx *g_ctx;
+ bool st_done;
+};
+
+struct tier4_max9295 {
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ struct tier4_max9295_client_ctx g_client;
+ struct mutex lock;
+ /* primary serializer properties */
+ __u32 def_addr;
+ __u32 pst2_ref;
+};
+
+#define MAX_CHANNEL_NUM 8
+
+/* count channel,the max MAX_CHANNEL_NUM*/
+static __u32 channel_count_isx021;
+
+static struct tier4_max9295 *prim_priv__[MAX_CHANNEL_NUM];
+
+struct map_ctx {
+ u8 dt;
+ u16 addr;
+ u8 val;
+ u8 st_id;
+};
+
+#if 0
+
+static int tier4_max9295_read_reg(struct device *dev, u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ char str_bus_num[4], str_sl_addr[4];
+ int len = 0;
+
+ memset(str_bus_num,0,4);
+ memset(str_sl_addr,0,4);
+
+ err = regmap_read(priv->regmap, addr, ®_val);
+
+ *val = reg_val & 0xFF;
+
+ dev_info(dev, "[%s ] : Max9295 I2C Read at 0x%04X=[0x%02X].\n", __func__, addr, *val );
+
+ if (( err == 0 ) && ( dev != NULL ) ) {
+ len = strlen(dev->kobj.name);
+ if (dev) {
+ strncpy(str_bus_num, &dev->kobj.name[0], 2);
+ strncpy(str_sl_addr, &dev->kobj.name[len-2], 2);
+ }
+ }
+ return err;
+}
+#endif
+
+static int tier4_max9295_write_reg(struct device *dev, u16 addr, u8 val)
+{
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ int err = 0;
+ // u8 e;
+ char str_bus_num[4], str_sl_addr[4];
+ int len;
+
+ memset(str_bus_num, 0, 4);
+ memset(str_sl_addr, 0, 4);
+
+ len = strlen(dev->kobj.name);
+
+ if ((err == 0) && (dev != NULL)) {
+ strncpy(str_bus_num, &dev->kobj.name[0], 2);
+ strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
+ }
+
+ err = regmap_write(priv->regmap, addr, val);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Max9295 I2C write failed Reg at 0x%04X:[0x%02X].\n",
+ __func__, addr, val);
+ }
+#if MAX9295_SHOW_I2C_WRITE_MSG
+ else {
+ dev_info(
+ dev,
+ "[%s] : Max9295 I2C write register at 0x%04X:[0x%02X]\n",
+ __func__, addr, val);
+ }
+#endif
+
+ /* delay before next i2c command as required for SERDES link */
+
+ usleep_range(100, 110);
+ //msleep(100);
+ // tier4_max9295_read_reg(dev, addr, &e);
+ usleep_range(100, 110);
+ //msleep(100);
+
+ return err;
+}
+
+int tier4_max9295_setup_streaming(struct device *dev)
+{
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ int err = 0;
+ u32 csi_mode;
+ u32 lane_map1;
+ u32 lane_map2;
+ u32 port;
+ u32 rx1_lanes;
+ u32 st_pipe;
+ u32 pipe_en;
+ u32 port_sel = 0;
+ struct tier4_gmsl_link_ctx *g_ctx;
+ u32 i;
+ u32 j;
+ u32 st_en;
+
+ struct map_ctx map_pipe_dtype[] = {
+ { GMSL_CSI_DT_YUV_8, MAX9295_PIPE_Z_DT_ADDR, 0x1E, // For YUV8
+ MAX9295_ST_ID_2 },
+ { GMSL_CSI_DT_UED_U1, MAX9295_PIPE_X_DT_ADDR,
+ 0x30, // User defined embedded data type
+ MAX9295_ST_ID_0 },
+ { GMSL_CSI_DT_EMBED, MAX9295_PIPE_Y_DT_ADDR, 0x12,
+ MAX9295_ST_ID_1 },
+ };
+
+ mutex_lock(&priv->lock);
+
+ if (!priv->g_client.g_ctx) {
+ dev_err(dev, "[%s] : No sdev client found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ if (priv->g_client.st_done) {
+ dev_dbg(dev, "[%s] : Stream setup is already done\n", __func__);
+ goto error;
+ }
+
+ g_ctx = priv->g_client.g_ctx;
+
+ switch (g_ctx->csi_mode) {
+ case GMSL_CSI_1X4_MODE:
+ csi_mode = MAX9295_CSI_MODE_1X4;
+ lane_map1 = MAX9295_CSI_1X4_MODE_LANE_MAP1;
+ lane_map2 = MAX9295_CSI_1X4_MODE_LANE_MAP2;
+ rx1_lanes = MAX9295_CSI_LN4;
+ break;
+ case GMSL_CSI_2X2_MODE:
+ csi_mode = MAX9295_CSI_MODE_2X2;
+ lane_map1 = MAX9295_CSI_2X2_MODE_LANE_MAP1;
+ lane_map2 = MAX9295_CSI_2X2_MODE_LANE_MAP2;
+ rx1_lanes = MAX9295_CSI_LN2;
+ break;
+ case GMSL_CSI_2X4_MODE:
+ csi_mode = MAX9295_CSI_MODE_2X4;
+ lane_map1 = MAX9295_CSI_2X4_MODE_LANE_MAP1;
+ lane_map2 = MAX9295_CSI_2X4_MODE_LANE_MAP2;
+ rx1_lanes = MAX9295_CSI_LN4;
+ break;
+ default:
+ dev_err(dev, "[%s] : Invalid csi mode\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ port = (g_ctx->src_csi_port == GMSL_CSI_PORT_B) ?
+ MAX9295_CSI_PORT_B(rx1_lanes) :
+ MAX9295_CSI_PORT_A(rx1_lanes);
+
+ tier4_max9295_write_reg(dev, MAX9295_MIPI_RX0_ADDR, csi_mode);
+ tier4_max9295_write_reg(dev, MAX9295_MIPI_RX1_ADDR, port);
+ tier4_max9295_write_reg(dev, MAX9295_MIPI_RX2_ADDR, lane_map1);
+ tier4_max9295_write_reg(dev, MAX9295_MIPI_RX3_ADDR, lane_map2);
+
+ for (i = 0; i < g_ctx->num_streams; i++) {
+ struct tier4_gmsl_stream *g_stream = &g_ctx->streams[i];
+
+ g_stream->st_id_sel = GMSL_ST_ID_UNUSED;
+
+ for (j = 0; j < ARRAY_SIZE(map_pipe_dtype); j++) {
+ if (map_pipe_dtype[j].dt == g_stream->st_data_type) {
+ /*
+ * TODO:
+ * 1) Remove link specific overrides, depends
+ * on #2.
+ * 2) Add support for vc id based stream sel
+ * overrides TX_SRC_SEL. would be useful in
+ * using same mappings in all ser devs.
+ */
+ if (g_ctx->serdes_csi_link ==
+ GMSL_SERDES_CSI_LINK_B) {
+ map_pipe_dtype[j].addr += 2;
+ map_pipe_dtype[j].st_id += 1;
+ }
+
+ g_stream->st_id_sel = map_pipe_dtype[j].st_id;
+
+ st_en = (map_pipe_dtype[j].addr ==
+ MAX9295_PIPE_X_DT_ADDR) ?
+ 0xC0 :
+ 0x40;
+
+ tier4_max9295_write_reg(
+ dev, map_pipe_dtype[j].addr,
+ (st_en | map_pipe_dtype[j].val));
+ }
+ }
+ }
+
+ for (i = 0; i < g_ctx->num_streams; i++)
+ if (g_ctx->streams[i].st_id_sel != GMSL_ST_ID_UNUSED)
+ port_sel |= (1 << g_ctx->streams[i].st_id_sel);
+
+ if (g_ctx->src_csi_port == GMSL_CSI_PORT_B) {
+ st_pipe = (MAX9295_PIPE_X_START_B | MAX9295_PIPE_Y_START_B |
+ MAX9295_PIPE_Z_START_B | MAX9295_PIPE_U_START_B);
+ port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_B);
+ } else {
+ st_pipe = MAX9295_PIPE_X_START_A | MAX9295_PIPE_Y_START_A |
+ MAX9295_PIPE_Z_START_A | MAX9295_PIPE_U_START_A;
+ port_sel |= (MAX9295_EN_LINE_INFO | MAX9295_START_PORT_A);
+ }
+
+ pipe_en =
+ (MAX9295_VID_TX_EN_X | MAX9295_VID_TX_EN_Y |
+ MAX9295_VID_TX_EN_Z | MAX9295_VID_TX_EN_U | MAX9295_VID_INIT);
+
+ tier4_max9295_write_reg(dev, MAX9295_START_PIPE_ADDR, st_pipe);
+ tier4_max9295_write_reg(dev, MAX9295_CSI_PORT_SEL_ADDR, port_sel);
+
+ tier4_max9295_write_reg(dev, MAX9295_PIPE_EN_ADDR, pipe_en);
+
+ priv->g_client.st_done = true;
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_setup_streaming);
+
+// ------------------------------------------------------------------
+
+int tier4_max9295_control_sensor_power_seq(struct device *dev, __u32 sensor_id,
+ bool power_on)
+{
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ struct tier4_gmsl_link_ctx *g_ctx;
+ int err = 0;
+
+ g_ctx = priv->g_client.g_ctx;
+
+#if 1
+
+ msleep(200);
+
+ if (power_on == true) { // power up camera sensor
+
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x00);
+
+ msleep(100);
+
+ if (sensor_id == SENSOR_ID_ISX021) {
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_5_ADDR,
+ 0x04);
+ msleep(100);
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR,
+ 0x10);
+ msleep(100);
+ } else if (sensor_id == SENSOR_ID_IMX728) {
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR,
+ 0x10);
+ msleep(100);
+ }
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x10);
+ } else { // power down caemra sensor
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_8_ADDR, 0x00);
+ msleep(100);
+ if (sensor_id == SENSOR_ID_ISX021) {
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_5_ADDR,
+ 0x04);
+ msleep(100);
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR,
+ 0x00);
+ msleep(100);
+ } else if (sensor_id == SENSOR_ID_IMX728) {
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_4_ADDR,
+ 0x00);
+ msleep(100);
+ }
+ }
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Ppower on/off Camera Sensor or ISP failed.\n",
+ __func__);
+ }
+
+ msleep(50);
+#endif
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_control_sensor_power_seq);
+
+int tier4_max9295_setup_gpo(struct device *dev)
+{
+ int err = 0;
+
+ dev_info(dev, "[%s] : Set up max9295 for fsync trigger mode \n",
+ __func__);
+
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_CONFIG_MFP3_ADDR,
+ 0x04);
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_GPIO_TX_ID_ADDR,
+ 0x00);
+ err += tier4_max9295_write_reg(dev, MAX9295_GPIO_3_GPIO_RX_ID_ADDR,
+ 0x06);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_setup_gpo);
+
+int tier4_max9295_setup_control(struct device *dev)
+{
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ int err = 0;
+ struct tier4_gmsl_link_ctx *g_ctx;
+ u32 offset1 = 0;
+ u32 offset2 = 0;
+ u32 i;
+
+ u8 i2c_ovrd[] = {
+ 0x6B, 0x10, 0x73, 0x11, 0x7B, 0x30, 0x83, 0x30, 0x93,
+ 0x30, 0x9B, 0x30, 0xA3, 0x30, 0xAB, 0x30, 0x8B, 0x30,
+ };
+
+ u8 addr_offset[] = {
+ 0x80, 0x00, 0x00, 0x84, 0x00, 0x01,
+ 0xC0, 0x02, 0x02, 0xC4, 0x02, 0x03,
+ };
+
+ mutex_lock(&priv->lock);
+
+ g_ctx = priv->g_client.g_ctx;
+
+ if (prim_priv__[g_ctx->reg_mux] == NULL) {
+ err = -EINVAL;
+ goto error;
+ }
+ /* update address reassingment */
+ tier4_max9295_write_reg(&prim_priv__[g_ctx->reg_mux]->i2c_client->dev,
+ MAX9295_DEV_ADDR, (g_ctx->ser_reg << 1));
+
+ msleep(100);
+
+ if (g_ctx->serdes_csi_link == GMSL_SERDES_CSI_LINK_A) {
+ err = tier4_max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x21);
+ } else {
+ err = tier4_max9295_write_reg(dev, MAX9295_CTRL0_ADDR, 0x22);
+ }
+
+ /* check if serializer device exists */
+ if (err) {
+ dev_err(dev, "[%s]: Ser device not found\n", __func__);
+ goto error;
+ }
+ /* delay to settle link */
+ msleep(100);
+
+ /* Set RCLKOUT soruce to the reference PLL clock*/
+ err = tier4_max9295_write_reg(dev, MAX9295_CLK_OUTPUT_ADDR, 0x03);
+
+ /* No need?*/
+ usleep_range(10000, 11000);
+
+ /* PLL setting & Reset PLL */
+ err = tier4_max9295_write_reg(dev, MAX9295_REF_VTG0_ADDR, 0x5A);
+ usleep_range(10000, 11000);
+ // err = tier4_max9295_write_reg(dev, MAX9295_REG570_ADDR, 0x0C);
+
+ for (i = 0; i < ARRAY_SIZE(addr_offset); i += 3) {
+ if ((g_ctx->ser_reg << 1) == addr_offset[i]) {
+ offset1 = addr_offset[i + 1];
+ offset2 = addr_offset[i + 2];
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(addr_offset)) {
+ dev_err(dev, "[%s] : Invalid ser slave address\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(i2c_ovrd); i += 2) {
+ /* update address overrides */
+ i2c_ovrd[i + 1] += (i < 4) ? offset1 : offset2;
+
+ /* i2c passthrough2 must be configured once for all devices */
+ if ((i2c_ovrd[i] == 0x8B) &&
+ prim_priv__[g_ctx->reg_mux]->pst2_ref)
+ continue;
+
+ tier4_max9295_write_reg(dev, i2c_ovrd[i], i2c_ovrd[i + 1]);
+ }
+
+ /* dev addr pass-through2 ref */
+
+ prim_priv__[g_ctx->reg_mux]->pst2_ref++;
+
+ tier4_max9295_write_reg(dev, MAX9295_I2C4_ADDR, (g_ctx->sdev_reg << 1));
+ tier4_max9295_write_reg(dev, MAX9295_I2C5_ADDR, (g_ctx->sdev_def << 1));
+
+ tier4_max9295_write_reg(dev, MAX9295_SRC_PWDN_ADDR, MAX9295_PWDN_GPIO);
+ tier4_max9295_write_reg(dev, MAX9295_SRC_CTRL_ADDR, MAX9295_RESET_SRC);
+ tier4_max9295_write_reg(dev, MAX9295_SRC_OUT_RCLK_ADDR,
+ MAX9295_SRC_RCLK);
+
+ /* PLL setting & Enable PLL */
+ tier4_max9295_write_reg(dev, MAX9295_REF_VTG0_ADDR, 0x59);
+
+ g_ctx->serdev_found = true;
+
+error:
+
+ mutex_unlock(&priv->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_setup_control);
+
+int tier4_max9295_reset_control(struct device *dev)
+{
+ struct tier4_max9295 *priv = dev_get_drvdata(dev);
+ int err = 0;
+
+ mutex_lock(&priv->lock);
+ if (!priv->g_client.g_ctx) {
+ dev_err(dev, "[%s] : No sdev client found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ prim_priv__[priv->g_client.g_ctx->reg_mux]->pst2_ref--;
+
+ priv->g_client.st_done = false;
+
+ tier4_max9295_write_reg(
+ dev, MAX9295_DEV_ADDR,
+ (prim_priv__[priv->g_client.g_ctx->reg_mux]->def_addr << 1));
+
+ tier4_max9295_write_reg(
+ &prim_priv__[priv->g_client.g_ctx->reg_mux]->i2c_client->dev,
+ MAX9295_CTRL0_ADDR, MAX9295_RESET_ALL);
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_reset_control);
+
+int tier4_max9295_sdev_pair(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx)
+{
+ struct tier4_max9295 *priv;
+ int err = 0;
+
+ if (!dev || !g_ctx || !g_ctx->s_dev) {
+ dev_err(dev, "[%s]: Invalid input params\n", __func__);
+ return -EINVAL;
+ }
+
+ priv = dev_get_drvdata(dev);
+ mutex_lock(&priv->lock);
+ if (priv->g_client.g_ctx) {
+ dev_err(dev, "[%s] : Device already paired\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+ priv->g_client.st_done = false;
+
+ priv->g_client.g_ctx = g_ctx;
+
+error:
+ mutex_unlock(&priv->lock);
+ return 0;
+}
+EXPORT_SYMBOL(tier4_max9295_sdev_pair);
+
+int tier4_max9295_sdev_unpair(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9295 *priv = NULL;
+ int err = 0;
+
+ if (!dev || !s_dev) {
+ dev_err(dev, "[%s] : Invalid input params\n", __func__);
+ return -EINVAL;
+ }
+
+ priv = dev_get_drvdata(dev);
+
+ mutex_lock(&priv->lock);
+
+ if (!priv->g_client.g_ctx) {
+ dev_err(dev, "[%s] : Device is not paired\n", __func__);
+ err = -ENOMEM;
+ goto error;
+ }
+
+ if (priv->g_client.g_ctx->s_dev != s_dev) {
+ dev_err(dev, "[%s] : Invalid device\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ priv->g_client.g_ctx = NULL;
+ priv->g_client.st_done = false;
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9295_sdev_unpair);
+
+static struct regmap_config tier4_max9295_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int tier4_max9295_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tier4_max9295 *priv;
+ int err = 0;
+ struct device_node *node = client->dev.of_node;
+
+ dev_info(&client->dev, "[%s] : probing GMSL Serializer\n", __func__);
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ priv->i2c_client = client;
+ priv->regmap = devm_regmap_init_i2c(priv->i2c_client,
+ &tier4_max9295_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&client->dev, "[%s] : devm_regmap_init() failed: %ld\n",
+ __func__, PTR_ERR(priv->regmap));
+ return -ENODEV;
+ }
+
+ mutex_init(&priv->lock);
+
+ if (of_get_property(node, "is-prim-ser", NULL)) {
+ if (prim_priv__[channel_count_isx021] &&
+ channel_count_isx021 >= MAX_CHANNEL_NUM) {
+ dev_err(&client->dev,
+ "[%s] : prim-ser already exists\n", __func__);
+ return -EEXIST;
+ }
+
+ err = of_property_read_u32(node, "reg", &priv->def_addr);
+ if (err < 0) {
+ dev_err(&client->dev, "[%s] : reg not found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (priv == NULL) {
+ dev_err(&client->dev, "[%s] : priv is NULL\n",
+ __func__);
+ return err;
+ }
+
+ prim_priv__[channel_count_isx021] = priv;
+
+ channel_count_isx021++;
+ }
+
+ dev_set_drvdata(&client->dev, priv);
+
+ /* dev communication gets validated when GMSL link setup is done */
+ dev_info(&client->dev, "[%s] : Probing succeeded\n", __func__);
+
+ return err;
+}
+
+static int tier4_max9295_remove(struct i2c_client *client)
+{
+ struct tier4_max9295 *priv;
+
+ if (channel_count_isx021 > 0)
+ channel_count_isx021--;
+
+ if (client != NULL) {
+ priv = dev_get_drvdata(&client->dev);
+ mutex_destroy(&priv->lock);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id tier4_max9295_id[] = {
+ { "tier4_max9295", 0 },
+ {},
+};
+
+const struct of_device_id tier4_max9295_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_max9295",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tier4_max9295_of_match);
+MODULE_DEVICE_TABLE(i2c, tier4_max9295_id);
+
+static struct i2c_driver tier4_max9295_i2c_driver = {
+ .driver = {
+ .name = "tier4_max9295",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tier4_max9295_of_match),
+ },
+ .probe = tier4_max9295_probe,
+ .remove = tier4_max9295_remove,
+ .id_table = tier4_max9295_id,
+};
+
+static int __init tier4_max9295_init(void)
+{
+ printk(KERN_INFO "MAX9295 Driver for TIER4 C1 camera : %s\n",
+ BUILD_STAMP);
+
+ return i2c_add_driver(&tier4_max9295_i2c_driver);
+}
+
+static void __exit tier4_max9295_exit(void)
+{
+ i2c_del_driver(&tier4_max9295_i2c_driver);
+}
+
+module_init(tier4_max9295_init);
+module_exit(tier4_max9295_exit);
+
+MODULE_DESCRIPTION("GMSL Serializer driver tier4_max9295");
+MODULE_AUTHOR("Originaly NVIDIA Corporation");
+MODULE_AUTHOR("K.Iwasaki");
+MODULE_AUTHOR("Y.Fujii");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-max9295.h b/src/tier4-camera-gmsl/tier4-max9295.h
similarity index 95%
rename from drivers/src/tier4-max9295.h
rename to src/tier4-camera-gmsl/tier4-max9295.h
index 0d3a764..7fd7ca0 100644
--- a/drivers/src/tier4-max9295.h
+++ b/src/tier4-camera-gmsl/tier4-max9295.h
@@ -73,7 +73,8 @@ int tier4_max9295_reset_control(struct device *dev);
*
* @return 0 for success, or -1 otherwise.
*/
-int tier4_max9295_sdev_pair(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx);
+int tier4_max9295_sdev_pair(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx);
/**
* @brief Unpairs a sensor device from a serializer device.
@@ -99,7 +100,8 @@ int tier4_max9295_sdev_unpair(struct device *dev, struct device *s_dev);
#if 0
int tier4_max9295_power_up_camera_sensor(struct device *dev);
#else
-int tier4_max9295_control_sensor_power_seq(struct device *dev, __u32 sensor_id, bool power_on);
+int tier4_max9295_control_sensor_power_seq(struct device *dev, __u32 sensor_id,
+ bool power_on);
#endif
/**
* Pre-sets up the serializer device's internal pipeline for a specified
@@ -121,4 +123,4 @@ int tier4_max9295_pre_setup_streaming(struct device *dev);
*/
int tier4_max9295_setup_streaming(struct device *dev);
-#endif // __TIER4_MAX9295_H__
+#endif // __TIER4_MAX9295_H__
diff --git a/src/tier4-camera-gmsl/tier4-max9296.c b/src/tier4-camera-gmsl/tier4-max9296.c
new file mode 100644
index 0000000..4b83256
--- /dev/null
+++ b/src/tier4-camera-gmsl/tier4-max9296.c
@@ -0,0 +1,1207 @@
+/*
+ * tier4_max9296.c - tier4_max9296 GMSL Deserializer driver
+ *
+ * Copyright (c) 2022, TIER IV Inc. All rights reserved.
+ * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tier4-max9296.h"
+#include "tier4-gmsl-link.h"
+#include "tier4-hw-model.h"
+
+struct tier4_max9296_source_ctx {
+ struct tier4_gmsl_link_ctx *g_ctx;
+ bool st_enabled;
+};
+
+#define _USE_CHECK_LINK_LOCKED_ 1
+
+#define MAX9296_SHOW_I2C_WRITE_MSG 1
+
+/* register specifics */
+
+#define MAX9296_LINK_ADDR 0x0013
+
+#define MAX9296_REG5_ADDR 0x0005
+#define MAX9296_CTRL0_ADDR 0x0010
+
+#define MAX9296_PIPE_X_ST_SEL_ADDR 0x0050
+
+#define MAX9296_GPIO0_CONFIG_MFP0_ADDR 0x02B0
+#define MAX9296_GPIO0_GPIO_TX_ID_ADDR 0x02B1
+#define MAX9296_GPIO0_GPIO_RX_ID_ADDR 0x02B2
+
+#define MAX9296_PHY1_CLK_ADDR 0x0320
+
+#define MAX9296_DST_CSI_MODE_ADDR 0x0330
+#define MAX9296_PWDN_PHYS_ADDR 0x0332
+#define MAX9296_LANE_MAP1_ADDR 0x0333
+#define MAX9296_LANE_MAP2_ADDR 0x0334
+
+#define MAX9296_LANE_CTRL0_ADDR 0x040A
+#define MAX9296_TX11_PIPE_X_EN_ADDR 0x040B
+#define MAX9296_PIPE_X_SRC_0_MAP_ADDR 0x040D
+#define MAX9296_PIPE_X_DST_0_MAP_ADDR 0x040E
+#define MAX9296_PIPE_X_SRC_1_MAP_ADDR 0x040F
+
+#define MAX9296_PIPE_X_DST_1_MAP_ADDR 0x0410
+#define MAX9296_PIPE_X_SRC_2_MAP_ADDR 0x0411
+#define MAX9296_PIPE_X_DST_2_MAP_ADDR 0x0412
+
+#define MAX9296_TX45_PIPE_X_DST_CTRL_ADDR 0x042D
+
+#define MAX9296_LANE_CTRL1_ADDR 0x044A
+#define MAX9296_LANE_CTRL2_ADDR 0x048A
+#define MAX9296_LANE_CTRL3_ADDR 0x04CA
+
+/* data defines */
+
+#define MAX9296_CSI_MODE_4X2 0x1
+#define MAX9296_CSI_MODE_2X4 0x4
+#define MAX9296_LANE_MAP1_4X2 0x44
+#define MAX9296_LANE_MAP2_4X2 0x44
+#define MAX9296_LANE_MAP1_2X4 0x4E
+#define MAX9296_LANE_MAP2_2X4 0xE4
+
+#define MAX9296_LANE_CTRL_MAP(num_lanes) (((num_lanes) << 6) & 0xF0)
+
+#define MAX9296_ALLPHYS_NOSTDBY 0xF0
+#define MAX9296_ST_ID_SEL_INVALID 0xF
+
+//#define MAX9296_PHY1_CLK 0x32
+#define MAX9296_PHY1_CLK_3100MHZ 0x3F
+#define MAX9296_PHY1_CLK_3000MHZ 0x3E
+#define MAX9296_PHY1_CLK_2900MHZ 0x3D
+#define MAX9296_PHY1_CLK_2800MHZ 0x3C
+#define MAX9296_PHY1_CLK_2700MHZ 0x3B
+#define MAX9296_PHY1_CLK_2600MHZ 0x3A
+#define MAX9296_PHY1_CLK_2500MHZ 0x39
+#define MAX9296_PHY1_CLK_2400MHZ 0x38
+#define MAX9296_PHY1_CLK_2300MHZ 0x37
+#define MAX9296_PHY1_CLK_2200MHZ 0x36
+#define MAX9296_PHY1_CLK_2100MHZ 0x35
+#define MAX9296_PHY1_CLK_2000MHZ 0x34
+#define MAX9296_PHY1_CLK_1900MHZ 0x33
+#define MAX9296_PHY1_CLK_1800MHZ 0x32
+#define MAX9296_PHY1_CLK_1700MHZ 0x31
+#define MAX9296_PHY1_CLK_1600MHZ 0x30
+#define MAX9296_PHY1_CLK_1500MHZ 0x2F
+#define MAX9296_PHY1_CLK_1400MHZ 0x2E
+#define MAX9296_PHY1_CLK_1300MHZ 0x2D
+#define MAX9296_PHY1_CLK_1200MHZ 0x2C
+#define MAX9296_PHY1_CLK_1100MHZ 0x2B
+#define MAX9296_PHY1_CLK_1000MHZ 0x2A
+#define MAX9296_PHY1_CLK_900MHZ 0x29
+#define MAX9296_PHY1_CLK_800MHZ 0x28
+#define MAX9296_PHY1_CLK_700MHZ 0x27
+
+#define MAX9296_PHY1_CLK MAX9296_PHY1_CLK_1500MHZ
+
+#define MAX9296_RESET_ALL 0x80
+
+/* Dual GMSL MAX9296A/B */
+
+#define MAX9296_MAX_SOURCES 2
+
+#define MAX9296_MAX_PIPES 4
+
+#define MAX9296_PIPE_X 0
+#define MAX9296_PIPE_Y 1
+#define MAX9296_PIPE_Z 2
+#define MAX9296_PIPE_U 3
+#define MAX9296_PIPE_INVALID 0xF
+
+#define MAX9296_CSI_CTRL_0 0
+#define MAX9296_CSI_CTRL_1 1
+#define MAX9296_CSI_CTRL_2 2
+#define MAX9296_CSI_CTRL_3 3
+
+#define MAX9296_INVAL_ST_ID 0xFF
+
+/* Use reset value as per spec, confirm with vendor */
+
+#define MAX9296_RESET_ST_ID 0x00
+
+struct pipe_ctx {
+ u32 id;
+ u32 dt_type;
+ u32 dst_csi_ctrl;
+ u32 st_count;
+ u32 st_id_sel;
+};
+
+struct tier4_max9296 {
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ u32 num_src;
+ u32 max_src;
+ u32 num_src_found;
+ u32 src_link;
+ bool splitter_enabled;
+
+ struct tier4_max9296_source_ctx sources[MAX9296_MAX_SOURCES];
+
+ struct mutex lock;
+ u32 sdev_ref;
+ bool lane_setup;
+ bool link_setup;
+ struct pipe_ctx pipe[MAX9296_MAX_PIPES];
+ u8 csi_mode;
+ u8 lane_mp1;
+ u8 lane_mp2;
+ int reset_gpio;
+ int pw_ref;
+ struct regulator *vdd_cam_1v2;
+};
+
+static int tier4_max9296_read_reg(struct device *dev, u16 addr, u8 *val)
+{
+ int err = 0;
+ u32 reg_val = 0;
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ char str_bus_num[4], str_sl_addr[4];
+ int len;
+
+ memset(str_bus_num, 0, 4);
+ memset(str_sl_addr, 0, 4);
+
+ err = regmap_read(priv->regmap, addr, ®_val);
+ *val = reg_val & 0xFF;
+
+ if ((err == 0) && (dev != NULL)) {
+ len = strlen(dev->kobj.name);
+
+ if (dev) {
+ strncpy(str_bus_num, &dev->kobj.name[0], 2);
+ strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
+ }
+ dev_info(dev, "tier4_max9296_read_reg %s 0x%s 0x%x\n",
+ str_bus_num, str_sl_addr, addr);
+ }
+
+ return err;
+}
+
+static int tier4_max9296_write_reg(struct device *dev, u16 addr, u8 val)
+{
+ struct tier4_max9296 *priv;
+ int err;
+ char str_bus_num[4], str_sl_addr[4];
+ int len;
+
+ priv = dev_get_drvdata(dev);
+
+ memset(str_bus_num, 0, 4);
+ memset(str_sl_addr, 0, 4);
+
+ len = strlen(dev->kobj.name);
+
+ if (dev) {
+ strncpy(str_bus_num, &dev->kobj.name[0], 2);
+ strncpy(str_sl_addr, &dev->kobj.name[len - 2], 2);
+ }
+
+ err = regmap_write(priv->regmap, addr, val);
+
+ if (err) {
+ dev_err(dev,
+ "[%s] : Max9296 I2C write failed Reg at 0x%04X:[0x%02X]\n",
+ __func__, addr, val);
+ return err;
+ }
+#if MAX9296_SHOW_I2C_WRITE_MSG
+ else {
+ dev_info(
+ dev,
+ "[%s] : Max9296 I2C write register at 0x%04X:[0x%02X]\n",
+ __func__, addr, val);
+ }
+#endif
+ /* delay before next i2c command as required for SERDES link */
+
+ usleep_range(100, 110);
+
+ return err;
+}
+
+static int tier4_max9296_get_sdev_idx(struct device *dev, struct device *s_dev,
+ int *idx)
+{
+ int i;
+ int err = 0;
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+
+ mutex_lock(&priv->lock);
+
+ for (i = 0; i < priv->max_src; i++) {
+ if (priv->sources[i].g_ctx->s_dev == s_dev) {
+ break;
+ }
+ }
+ if (i == priv->max_src) {
+ dev_err(dev, "[%s] : No sdev found\n", __func__);
+ err = -EINVAL;
+ goto ret;
+ }
+
+ if (idx) {
+ *idx = i;
+ }
+
+ret:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+
+static void tier4_max9296_pipes_reset(struct tier4_max9296 *priv)
+{
+ /*
+ * This is default pipes combination. add more mappings
+ * for other combinations and requirements.
+ */
+ struct pipe_ctx pipe_defaults[] = {
+ { MAX9296_PIPE_X, GMSL_CSI_DT_YUV_8, // For YUV8
+ MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID },
+ { MAX9296_PIPE_Y, GMSL_CSI_DT_YUV_8, // For YUV8
+ MAX9296_CSI_CTRL_1, 0, MAX9296_INVAL_ST_ID },
+ { MAX9296_PIPE_Z, GMSL_CSI_DT_EMBED, MAX9296_CSI_CTRL_1, 0,
+ MAX9296_INVAL_ST_ID },
+ { MAX9296_PIPE_U, GMSL_CSI_DT_EMBED, MAX9296_CSI_CTRL_1, 0,
+ MAX9296_INVAL_ST_ID }
+ };
+
+ /*
+ * Add DT props for num-streams and stream sequence, and based on that
+ * set the appropriate pipes defaults.
+ * For now default it supports "2 RAW12 and 2 EMBED" 1:1 mappings.
+ */
+ memcpy(priv->pipe, pipe_defaults, sizeof(pipe_defaults));
+}
+
+static void tier4_max9296_reset_ctx(struct tier4_max9296 *priv)
+{
+ int i;
+
+ priv->link_setup = false;
+ priv->lane_setup = false;
+ priv->num_src_found = 0;
+ priv->src_link = 0;
+ priv->splitter_enabled = false;
+
+ tier4_max9296_pipes_reset(priv);
+
+ for (i = 0; i < priv->num_src; i++) {
+ priv->sources[i].st_enabled = false;
+ }
+}
+
+int tier4_max9296_power_on(struct device *dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ int i, err = 0;
+
+ mutex_lock(&priv->lock);
+
+ if (priv->pw_ref == 0) {
+ usleep_range(1, 2);
+
+ for (i = 0; i < priv->max_src; i++) {
+ if (priv->sources[i].g_ctx) {
+ break;
+ }
+ }
+ // if (priv->reset_gpio)
+ if (gpio_is_valid(priv->reset_gpio)) {
+ gpio_direction_output(priv->reset_gpio, 0);
+ }
+
+ usleep_range(50, 80);
+
+ if (priv->vdd_cam_1v2) {
+ err = regulator_enable(priv->vdd_cam_1v2);
+ if (unlikely(err))
+ goto ret;
+ }
+ usleep_range(50, 80);
+
+ /*exit reset mode: XCLR */
+ // if (priv->reset_gpio)
+ if (gpio_is_valid(priv->reset_gpio)) {
+ // gpio_set_value(priv->reset_gpio, 0);
+ gpio_direction_output(priv->reset_gpio, 0);
+
+ usleep_range(50, 80);
+ usleep_range(1000000, 1100000);
+ // gpio_set_value(priv->reset_gpio, 1);
+
+ gpio_direction_output(priv->reset_gpio, 1);
+
+ usleep_range(50, 80);
+ }
+
+ /* delay to settle reset */
+ // msleep(1000);
+ }
+
+ priv->pw_ref++;
+
+ret:
+
+ mutex_unlock(&priv->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_power_on);
+
+void tier4_max9296_power_off(struct device *dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+
+ mutex_lock(&priv->lock);
+ priv->pw_ref--;
+
+ if (priv->pw_ref == 0) {
+ /* enter reset mode: XCLR */
+ usleep_range(1, 2);
+ if (priv->reset_gpio)
+ // gpio_set_value(priv->reset_gpio, 0);
+ gpio_direction_output(priv->reset_gpio, 0);
+
+ if (priv->vdd_cam_1v2)
+ regulator_disable(priv->vdd_cam_1v2);
+ }
+
+ mutex_unlock(&priv->lock);
+}
+EXPORT_SYMBOL(tier4_max9296_power_off);
+
+static int tier4_max9296_write_link(struct device *dev, u32 link)
+{
+ int err = 0;
+
+ if (link == GMSL_SERDES_CSI_LINK_A) {
+ err = tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x01);
+ err |= tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x21);
+ } else if (link == GMSL_SERDES_CSI_LINK_B) {
+ err = tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x02);
+ err |= tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x22);
+ } else {
+ dev_err(dev, "[%s] : Invalid GMSL link\n", __func__);
+ return -EINVAL;
+ }
+
+ /* delay to settle link */
+ msleep(100);
+
+ return 0;
+}
+
+int tier4_max9296_setup_link(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ int err = 0;
+ int i;
+
+ err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx failed.\n",
+ __func__);
+ return err;
+ }
+
+ // max9296_debug_i2c_write = priv->sources[i].g_ctx->debug_i2c_write;
+
+ mutex_lock(&priv->lock);
+
+ if (!priv->splitter_enabled) {
+ err = tier4_max9296_write_link(
+ dev, priv->sources[i].g_ctx->serdes_csi_link);
+ if (err) {
+ dev_err(dev,
+ "[%s] : tier4_max9296_write_link failed.\n",
+ __func__);
+ goto ret;
+ }
+ priv->link_setup = true;
+ }
+
+ret:
+ mutex_unlock(&priv->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_setup_link);
+
+static int tier4_max9296_link_locked(struct device *dev)
+{
+ u8 val;
+
+ usleep_range(100, 110);
+ tier4_max9296_read_reg(dev, MAX9296_LINK_ADDR, &val);
+
+ if (0 == (val & 0x08)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int tier4_max9296_setup_gpi(struct device *dev, int fsync_mfp)
+{
+ int err = 0;
+ u16 gpio_mfp_base;
+
+ dev_info(dev, "[%s] : MFP%d is used for fsync\n", __func__, fsync_mfp);
+
+ gpio_mfp_base = (MAX9296_GPIO0_CONFIG_MFP0_ADDR + 3 * fsync_mfp) &
+ 0xFFFF;
+
+ err += tier4_max9296_write_reg(dev, gpio_mfp_base, 0x03);
+ err += tier4_max9296_write_reg(dev, gpio_mfp_base + 1, 0x06);
+ err += tier4_max9296_write_reg(dev, gpio_mfp_base + 2, 0x00);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_setup_gpi);
+
+int tier4_max9296_setup_control(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ int err = 0;
+ int i;
+
+ err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx() failed.\n",
+ __func__);
+ return err;
+ }
+
+ mutex_lock(&priv->lock);
+
+ if (!priv->link_setup) {
+ dev_err(dev, "[%s] : Invalid state\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ if (priv->sources[i].g_ctx->serdev_found) {
+ priv->num_src_found++;
+ priv->src_link = priv->sources[i].g_ctx->serdes_csi_link;
+ }
+
+ /* Enable splitter mode */
+ if ((priv->max_src > 1U) && (priv->num_src_found > 0U) &&
+ (priv->splitter_enabled == false)) {
+ tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x03);
+ tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR, 0x23);
+
+ priv->splitter_enabled = true;
+
+ /* delay to settle link */
+ msleep(500);
+ }
+
+#if _USE_CHECK_LINK_LOCKED_
+ // Check GMSL link
+ err = tier4_max9296_link_locked(dev);
+ if (err) {
+ // GMSL2 link not locked
+ dev_info(dev, "[%s]: max9296 link is not locked.\n", __func__);
+ err = tier4_max9296_write_link(dev, priv->src_link);
+ if (err) {
+ dev_err(dev,
+ "[%s]: tier4_max9296_write_link() failed.\n",
+ __func__);
+ goto error;
+ }
+ }
+#endif
+
+ if (!priv->splitter_enabled) {
+ tier4_max9296_write_reg(dev, MAX9296_PWDN_PHYS_ADDR,
+ MAX9296_ALLPHYS_NOSTDBY);
+ priv->splitter_enabled = true;
+ }
+ priv->link_setup = true;
+
+ priv->sdev_ref++;
+
+ /* Reset splitter mode if all devices are not found */
+ if ((priv->sdev_ref == priv->max_src) &&
+ (priv->splitter_enabled == true) && (priv->num_src_found > 0U) &&
+ (priv->num_src_found < priv->max_src)) {
+ err = tier4_max9296_write_link(dev, priv->src_link);
+ if (err)
+ goto error;
+
+ priv->splitter_enabled = false;
+ }
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_setup_control);
+
+int tier4_max9296_reset_control(struct device *dev, struct device *s_dev,
+ bool force_reset)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ int err = 0;
+
+ mutex_lock(&priv->lock);
+ if (!priv->sdev_ref && force_reset == false) {
+ dev_info(dev, "[%s] : dev is already in reset state\n",
+ __func__);
+ goto ret;
+ }
+
+ priv->sdev_ref--;
+ if (priv->sdev_ref == 0 || force_reset == true) {
+ tier4_max9296_reset_ctx(priv);
+ tier4_max9296_write_reg(dev, MAX9296_CTRL0_ADDR,
+ MAX9296_RESET_ALL);
+
+ /* delay to settle reset */
+ msleep(100);
+ }
+
+ret:
+ mutex_unlock(&priv->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_reset_control);
+
+int tier4_max9296_sdev_register(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx)
+{
+ struct tier4_max9296 *priv = NULL;
+ int i;
+ int err = 0;
+
+ if (!dev || !g_ctx || !g_ctx->s_dev) {
+ dev_err(dev, "[%s] : Invalid input params\n", __func__);
+ return -EINVAL;
+ }
+
+ priv = dev_get_drvdata(dev);
+
+ mutex_lock(&priv->lock);
+
+ if ((g_ctx->hardware_model == HW_MODEL_NVIDIA_ORIN_DEVKIT) ||
+ (g_ctx->hardware_model == HW_MODEL_ADLINK_ROSCUBE_ORIN)) {
+ for (i = 0; i < MAX9296_MAX_SOURCES; i++) {
+ if (priv->sources[i].g_ctx != NULL) {
+ priv->sources[i].g_ctx->serdes_csi_link = 0;
+ }
+ }
+ }
+
+ if (priv->num_src > priv->max_src) {
+ dev_err(dev, "[%s] : MAX9296 inputs size exhausted\n",
+ __func__);
+ err = -ENOMEM;
+ goto error;
+ }
+
+ /* Check csi mode compatibility */
+ if (!((priv->csi_mode == MAX9296_CSI_MODE_2X4) ?
+ ((g_ctx->csi_mode == GMSL_CSI_1X4_MODE) ||
+ (g_ctx->csi_mode == GMSL_CSI_2X4_MODE)) :
+ ((g_ctx->csi_mode == GMSL_CSI_2X2_MODE) ||
+ (g_ctx->csi_mode == GMSL_CSI_4X2_MODE)))) {
+ dev_err(dev, "[%s] : CSI mode not supported\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+ asm("dsb sy");
+
+ for (i = 0; i < priv->num_src; i++) {
+ // dev_info(dev, "[%s]: g_ctx->serdes_csi_link = %u priv->sources[%d].g_ctx->serdes_csi_link = %u\n"
+ // , __func__, g_ctx->serdes_csi_link, i, priv->sources[i].g_ctx->serdes_csi_link );
+
+ // usleep_range(1000,1100);
+
+ if (g_ctx->serdes_csi_link ==
+ priv->sources[i].g_ctx->serdes_csi_link) {
+ // WARN_ON(1);
+ dev_info(dev, "[%s]: g_ctx->serdes_csi_link = %u\n",
+ __func__, g_ctx->serdes_csi_link);
+ dev_err(dev, "[%s] : Serdes CSI link is in use\n",
+ __func__);
+ err = -EINVAL;
+ goto error;
+ }
+ /*
+ * All sdevs should have same num-csi-lanes regardless of
+ * dst csi port selected.
+ * Later if there is any usecase which requires each port
+ * to be configured with different num-csi-lanes, then this
+ * check should be performed per port.
+ */
+
+ if (g_ctx->num_csi_lanes !=
+ priv->sources[i].g_ctx->num_csi_lanes) {
+ dev_err(dev,
+ "[%s] : CSI num lanes mismatch. %d, %d i=%d\n",
+ __func__, g_ctx->num_csi_lanes,
+ priv->sources[i].g_ctx->num_csi_lanes, i);
+ err = -EINVAL;
+ goto error;
+ }
+ }
+
+ priv->sources[priv->num_src].g_ctx = g_ctx;
+ priv->sources[priv->num_src].st_enabled = false;
+
+ priv->num_src++;
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_sdev_register);
+
+int tier4_max9296_sdev_unregister(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = NULL;
+ int err = 0;
+ int i = 0;
+
+ if (!dev || !s_dev) {
+ dev_err(dev, "[%s] : Invalid input params\n", __func__);
+ return -EINVAL;
+ }
+
+ priv = dev_get_drvdata(dev);
+ mutex_lock(&priv->lock);
+
+ if (priv->num_src == 0) {
+ dev_err(dev, "[%s] : No source found\n", __func__);
+ err = -ENODATA;
+ goto error;
+ }
+
+ for (i = 0; i < priv->num_src; i++) {
+ if (s_dev == priv->sources[i].g_ctx->s_dev) {
+ priv->sources[i].g_ctx = NULL;
+ priv->num_src--;
+ break;
+ }
+ }
+
+ if (i == priv->num_src) {
+ dev_err(dev, "[%s] : Requested device not found\n", __func__);
+ err = -EINVAL;
+ goto error;
+ }
+
+error:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_sdev_unregister);
+
+static int tier4_max9296_get_available_pipe(struct device *dev,
+ u32 st_data_type, u32 dst_csi_port)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < MAX9296_MAX_PIPES; i++) {
+ /*
+ * TODO: Enable a pipe for multi stream configuration having
+ * similar stream data type. For now use st_count as a flag
+ * for 1 to 1 mapping in pipe and stream data type, same can
+ * be extended as count for many to 1 mapping. Would also need
+ * few more checks such as input stream id select, dst port etc.
+ */
+ if ((priv->pipe[i].dt_type == st_data_type) &&
+ ((dst_csi_port == GMSL_CSI_PORT_A) ?
+ (priv->pipe[i].dst_csi_ctrl ==
+ MAX9296_CSI_CTRL_0) ||
+ (priv->pipe[i].dst_csi_ctrl ==
+ MAX9296_CSI_CTRL_1) :
+ (priv->pipe[i].dst_csi_ctrl ==
+ MAX9296_CSI_CTRL_2) ||
+ (priv->pipe[i].dst_csi_ctrl ==
+ MAX9296_CSI_CTRL_3)) &&
+ (!priv->pipe[i].st_count))
+ break;
+ }
+
+ if (i == MAX9296_MAX_PIPES) {
+ dev_err(dev, "[%s] : All pipes are busy\n", __func__);
+ return -ENOMEM;
+ }
+
+ return i;
+}
+
+struct reg_pair {
+ u16 addr;
+ u8 val;
+};
+
+static int tier4_max9296_setup_pipeline(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ struct tier4_gmsl_stream *g_stream;
+ struct reg_pair *map_list;
+ u32 arr_sz = 0;
+ int pipe_id = 0;
+ u32 i = 0;
+ u32 j = 0;
+ u32 vc_idx = 0;
+
+ for (i = 0; i < g_ctx->num_streams; i++) {
+ /* Base data type mapping: pipeX/RAW12/CSICNTR1 */
+ struct reg_pair map_pipe_yuv8[] = {
+ // for YUV8
+ /* addr, val */
+ { MAX9296_TX11_PIPE_X_EN_ADDR, 0x7 },
+ { MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15 },
+
+ { MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x1E }, // for YUV8
+ { MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x1E }, // for YUV8
+ { MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00 },
+ { MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00 },
+ { MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01 },
+ { MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01 },
+ };
+
+ /* Base data type mapping: pipeX/EMBED/CSICNTR1 */
+ struct reg_pair map_pipe_embed[] = {
+ /* addr, val */
+ { MAX9296_TX11_PIPE_X_EN_ADDR, 0x7 },
+ { MAX9296_TX45_PIPE_X_DST_CTRL_ADDR, 0x15 },
+ { MAX9296_PIPE_X_SRC_0_MAP_ADDR, 0x12 },
+ { MAX9296_PIPE_X_DST_0_MAP_ADDR, 0x12 },
+ { MAX9296_PIPE_X_SRC_1_MAP_ADDR, 0x00 },
+ { MAX9296_PIPE_X_DST_1_MAP_ADDR, 0x00 },
+ { MAX9296_PIPE_X_SRC_2_MAP_ADDR, 0x01 },
+ { MAX9296_PIPE_X_DST_2_MAP_ADDR, 0x01 },
+ };
+
+ g_stream = &g_ctx->streams[i];
+ g_stream->des_pipe = MAX9296_PIPE_INVALID;
+
+ if (g_stream->st_data_type == GMSL_CSI_DT_YUV_8) { // for YUV8
+ map_list = map_pipe_yuv8; // for YUV8
+ arr_sz = ARRAY_SIZE(map_pipe_yuv8); // for YUV8
+ } else if (g_stream->st_data_type == GMSL_CSI_DT_EMBED) {
+ map_list = map_pipe_embed;
+ arr_sz = ARRAY_SIZE(map_pipe_embed);
+ } else if (g_stream->st_data_type == GMSL_CSI_DT_UED_U1) {
+ continue;
+ } else {
+ dev_err(dev, "[%s] : Invalid data type\n", __func__);
+ return -EINVAL;
+ }
+
+ pipe_id = tier4_max9296_get_available_pipe(
+ dev, g_stream->st_data_type, g_ctx->dst_csi_port);
+ if (pipe_id < 0)
+ return pipe_id;
+
+ for (j = 0, vc_idx = 3; j < arr_sz; j++, vc_idx += 2) {
+ /* update pipe configuration */
+ map_list[j].addr += (0x40 * pipe_id);
+ /* update vc id configuration */
+ if (vc_idx < arr_sz) {
+ map_list[vc_idx].val |= (g_ctx->dst_vc << 6);
+ }
+ tier4_max9296_write_reg(dev, map_list[j].addr,
+ map_list[j].val);
+ }
+
+ /* Set stream id select input */
+ if (g_stream->st_id_sel == GMSL_ST_ID_UNUSED) {
+ dev_err(dev, "[%s] : Invalid stream st_id_sel\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ g_stream->des_pipe = MAX9296_PIPE_X_ST_SEL_ADDR + pipe_id;
+
+ /* Update pipe internals */
+ priv->pipe[pipe_id].st_count++;
+ priv->pipe[pipe_id].st_id_sel = g_stream->st_id_sel;
+ }
+
+ return 0;
+}
+
+int tier4_max9296_start_streaming(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ struct tier4_gmsl_link_ctx *g_ctx;
+ struct tier4_gmsl_stream *g_stream;
+ int err = 0;
+ int i = 0;
+
+ err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx failed.\n",
+ __func__);
+ return err;
+ }
+
+ mutex_lock(&priv->lock);
+
+ g_ctx = priv->sources[i].g_ctx;
+
+ for (i = 0; i < g_ctx->num_streams; i++) {
+ g_stream = &g_ctx->streams[i];
+
+ if (g_stream->des_pipe != MAX9296_PIPE_INVALID) {
+ tier4_max9296_write_reg(dev, g_stream->des_pipe,
+ g_stream->st_id_sel);
+ }
+ }
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(tier4_max9296_start_streaming);
+
+int tier4_max9296_stop_streaming(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ struct tier4_gmsl_link_ctx *g_ctx;
+ struct tier4_gmsl_stream *g_stream;
+ int err = 0;
+ int i = 0;
+
+ err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
+ if (err)
+ return err;
+
+ mutex_lock(&priv->lock);
+ g_ctx = priv->sources[i].g_ctx;
+
+ for (i = 0; i < g_ctx->num_streams; i++) {
+ g_stream = &g_ctx->streams[i];
+
+ if (g_stream->des_pipe != MAX9296_PIPE_INVALID) {
+ tier4_max9296_write_reg(dev, g_stream->des_pipe,
+ MAX9296_RESET_ST_ID);
+ }
+ }
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(tier4_max9296_stop_streaming);
+
+int tier4_max9296_setup_streaming(struct device *dev, struct device *s_dev)
+{
+ struct tier4_max9296 *priv = dev_get_drvdata(dev);
+ struct tier4_gmsl_link_ctx *g_ctx;
+ int err = 0;
+ int i = 0;
+ u16 lane_ctrl_addr;
+
+ err = tier4_max9296_get_sdev_idx(dev, s_dev, &i);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_get_sdev_idx() failed.\n",
+ __func__);
+ return err;
+ }
+
+ mutex_lock(&priv->lock);
+ if (priv->sources[i].st_enabled)
+ goto ret;
+
+ g_ctx = priv->sources[i].g_ctx;
+
+ err = tier4_max9296_setup_pipeline(dev, g_ctx);
+
+ if (err) {
+ dev_err(dev, "[%s] : tier4_max9296_setup_pipeline() failed.\n",
+ __func__);
+ goto ret;
+ }
+
+ /* Derive CSI lane map register */
+ switch (g_ctx->dst_csi_port) {
+ case GMSL_CSI_PORT_A:
+ case GMSL_CSI_PORT_D:
+ lane_ctrl_addr = MAX9296_LANE_CTRL1_ADDR;
+ break;
+ case GMSL_CSI_PORT_B:
+ case GMSL_CSI_PORT_E:
+ lane_ctrl_addr = MAX9296_LANE_CTRL2_ADDR;
+ break;
+ case GMSL_CSI_PORT_C:
+ lane_ctrl_addr = MAX9296_LANE_CTRL0_ADDR;
+ break;
+ case GMSL_CSI_PORT_F:
+ lane_ctrl_addr = MAX9296_LANE_CTRL3_ADDR;
+ break;
+ default:
+ dev_err(dev, "[%s] : Invalid GMSL CSI port!\n", __func__);
+ err = -EINVAL;
+ goto ret;
+ };
+
+ /*
+ * rewrite num_lanes to same dst port should not be an issue,
+ * as the device compatibility is already
+ * checked during sdev registration against the des properties.
+ */
+
+ tier4_max9296_write_reg(
+ dev, lane_ctrl_addr,
+ MAX9296_LANE_CTRL_MAP(g_ctx->num_csi_lanes - 1));
+
+ if (!priv->lane_setup) {
+ tier4_max9296_write_reg(dev, MAX9296_DST_CSI_MODE_ADDR,
+ priv->csi_mode);
+ tier4_max9296_write_reg(dev, MAX9296_LANE_MAP1_ADDR,
+ priv->lane_mp1);
+ tier4_max9296_write_reg(dev, MAX9296_LANE_MAP2_ADDR,
+ priv->lane_mp2);
+ if (g_ctx->hardware_model == HW_MODEL_NVIDIA_ORIN_DEVKIT) {
+ tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR,
+ MAX9296_PHY1_CLK_1400MHZ);
+ } else if (g_ctx->hardware_model ==
+ HW_MODEL_ADLINK_ROSCUBE_ORIN) {
+ tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR,
+ MAX9296_PHY1_CLK_1500MHZ);
+ } else if (g_ctx->hardware_model ==
+ HW_MODEL_ADLINK_ROSCUBE_XAVIER) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 65)
+ // RQX-58G L4T 35.4.1
+ tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR,
+ MAX9296_PHY1_CLK_1600MHZ);
+#else // RQX-58G L4T 32.x
+ tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR,
+ MAX9296_PHY1_CLK_1800MHZ);
+#endif
+ } else {
+ tier4_max9296_write_reg(dev, MAX9296_PHY1_CLK_ADDR,
+ MAX9296_PHY1_CLK_1400MHZ);
+ }
+
+ priv->lane_setup = true;
+ }
+
+#if 0
+ tier4_max9296_write_reg(dev, MAX9296_REG5_ADDR, 0xC0); // informed from Maxim
+#endif
+ priv->sources[i].st_enabled = true;
+
+ret:
+ mutex_unlock(&priv->lock);
+ return err;
+}
+EXPORT_SYMBOL(tier4_max9296_setup_streaming);
+
+const struct of_device_id tier4_max9296_of_match[] = {
+ {
+ .compatible = "nvidia,tier4_max9296",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tier4_max9296_of_match);
+
+static int tier4_max9296_parse_dt(struct tier4_max9296 *priv,
+ struct i2c_client *client)
+{
+ struct device_node *node = client->dev.of_node;
+ int err = 0;
+ const char *str_value;
+ int value;
+ const struct of_device_id *match;
+
+ if (!node)
+ return -EINVAL;
+
+ match = of_match_device(tier4_max9296_of_match, &client->dev);
+ if (!match) {
+ dev_err(&client->dev,
+ "[%s] : Failed to match device with dt id\n", __func__);
+ return -EFAULT;
+ }
+
+ err = of_property_read_string(node, "csi-mode", &str_value);
+ if (err < 0) {
+ dev_err(&client->dev, "[%s] : csi-mode property not found\n",
+ __func__);
+ return err;
+ }
+
+ if (!strcmp(str_value, "2x4")) {
+ priv->csi_mode = MAX9296_CSI_MODE_2X4;
+ priv->lane_mp1 = MAX9296_LANE_MAP1_2X4;
+ priv->lane_mp2 = MAX9296_LANE_MAP2_2X4;
+ } else if (!strcmp(str_value, "4x2")) {
+ priv->csi_mode = MAX9296_CSI_MODE_4X2;
+ priv->lane_mp1 = MAX9296_LANE_MAP1_4X2;
+ priv->lane_mp2 = MAX9296_LANE_MAP2_4X2;
+ } else {
+ dev_err(&client->dev, "[%s] : Invalid csi mode\n", __func__);
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32(node, "max-src", &value);
+ if (err < 0) {
+ dev_err(&client->dev, "[%s] : No max-src info\n", __func__);
+ return err;
+ }
+
+ priv->max_src = value;
+
+ priv->reset_gpio = of_get_named_gpio(node, "reset-gpios", 0);
+ if (priv->reset_gpio < 0) {
+ dev_err(&client->dev, "[%s] : reset-gpios not found %d\n",
+ __func__, err);
+ return err;
+ }
+
+ /* digital 1.2v */
+ if (of_get_property(node, "vdd_cam_1v2-supply", NULL)) {
+ priv->vdd_cam_1v2 = regulator_get(&client->dev, "vdd_cam_1v2");
+ if (IS_ERR(priv->vdd_cam_1v2)) {
+ dev_err(&client->dev,
+ "[%s] : vdd_cam_1v2 regulator get failed\n",
+ __func__);
+ err = PTR_ERR(priv->vdd_cam_1v2);
+ priv->vdd_cam_1v2 = NULL;
+ return err;
+ }
+ } else {
+ priv->vdd_cam_1v2 = NULL;
+ }
+
+ return 0;
+}
+
+static struct regmap_config tier4_max9296_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int tier4_max9296_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tier4_max9296 *priv;
+ int err = 0;
+
+ dev_info(&client->dev, "[%s]: Probing GMSL deserializer\n", __func__);
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ priv->i2c_client = client;
+ priv->regmap = devm_regmap_init_i2c(priv->i2c_client,
+ &tier4_max9296_regmap_config);
+ if (IS_ERR(priv->regmap)) {
+ dev_err(&client->dev, "[%s] : devm_regmap_init() failed: %ld\n",
+ __func__, PTR_ERR(priv->regmap));
+ return -ENODEV;
+ }
+
+ err = tier4_max9296_parse_dt(priv, client);
+ if (err) {
+ dev_err(&client->dev, "[%s] : Unable to parse dt\n", __func__);
+ return -EFAULT;
+ }
+
+ tier4_max9296_pipes_reset(priv);
+
+ if (priv->max_src > MAX9296_MAX_SOURCES) {
+ dev_err(&client->dev,
+ "[%s] : Max sources more than currently supported\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ mutex_init(&priv->lock);
+
+ dev_set_drvdata(&client->dev, priv);
+
+ /* dev communication gets validated when GMSL link setup is done */
+ dev_info(&client->dev, "[%s] : Probing GMSL Deserializer is done.\n",
+ __func__);
+
+ return err;
+}
+
+static int tier4_max9296_remove(struct i2c_client *client)
+{
+ struct tier4_max9296 *priv;
+
+ if (client != NULL) {
+ priv = dev_get_drvdata(&client->dev);
+ mutex_destroy(&priv->lock);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id tier4_max9296_id[] = {
+ { "tier4_max9296", 0 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tier4_max9296_id);
+
+static struct i2c_driver tier4_max9296_i2c_driver = {
+ .driver = {
+ .name = "tier4_max9296",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tier4_max9296_of_match),
+ },
+ .probe = tier4_max9296_probe,
+ .remove = tier4_max9296_remove,
+ .id_table = tier4_max9296_id,
+};
+
+static int __init tier4_max9296_init(void)
+{
+ printk(KERN_INFO "MAX9296 Driver for TIERIV Camera : %s\n",
+ BUILD_STAMP);
+ return i2c_add_driver(&tier4_max9296_i2c_driver);
+}
+
+static void __exit tier4_max9296_exit(void)
+{
+ i2c_del_driver(&tier4_max9296_i2c_driver);
+}
+
+module_init(tier4_max9296_init);
+module_exit(tier4_max9296_exit);
+
+MODULE_DESCRIPTION("Dual GMSL Deserializer driver tier4_max9296");
+MODULE_AUTHOR("Originaly NVIDIA Corporation");
+MODULE_AUTHOR("K.Iwasaki");
+MODULE_AUTHOR("Y.Fujii");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/src/tier4-max9296.h b/src/tier4-camera-gmsl/tier4-max9296.h
similarity index 97%
rename from drivers/src/tier4-max9296.h
rename to src/tier4-camera-gmsl/tier4-max9296.h
index 75465e3..970836a 100644
--- a/drivers/src/tier4-max9296.h
+++ b/src/tier4-camera-gmsl/tier4-max9296.h
@@ -78,7 +78,8 @@ int tier4_max9296_setup_control(struct device *dev, struct device *s_dev);
*
* @return 0 for success, or -1 otherwise.
*/
-int tier4_max9296_reset_control(struct device *dev, struct device *s_dev, bool force_reset);
+int tier4_max9296_reset_control(struct device *dev, struct device *s_dev,
+ bool force_reset);
/**
* @brief Registers a source sensor device with a deserializer device.
@@ -93,7 +94,8 @@ int tier4_max9296_reset_control(struct device *dev, struct device *s_dev, bool f
*
* @return 0 for success, or -1 otherwise.
*/
-int tier4_max9296_sdev_register(struct device *dev, struct tier4_gmsl_link_ctx *g_ctx);
+int tier4_max9296_sdev_register(struct device *dev,
+ struct tier4_gmsl_link_ctx *g_ctx);
/**
* Unregisters a source sensor device from its deserializer device.
diff --git a/tools/dts_generator/.gitignore b/tools/dts_generator/.gitignore
new file mode 100644
index 0000000..82f9275
--- /dev/null
+++ b/tools/dts_generator/.gitignore
@@ -0,0 +1,162 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
+.pdm.toml
+.pdm-python
+.pdm-build/
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
diff --git a/drivers/src/dts_generator/__init__.py b/tools/dts_generator/dts_generator/__init__.py
similarity index 100%
rename from drivers/src/dts_generator/__init__.py
rename to tools/dts_generator/dts_generator/__init__.py
diff --git a/drivers/src/dts_generator/camera.py b/tools/dts_generator/dts_generator/camera.py
similarity index 100%
rename from drivers/src/dts_generator/camera.py
rename to tools/dts_generator/dts_generator/camera.py
diff --git a/drivers/src/dts_generator/const.py b/tools/dts_generator/dts_generator/const.py
similarity index 100%
rename from drivers/src/dts_generator/const.py
rename to tools/dts_generator/dts_generator/const.py
diff --git a/drivers/src/dts_generator/devicetree.py b/tools/dts_generator/dts_generator/devicetree.py
similarity index 97%
rename from drivers/src/dts_generator/devicetree.py
rename to tools/dts_generator/dts_generator/devicetree.py
index 29b555e..d4a1760 100644
--- a/drivers/src/dts_generator/devicetree.py
+++ b/tools/dts_generator/dts_generator/devicetree.py
@@ -50,7 +50,7 @@ def __init__(self, name: str, label: str = '') -> None:
self.footer_str: str = ''
def header(self, header: str) -> DeviceTreeNode:
- self.header_str = header
+ self.header_str += header
return self
def name(self, name: str) -> DeviceTreeNode:
@@ -159,12 +159,12 @@ def overlay_target_label(self, label: str) -> FragmentNode:
def quote(string: str) -> str:
- """Quote a value of devicetree 'string' type"""
+ """Quote a value of devicetree 'string' type."""
return f'"{string}"'
def unquote(string: str) -> str:
- """Unquote a value of devicetree 'string' type"""
+ """Unquote a value of devicetree 'string' type."""
return string.strip('"')
diff --git a/drivers/src/dts_generator/gmsl.py b/tools/dts_generator/dts_generator/gmsl.py
similarity index 100%
rename from drivers/src/dts_generator/gmsl.py
rename to tools/dts_generator/dts_generator/gmsl.py
diff --git a/drivers/src/dts_generator/media_graph.py b/tools/dts_generator/dts_generator/media_graph.py
similarity index 100%
rename from drivers/src/dts_generator/media_graph.py
rename to tools/dts_generator/dts_generator/media_graph.py
diff --git a/drivers/src/dts_generator/options.py b/tools/dts_generator/dts_generator/options.py
similarity index 90%
rename from drivers/src/dts_generator/options.py
rename to tools/dts_generator/dts_generator/options.py
index 93def6e..1a4a92c 100644
--- a/drivers/src/dts_generator/options.py
+++ b/tools/dts_generator/dts_generator/options.py
@@ -5,7 +5,8 @@
import argparse
import sys
from dataclasses import dataclass
-from typing import Any, List, Optional
+from enum import Enum
+from typing import Any, Dict, List, Optional
from . import camera, tegra_nvcsi
@@ -56,6 +57,34 @@ def __call__(self, parser: argparse.ArgumentParser, namespace: argparse.Namespac
setattr(namespace, 'ordered_args', previous)
+class JetsonSoM(Enum):
+ AGX_Xavier = 1
+ AGX_Orin = 2
+
+
+class Board(Enum):
+ Xavier_devkit = 1
+ Orin_devkit = 2
+ ROSCube_58g = 3
+ ROSCube_59g = 4
+ EAC_5000 = 5
+ Anvil = 6
+
+ @property
+ def som(self) -> JetsonSoM:
+ return _board_som[self]
+
+
+_board_som: Dict[Board, JetsonSoM] = {
+ Board.Xavier_devkit: JetsonSoM.AGX_Xavier,
+ Board.Orin_devkit: JetsonSoM.AGX_Orin,
+ Board.ROSCube_58g: JetsonSoM.AGX_Xavier,
+ Board.ROSCube_59g: JetsonSoM.AGX_Orin,
+ Board.EAC_5000: JetsonSoM.AGX_Orin,
+ Board.Anvil: JetsonSoM.AGX_Orin,
+}
+
+
@dataclass
class GeneratorOptions:
args: argparse.Namespace
diff --git a/drivers/src/dts_generator/tegra_nvcsi.py b/tools/dts_generator/dts_generator/tegra_nvcsi.py
similarity index 75%
rename from drivers/src/dts_generator/tegra_nvcsi.py
rename to tools/dts_generator/dts_generator/tegra_nvcsi.py
index 0df72b4..6db1eb1 100644
--- a/drivers/src/dts_generator/tegra_nvcsi.py
+++ b/tools/dts_generator/dts_generator/tegra_nvcsi.py
@@ -4,22 +4,31 @@
from . import validate_csi_lanes
from .devicetree import FragmentNode
+from .options import GeneratorOptions
MAX_CHANNELS: Final[int] = 8
-nvcsi_node_fragment = FragmentNode(target_path='/host1x@13e00000/nvcsi@15a00000') \
- .overlay_properties([
- 'status = "okay"',
- f'num-channels = <{MAX_CHANNELS}>',
- ])
+
+def create_nvcsi_node_fragment(opts: GeneratorOptions, index: Optional[int] = None) -> FragmentNode:
+ target_path = '/host1x@13e00000/nvcsi@15a00000'
+ if opts.l4t_version.major == 36:
+ target_path = '/bus@0' + target_path
+
+ return FragmentNode(index=index, target_path=target_path) \
+ .overlay_properties([
+ 'status = "okay"',
+ f'num-channels = <{MAX_CHANNELS}>',
+ ])
class NvcsiChannel:
- def __init__(self, channel_index: Any, port_index: Any, bus_width: SupportsInt) -> None:
+ def __init__(self, opts: GeneratorOptions, channel_index: Any, port_index: Any, bus_width: SupportsInt) -> None:
bus_width = int(bus_width)
validate_csi_lanes(bus_width)
channel_path = f'/host1x@13e00000/nvcsi@15a00000/channel@{channel_index}'
+ if opts.l4t_version.major == 36:
+ channel_path = '/bus@0' + channel_path
self.channel = FragmentNode(target_path=channel_path) \
.overlay_properties([
diff --git a/drivers/src/dts_generator/tegra_vi.py b/tools/dts_generator/dts_generator/tegra_vi.py
similarity index 79%
rename from drivers/src/dts_generator/tegra_vi.py
rename to tools/dts_generator/dts_generator/tegra_vi.py
index 4a79b8e..c3839a2 100644
--- a/drivers/src/dts_generator/tegra_vi.py
+++ b/tools/dts_generator/dts_generator/tegra_vi.py
@@ -1,20 +1,23 @@
#!/usr/bin/env python3
-from typing import Any, List, Optional, SupportsInt
+from typing import List, Optional, SupportsInt
from . import StringLike, camera, validate_csi_lanes
from .devicetree import FragmentNode
+from .options import GeneratorOptions
from .tegra_nvcsi import MAX_CHANNELS
-vi_node_fragment = FragmentNode(index=None, target_path='/tegra-capture-vi') \
- .overlay_properties([
- 'status = "okay"',
- f'num-channels = <{MAX_CHANNELS}>',
- ])
+
+def create_vi_node_fragment(opts: GeneratorOptions, index: Optional[int] = None) -> FragmentNode:
+ return FragmentNode(index=index, target_path='/tegra-capture-vi') \
+ .overlay_properties([
+ 'status = "okay"',
+ f'num-channels = <{MAX_CHANNELS}>',
+ ])
class ViPort:
- def __init__(self, port_number: StringLike, port_index: StringLike, vc_id: StringLike, bus_width: SupportsInt) -> None:
+ def __init__(self, opts: GeneratorOptions, port_number: StringLike, port_index: StringLike, vc_id: StringLike, bus_width: SupportsInt) -> None:
bus_width = int(bus_width)
validate_csi_lanes(bus_width)
@@ -41,7 +44,7 @@ def to_list(self) -> List[Optional[FragmentNode]]:
class CameraPlatform:
@staticmethod
- def node_fragment(num_csi_lanes: StringLike, max_lane_speed: StringLike) -> FragmentNode:
+ def node_fragment(opts: GeneratorOptions, num_csi_lanes: StringLike, max_lane_speed: StringLike) -> FragmentNode:
return FragmentNode(target_path='/tegra-camera-platform') \
.overlay_properties([
'status = "okay"',
@@ -58,7 +61,7 @@ def node_fragment(num_csi_lanes: StringLike, max_lane_speed: StringLike) -> Frag
# The `position` argument corresponds to the `position` property for `tegra-camera-platform`.
# It seems like only Argus makes use of it.
@staticmethod
- def module_fragment(index: int, cam: Optional[camera.Camera], position: str,
+ def module_fragment(opts: GeneratorOptions, index: int, cam: Optional[camera.Camera], position: str,
i2c_bus_number: StringLike, i2c_bus_path: StringLike
) -> List[Optional[FragmentNode]]:
if cam is None:
diff --git a/tools/dts_generator/dtsi/tegra-camera-base-r36.dtsi b/tools/dts_generator/dtsi/tegra-camera-base-r36.dtsi
new file mode 100644
index 0000000..dac5d60
--- /dev/null
+++ b/tools/dts_generator/dtsi/tegra-camera-base-r36.dtsi
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// tegra-camera-base-r36.dtsi
+/ {
+ fragment-camera-module@0 {
+ target-path = "/tegra-capture-vi";
+ __overlay__ {
+ /* all cameras are disabled by default */
+ ports {
+ vi_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ vi_in0: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ vi_in1: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port2: port@2 {
+ reg = <2>;
+ status = "disabled";
+ vi_in2: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port3: port@3 {
+ reg = <3>;
+ status = "disabled";
+ vi_in3: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port4: port@4 {
+ reg = <4>;
+ status = "disabled";
+ vi_in4: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port5: port@5 {
+ reg = <5>;
+ status = "disabled";
+ vi_in5: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port6: port@6 {
+ reg = <6>;
+ status = "disabled";
+ vi_in6: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port7: port@7 {
+ reg = <7>;
+ status = "disabled";
+ vi_in7: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ };
+ };
+ };
+
+ fragment-camera-module@1 {
+ target-path = "/";
+ __overlay__ {
+ tcp: tegra-camera-platform {
+ compatible = "nvidia, tegra-camera-platform";
+ /**
+ * tpg_max_iso = <>;
+ * Max iso bw for 6 streams of tpg
+ * streams * nvcsi_freq * PG_bitrate / RG10 * BPP
+ * 6 * 102Mhz * 32 bits/ 10 bits * 2 Bps
+ * = 3916.8 MBps
+ */
+ tpg_max_iso = <3916800>;
+ modules {
+ cam_module0: module0 {
+ status = "disabled";
+ cam_module0_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module0_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module1: module1 {
+ status = "disabled";
+ cam_module1_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module1_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module2: module2 {
+ status = "disabled";
+ cam_module2_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module2_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module3: module3 {
+ status = "disabled";
+ cam_module3_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module3_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module4: module4 {
+ status = "disabled";
+ cam_module4_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module4_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module5: module5 {
+ status = "disabled";
+ cam_module5_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module5_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module6: module6 {
+ status = "disabled";
+ cam_module6_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module6_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module7: module7 {
+ status = "disabled";
+ cam_module7_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module7_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment-camera-module@2 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000";
+ __overlay__ {
+ num-tpg-channels = <36>;
+ csi_chan0: channel@0 {
+ reg = <0>;
+ status = "disabled";
+ ports {
+ csi_chan0_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in0: endpoint@0 {
+ status = "disabled";
+ };
+ };
+ csi_chan0_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out0: endpoint@1 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan1: channel@1 {
+ reg = <1>;
+ status = "disabled";
+ ports {
+ csi_chan1_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in1: endpoint@2 {
+ status = "disabled";
+ };
+ };
+ csi_chan1_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out1: endpoint@3 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan2: channel@2 {
+ reg = <2>;
+ status = "disabled";
+ ports {
+ csi_chan2_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in2: endpoint@4 {
+ status = "disabled";
+ };
+ };
+ csi_chan2_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out2: endpoint@5 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan3: channel@3 {
+ reg = <3>;
+ status = "disabled";
+ ports {
+ csi_chan3_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in3: endpoint@6 {
+ status = "disabled";
+ };
+ };
+ csi_chan3_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out3: endpoint@7 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan4: channel@4 {
+ reg = <4>;
+ status = "disabled";
+ ports {
+ csi_chan4_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in4: endpoint@8 {
+ status = "disabled";
+ };
+ };
+ csi_chan4_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out4: endpoint@9 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan5: channel@5 {
+ reg = <5>;
+ status = "disabled";
+ ports {
+ csi_chan5_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in5: endpoint@10 {
+ status = "disabled";
+ };
+ };
+ csi_chan5_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out5: endpoint@11 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan6: channel@6 {
+ reg = <6>;
+ status = "disabled";
+ ports {
+ csi_chan6_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in6: endpoint@12 {
+ status = "disabled";
+ };
+ };
+ csi_chan6_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out6: endpoint@13 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan7: channel@7 {
+ reg = <7>;
+ status = "disabled";
+ ports {
+ csi_chan7_port0: port@0 {
+ reg = <0>;
+ status = "disabled";
+ csi_in7: endpoint@14 {
+ status = "disabled";
+ };
+ };
+ csi_chan7_port1: port@1 {
+ reg = <1>;
+ status = "disabled";
+ csi_out7: endpoint@15 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ };
+ };
+};
+// tegra-camera-base-r36.dtsi
diff --git a/drivers/src/make_overlay_dts_anvil.py b/tools/dts_generator/make_overlay_dts_anvil.py
similarity index 53%
rename from drivers/src/make_overlay_dts_anvil.py
rename to tools/dts_generator/make_overlay_dts_anvil.py
index dbc4509..79a4208 100755
--- a/drivers/src/make_overlay_dts_anvil.py
+++ b/tools/dts_generator/make_overlay_dts_anvil.py
@@ -24,6 +24,7 @@
from dts_generator.tegra_vi import CameraPlatform, ViPort
PLATFORM_NAME: str = 'Anvil'
+TEGRA_CAMERA_BASE_OVERLAY_R36: str = 'dtsi/tegra-camera-base-r36.dtsi'
CSI_LANES: int = 4
NUM_GMSL_DESERIALIZERS: int = 4
@@ -32,8 +33,14 @@
PIXEL_CLOCK: int = 350000000
-def build_cameras(camera_list: Iterable[camera.Type], gmsl_dsers: Iterable[FragmentNode]) -> List[camera.Camera]:
- dser_label = list(filter(None, [gmsl_dser.target_label for gmsl_dser in gmsl_dsers]))
+def build_cameras(camera_list: Iterable[camera.Type], gmsl_dsers: Iterable[DeviceTreeNode]) -> List[camera.Camera]:
+ def get_label(node: DeviceTreeNode) -> str:
+ label = node.target_label if isinstance(node, FragmentNode) else node.node_label
+ if label is None:
+ raise ValueError('A GMSL deserializer node has no label')
+ return label
+
+ dser_label = list(filter(None, [get_label(gmsl_dser) for gmsl_dser in gmsl_dsers]))
assert len(dser_label) >= 4
c1_cameras = [
@@ -85,36 +92,26 @@ def at(lst: Sequence[T], index: int) -> Optional[T]:
return lst[index] if index < len(lst) else None
-def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
- num_channels = opts.number_of_cameras
-
- tegra_vi.vi_node_fragment.overlay_properties([f'num-channels = <{num_channels}>'])
- vi_ports = [
- ViPort(port_number=7, port_index=0, vc_id=1, bus_width=CSI_LANES),
- ViPort(port_number=6, port_index=0, vc_id=0, bus_width=CSI_LANES),
- ViPort(port_number=5, port_index=2, vc_id=1, bus_width=CSI_LANES),
- ViPort(port_number=4, port_index=2, vc_id=0, bus_width=CSI_LANES),
- ViPort(port_number=3, port_index=4, vc_id=1, bus_width=CSI_LANES),
- ViPort(port_number=2, port_index=4, vc_id=0, bus_width=CSI_LANES),
- ViPort(port_number=1, port_index=5, vc_id=1, bus_width=CSI_LANES),
- ViPort(port_number=0, port_index=5, vc_id=0, bus_width=CSI_LANES),
- ][:num_channels]
- vi_fragments = sum(map(ViPort.to_list, vi_ports), [tegra_vi.vi_node_fragment])
-
- tegra_nvcsi.nvcsi_node_fragment.overlay_properties([f'num-channels = <{num_channels}>'])
- nvcsi_channels = [
- NvcsiChannel(channel_index=7, port_index=0, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=6, port_index=0, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=5, port_index=2, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=4, port_index=2, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=3, port_index=4, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=2, port_index=4, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=1, port_index=6, bus_width=CSI_LANES),
- NvcsiChannel(channel_index=0, port_index=6, bus_width=CSI_LANES),
- ][:num_channels]
- nvcsi_fragments = sum(map(NvcsiChannel.to_list, nvcsi_channels), [tegra_nvcsi.nvcsi_node_fragment])
-
- gmsl_dsers = [
+gmsl_dsers_nodes = [
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dsera')
+ .properties([
+ f'reset-gpios = <&tca9539_74 0 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserb')
+ .properties([
+ f'reset-gpios = <&tca9539_74 2 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserc')
+ .properties([
+ f'reset-gpios = <&tca9539_74 4 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserd')
+ .properties([
+ f'reset-gpios = <&tca9539_74 6 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+]
+
+gmsl_dser_fragments = [
gmsl.Deserializer.fragment(target='dsera', csi_lanes=CSI_LANES)
.overlay_properties([
f'reset-gpios = <&tca9539_74 0 {const.GPIO_ACTIVE_HIGH}>'
@@ -131,30 +128,76 @@ def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
.overlay_properties([
f'reset-gpios = <&tca9539_74 6 {const.GPIO_ACTIVE_HIGH}>'
]),
- ]
- cameras = build_cameras(opts.camera_list, gmsl_dsers)
+]
- graph = MediaGraph(vi_ports, nvcsi_channels, cameras)
- graph.connect_all_endpoints()
+
+def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
+ num_channels = opts.number_of_cameras
+
+ vi_node_fragment = tegra_vi.create_vi_node_fragment(opts) \
+ .overlay_properties([f'num-channels = <{num_channels}>'])
+ vi_ports = [
+ ViPort(opts, port_number=7, port_index=0, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=6, port_index=0, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=5, port_index=2, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=4, port_index=2, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=3, port_index=4, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=2, port_index=4, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=1, port_index=5, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=0, port_index=5, vc_id=0, bus_width=CSI_LANES),
+ ][:num_channels]
+ vi_fragments = sum(map(ViPort.to_list, vi_ports), [vi_node_fragment])
+
+ nvcsi_node_fragment = tegra_nvcsi.create_nvcsi_node_fragment(opts) \
+ .overlay_properties([f'num-channels = <{num_channels}>'])
+ nvcsi_channels = [
+ NvcsiChannel(opts, channel_index=7, port_index=0, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=6, port_index=0, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=5, port_index=2, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=4, port_index=2, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=3, port_index=4, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=2, port_index=4, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=1, port_index=6, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=0, port_index=6, bus_width=CSI_LANES),
+ ][:num_channels]
+ nvcsi_fragments = sum(map(NvcsiChannel.to_list, nvcsi_channels), [nvcsi_node_fragment])
+
+ root = devicetree.jetson_camera_overlay_root(opts.overlay_name)
i2c_bus_number: int = 0x28
i2c_mux_path = '/i2c@31e0000/tca9544@72'
+ gmsl_dsers: Sequence[DeviceTreeNode] = gmsl_dser_fragments
+
+ if opts.l4t_version.major >= 36:
+ i2c_mux_path = '/bus@0' + i2c_mux_path
+ gmsl_dsers = gmsl_dsers_nodes
+ with open(TEGRA_CAMERA_BASE_OVERLAY_R36, 'r', encoding='utf-8') as tegra_cam_dtsi:
+ (root
+ .header('\n' + tegra_cam_dtsi.read())
+ .nodes(i2c_mux_and_gmsl_dsers(gmsl_dsers)))
+ else:
+ root.nodes(gmsl_dsers)
+
+ cameras = build_cameras(opts.camera_list, gmsl_dsers)
+
+ graph = MediaGraph(vi_ports, nvcsi_channels, cameras)
+ graph.connect_all_endpoints()
tegra_camera_platform_modules = [
- CameraPlatform.module_fragment(index=7, cam=at(cameras, 0), position='bottom', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
- CameraPlatform.module_fragment(index=6, cam=at(cameras, 1), position='top', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
- CameraPlatform.module_fragment(index=5, cam=at(cameras, 2), position='right2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
- CameraPlatform.module_fragment(index=4, cam=at(cameras, 3), position='left2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
- CameraPlatform.module_fragment(index=3, cam=at(cameras, 4), position='right', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
- CameraPlatform.module_fragment(index=2, cam=at(cameras, 5), position='left', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
- CameraPlatform.module_fragment(index=1, cam=at(cameras, 6), position='front', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
- CameraPlatform.module_fragment(index=0, cam=at(cameras, 7), position='rear', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
+ CameraPlatform.module_fragment(opts, index=7, cam=at(cameras, 0), position='bottom', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
+ CameraPlatform.module_fragment(opts, index=6, cam=at(cameras, 1), position='top', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
+ CameraPlatform.module_fragment(opts, index=5, cam=at(cameras, 2), position='right2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
+ CameraPlatform.module_fragment(opts, index=4, cam=at(cameras, 3), position='left2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
+ CameraPlatform.module_fragment(opts, index=3, cam=at(cameras, 4), position='right', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
+ CameraPlatform.module_fragment(opts, index=2, cam=at(cameras, 5), position='left', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
+ CameraPlatform.module_fragment(opts, index=1, cam=at(cameras, 6), position='front', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
+ CameraPlatform.module_fragment(opts, index=0, cam=at(cameras, 7), position='rear', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
]
tegra_camera_platform_fragments = sum(tegra_camera_platform_modules, [
- CameraPlatform.node_fragment(num_csi_lanes=TOTAL_CSI_LANES, max_lane_speed=2500000)
+ CameraPlatform.node_fragment(opts, num_csi_lanes=TOTAL_CSI_LANES, max_lane_speed=2500000)
])
- root = (devicetree.jetson_camera_overlay_root(opts.overlay_name)
+ (root
.nodes(vi_fragments)
.nodes(nvcsi_fragments)
.nodes(tegra_camera_platform_fragments)
@@ -203,13 +246,107 @@ def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
'reg = <0>',
'i2c-mux,deselect-on-exit',
])
- .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[6:8]), [])),
- ])
- .nodes(gmsl_dsers))
+ .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[6:8]), []))
+ ]))
return root
+def i2c_mux_and_gmsl_dsers(gmsl_dsers: Sequence[DeviceTreeNode]) -> List[FragmentNode]:
+ return ([
+ FragmentNode(target_path='/bus@0/i2c@31e0000')
+ .overlay_nodes([
+ DeviceTreeNode('tca9544@72')
+ .properties([
+ 'status = "okay"',
+ 'compatible = "nxp,pca9544"',
+ 'reg = <0x72>',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ 'vcc-supply = <&vdd_1v8_sys>',
+ 'vcc_lp = "vcc"',
+ 'skip_mux_detect = "yes"',
+ 'force_bus_start = <40>',
+ ])
+ .nodes([
+ DeviceTreeNode('i2c@0')
+ .properties([
+ 'status = "okay"',
+ 'reg = <0>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[0]
+ ]),
+ DeviceTreeNode('i2c@1')
+ .properties([
+ 'status = "okay"',
+ 'reg = <1>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[1]
+ ]),
+ DeviceTreeNode('i2c@2')
+ .properties([
+ 'status = "okay"',
+ 'reg = <2>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[2]
+ ]),
+ DeviceTreeNode('i2c@3')
+ .properties([
+ 'status = "okay"',
+ 'reg = <3>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[3]
+ ]),
+ ])
+ ]),
+ FragmentNode(target_path='/bus@0/i2c@3180000')
+ .overlay_properties([
+ 'status = "okay"',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .overlay_nodes([
+ DeviceTreeNode('tca9539@74', label='tca9539_74')
+ .properties([
+ 'compatible = "ti,tca9539"',
+ 'gpio-controller',
+ '#gpio-cells = <2>',
+ 'ngpios = <16>',
+ 'reg = <0x74>',
+ 'status = "okay"',
+ ])
+ .nodes([
+ DeviceTreeNode('tca9539_74_outlow')
+ .properties([
+ 'status = "okay"',
+ 'gpio-hog',
+ 'output-low',
+ ]),
+ DeviceTreeNode('ca9539_74_outhigh')
+ .properties(['status = "disabled"']),
+ DeviceTreeNode('tca9539_74_input')
+ .properties(['status = "disabled"']),
+ ])
+ ])
+ ])
+
+
if __name__ == '__main__':
help_desc = 'The Jetson camera devicetree overlay generator for Connect Tech Anvil.'
@@ -219,8 +356,8 @@ def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
print(f'Error: {e}', file=sys.stderr)
sys.exit(1)
- if opts.l4t_version.major != 35:
- print(f'Error: {sys.argv[0]} only supports major version R35', file=sys.stderr)
+ if not 35 <= opts.l4t_version.major <= 36:
+ print(f'Error: {sys.argv[0]} only supports major version R35 and R36', file=sys.stderr)
sys.exit(1)
camera_overlay = generate_jetson_camera_overlay(opts)
diff --git a/drivers/src/make_overlay_dts_eac-5000.py b/tools/dts_generator/make_overlay_dts_eac-5000.py
similarity index 100%
rename from drivers/src/make_overlay_dts_eac-5000.py
rename to tools/dts_generator/make_overlay_dts_eac-5000.py
diff --git a/tools/dts_generator/make_overlay_dts_orin-devkit-r36.py b/tools/dts_generator/make_overlay_dts_orin-devkit-r36.py
new file mode 100755
index 0000000..7428492
--- /dev/null
+++ b/tools/dts_generator/make_overlay_dts_orin-devkit-r36.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python3
+"""
+Jetson camera devicetree overlay generator for Jetson AGX Orin Developer Kit.
+"""
+
+import sys
+from typing import Dict, Iterable, List, Optional, Sequence, TypeVar
+
+from dts_generator import camera
+from dts_generator import const
+from dts_generator import devicetree
+from dts_generator import gmsl
+from dts_generator import tegra_nvcsi
+from dts_generator import tegra_vi
+from dts_generator.devicetree import DeviceTreeNode, FragmentNode
+from dts_generator.media_graph import MediaGraph
+from dts_generator.options import GeneratorOptions
+from dts_generator.tegra_nvcsi import NvcsiChannel
+from dts_generator.tegra_vi import CameraPlatform, ViPort
+
+PLATFORM_NAME: str = 'orin-devkit'
+TEGRA_CAMERA_BASE_OVERLAY_R36: str = 'dtsi/tegra-camera-base-r36.dtsi'
+
+CSI_LANES: int = 4
+NUM_GMSL_DESERIALIZERS: int = 4
+TOTAL_CSI_LANES: int = CSI_LANES * NUM_GMSL_DESERIALIZERS
+
+PIXEL_CLOCK: int = 350000000
+
+
+def build_cameras(camera_list: Iterable[camera.Type], gmsl_dsers: Iterable[DeviceTreeNode]) -> List[camera.Camera]:
+ def get_label(node: DeviceTreeNode) -> str:
+ label = node.target_label if isinstance(node, FragmentNode) else node.node_label
+ if label is None:
+ raise ValueError('A GMSL deserializer node has no label')
+ return label
+
+ dser_label = list(filter(None, [get_label(gmsl_dser) for gmsl_dser in gmsl_dsers]))
+ assert len(dser_label) >= 4
+
+ c1_cameras = [
+ camera.C1(index=0, suffix='a', address='1b', vc_id='0', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='a', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C1(index=1, suffix='b', address='1c', vc_id='1', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='b', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C1(index=2, suffix='c', address='1b', vc_id='0', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='a', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C1(index=3, suffix='d', address='1c', vc_id='1', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='b', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C1(index=4, suffix='e', address='1b', vc_id='0', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='a', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C1(index=5, suffix='f', address='1c', vc_id='1', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='b', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C1(index=6, suffix='g', address='1b', vc_id='0', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='a', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C1(index=7, suffix='h', address='1c', vc_id='1', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='b', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ ]
+
+ c2_cameras = [
+ camera.C2(index=0, suffix='a', address='2b', vc_id='0', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='a', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C2(index=1, suffix='b', address='2c', vc_id='1', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='b', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C2(index=2, suffix='c', address='2b', vc_id='0', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='a', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C2(index=3, suffix='d', address='2c', vc_id='1', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='b', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C2(index=4, suffix='e', address='2b', vc_id='0', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='a', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C2(index=5, suffix='f', address='2c', vc_id='1', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='b', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C2(index=6, suffix='g', address='2b', vc_id='0', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='a', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C2(index=7, suffix='h', address='2c', vc_id='1', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='b', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ ]
+
+ c3_cameras = [
+ camera.C3(index=0, suffix='a', address='3b', vc_id='0', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='a', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C3(index=1, suffix='b', address='3c', vc_id='1', csi_lanes=CSI_LANES, port_index=0, serdes_csi_link='b', dser_label=dser_label[0], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C3(index=2, suffix='c', address='3b', vc_id='0', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='a', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C3(index=3, suffix='d', address='3c', vc_id='1', csi_lanes=CSI_LANES, port_index=2, serdes_csi_link='b', dser_label=dser_label[1], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C3(index=4, suffix='e', address='3b', vc_id='0', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='a', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C3(index=5, suffix='f', address='3c', vc_id='1', csi_lanes=CSI_LANES, port_index=4, serdes_csi_link='b', dser_label=dser_label[2], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ camera.C3(index=6, suffix='g', address='3b', vc_id='0', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='a', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=True),
+ camera.C3(index=7, suffix='h', address='3c', vc_id='1', csi_lanes=CSI_LANES, port_index=6, serdes_csi_link='b', dser_label=dser_label[3], serdes_pix_clk_hz=PIXEL_CLOCK, primary=False),
+ ]
+
+ cameras_map: Dict[camera.Type, Sequence[camera.Camera]] = {
+ camera.Type.C1: c1_cameras,
+ camera.Type.C2: c2_cameras,
+ camera.Type.C3: c3_cameras,
+ }
+
+ return [cameras_map[cam_type][i] for i, cam_type in enumerate(camera_list)]
+
+
+T = TypeVar('T')
+
+
+def at(lst: Sequence[T], index: int) -> Optional[T]:
+ return lst[index] if index < len(lst) else None
+
+
+gmsl_dsers_nodes = [
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dsera')
+ .properties([
+ f'reset-gpios = <&gpio 0x3b {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserb')
+ .properties([
+ f'reset-gpios = <&gpio 0x3e {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserc')
+ .properties([
+ f'reset-gpios = <&gpio 0xa2 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+ gmsl.Deserializer.node(name='max9296', csi_lanes=CSI_LANES, label='dserd')
+ .properties([
+ f'reset-gpios = <&gpio 0xa0 {const.GPIO_ACTIVE_HIGH}>'
+ ]),
+]
+
+
+def generate_jetson_camera_overlay(opts: GeneratorOptions) -> DeviceTreeNode:
+ num_channels = opts.number_of_cameras
+
+ vi_node_fragment = tegra_vi.create_vi_node_fragment(opts) \
+ .overlay_properties([f'num-channels = <{num_channels}>'])
+ vi_ports = [
+ ViPort(opts, port_number=0, port_index=0, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=1, port_index=0, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=2, port_index=2, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=3, port_index=2, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=4, port_index=4, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=5, port_index=4, vc_id=1, bus_width=CSI_LANES),
+ ViPort(opts, port_number=6, port_index=5, vc_id=0, bus_width=CSI_LANES),
+ ViPort(opts, port_number=7, port_index=5, vc_id=1, bus_width=CSI_LANES),
+ ][:num_channels]
+ vi_fragments = sum(map(ViPort.to_list, vi_ports), [vi_node_fragment])
+
+ nvcsi_node_fragment = tegra_nvcsi.create_nvcsi_node_fragment(opts) \
+ .overlay_properties([f'num-channels = <{num_channels}>'])
+ nvcsi_channels = [
+ NvcsiChannel(opts, channel_index=0, port_index=0, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=1, port_index=0, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=2, port_index=2, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=3, port_index=2, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=4, port_index=4, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=5, port_index=4, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=6, port_index=6, bus_width=CSI_LANES),
+ NvcsiChannel(opts, channel_index=7, port_index=6, bus_width=CSI_LANES),
+ ][:num_channels]
+ nvcsi_fragments = sum(map(NvcsiChannel.to_list, nvcsi_channels), [nvcsi_node_fragment])
+
+ root = devicetree.jetson_camera_overlay_root(opts.overlay_name)
+
+ i2c_bus_number: int = 0x28
+ i2c_mux_path = '/i2c@3180000/tca9546@70'
+ gmsl_dsers: Sequence[DeviceTreeNode] = gmsl_dsers_nodes
+
+ if opts.l4t_version.major >= 36:
+ i2c_mux_path = '/bus@0' + i2c_mux_path
+ with open(TEGRA_CAMERA_BASE_OVERLAY_R36, 'r', encoding='utf-8') as tegra_cam_dtsi:
+ (root
+ .header('\n' + tegra_cam_dtsi.read())
+ .nodes(i2c_mux_and_gmsl_dsers(gmsl_dsers)))
+ else:
+ root.nodes(gmsl_dsers)
+
+ cameras = build_cameras(opts.camera_list, gmsl_dsers)
+
+ graph = MediaGraph(vi_ports, nvcsi_channels, cameras)
+ graph.connect_all_endpoints()
+
+ tegra_camera_platform_modules = [
+ CameraPlatform.module_fragment(opts, index=0, cam=at(cameras, 0), position='rear', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
+ CameraPlatform.module_fragment(opts, index=1, cam=at(cameras, 1), position='front', i2c_bus_number=i2c_bus_number + 0, i2c_bus_path=f'{i2c_mux_path}/i2c@0'),
+ CameraPlatform.module_fragment(opts, index=2, cam=at(cameras, 2), position='left', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
+ CameraPlatform.module_fragment(opts, index=3, cam=at(cameras, 3), position='right', i2c_bus_number=i2c_bus_number + 1, i2c_bus_path=f'{i2c_mux_path}/i2c@1'),
+ CameraPlatform.module_fragment(opts, index=4, cam=at(cameras, 4), position='left2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
+ CameraPlatform.module_fragment(opts, index=5, cam=at(cameras, 5), position='right2', i2c_bus_number=i2c_bus_number + 2, i2c_bus_path=f'{i2c_mux_path}/i2c@2'),
+ CameraPlatform.module_fragment(opts, index=6, cam=at(cameras, 6), position='top', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
+ CameraPlatform.module_fragment(opts, index=7, cam=at(cameras, 7), position='bottom', i2c_bus_number=i2c_bus_number + 3, i2c_bus_path=f'{i2c_mux_path}/i2c@3'),
+ ]
+ tegra_camera_platform_fragments = sum(tegra_camera_platform_modules, [
+ CameraPlatform.node_fragment(opts, num_csi_lanes=TOTAL_CSI_LANES, max_lane_speed=2500000)
+ ])
+
+ (root
+ .nodes(vi_fragments)
+ .nodes(nvcsi_fragments)
+ .nodes(tegra_camera_platform_fragments)
+ .nodes([
+ FragmentNode(target_path='/')
+ .overlay_properties([
+ # string list of all the connected cameras
+ 'tier4,cameras = %s' % devicetree.string_list([cam.name for cam in opts.camera_list]),
+ ]),
+
+ FragmentNode(target_path=i2c_mux_path)
+ .overlay_properties([
+ 'status = "okay"',
+ 'compatible = "nxp,pca9546"',
+ 'reg = <0x70>',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ 'vcc-supply = <&vdd_1v8_sys>',
+ 'skip_mux_detect',
+ f'force_bus_start = <{i2c_bus_number}>',
+ ]),
+ FragmentNode(target_path=f'{i2c_mux_path}/i2c@0')
+ .overlay_properties([
+ 'status = "okay"',
+ 'reg = <3>',
+ 'i2c-mux,deselect-on-exit',
+ ])
+ .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[0:2]), [])),
+ FragmentNode(target_path=f'{i2c_mux_path}/i2c@1')
+ .overlay_properties([
+ 'status = "okay"',
+ 'reg = <2>',
+ 'i2c-mux,deselect-on-exit',
+ ])
+ .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[2:4]), [])),
+ FragmentNode(target_path=f'{i2c_mux_path}/i2c@2')
+ .overlay_properties([
+ 'status = "okay"',
+ 'reg = <1>',
+ 'i2c-mux,deselect-on-exit',
+ ])
+ .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[4:6]), [])),
+ FragmentNode(target_path=f'{i2c_mux_path}/i2c@3')
+ .overlay_properties([
+ 'status = "okay"',
+ 'reg = <0>',
+ 'i2c-mux,deselect-on-exit',
+ ])
+ .overlay_nodes(sum(map(lambda cam: cam.to_list(), cameras[6:8]), []))
+ ]))
+
+ return root
+
+
+def i2c_mux_and_gmsl_dsers(gmsl_dsers: Sequence[DeviceTreeNode]) -> List[FragmentNode]:
+ return ([
+ FragmentNode(target_path='/bus@0/i2c@3180000')
+ .overlay_nodes([
+ DeviceTreeNode('tca9546@70')
+ .properties([
+ 'status = "okay"',
+ 'compatible = "nxp,pca9546"',
+ 'reg = <0x70>',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ 'vcc-supply = <&vdd_1v8_sys>',
+ 'vcc_lp = "vcc"',
+ 'skip_mux_detect = "yes"',
+ 'force_bus_start = <40>',
+ ])
+ .nodes([
+ DeviceTreeNode('i2c@0')
+ .properties([
+ 'status = "okay"',
+ 'reg = <0>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[0]
+ ]),
+ DeviceTreeNode('i2c@1')
+ .properties([
+ 'status = "okay"',
+ 'reg = <1>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[1]
+ ]),
+ DeviceTreeNode('i2c@2')
+ .properties([
+ 'status = "okay"',
+ 'reg = <2>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[2]
+ ]),
+ DeviceTreeNode('i2c@3')
+ .properties([
+ 'status = "okay"',
+ 'reg = <3>',
+ 'i2c-mux,deselect-on-exit',
+ '#address-cells = <1>',
+ '#size-cells = <0>',
+ ])
+ .nodes([
+ gmsl_dsers[3]
+ ]),
+ ])
+ ]),
+ FragmentNode(target_path='/bus@0/gpio@2200000')
+ .overlay_nodes([
+ DeviceTreeNode('camera-control-input')
+ .properties([
+ 'status = "disabled"',
+ ]),
+ DeviceTreeNode('camera-control-output-low')
+ .properties([
+ 'status = "okay"',
+ ])
+ ])
+ ])
+
+
+if __name__ == '__main__':
+ help_desc = 'The Jetson camera devicetree overlay generator for Jetson AGX Orin Developer Kit.'
+
+ try:
+ opts = GeneratorOptions.parse_args(description=help_desc)
+ except ValueError as e:
+ print(f'Error: {e}', file=sys.stderr)
+ sys.exit(1)
+
+ if not 35 <= opts.l4t_version.major <= 36:
+ print(f'Error: {sys.argv[0]} only supports major version R35 and R36', file=sys.stderr)
+ sys.exit(1)
+
+ camera_overlay = generate_jetson_camera_overlay(opts)
+
+ output_path = opts.get_overlay_output_path(PLATFORM_NAME)
+ if output_path == '-':
+ print(camera_overlay, end='')
+ else:
+ with open(output_path, 'w', encoding='utf-8') as overlay_dts_file:
+ print(camera_overlay, end='', file=overlay_dts_file)
diff --git a/drivers/src/make_overlay_dts_orin-devkit.py b/tools/dts_generator/make_overlay_dts_orin-devkit.py
similarity index 100%
rename from drivers/src/make_overlay_dts_orin-devkit.py
rename to tools/dts_generator/make_overlay_dts_orin-devkit.py
diff --git a/drivers/src/make_overlay_dts_roscube-orin.py b/tools/dts_generator/make_overlay_dts_roscube-orin.py
similarity index 100%
rename from drivers/src/make_overlay_dts_roscube-orin.py
rename to tools/dts_generator/make_overlay_dts_roscube-orin.py
diff --git a/drivers/src/make_overlay_dts_roscube.py b/tools/dts_generator/make_overlay_dts_roscube.py
similarity index 100%
rename from drivers/src/make_overlay_dts_roscube.py
rename to tools/dts_generator/make_overlay_dts_roscube.py
diff --git a/drivers/src/make_overlay_dts_xavier-devkit.py b/tools/dts_generator/make_overlay_dts_xavier-devkit.py
similarity index 100%
rename from drivers/src/make_overlay_dts_xavier-devkit.py
rename to tools/dts_generator/make_overlay_dts_xavier-devkit.py
diff --git a/tools/dts_generator/tier4-imx490-gmsl-device-tree-overlay-anvil-r36.dts b/tools/dts_generator/tier4-imx490-gmsl-device-tree-overlay-anvil-r36.dts
new file mode 100644
index 0000000..2ea0cb0
--- /dev/null
+++ b/tools/dts_generator/tier4-imx490-gmsl-device-tree-overlay-anvil-r36.dts
@@ -0,0 +1,2192 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+ overlay-name = "TIERIV GMSL2 Camera Device Tree Overlay: C2x8";
+ jetson-header-name = "Jetson AGX CSI Connector";
+ compatible = "nvidia,p2822-0000+p2888-0001", "nvidia,p3509-0000+p3668-0001", "nvidia,p3737-0000+p3701-0000", "nvidia,p3737-0000+p3701-0000", "nvidia,p3737-0000+p3701-0004", "nvidia,p3737-0000+p3701-0005", "nvidia,tegra234", "nvidia,tegra23x";
+
+ fragment@1 {
+ target-path = "/tegra-capture-vi";
+
+ __overlay__ {
+ status = "okay";
+ num-channels = <8>;
+ };
+ };
+
+ fragment@2 {
+ target-path = "/tegra-capture-vi/ports/port@7";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@3 {
+ target-path = "/tegra-capture-vi/ports/port@7/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ vc-id = <1>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out7>;
+ };
+ };
+
+ fragment@4 {
+ target-path = "/tegra-capture-vi/ports/port@6";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@5 {
+ target-path = "/tegra-capture-vi/ports/port@6/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ vc-id = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out6>;
+ };
+ };
+
+ fragment@6 {
+ target-path = "/tegra-capture-vi/ports/port@5";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@7 {
+ target-path = "/tegra-capture-vi/ports/port@5/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ vc-id = <1>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out5>;
+ };
+ };
+
+ fragment@8 {
+ target-path = "/tegra-capture-vi/ports/port@4";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@9 {
+ target-path = "/tegra-capture-vi/ports/port@4/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ vc-id = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out4>;
+ };
+ };
+
+ fragment@10 {
+ target-path = "/tegra-capture-vi/ports/port@3";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@11 {
+ target-path = "/tegra-capture-vi/ports/port@3/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ vc-id = <1>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out3>;
+ };
+ };
+
+ fragment@12 {
+ target-path = "/tegra-capture-vi/ports/port@2";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@13 {
+ target-path = "/tegra-capture-vi/ports/port@2/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ vc-id = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out2>;
+ };
+ };
+
+ fragment@14 {
+ target-path = "/tegra-capture-vi/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@15 {
+ target-path = "/tegra-capture-vi/ports/port@1/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <5>;
+ vc-id = <1>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out1>;
+ };
+ };
+
+ fragment@16 {
+ target-path = "/tegra-capture-vi/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@17 {
+ target-path = "/tegra-capture-vi/ports/port@0/endpoint";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <5>;
+ vc-id = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_out0>;
+ };
+ };
+
+ fragment@18 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000";
+
+ __overlay__ {
+ status = "okay";
+ num-channels = <8>;
+ };
+ };
+
+ fragment@19 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@7";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@20 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@7/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@21 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@7/ports/port@0/endpoint@14";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out7>;
+ };
+ };
+
+ fragment@22 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@7/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@23 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@7/ports/port@1/endpoint@15";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in7>;
+ };
+ };
+
+ fragment@24 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@6";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@25 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@6/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@26 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@6/ports/port@0/endpoint@12";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out6>;
+ };
+ };
+
+ fragment@27 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@6/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@28 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@6/ports/port@1/endpoint@13";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in6>;
+ };
+ };
+
+ fragment@29 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@5";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@30 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@5/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@31 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@5/ports/port@0/endpoint@10";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out5>;
+ };
+ };
+
+ fragment@32 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@5/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@33 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@5/ports/port@1/endpoint@11";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in5>;
+ };
+ };
+
+ fragment@34 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@4";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@35 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@4/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@36 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@4/ports/port@0/endpoint@8";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out4>;
+ };
+ };
+
+ fragment@37 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@4/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@38 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@4/ports/port@1/endpoint@9";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in4>;
+ };
+ };
+
+ fragment@39 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@3";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@40 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@3/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@41 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@3/ports/port@0/endpoint@6";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out3>;
+ };
+ };
+
+ fragment@42 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@3/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@43 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@3/ports/port@1/endpoint@7";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in3>;
+ };
+ };
+
+ fragment@44 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@2";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@45 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@2/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@46 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@2/ports/port@0/endpoint@4";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out2>;
+ };
+ };
+
+ fragment@47 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@2/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@48 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@2/ports/port@1/endpoint@5";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in2>;
+ };
+ };
+
+ fragment@49 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@50 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@1/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@51 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@1/ports/port@0/endpoint@2";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out1>;
+ };
+ };
+
+ fragment@52 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@1/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@53 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@1/ports/port@1/endpoint@3";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in1>;
+ };
+ };
+
+ fragment@54 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@55 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@0";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@56 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@0/endpoint@0";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&cam_out0>;
+ };
+ };
+
+ fragment@57 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@1";
+
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ fragment@58 {
+ target-path = "/bus@0/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@1/endpoint@1";
+
+ __overlay__ {
+ status = "okay";
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&vi_in0>;
+ };
+ };
+
+ fragment@79 {
+ target-path = "/tegra-camera-platform";
+
+ __overlay__ {
+ status = "okay";
+ num_csi_lanes = <16>;
+ max_lane_speed = <2500000>;
+ min_bits_per_pixel = <10>;
+ vi_peak_byte_per_pixel = <2>;
+ vi_bw_margin_pct = <25>;
+ isp_peak_byte_per_pixel = <5>;
+ isp_bw_margin_pct = <25>;
+ };
+ };
+
+ fragment@63 {
+ target-path = "/tegra-camera-platform/modules/module7";
+
+ __overlay__ {
+ badge = "imx490_bottom";
+ position = "bottom";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@64 {
+ target-path = "/tegra-camera-platform/modules/module7/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 43-002c";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@3/imx490_a@2c";
+ };
+ };
+
+ fragment@65 {
+ target-path = "/tegra-camera-platform/modules/module6";
+
+ __overlay__ {
+ badge = "imx490_top";
+ position = "top";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@66 {
+ target-path = "/tegra-camera-platform/modules/module6/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 43-002b";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@3/imx490_b@2b";
+ };
+ };
+
+ fragment@67 {
+ target-path = "/tegra-camera-platform/modules/module5";
+
+ __overlay__ {
+ badge = "imx490_right2";
+ position = "right2";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@68 {
+ target-path = "/tegra-camera-platform/modules/module5/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 42-002c";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@2/imx490_c@2c";
+ };
+ };
+
+ fragment@69 {
+ target-path = "/tegra-camera-platform/modules/module4";
+
+ __overlay__ {
+ badge = "imx490_left2";
+ position = "left2";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@70 {
+ target-path = "/tegra-camera-platform/modules/module4/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 42-002b";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@2/imx490_d@2b";
+ };
+ };
+
+ fragment@71 {
+ target-path = "/tegra-camera-platform/modules/module3";
+
+ __overlay__ {
+ badge = "imx490_right";
+ position = "right";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@72 {
+ target-path = "/tegra-camera-platform/modules/module3/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 41-002c";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@1/imx490_e@2c";
+ };
+ };
+
+ fragment@73 {
+ target-path = "/tegra-camera-platform/modules/module2";
+
+ __overlay__ {
+ badge = "imx490_left";
+ position = "left";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@74 {
+ target-path = "/tegra-camera-platform/modules/module2/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 41-002b";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@1/imx490_f@2b";
+ };
+ };
+
+ fragment@75 {
+ target-path = "/tegra-camera-platform/modules/module1";
+
+ __overlay__ {
+ badge = "imx490_front";
+ position = "front";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@76 {
+ target-path = "/tegra-camera-platform/modules/module1/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 40-002c";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@0/imx490_g@2c";
+ };
+ };
+
+ fragment@77 {
+ target-path = "/tegra-camera-platform/modules/module0";
+
+ __overlay__ {
+ badge = "imx490_rear";
+ position = "rear";
+ orientation = "1";
+ status = "okay";
+ };
+ };
+
+ fragment@78 {
+ target-path = "/tegra-camera-platform/modules/module0/drivernode0";
+
+ __overlay__ {
+ status = "okay";
+ pcl_id = "v4l2_sensor";
+ devname = "imx490 40-002b";
+ proc-device-tree = "/proc/device-tree/bus@0/i2c@31e0000/tca9544@72/i2c@0/imx490_h@2b";
+ };
+ };
+
+ fragment@80 {
+ target-path = "/";
+
+ __overlay__ {
+ tier4,cameras = "C2", "C2", "C2", "C2", "C2", "C2", "C2", "C2";
+ };
+ };
+
+ fragment@81 {
+ target-path = "/bus@0/i2c@31e0000/tca9544@72";
+
+ __overlay__ {
+ status = "okay";
+ compatible = "nxp,pca9544";
+ reg = <0x72>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vcc-supply = <&vdd_1v8_sys>;
+ skip_mux_detect;
+ force_bus_start = <40>;
+ };
+ };
+
+ fragment@82 {
+ target-path = "/bus@0/i2c@31e0000/tca9544@72/i2c@3";
+
+ __overlay__ {
+ status = "okay";
+ reg = <3>;
+ i2c-mux,deselect-on-exit;
+
+ ser7_b: max9295_a@60 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x60>;
+ nvidia,gmsl-dser-device = <&dserd>;
+ vc-id = <1>;
+ };
+
+ isp7_b: gw5300_a@6f {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6f>;
+ };
+
+ imx490_a@2c {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2c>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp7_b>;
+ nvidia,gmsl-ser-device = <&ser7_b>;
+ nvidia,gmsl-dser-device = <&dserd>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <3>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out7: endpoint {
+ vc-id = <1>;
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in7>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "b";
+ csi-mode = "1x4";
+ st-vc = <1>;
+ vc-id = <1>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+
+ ser6_prim: max9295_prim@62 {
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x62>;
+ is-prim-ser;
+ status = "okay";
+ };
+
+ ser6_a: max9295_b@42 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x42>;
+ nvidia,gmsl-dser-device = <&dserd>;
+ vc-id = <0>;
+ };
+
+ isp6_prim: gw5300_prim@6d {
+ status = "okay";
+ compatible = "nvidia,tier4_gw5300";
+ reg = <0x6d>;
+ is-prim-isp;
+ };
+
+ isp6_a: gw5300_b@6e {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6e>;
+ };
+
+ imx490_b@2b {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2b>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp6_a>;
+ nvidia,gmsl-ser-device = <&ser6_a>;
+ nvidia,gmsl-dser-device = <&dserd>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <3>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out6: endpoint {
+ vc-id = <0>;
+ port-index = <0>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in6>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "a";
+ csi-mode = "1x4";
+ st-vc = <0>;
+ vc-id = <0>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+ };
+ };
+
+ fragment@83 {
+ target-path = "/bus@0/i2c@31e0000/tca9544@72/i2c@2";
+
+ __overlay__ {
+ status = "okay";
+ reg = <2>;
+ i2c-mux,deselect-on-exit;
+
+ ser5_b: max9295_c@60 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x60>;
+ nvidia,gmsl-dser-device = <&dserc>;
+ vc-id = <1>;
+ };
+
+ isp5_b: gw5300_c@6f {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6f>;
+ };
+
+ imx490_c@2c {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2c>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp5_b>;
+ nvidia,gmsl-ser-device = <&ser5_b>;
+ nvidia,gmsl-dser-device = <&dserc>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <2>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out5: endpoint {
+ vc-id = <1>;
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in5>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "b";
+ csi-mode = "1x4";
+ st-vc = <1>;
+ vc-id = <1>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+
+ ser4_prim: max9295_prim@62 {
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x62>;
+ is-prim-ser;
+ status = "okay";
+ };
+
+ ser4_a: max9295_d@42 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x42>;
+ nvidia,gmsl-dser-device = <&dserc>;
+ vc-id = <0>;
+ };
+
+ isp4_prim: gw5300_prim@6d {
+ status = "okay";
+ compatible = "nvidia,tier4_gw5300";
+ reg = <0x6d>;
+ is-prim-isp;
+ };
+
+ isp4_a: gw5300_d@6e {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6e>;
+ };
+
+ imx490_d@2b {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2b>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp4_a>;
+ nvidia,gmsl-ser-device = <&ser4_a>;
+ nvidia,gmsl-dser-device = <&dserc>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <2>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out4: endpoint {
+ vc-id = <0>;
+ port-index = <2>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in4>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "a";
+ csi-mode = "1x4";
+ st-vc = <0>;
+ vc-id = <0>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+ };
+ };
+
+ fragment@84 {
+ target-path = "/bus@0/i2c@31e0000/tca9544@72/i2c@1";
+
+ __overlay__ {
+ status = "okay";
+ reg = <1>;
+ i2c-mux,deselect-on-exit;
+
+ ser3_b: max9295_e@60 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x60>;
+ nvidia,gmsl-dser-device = <&dserb>;
+ vc-id = <1>;
+ };
+
+ isp3_b: gw5300_e@6f {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6f>;
+ };
+
+ imx490_e@2c {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2c>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp3_b>;
+ nvidia,gmsl-ser-device = <&ser3_b>;
+ nvidia,gmsl-dser-device = <&dserb>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <1>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out3: endpoint {
+ vc-id = <1>;
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in3>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "b";
+ csi-mode = "1x4";
+ st-vc = <1>;
+ vc-id = <1>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+
+ ser2_prim: max9295_prim@62 {
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x62>;
+ is-prim-ser;
+ status = "okay";
+ };
+
+ ser2_a: max9295_f@42 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x42>;
+ nvidia,gmsl-dser-device = <&dserb>;
+ vc-id = <0>;
+ };
+
+ isp2_prim: gw5300_prim@6d {
+ status = "okay";
+ compatible = "nvidia,tier4_gw5300";
+ reg = <0x6d>;
+ is-prim-isp;
+ };
+
+ isp2_a: gw5300_f@6e {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6e>;
+ };
+
+ imx490_f@2b {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2b>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp2_a>;
+ nvidia,gmsl-ser-device = <&ser2_a>;
+ nvidia,gmsl-dser-device = <&dserb>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <1>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out2: endpoint {
+ vc-id = <0>;
+ port-index = <4>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in2>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "a";
+ csi-mode = "1x4";
+ st-vc = <0>;
+ vc-id = <0>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+ };
+ };
+
+ fragment@85 {
+ target-path = "/bus@0/i2c@31e0000/tca9544@72/i2c@0";
+
+ __overlay__ {
+ status = "okay";
+ reg = <0>;
+ i2c-mux,deselect-on-exit;
+
+ ser1_b: max9295_g@60 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x60>;
+ nvidia,gmsl-dser-device = <&dsera>;
+ vc-id = <1>;
+ };
+
+ isp1_b: gw5300_g@6f {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6f>;
+ };
+
+ imx490_g@2c {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2c>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp1_b>;
+ nvidia,gmsl-ser-device = <&ser1_b>;
+ nvidia,gmsl-dser-device = <&dsera>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <0>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out1: endpoint {
+ vc-id = <1>;
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in1>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "b";
+ csi-mode = "1x4";
+ st-vc = <1>;
+ vc-id = <1>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+
+ ser0_prim: max9295_prim@62 {
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x62>;
+ is-prim-ser;
+ status = "okay";
+ };
+
+ ser0_a: max9295_h@42 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9295";
+ reg = <0x42>;
+ nvidia,gmsl-dser-device = <&dsera>;
+ vc-id = <0>;
+ };
+
+ isp0_prim: gw5300_prim@6d {
+ status = "okay";
+ compatible = "nvidia,tier4_gw5300";
+ reg = <0x6d>;
+ is-prim-isp;
+ };
+
+ isp0_a: gw5300_h@6e {
+ compatible = "nvidia,tier4_gw5300";
+ status = "okay";
+ reg = <0x6e>;
+ };
+
+ imx490_h@2b {
+ status = "okay";
+ compatible = "nvidia,tier4_imx490";
+ reg = <0x2b>;
+ def-addr = <0x1a>;
+ mclk = "extperiph1";
+ clocks = <&bpmp 36U>, <&bpmp 36U>;
+ clock-names = "extperiph1","pllp_grtba";
+ nvidia,isp-device = <&isp0_a>;
+ nvidia,gmsl-ser-device = <&ser0_a>;
+ nvidia,gmsl-dser-device = <&dsera>;
+ physical_w = "15.0";
+ physical_h = "12.5";
+ sensor_model = "imx490";
+ fsync-mode = "false";
+ distortion-correction = "false";
+ auto-exposure = "true";
+ post_crop_frame_drop = "0";
+ use_decibel_gain = "true";
+ use_sensor_mode_id = "true";
+ reg_mux = <0>;
+
+ /* mode IMX490_MODE_2880X1860_CROP_30FPS */
+ mode0 {
+ num_lanes = "4";
+ vc_id = "0";
+ tegra_sinterface = "serial_g";
+ mclk_khz = "24000";
+ discontinuous_clk = "no";
+ dpcm_enable = "false";
+ phy_mode = "DPHY";
+ cil_settletime = "0";
+ dynamic_pixel_bit_depth = "16";
+ csi_pixel_bit_depth = "16";
+ mode_type = "yuv";
+ pixel_phase = "uyvy";
+ active_w = "2880";
+ active_h = "1860";
+ readout_orientation = "0";
+ line_length = "2250";
+ inherent_gain = "1";
+ pix_clk_hz = "757";
+ serdes_pix_clk_hz = "350000000";
+ gain_factor = "10";
+ min_gain_val = "0";
+ max_gain_val = "300";
+ step_gain_val = "3";
+ default_gain = "0";
+ min_hdr_ratio = "1";
+ max_hdr_ratio = "1";
+ framerate_factor = "1000000";
+ min_framerate = "30000000";
+ max_framerate = "30000000";
+ step_framerate = "1";
+ default_framerate = "30000000";
+ exposure_factor = "1000000";
+ min_exp_time = "24";
+ max_exp_time = "33333";
+ step_exp_time = "1";
+ default_exp_time = "33333";
+ embedded_metadata_height = "0";
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ cam_out0: endpoint {
+ vc-id = <0>;
+ port-index = <6>;
+ bus-width = <4>;
+ remote-endpoint = <&csi_in0>;
+ };
+ };
+ };
+
+ gmsl-link {
+ src-csi-port = "b";
+ dst-csi-port = "a";
+ serdes-csi-link = "a";
+ csi-mode = "1x4";
+ st-vc = <0>;
+ vc-id = <0>;
+ num-lanes = <4>;
+ streams = "ued-u1","yuv8";
+ };
+ };
+ };
+ };
+
+ fragment@59 {
+ target = <&dsera>;
+
+ __overlay__ {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ reset-gpios = <&tca9539_74 0 0>;
+ };
+ };
+
+ fragment@60 {
+ target = <&dserb>;
+
+ __overlay__ {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ reset-gpios = <&tca9539_74 2 0>;
+ };
+ };
+
+ fragment@61 {
+ target = <&dserc>;
+
+ __overlay__ {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ reset-gpios = <&tca9539_74 4 0>;
+ };
+ };
+
+ fragment@62 {
+ target = <&dserd>;
+
+ __overlay__ {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ reset-gpios = <&tca9539_74 6 0>;
+ };
+ };
+
+ fragment@86 {
+ target-path = "/bus@0/i2c@31e0000/";
+
+ __overlay__ {
+
+ tca9544@72 {
+ status = "okay";
+ compatible = "nxp,pca9544";
+ reg = <0x72>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vcc-supply = <&vdd_1v8_sys>;
+ vcc_lp = "vcc";
+ skip_mux_detect = "yes";
+ force_bus_start = <40>;
+
+ i2c@0 {
+ status = "okay";
+ reg = <0>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsera: max9296@48 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ };
+ };
+
+ i2c@1 {
+ status = "okay";
+ reg = <1>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dserb: max9296@48 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ };
+ };
+
+ i2c@2 {
+ status = "okay";
+ reg = <2>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dserc: max9296@48 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ };
+ };
+
+ i2c@3 {
+ status = "okay";
+ reg = <3>;
+ i2c-mux,deselect-on-exit;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dserd: max9296@48 {
+ status = "okay";
+ compatible = "nvidia,tier4_max9296";
+ reg = <0x48>;
+ csi-mode = "2x4";
+ max-src = <2>;
+ clk-mhz = <2000>;
+ };
+ };
+ };
+ };
+ };
+
+ fragment@87 {
+ target-path = "/bus@0/i2c@3180000";
+
+ __overlay__ {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tca9539_74: tca9539@74 {
+ compatible = "ti,tca9539";
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <16>;
+ reg = <0x74>;
+ status = "okay";
+
+ tca9539_74_outlow {
+ status = "okay";
+ gpio-hog;
+ output-low;
+ };
+
+ ca9539_74_outhigh {
+ status = "disabled";
+ };
+
+ tca9539_74_input {
+ status = "disabled";
+ };
+ };
+ };
+ };
+};
+
+/* Generated by TIER IV camera devicetree overlay generation script */
+
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+/ {
+ fragment-camera-module@0 {
+ target-path = "/";
+ __overlay__ {
+ /* all cameras are disabled by default */
+ capture_vi_base: tegra-capture-vi {
+ ports {
+ vi_port0: port@0 {
+ status = "disabled";
+ vi_in0: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port1: port@1 {
+ status = "disabled";
+ vi_in1: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port2: port@2 {
+ status = "disabled";
+ vi_in2: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port3: port@3 {
+ status = "disabled";
+ vi_in3: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port4: port@4 {
+ status = "disabled";
+ vi_in4: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port5: port@5 {
+ status = "disabled";
+ vi_in5: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port6: port@6 {
+ status = "disabled";
+ vi_in6: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ vi_port7: port@7 {
+ status = "disabled";
+ vi_in7: endpoint {
+ vc-id = <0>;
+ status = "disabled";
+ };
+ };
+ };
+ };
+
+ tcp: tegra-camera-platform {
+ compatible = "nvidia, tegra-camera-platform";
+ /**
+ * tpg_max_iso = <>;
+ * Max iso bw for 6 streams of tpg
+ * streams * nvcsi_freq * PG_bitrate / RG10 * BPP
+ * 6 * 102Mhz * 32 bits/ 10 bits * 2 Bps
+ * = 3916.8 MBps
+ */
+ tpg_max_iso = <3916800>;
+ modules {
+ cam_module0: module0 {
+ status = "disabled";
+ cam_module0_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module0_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module1: module1 {
+ status = "disabled";
+ cam_module1_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module1_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module2: module2 {
+ status = "disabled";
+ cam_module2_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module2_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module3: module3 {
+ status = "disabled";
+ cam_module3_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module3_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module4: module4 {
+ status = "disabled";
+ cam_module4_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module4_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module5: module5 {
+ status = "disabled";
+ cam_module5_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module5_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module6: module6 {
+ status = "disabled";
+ cam_module6_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module6_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ cam_module7: module7 {
+ status = "disabled";
+ cam_module7_drivernode0: drivernode0 {
+ status = "disabled";
+ };
+ cam_module7_drivernode1: drivernode1 {
+ status = "disabled";
+ pcl_id = "v4l2_lens";
+ };
+ };
+ };
+ };
+
+ bus@0 {
+ host1x@13e00000 {
+ csi_base: nvcsi@15a00000 {
+ num-tpg-channels = <36>;
+ csi_chan0: channel@0 {
+ status = "disabled";
+ ports {
+ csi_chan0_port0: port@0 {
+ status = "disabled";
+ csi_in0: endpoint@0 {
+ status = "disabled";
+ };
+ };
+ csi_chan0_port1: port@1 {
+ status = "disabled";
+ csi_out0: endpoint@1 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan1: channel@1 {
+ status = "disabled";
+ ports {
+ csi_chan1_port0: port@0 {
+ status = "disabled";
+ csi_in1: endpoint@2 {
+ status = "disabled";
+ };
+ };
+ csi_chan1_port1: port@1 {
+ status = "disabled";
+ csi_out1: endpoint@3 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan2: channel@2 {
+ status = "disabled";
+ ports {
+ csi_chan2_port0: port@0 {
+ status = "disabled";
+ csi_in2: endpoint@4 {
+ status = "disabled";
+ };
+ };
+ csi_chan2_port1: port@1 {
+ status = "disabled";
+ csi_out2: endpoint@5 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan3: channel@3 {
+ status = "disabled";
+ ports {
+ csi_chan3_port0: port@0 {
+ status = "disabled";
+ csi_in3: endpoint@6 {
+ status = "disabled";
+ };
+ };
+ csi_chan3_port1: port@1 {
+ status = "disabled";
+ csi_out3: endpoint@7 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan4: channel@4 {
+ status = "disabled";
+ ports {
+ csi_chan4_port0: port@0 {
+ status = "disabled";
+ csi_in4: endpoint@8 {
+ status = "disabled";
+ };
+ };
+ csi_chan4_port1: port@1 {
+ status = "disabled";
+ csi_out4: endpoint@9 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan5: channel@5 {
+ status = "disabled";
+ ports {
+ csi_chan5_port0: port@0 {
+ status = "disabled";
+ csi_in5: endpoint@10 {
+ status = "disabled";
+ };
+ };
+ csi_chan5_port1: port@1 {
+ status = "disabled";
+ csi_out5: endpoint@11 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan6: channel@6 {
+ status = "disabled";
+ ports {
+ csi_chan6_port0: port@0 {
+ status = "disabled";
+ csi_in6: endpoint@10 {
+ status = "disabled";
+ };
+ };
+ csi_chan6_port1: port@1 {
+ status = "disabled";
+ csi_out6: endpoint@11 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ csi_chan7: channel@7 {
+ status = "disabled";
+ ports {
+ csi_chan7_port0: port@0 {
+ status = "disabled";
+ csi_in7: endpoint@10 {
+ status = "disabled";
+ };
+ };
+ csi_chan7_port1: port@1 {
+ status = "disabled";
+ csi_out7: endpoint@11 {
+ status = "disabled";
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+};