Compare commits
No commits in common. "master" and "jetpack-4.2.2" have entirely different histories.
master
...
jetpack-4.
114
README.md
114
README.md
|
@ -1,20 +1,34 @@
|
|||
# Leopard Imaging LI-M021C-MIPI Stereo-Optic Cameras
|
||||
|
||||
## Cameras setup
|
||||
The camera sensors should be conencted to a ConnectTech's Elroy board.
|
||||
## Kernel Changes
|
||||
The source code we have modified or added and is pertinent to these cameras is in the following files:
|
||||
* controls-utility.sh
|
||||
* hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-tx2-spiri-camera-base.dtsi
|
||||
* hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/tegra186-tx2-spiri-camera.dtsi
|
||||
* hardware/nvidia/platform/t18x/quill/kernel-dts/Makefile
|
||||
* hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-tx2-spiri-USB3.dts
|
||||
* hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-tx2-spiri-base.dts
|
||||
* hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-tx2-spiri-mPCIe.dts
|
||||
* hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-tx2-spiri-revF+.dts
|
||||
* nvidia/drivers/media/i2c/mt9m021.c
|
||||
* nvidia/drivers/media/i2c/mt9m021_mode_tbls.h
|
||||
* nvidia/drivers/media/platform/tegra/camera/camera_common.c
|
||||
* nvidia/drivers/media/platform/tegra/camera/tegracam_ctrls.c
|
||||
* nvidia/include/media/camera_common.h
|
||||
* nvidia/include/media/tegra-v4l2-camera.h
|
||||
|
||||
All these modifications and additions are part of the Spiri Mu kernel, and are represented by symbolic links from this repository into https://git.spirirobotics.com/Spiri/mu_kernel_sources, with the exception of the controls-utility.sh script, which is transferred in the spiri_scripts folder of the rootfs.
|
||||
|
||||
## Features
|
||||
|
||||
* V4L2 Kernel Driver Version 2.0 supported on L4T32.4.4
|
||||
* V4L2 Kernel Driver Version 2.0 supported on L4T32.2.1
|
||||
* V4l2 controls
|
||||
* test pattern
|
||||
* individual gains
|
||||
* vertical/horizontal flip
|
||||
* flash control
|
||||
* LibArgus and nvarguscamerasrc
|
||||
* Resolutions supported:
|
||||
* 1280x720 @ 60fps
|
||||
* 1280x960 @ 45fps
|
||||
* Resolution supported: 1280x720 @ 60fps
|
||||
* Gain, exposure, and framerate controls
|
||||
* Camera synchronization
|
||||
|
||||
|
@ -35,7 +49,7 @@ gst-launch-1.0 nvarguscamerasrc sensor-id=0 aelock=true awblock=true ! 'video/x-
|
|||
### UDP Streaming Test
|
||||
#### Sender Endpoint
|
||||
```
|
||||
gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! omxh264enc control-rate=2 bitrate=8000000 ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264pay mtu=1400 ! udpsink host=$HOST_IP port=5000 sync=false async=false
|
||||
gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)30/1' ! omxh264enc control-rate=2 bitrate=8000000 ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264pay mtu=1400 ! udpsink host=$HOST_IP port=5000 sync=false async=false
|
||||
```
|
||||
|
||||
#### Receiver Endpoint
|
||||
|
@ -73,92 +87,10 @@ v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=RG12 -
|
|||
|
||||
#### Slave
|
||||
```
|
||||
v4l2-ctl -d /dev/video1 --set-fmt-video=width=1280,height=720,pixelformat=RG12 --set-ctrl bypass_mode=0 --stream-mmap
|
||||
v4l2-ctl -d /dev/video01 --set-fmt-video=width=1280,height=720,pixelformat=RG12 --set-ctrl bypass_mode=0 --stream-mmap
|
||||
```
|
||||
|
||||
### AE Synchronized
|
||||
First run the master pipeline and then the slave pipeline:
|
||||
|
||||
#### Master Pipeline
|
||||
```
|
||||
gst-launch-1.0 nvarguscamerasrc sensor-id=1 ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! fakesink
|
||||
```
|
||||
|
||||
#### Slave Pipeline
|
||||
```
|
||||
gst-launch-1.0 nvarguscamerasrc sensor-id=0 aelock=true awblock=true ! 'video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, format=(string)NV12,framerate=(fraction)60/1' ! fakesink
|
||||
```
|
||||
|
||||
### Run script
|
||||
```
|
||||
./script_to_control_gain_exposure.sh &
|
||||
```
|
||||
|
||||
## Appends
|
||||
|
||||
#### Auto Exposure
|
||||
|
||||
The AE controls realays in the feedback provided by the Driver's camera sensor to the nvarguscamerasrc libraries,
|
||||
and the custom DTSIs with the sensor parameters definitions.
|
||||
As the AE has interdependency with the digital gain. This gain it's and operation on the Driver, and follows this setup:
|
||||
|
||||
MT9M021 sensor datasheet:
|
||||
|
||||
* <a href="https://files.niemo.de/aptina_pdfs/MT9M021-M031_Developer_Guide.pdf">MT9M021 Developer Guide</a>
|
||||
|
||||
|
||||
Where, the `min_gain_val, max_gain_val, step_gain_val` are part of the cameras' DTSI (tegra186-tx2-spiri-camera.dtsi) fixed parameters
|
||||
as per the datasheet. The `gain` consists on the steps (1x + n * 1/32 for the register) scaled to a value that represents this fraction in an integer value for the gain register.
|
||||
|
||||
#### Kernel Changes
|
||||
|
||||
The Driver for the MT9M021 cameras consists on the following structure, that adds the DTB and Kernel sources, along with its Makefiles that lead its portability to a Kernel source.
|
||||
```bash
|
||||
.
|
||||
├── hardware
|
||||
│ └── nvidia-spiri
|
||||
│ └── platform
|
||||
│ └── t18x
|
||||
│ ├── common
|
||||
│ │ └── kernel-dts
|
||||
│ │ └── t18x-common-platforms
|
||||
│ │ ├── tegra186-tx2-spiri-camera-base.dtsi
|
||||
│ │ └── tegra186-tx2-spiri-camera.dtsi
|
||||
│ └── quill
|
||||
│ └── kernel-dts
|
||||
│ ├── Makefile
|
||||
│ ├── tegra186-tx2-spiri-base.dts
|
||||
│ ├── tegra186-tx2-spiri-mPCIe.dts
|
||||
│ ├── tegra186-tx2-spiri-revF+.dts
|
||||
│ └── tegra186-tx2-spiri-USB3.dts
|
||||
├── kernel
|
||||
│ ├── kernel-4.9
|
||||
│ │ └── arch
|
||||
│ │ └── arm64
|
||||
│ │ └── configs
|
||||
│ │ └── tegra_defconfig
|
||||
│ └── nvidia-spiri
|
||||
│ ├── drivers
|
||||
│ │ └── media
|
||||
│ │ ├── i2c
|
||||
│ │ │ ├── Kconfig
|
||||
│ │ │ ├── Makefile
|
||||
│ │ │ ├── mt9m021.c
|
||||
│ │ │ └── mt9m021_mode_tbls.h
|
||||
│ └── include
|
||||
│ └── media
|
||||
│ └── mt9m021.h
|
||||
└── README.md
|
||||
```
|
||||
In order to add the Driver to the Kernel, the following reference Kernel files are patched for adding custom controls that the camera implements.
|
||||
|
||||
* kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c
|
||||
* kernel/nvidia/drivers/media/platform/tegra/camera/tegracam_ctrls.c
|
||||
* kernel/nvidia/include/media/camera_common.h
|
||||
* kernel/nvidia/include/media/tegra-v4l2-camera.h
|
||||
|
||||
|
||||
#### Documentation
|
||||
## Documentation
|
||||
* <a href="https://nextcloud.spirirobotics.com/f/3369">CSI2 adapter board guide</a>
|
||||
* <a href="https://nextcloud.spirirobotics.com/f/3382">Camera module data sheet</a>
|
||||
* <a href="https://nextcloud.spirirobotics.com/f/3392">Camera sensor data sheet</a>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/*Base include for cameras, sets up all the CSI and VI lanes etc,
|
||||
include this file in any baord specific camera files */
|
||||
|
||||
|
@ -19,26 +20,35 @@ include this file in any baord specific camera files */
|
|||
tpg_max_iso = <3916800>;
|
||||
};
|
||||
|
||||
// all cameras are disabled by default
|
||||
/* set camera gpio direction to output */
|
||||
/* gpio@2200000 {
|
||||
camera-control-output-low {
|
||||
gpio-hog;
|
||||
output-low;
|
||||
gpios = <CAM0_RST_L 0 CAM0_PWDN 0
|
||||
CAM1_RST_L 0 CAM1_PWDN 0>;
|
||||
label = "cam0-rst", "cam0-pwdn",
|
||||
"cam1-rst", "cam1-pwdn";
|
||||
};
|
||||
};*/
|
||||
|
||||
/* all cameras are disabled by default */
|
||||
host1x {
|
||||
vi_base: vi@15700000 {
|
||||
num-channels = <6>;
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
vi_port0: port@0 {
|
||||
status = "okay";
|
||||
reg = <0>;
|
||||
status = "disabled";
|
||||
vi_in0: endpoint {
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
vi_port1: port@1 {
|
||||
reg = <1>;
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
vi_in1: endpoint {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -71,10 +81,8 @@ include this file in any baord specific camera files */
|
|||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
csi_base: nvcsi@150c0000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -216,6 +224,97 @@ include this file in any baord specific camera files */
|
|||
};
|
||||
};
|
||||
|
||||
i2c@3180000 {
|
||||
e3326_cam0: ov5693_c@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3323_cam0: ov23850_a@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3323_vcm0: lc898212@72 {
|
||||
status = "disabled";
|
||||
};
|
||||
tca6408@21 {
|
||||
status = "disabled";
|
||||
};
|
||||
tca9548@77 {
|
||||
status = "disabled";
|
||||
i2c@0 {
|
||||
e3333_cam0: ov5693_a@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam0: imx219_a@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
i2c@1 {
|
||||
e3333_cam1: ov5693_b@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam1: imx219_b@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
i2c@2 {
|
||||
e3333_cam2: ov5693_c@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam2: imx219_c@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
i2c@3 {
|
||||
e3333_cam3: ov5693_d@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam3: imx219_d@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
i2c@4 {
|
||||
e3333_cam4: ov5693_e@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam4: imx219_e@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
i2c@5 {
|
||||
e3333_cam5: ov5693_f@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3322_cam5: imx219_f@10 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
tca9546_70: tca9546@70 {
|
||||
status = "disabled";
|
||||
i2c@0 {
|
||||
imx185_cam0: imx185_a@1a {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
tca9546_70: tca9546@70 {
|
||||
status = "disabled";
|
||||
i2c@0 {
|
||||
imx274_cam0: imx274_a@1a {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@c240000 {
|
||||
e3323_cam1: ov23850_c@36 {
|
||||
status = "disabled";
|
||||
};
|
||||
e3323_vcm1: lc898212@72 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
tcp: tegra-camera-platform {
|
||||
compatible = "nvidia, tegra-camera-platform";
|
||||
modules {
|
||||
|
|
|
@ -35,9 +35,7 @@ i2c7 = "/i2c@c250000";
|
|||
i2c8 = "/i2c@31e0000";
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
|
||||
gpio@2200000 {
|
||||
camera-control-output-low {
|
||||
gpio-hog;
|
||||
|
@ -47,7 +45,6 @@ i2c8 = "/i2c@31e0000";
|
|||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
i2c@c240000 {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
|
@ -56,27 +53,27 @@ i2c8 = "/i2c@31e0000";
|
|||
mt9m021_b@10 {
|
||||
compatible = "nvidia,mt9m021";
|
||||
|
||||
// I2C device address
|
||||
/* I2C device address */
|
||||
reg = <0x10>;
|
||||
|
||||
// Physical dimensions of sensor
|
||||
/* Physical dimensions of sensor */
|
||||
physical_w = "10";
|
||||
physical_h = "10";
|
||||
|
||||
// Sensor Model
|
||||
/* Sensor Model */
|
||||
sensor_model ="mt9m021";
|
||||
|
||||
// slave or master mode
|
||||
/* slave or master mode */
|
||||
trigger_mode = "slave";
|
||||
|
||||
// input clock for the device in MHz
|
||||
/* input clock for the device in MHz*/
|
||||
clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH2>,
|
||||
<&tegra_car TEGRA186_CLK_PLLP_OUT0>;
|
||||
clock-names = "extperiph2", "pllp_grtba";
|
||||
clock-frequency = <24000000>;
|
||||
mclk = "extperiph2";
|
||||
|
||||
// gpios
|
||||
/* gpios */
|
||||
reset-gpios = <&tegra_main_gpio CAM1_RST GPIO_ACTIVE_HIGH>;
|
||||
|
||||
mode0 {
|
||||
|
@ -98,73 +95,32 @@ i2c8 = "/i2c@31e0000";
|
|||
inherent_gain = "1";
|
||||
pix_clk_hz = "74250000";
|
||||
|
||||
gain_factor = "3125";
|
||||
gain_factor = "1";
|
||||
framerate_factor = "1000000";
|
||||
exposure_factor = "1000000";
|
||||
min_gain_val = "100000"; /* 1x */
|
||||
max_gain_val = "796875"; /* 7.97x */
|
||||
min_gain_val = "4";
|
||||
max_gain_val = "6476";
|
||||
step_gain_val = "1";
|
||||
default_gain = "100000"; /* 1x */
|
||||
default_gain = "100";
|
||||
min_hdr_ratio = "1";
|
||||
max_hdr_ratio = "1";
|
||||
|
||||
min_framerate = "2000000";
|
||||
max_framerate = "60000000";
|
||||
step_framerate = "1";
|
||||
default_framerate = "60000000"; // 60.0 fps
|
||||
default_framerate = "6000000"; /* 60.0 fps */
|
||||
|
||||
min_exp_time = "100"; // us
|
||||
max_exp_time = "16620"; // us
|
||||
min_exp_time = "23"; /* us */
|
||||
max_exp_time = "14933"; /* us */
|
||||
step_exp_time = "1";
|
||||
default_exp_time = "16620"; // us
|
||||
default_exp_time = "10000"; /* us */
|
||||
};
|
||||
mode1 {
|
||||
mclk_khz = "24000";
|
||||
num_lanes = "1";
|
||||
tegra_sinterface = "serial_b";
|
||||
discontinuous_clk = "no";
|
||||
dpcm_enable = "false";
|
||||
cil_settletime = "26";
|
||||
|
||||
active_w = "1280";
|
||||
active_h = "960";
|
||||
dynamic_pixel_bit_depth = "12";
|
||||
csi_pixel_bit_depth = "12";
|
||||
mode_type = "bayer";
|
||||
pixel_phase = "rggb";
|
||||
readout_orientation = "0";
|
||||
line_length = "1650";
|
||||
inherent_gain = "1";
|
||||
pix_clk_hz = "74250000";
|
||||
|
||||
gain_factor = "3125";
|
||||
framerate_factor = "1000000";
|
||||
exposure_factor = "1000000";
|
||||
min_gain_val = "100000"; /* 1x */
|
||||
max_gain_val = "796875"; /* 7.97x */
|
||||
step_gain_val = "1";
|
||||
default_gain = "100000"; /* 1x */
|
||||
min_hdr_ratio = "1";
|
||||
max_hdr_ratio = "1";
|
||||
|
||||
min_framerate = "2000000";
|
||||
max_framerate = "45000000";
|
||||
step_framerate = "1";
|
||||
default_framerate = "45000000"; // 45.0 fps
|
||||
|
||||
min_exp_time = "100"; // us
|
||||
max_exp_time = "22220"; // us
|
||||
step_exp_time = "1";
|
||||
default_exp_time = "22220"; // us
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0x0>;
|
||||
status = "okay";
|
||||
mt9m021_slave: endpoint {
|
||||
port-index = <0x1>;
|
||||
bus-width = <0x1>;
|
||||
|
@ -180,32 +136,32 @@ i2c8 = "/i2c@31e0000";
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
||||
mt9m021_a@10 {
|
||||
compatible = "nvidia,mt9m021";
|
||||
|
||||
// I2C device address
|
||||
/* I2C device address */
|
||||
reg = <0x10>;
|
||||
|
||||
// Physical dimensions of sensor
|
||||
/* Physical dimensions of sensor */
|
||||
physical_w = "10";
|
||||
physical_h = "10";
|
||||
|
||||
// Sensor Model /
|
||||
/* Sensor Model */
|
||||
sensor_model ="mt9m021";
|
||||
|
||||
// slave or master mode //
|
||||
/* slave or master mode */
|
||||
trigger_mode = "master";
|
||||
|
||||
// input clock for the device in MHz
|
||||
/* input clock for the device in MHz*/
|
||||
clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
|
||||
<&tegra_car TEGRA186_CLK_PLLP_OUT0>;
|
||||
clock-names = "extperiph1", "pllp_grtba";
|
||||
clock-frequency = <24000000>;
|
||||
mclk = "extperiph1";
|
||||
|
||||
// gpios
|
||||
/* gpios */
|
||||
reset-gpios = <&tegra_main_gpio CAM0_RST GPIO_ACTIVE_HIGH>;
|
||||
|
||||
mode0 {
|
||||
mclk_khz = "24000";
|
||||
num_lanes = "1";
|
||||
|
@ -225,64 +181,25 @@ i2c8 = "/i2c@31e0000";
|
|||
inherent_gain = "1";
|
||||
pix_clk_hz = "74250000";
|
||||
|
||||
gain_factor = "3125";
|
||||
gain_factor = "1";
|
||||
framerate_factor = "1000000";
|
||||
exposure_factor = "1000000";
|
||||
min_gain_val = "100000"; /* 1x */
|
||||
max_gain_val = "796875"; /* 7.97x */
|
||||
min_gain_val = "4";
|
||||
max_gain_val = "6476";
|
||||
step_gain_val = "1";
|
||||
default_gain = "100000"; /* 1x */
|
||||
default_gain = "100";
|
||||
min_hdr_ratio = "1";
|
||||
max_hdr_ratio = "1";
|
||||
|
||||
min_framerate = "2000000";
|
||||
max_framerate = "60000000";
|
||||
step_framerate = "1";
|
||||
default_framerate = "60000000"; // 60.0 fps
|
||||
default_framerate = "6000000"; /* 60.0 fps */
|
||||
|
||||
min_exp_time = "100"; // us
|
||||
max_exp_time = "16620"; // us
|
||||
min_exp_time = "23"; /* us */
|
||||
max_exp_time = "14933"; /* us */
|
||||
step_exp_time = "1";
|
||||
default_exp_time = "16620"; // us
|
||||
};
|
||||
mode1 {
|
||||
mclk_khz = "24000";
|
||||
num_lanes = "1";
|
||||
tegra_sinterface = "serial_a";
|
||||
discontinuous_clk = "no";
|
||||
dpcm_enable = "false";
|
||||
cil_settletime = "26";
|
||||
|
||||
active_w = "1280";
|
||||
active_h = "960";
|
||||
dynamic_pixel_bit_depth = "12";
|
||||
csi_pixel_bit_depth = "12";
|
||||
mode_type = "bayer";
|
||||
pixel_phase = "rggb";
|
||||
readout_orientation = "0";
|
||||
line_length = "1650";
|
||||
inherent_gain = "1";
|
||||
pix_clk_hz = "74250000";
|
||||
|
||||
gain_factor = "3125";
|
||||
framerate_factor = "1000000";
|
||||
exposure_factor = "1000000";
|
||||
min_gain_val = "100000"; /* 1x */
|
||||
max_gain_val = "796875"; /* 7.97x */
|
||||
step_gain_val = "1";
|
||||
default_gain = "100000"; /* 1x */
|
||||
min_hdr_ratio = "1";
|
||||
max_hdr_ratio = "1";
|
||||
|
||||
min_framerate = "2000000";
|
||||
max_framerate = "45000000";
|
||||
step_framerate = "1";
|
||||
default_framerate = "45000000"; // 45.0 fps
|
||||
|
||||
min_exp_time = "100"; // us
|
||||
max_exp_time = "22220"; // us
|
||||
step_exp_time = "1";
|
||||
default_exp_time = "22220"; // us
|
||||
default_exp_time = "10000"; /* us */
|
||||
};
|
||||
ports {
|
||||
#address-cells = <0x1>;
|
||||
|
@ -296,10 +213,8 @@ i2c8 = "/i2c@31e0000";
|
|||
remote-endpoint = <&mt9m021_master_nvcsi_port0>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
host1x {
|
||||
|
@ -308,7 +223,6 @@ i2c8 = "/i2c@31e0000";
|
|||
ports {
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
status = "okay";
|
||||
port@0 {
|
||||
reg = <0x0>;
|
||||
status = "okay";
|
||||
|
@ -332,8 +246,6 @@ i2c8 = "/i2c@31e0000";
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
nvcsi@150c0000 {
|
||||
status = "okay";
|
||||
num-channels = <0x2>;
|
||||
|
@ -432,5 +344,4 @@ i2c8 = "/i2c@31e0000";
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
/ {
|
||||
model = "quill";
|
||||
compatible = "nvidia,quill", "nvidia,p2597-0000+p3310-1000", "nvidia,tegra186";
|
||||
compatible = "nvidia,quill", "nvidia,tegra186";
|
||||
|
||||
nvidia,boardids = "3310:0000:C03";
|
||||
nvidia,proc-boardid = "3310:0000:C03";
|
||||
|
||||
|
@ -78,14 +79,11 @@
|
|||
/*
|
||||
gpio@74{
|
||||
status = "disabled";
|
||||
/delete-node/ touch-rails;
|
||||
|
||||
};
|
||||
*/
|
||||
/*
|
||||
gpio@77{
|
||||
status = "disabled";
|
||||
/delete-node/ lcd-bias-rails;
|
||||
|
||||
};
|
||||
*/
|
||||
|
@ -99,10 +97,6 @@
|
|||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
spi@3240000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
cpus {
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -223,59 +217,6 @@
|
|||
regulator@1 {
|
||||
gpio = <&tegra_main_gpio TEGRA_MAIN_GPIO(P, 6) 0>;
|
||||
};
|
||||
regulator@2 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
/delete-property/ enable-active-high;
|
||||
};
|
||||
regulator@3 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@6 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@7 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@8 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@9 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@10 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@11 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@12 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@13 { //fixes PWM fan
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@15 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@17 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
regulator@118 {
|
||||
regulator-always-on;
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
};
|
||||
|
||||
bpmp_i2c {
|
||||
|
|
|
@ -129,18 +129,5 @@
|
|||
};
|
||||
};
|
||||
|
||||
spi@3210000 {
|
||||
status = "okay";
|
||||
spi@0 {
|
||||
compatible = "spidev";
|
||||
reg = <0x0>;
|
||||
spi-max-frequency = <33000000>;
|
||||
controller-data {
|
||||
nvidia,enable-hw-based-cs;
|
||||
nvidia,rx-clk-tap-delay = <0x8>;
|
||||
nvidia,tx-clk-tap-delay = <0x16>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
CONFIG_VIDEO_I2C_SPIRI_CAM=y
|
|
@ -1,13 +0,0 @@
|
|||
if VIDEO_V4L2
|
||||
|
||||
menu "NVIDIA overlay Encoders, decoders, sensors and other helper chips"
|
||||
visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST
|
||||
|
||||
config VIDEO_I2C_SPIRI_CAM
|
||||
tristate "Spiri mt9m021 camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for Spiri Cameras
|
||||
endmenu
|
||||
endif
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
subdir-ccflags-y += -Werror
|
||||
|
||||
obj-$(CONFIG_VIDEO_I2C_SPIRI_CAM) += mt9m021.o
|
||||
|
||||
ccflags-$(CONFIG_VIDEO_I2C_SPIRI_CAM) := -I$(srctree.nvidia-spiri)/include/
|
||||
ccflags-$(CONFIG_VIDEO_I2C_SPIRI_CAM) += -I$(srctree.nvidia-spiri)/include/media/
|
||||
ccflags-$(CONFIG_VIDEO_I2C_SPIRI_CAM) += -I$(srctree.nvidia-spiri)/drivers/media/i2c/
|
||||
|
||||
ccflags-$(CONFIG_VIDEO_I2C_SPIRI_CAM) += -I$(srctree.nvidia)/drivers/media/platform/tegra/camera
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
#include <media/tegra_v4l2_camera.h>
|
||||
#include <media/tegracam_core.h>
|
||||
|
||||
#include "camera_gpio.h"
|
||||
#include "../platform/tegra/camera/camera_gpio.h"
|
||||
#include "mt9m021_mode_tbls.h"
|
||||
|
||||
/***************************************************
|
||||
|
@ -135,8 +135,8 @@
|
|||
#define MT9M021_ANALOG_GAIN_SHIFT 4
|
||||
#define MT9M021_ANALOG_GAIN_MASK 0x0030
|
||||
|
||||
#define MT9M021_GLOBAL_GAIN_MIN 100
|
||||
#define MT9M021_GLOBAL_GAIN_MAX 762
|
||||
#define MT9M021_GLOBAL_GAIN_MIN 4
|
||||
#define MT9M021_GLOBAL_GAIN_MAX 6476
|
||||
#define MT9M021_GLOBAL_GAIN_DEF 100
|
||||
|
||||
#define MT9M021_COARSE_INT_TIME_MIN 0x0001
|
||||
|
@ -397,38 +397,59 @@ static int mt9m021_set_gain(struct tegracam_device *tc_dev, s64 val)
|
|||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
struct device *dev = tc_dev->dev;
|
||||
int err = 0;
|
||||
u64 gain = 0;
|
||||
u16 gain_mul;
|
||||
u16 reg16 = 0;
|
||||
u8 integer, fraction;
|
||||
|
||||
dev_dbg(dev, "Setting Gain to: %lld", val);
|
||||
|
||||
/*
|
||||
* Digital gain equation:
|
||||
*
|
||||
* RANGE: 1x, 7.97x
|
||||
* STEPS: 1/32
|
||||
*
|
||||
* gain accepts mapping from range 32 - 255
|
||||
*
|
||||
* SCALE FACTOR = 3125
|
||||
*
|
||||
* min_gain_val = 100000
|
||||
* max_gain_val = 796875
|
||||
* gain_factor = 3125
|
||||
*
|
||||
*/
|
||||
gain = val / 3125;
|
||||
if (val >= MT9M021_GAIN_8X_FIXED) {
|
||||
integer = val / MT9M021_GAIN_8X_FIXED;
|
||||
fraction = ((val / 8) % 100) * 32 / 100;
|
||||
gain_mul = MT9M021_GAIN_8X;
|
||||
} else if (val >= MT9M021_GAIN_4X_FIXED) {
|
||||
integer = val / MT9M021_GAIN_4X_FIXED;
|
||||
fraction = ((val / 4) % 100) * 32 / 100;
|
||||
gain_mul = MT9M021_GAIN_4X;
|
||||
} else if (val >= MT9M021_GAIN_2X_FIXED) {
|
||||
integer = val / MT9M021_GAIN_2X_FIXED;
|
||||
fraction = ((val / 2) % 100) * 32 / 100;
|
||||
gain_mul = MT9M021_GAIN_2X;
|
||||
} else {
|
||||
integer = val / MT9M021_GAIN_1X_FIXED;
|
||||
fraction = (val % 100) * 32 / 100;
|
||||
gain_mul = MT9M021_GAIN_1X;
|
||||
}
|
||||
|
||||
/* Update global gain */
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN, gain);
|
||||
/* Update analog gain multiplier */
|
||||
err = mt9m021_read_reg16(s_data, MT9M021_DIGITAL_TEST, ®16);
|
||||
if (err)
|
||||
goto exit;
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN_CB, gain);
|
||||
reg16 =
|
||||
(reg16 & ~MT9M021_ANALOG_GAIN_MASK) |
|
||||
((gain_mul << MT9M021_ANALOG_GAIN_SHIFT) &
|
||||
MT9M021_ANALOG_GAIN_MASK);
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16);
|
||||
msleep(10);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
/* Update global gain */
|
||||
err =
|
||||
mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN,
|
||||
(integer << 5) | fraction);
|
||||
msleep(10);
|
||||
if (err)
|
||||
goto exit;
|
||||
err =
|
||||
mt9m021_write_reg16(s_data, MT9M021_GLOBAL_GAIN_CB,
|
||||
(integer << 5) | fraction);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Gain control error: %d", err);
|
||||
|
||||
return err;
|
||||
|
@ -473,7 +494,7 @@ static int mt9m021_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
|
|||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Frame rate control error: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -492,6 +513,7 @@ static int mt9m021_set_coarse_time(struct mt9m021 *priv, s64 val)
|
|||
err = mt9m021_write_reg16(s_data, MT9M021_COARSE_INT_TIME_CB, val);
|
||||
if (err)
|
||||
return err;
|
||||
msleep(30);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -506,11 +528,11 @@ static int mt9m021_set_exposure(struct tegracam_device *tc_dev, s64 val)
|
|||
u64 coarse_time;
|
||||
int err = 0;
|
||||
|
||||
dev_dbg(dev, "Setting Exposure Time to : %lld", val);
|
||||
dev_dbg(dev, "Setting Exposure Time to: %lld", val);
|
||||
|
||||
coarse_time =
|
||||
val * mode->signal_properties.pixel_clock.val /
|
||||
mode->image_properties.line_length /
|
||||
/* Calculate coarse-time */
|
||||
coarse_time = mode->signal_properties.pixel_clock.val *
|
||||
val / mode->image_properties.line_length /
|
||||
mode->control_properties.exposure_factor;
|
||||
|
||||
err = mt9m021_set_coarse_time(priv, coarse_time);
|
||||
|
@ -519,7 +541,7 @@ static int mt9m021_set_exposure(struct tegracam_device *tc_dev, s64 val)
|
|||
|
||||
return err;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Exposure control error: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -539,14 +561,16 @@ static int mt9m021_set_analog_gain(struct tegracam_device *tc_dev, s64 val)
|
|||
goto exit;
|
||||
reg16 =
|
||||
(reg16 & ~MT9M021_ANALOG_GAIN_MASK) |
|
||||
((val << MT9M021_ANALOG_GAIN_SHIFT) & MT9M021_ANALOG_GAIN_MASK);
|
||||
((val << MT9M021_ANALOG_GAIN_SHIFT) &
|
||||
MT9M021_ANALOG_GAIN_MASK);
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_DIGITAL_TEST, reg16);
|
||||
msleep(30);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Analog Gain control error: %d", err);
|
||||
|
||||
return err;
|
||||
|
@ -596,10 +620,11 @@ static int mt9m021_set_digital_gain(struct tegracam_device *tc_dev, s64 val,
|
|||
err = mt9m021_write_reg16(s_data, gain_cb_reg, val);
|
||||
if (err)
|
||||
goto exit;
|
||||
msleep(30);
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Digital Gain control error: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -616,13 +641,15 @@ static int mt9m021_set_test_pattern(struct tegracam_device *tc_dev, s32 val)
|
|||
err = mt9m021_write_reg16(s_data, MT9M021_TEST_PATTERN,
|
||||
MT9M021_TEST_PATTERN_VAL);
|
||||
else
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_TEST_PATTERN, val);
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_TEST_PATTERN,
|
||||
val);
|
||||
msleep(30);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Test Pattern control error: %d", err);
|
||||
|
||||
return err;
|
||||
|
@ -637,7 +664,7 @@ static int mt9m021_set_flash(struct tegracam_device *tc_dev, s32 val)
|
|||
|
||||
dev_dbg(dev, "Setting Flash to: %d", val);
|
||||
|
||||
switch (val) {
|
||||
switch(val) {
|
||||
case V4L2_FLASH_LED_MODE_NONE:
|
||||
err = mt9m021_write_reg16(s_data, MT9M021_FLASH, 0x0000);
|
||||
priv->flash_en = false;
|
||||
|
@ -656,7 +683,7 @@ static int mt9m021_set_flash(struct tegracam_device *tc_dev, s32 val)
|
|||
goto exit;
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Flash control error: %d", err);
|
||||
|
||||
return err;
|
||||
|
@ -670,7 +697,7 @@ static int mt9m021_set_flip(struct tegracam_device *tc_dev, s32 val, int id)
|
|||
|
||||
dev_dbg(dev, "Setting Flip to: %d", val);
|
||||
|
||||
switch (id) {
|
||||
switch(id) {
|
||||
case V4L2_CID_HFLIP:
|
||||
err = mt9m021_update_bits(s_data, MT9M021_READ_MODE,
|
||||
val << 14, MT9M021_HFLIP_MASK);
|
||||
|
@ -689,7 +716,7 @@ static int mt9m021_set_flip(struct tegracam_device *tc_dev, s32 val, int id)
|
|||
goto exit;
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
exit:
|
||||
dev_err(dev, "Flip control error: %d", err);
|
||||
|
||||
return err;
|
||||
|
@ -760,7 +787,7 @@ static int mt9m021_power_off(struct camera_common_data *s_data)
|
|||
usleep_range(2000, 2010);
|
||||
}
|
||||
|
||||
power_off_done:
|
||||
power_off_done:
|
||||
pw->state = SWITCH_OFF;
|
||||
|
||||
return 0;
|
||||
|
@ -882,7 +909,7 @@ static struct camera_common_pdata *mt9m021_parse_dt(struct tegracam_device
|
|||
|
||||
return board_priv_pdata;
|
||||
|
||||
error:
|
||||
error:
|
||||
devm_kfree(dev, board_priv_pdata);
|
||||
|
||||
return ret;
|
||||
|
@ -929,10 +956,13 @@ static int mt9m021_col_correction(struct mt9m021 *priv)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
msleep(200);
|
||||
|
||||
/* Enable Streaming */
|
||||
ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_START_STREAM]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(200);
|
||||
|
||||
/* Disable Streaming */
|
||||
ret = mt9m021_write_table(priv, mode_table[MT9M021_MODE_STOP_STREAM]);
|
||||
|
@ -943,6 +973,7 @@ static int mt9m021_col_correction(struct mt9m021 *priv)
|
|||
ret = mt9m021_write_reg16(s_data, MT9M021_COLUMN_CORRECTION, 0xE007);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(200);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1089,8 +1120,7 @@ static int mt9m021_verify_chip_id(struct mt9m021 *priv)
|
|||
err = mt9m021_read_reg16(s_data, MT9M021_CHIP_ID_REG, &chip_id);
|
||||
if (!err)
|
||||
break;
|
||||
dev_info(&client->dev,
|
||||
"Failed to read Chip ID, trying again\n");
|
||||
dev_info(&client->dev, "Failed to read Chip ID, trying again\n");
|
||||
max_retries--;
|
||||
msleep(30);
|
||||
}
|
||||
|
@ -1106,7 +1136,7 @@ static int mt9m021_verify_chip_id(struct mt9m021 *priv)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
exit:
|
||||
ret = mt9m021_power_off(s_data);
|
||||
if (ret)
|
||||
return ret;
|
|
@ -21,7 +21,7 @@
|
|||
#ifndef __MT9M021_I2C_TABLES__
|
||||
#define __MT9M021_I2C_TABLES__
|
||||
|
||||
#include "media/camera_common.h"
|
||||
#include <media/camera_common.h>
|
||||
|
||||
#define MT9M021_TABLE_WAIT_MS 0
|
||||
#define MT9M021_TABLE_END 1
|
||||
|
@ -102,42 +102,8 @@ static const mt9m021_reg mt9m021_mode_1280x720_60fps[] = {
|
|||
{MT9M021_TABLE_END, 0x00}
|
||||
};
|
||||
|
||||
static const mt9m021_reg mt9m021_mode_1280x960_45fps[] = {
|
||||
/* Rev2 Settings */
|
||||
{0x307A, 0x0000},
|
||||
{0x30EA, 0x0C00},
|
||||
{0x3044, 0x0404},
|
||||
{0x301E, 0x012C},
|
||||
{0x3180, 0x8000},
|
||||
{0x3014, 0x0000},
|
||||
|
||||
/* Analog Settings */
|
||||
{0x3ED6, 0x00FD},
|
||||
{0x3ED8, 0x0FFF},
|
||||
{0x3EDA, 0x0003},
|
||||
{0x3EDC, 0xF87A},
|
||||
{0x3EDE, 0xE075},
|
||||
{0x3EE0, 0x077C},
|
||||
{0x3EE2, 0xA4EB},
|
||||
{0x3EE4, 0xD208},
|
||||
|
||||
/* Size Settings */
|
||||
{0x3064, 0x1802}, /* EMBEDDED_DATA_CTRL */
|
||||
{0x3032, 0x0020}, /* DIGITAL_BINNING */
|
||||
{0x3002, 0x0004}, /* Y ADDR START */
|
||||
{0x3004, 0x0001}, /* X ADDR START */
|
||||
{0x3006, 0x03C3}, /* Y ADDR END */
|
||||
{0x3008, 0x0500}, /* X ADDR END */
|
||||
{0x300A, 0x03DE}, /* FRAME_LENGTH_LINES */
|
||||
{0x300C, 0x0672}, /* LINE_LENGTH_PCK */
|
||||
{0x30A2, 0x0001}, /* X_ODD_INC */
|
||||
{0x30A6, 0x0001}, /* Y_ODD_INC */
|
||||
{MT9M021_TABLE_END, 0x00}
|
||||
};
|
||||
|
||||
enum {
|
||||
MT9M021_MODE_1280x720_60FPS,
|
||||
MT9M021_MODE_1280x960_45FPS,
|
||||
|
||||
MT9M021_MODE_PLL_SETUP,
|
||||
|
||||
|
@ -147,7 +113,6 @@ enum {
|
|||
|
||||
static const mt9m021_reg *mode_table[] = {
|
||||
[MT9M021_MODE_1280x720_60FPS] = mt9m021_mode_1280x720_60fps,
|
||||
[MT9M021_MODE_1280x960_45FPS] = mt9m021_mode_1280x960_45fps,
|
||||
|
||||
[MT9M021_MODE_PLL_SETUP] = mt9m021_pll_setup,
|
||||
|
||||
|
@ -155,7 +120,7 @@ static const mt9m021_reg *mode_table[] = {
|
|||
[MT9M021_MODE_STOP_STREAM] = mt9m021_stop,
|
||||
};
|
||||
|
||||
static const int mt9m021_framerates_1280x720[] = {
|
||||
static const int mt9m021_framerates[] = {
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
|
@ -164,19 +129,8 @@ static const int mt9m021_framerates_1280x720[] = {
|
|||
60,
|
||||
};
|
||||
|
||||
static const int mt9m021_framerates_1280x960[] = {
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
45,
|
||||
};
|
||||
|
||||
static const struct camera_common_frmfmt mt9m021_frmfmt[] = {
|
||||
{{1280, 720}, mt9m021_framerates_1280x720, 1, 0,
|
||||
MT9M021_MODE_1280x720_60FPS},
|
||||
{{1280, 960}, mt9m021_framerates_1280x960, 1, 0,
|
||||
MT9M021_MODE_1280x960_45FPS},
|
||||
{{1280, 720}, mt9m021_framerates, 1, 0, MT9M021_MODE_1280x720_60FPS},
|
||||
};
|
||||
|
||||
#endif /* __MT9M021_I2C_TABLES__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,786 @@
|
|||
/*
|
||||
* tegracam_ctrls - control framework for tegra camera drivers
|
||||
*
|
||||
* Copyright (c) 2017-2019, 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <media/tegra-v4l2-camera.h>
|
||||
#include <media/camera_common.h>
|
||||
#include <media/tegracam_utils.h>
|
||||
|
||||
#define CTRL_U32_MIN 0
|
||||
#define CTRL_U32_MAX 0x7FFFFFFF
|
||||
#define CTRL_U64_MIN 0
|
||||
#define CTRL_U64_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
#define CTRL_S32_MIN 0x80000000
|
||||
#define CTRL_S32_MAX 0x7FFFFFFF
|
||||
#define CTRL_S64_MIN 0x8000000000000000LL
|
||||
#define CTRL_S64_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
#define CTRL_MAX_STR_SIZE 4096
|
||||
|
||||
#define TEGRACAM_DEF_CTRLS 1
|
||||
|
||||
/* MT9M021 Controls Information */
|
||||
#define MT9M021_DEFAULT_ANALOG_GAIN (0x0)
|
||||
#define MT9M021_MAX_ANALOG_GAIN (0x3)
|
||||
|
||||
static const char * const mt9m021_test_pattern_menu[] = {
|
||||
"0:Disabled",
|
||||
"1:Solid color test pattern",
|
||||
"2:color bar test pattern",
|
||||
"3:Fade to gray color bar test pattern",
|
||||
"256:Walking 1s test pattern (12 bit)"
|
||||
};
|
||||
|
||||
static int tegracam_s_ctrl(struct v4l2_ctrl *ctrl);
|
||||
static const struct v4l2_ctrl_ops tegracam_ctrl_ops = {
|
||||
.s_ctrl = tegracam_s_ctrl,
|
||||
};
|
||||
|
||||
static const u32 tegracam_def_cids[] = {
|
||||
TEGRA_CAMERA_CID_GROUP_HOLD,
|
||||
};
|
||||
|
||||
/*
|
||||
* For auto control, the states of the previous controls must
|
||||
* be applied to get optimal quality faster. List all the controls
|
||||
* which must be overriden
|
||||
*/
|
||||
static const u32 tegracam_override_cids[] = {
|
||||
TEGRA_CAMERA_CID_GAIN,
|
||||
TEGRA_CAMERA_CID_EXPOSURE,
|
||||
TEGRA_CAMERA_CID_FRAME_RATE,
|
||||
};
|
||||
#define NUM_OVERRIDE_CTRLS ARRAY_SIZE(tegracam_override_cids)
|
||||
|
||||
static struct v4l2_ctrl_config ctrl_cfg_list[] = {
|
||||
/* Do not change the name field for the controls! */
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_GAIN,
|
||||
.name = "Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_EXPOSURE,
|
||||
.name = "Exposure",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_EXPOSURE_SHORT,
|
||||
.name = "Exposure Short",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_FRAME_RATE,
|
||||
.name = "Frame Rate",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_GROUP_HOLD,
|
||||
.name = "Group Hold",
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.flags = V4L2_CTRL_FLAG_EXECUTE_ON_WRITE,
|
||||
.min = 0,
|
||||
.max = 1,
|
||||
.def = 0,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_EEPROM_DATA,
|
||||
.name = "EEPROM Data",
|
||||
.type = V4L2_CTRL_TYPE_STRING,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
.min = 0,
|
||||
.max = CTRL_MAX_STR_SIZE,
|
||||
.step = 2,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_FUSE_ID,
|
||||
.name = "Fuse ID",
|
||||
.type = V4L2_CTRL_TYPE_STRING,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
.min = 0,
|
||||
.max = CTRL_MAX_STR_SIZE,
|
||||
.step = 2,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_SENSOR_MODE_ID,
|
||||
.name = "Sensor Mode",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U32_MIN,
|
||||
.max = CTRL_U32_MAX,
|
||||
.def = CTRL_U32_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_HDR_EN,
|
||||
.name = "HDR enable",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER_MENU,
|
||||
.min = 0,
|
||||
.max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
|
||||
.menu_skip_mask = 0,
|
||||
.def = 0,
|
||||
.qmenu_int = switch_ctrl_qmenu,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = TEGRA_CAMERA_CID_OTP_DATA,
|
||||
.name = "OTP Data",
|
||||
.type = V4L2_CTRL_TYPE_STRING,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
.min = 0,
|
||||
.max = CTRL_MAX_STR_SIZE,
|
||||
.step = 2,
|
||||
},
|
||||
|
||||
/* Controls extension for MT9M021 */
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_ANALOGUE_GAIN,
|
||||
.name = "Analog Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = MT9M021_MAX_ANALOG_GAIN,
|
||||
.def = MT9M021_DEFAULT_ANALOG_GAIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_GAIN_RED,
|
||||
.name = "Red Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_GAIN_GREENR,
|
||||
.name = "GreenR Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_GAIN_GREENB,
|
||||
.name = "GreenB Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_GAIN_BLUE,
|
||||
.name = "Blue Gain",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER64,
|
||||
.flags = V4L2_CTRL_FLAG_SLIDER,
|
||||
.min = CTRL_U64_MIN,
|
||||
.max = CTRL_U64_MAX,
|
||||
.def = CTRL_U64_MIN,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_TEST_PATTERN,
|
||||
.type = V4L2_CTRL_TYPE_MENU,
|
||||
.name = "Test Pattern",
|
||||
.min = 0,
|
||||
.max = ARRAY_SIZE(mt9m021_test_pattern_menu) - 1,
|
||||
.step = 0,
|
||||
.def = 0,
|
||||
.flags = 0,
|
||||
.menu_skip_mask = 0,
|
||||
.qmenu = mt9m021_test_pattern_menu,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_FLASH_LED_MODE,
|
||||
.name = "Flash",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.flags = 0,
|
||||
.min = V4L2_FLASH_LED_MODE_NONE,
|
||||
.max = V4L2_FLASH_LED_MODE_FLASH,
|
||||
.def = V4L2_FLASH_LED_MODE_FLASH,
|
||||
.step = 1,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_HFLIP,
|
||||
.name = "Horizontal Flip",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER_MENU,
|
||||
.min = 0,
|
||||
.max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
|
||||
.menu_skip_mask = 0,
|
||||
.def = 0,
|
||||
.qmenu_int = switch_ctrl_qmenu,
|
||||
},
|
||||
{
|
||||
.ops = &tegracam_ctrl_ops,
|
||||
.id = V4L2_CID_VFLIP,
|
||||
.name = "Vertical Flip",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER_MENU,
|
||||
.min = 0,
|
||||
.max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
|
||||
.menu_skip_mask = 0,
|
||||
.def = 0,
|
||||
.qmenu_int = switch_ctrl_qmenu,
|
||||
},
|
||||
};
|
||||
|
||||
static int tegracam_get_ctrl_index(u32 cid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ctrl_cfg_list); i++) {
|
||||
if (ctrl_cfg_list[i].id == cid)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tegracam_get_string_ctrl_size(u32 cid,
|
||||
const struct tegracam_ctrl_ops *ops)
|
||||
{
|
||||
u32 index = 0;
|
||||
|
||||
switch (cid) {
|
||||
case TEGRA_CAMERA_CID_EEPROM_DATA:
|
||||
index = TEGRA_CAM_STRING_CTRL_EEPROM_INDEX;
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_FUSE_ID:
|
||||
index = TEGRA_CAM_STRING_CTRL_FUSEID_INDEX;
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_OTP_DATA:
|
||||
index = TEGRA_CAM_STRING_CTRL_OTP_INDEX;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ops->string_ctrl_size[index];
|
||||
}
|
||||
|
||||
static int tegracam_setup_string_ctrls(struct tegracam_device *tc_dev,
|
||||
struct tegracam_ctrl_handler *handler)
|
||||
{
|
||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||
u32 numctrls = ops->numctrls;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; i < numctrls; i++) {
|
||||
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
||||
|
||||
if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
|
||||
err = ops->fill_string_ctrl(tc_dev, ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegracam_set_ctrls(struct tegracam_ctrl_handler *handler,
|
||||
struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
int err = 0;
|
||||
u32 status = 0;
|
||||
|
||||
/* For controls that are independent of power state */
|
||||
switch (ctrl->id) {
|
||||
case TEGRA_CAMERA_CID_SENSOR_MODE_ID:
|
||||
s_data->sensor_mode_id = (int) (*ctrl->p_new.p_s64);
|
||||
return 0;
|
||||
case TEGRA_CAMERA_CID_HDR_EN:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (v4l2_subdev_call(&s_data->subdev, video,
|
||||
g_input_status, &status)) {
|
||||
dev_err(s_data->dev, "power status query unsupported\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* power state is turned off, do not program sensor now */
|
||||
if (!status)
|
||||
return 0;
|
||||
|
||||
/* For controls that require sensor to be on */
|
||||
switch (ctrl->id) {
|
||||
case TEGRA_CAMERA_CID_GAIN:
|
||||
err = ops->set_gain(tc_dev, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_FRAME_RATE:
|
||||
err = ops->set_frame_rate(tc_dev, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||
err = ops->set_exposure(tc_dev, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE_SHORT:
|
||||
err = ops->set_exposure_short(tc_dev, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_GROUP_HOLD:
|
||||
err = ops->set_group_hold(tc_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
err = ops->set_analog_gain(tc_dev, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case V4L2_CID_GAIN_RED:
|
||||
case V4L2_CID_GAIN_GREENR:
|
||||
case V4L2_CID_GAIN_GREENB:
|
||||
case V4L2_CID_GAIN_BLUE:
|
||||
err = ops->set_digital_gain(tc_dev, *ctrl->p_new.p_s64,
|
||||
ctrl->id);
|
||||
break;
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
err = ops->set_test_pattern(tc_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_FLASH_LED_MODE:
|
||||
err = ops->set_flash(tc_dev, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
case V4L2_CID_VFLIP:
|
||||
err = ops->set_flip(tc_dev, ctrl->val, ctrl->id);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown ctrl id.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegracam_set_grouphold_ex(struct tegracam_device *tc_dev,
|
||||
struct sensor_blob *blob,
|
||||
bool status)
|
||||
{
|
||||
const struct tegracam_ctrl_ops *ops = tc_dev->tcctrl_ops;
|
||||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* when grouphold is set, reset control blob
|
||||
* set grouphold register using set API
|
||||
* start packetize commands for delivering the blob
|
||||
* when grouphold is unset, unset grouphold register
|
||||
* and write the blob only if sensor is streaming.
|
||||
*/
|
||||
if (status) {
|
||||
memset(blob, 0, sizeof(struct sensor_blob));
|
||||
err = ops->set_group_hold_ex(tc_dev, blob, status);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = ops->set_group_hold_ex(tc_dev, blob, status);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* TODO: block this write selectively from VI5 */
|
||||
if (tc_dev->is_streaming) {
|
||||
err = write_sensor_blob(s_data->regmap, blob);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegracam_set_ctrls_ex(struct tegracam_ctrl_handler *handler,
|
||||
struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
struct tegracam_sensor_data *sensor_data = &handler->sensor_data;
|
||||
struct sensor_blob *blob = &sensor_data->ctrls_blob;
|
||||
int err = 0;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case TEGRA_CAMERA_CID_GAIN:
|
||||
err = ops->set_gain_ex(tc_dev, blob, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_FRAME_RATE:
|
||||
err = ops->set_frame_rate_ex(tc_dev, blob, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||
err = ops->set_exposure_ex(tc_dev, blob, *ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_GROUP_HOLD:
|
||||
err = tegracam_set_grouphold_ex(tc_dev, blob, ctrl->val);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_SENSOR_MODE_ID:
|
||||
s_data->sensor_mode_id = (int) (*ctrl->p_new.p_s64);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_HDR_EN:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown ctrl id.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int tegracam_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct tegracam_ctrl_handler *handler =
|
||||
container_of(ctrl->handler,
|
||||
struct tegracam_ctrl_handler, ctrl_handler);
|
||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||
|
||||
if (ops->is_blob_supported)
|
||||
return tegracam_set_ctrls_ex(handler, ctrl);
|
||||
else
|
||||
return tegracam_set_ctrls(handler, ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *hdl)
|
||||
{
|
||||
struct v4l2_ext_controls ctrls;
|
||||
struct v4l2_ext_control control;
|
||||
struct tegracam_device *tc_dev = hdl->tc_dev;
|
||||
struct device *dev = tc_dev->dev;
|
||||
const struct tegracam_ctrl_ops *ops = hdl->ctrl_ops;
|
||||
struct tegracam_sensor_data *sensor_data = &hdl->sensor_data;
|
||||
struct sensor_blob *blob = &sensor_data->ctrls_blob;
|
||||
bool is_blob_supported = ops->is_blob_supported;
|
||||
int err, result = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* write list of override regs for the asking frame length,
|
||||
* coarse integration time, and gain. Failures to write
|
||||
* overrides are non-fatal
|
||||
*/
|
||||
memset(&ctrls, 0, sizeof(ctrls));
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 9, 0)
|
||||
ctrls.which = V4L2_CTRL_ID2WHICH(TEGRA_CAMERA_CID_BASE);
|
||||
#else
|
||||
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(TEGRA_CAMERA_CID_BASE);
|
||||
#endif
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &control;
|
||||
|
||||
for (i = 0; i < NUM_OVERRIDE_CTRLS; i++) {
|
||||
s64 val = 0;
|
||||
|
||||
control.id = tegracam_override_cids[i];
|
||||
result = v4l2_g_ext_ctrls(&hdl->ctrl_handler, &ctrls);
|
||||
if (result == 0) {
|
||||
val = control.value64;
|
||||
switch (control.id) {
|
||||
case TEGRA_CAMERA_CID_GAIN:
|
||||
if (is_blob_supported)
|
||||
err = ops->set_gain_ex(tc_dev,
|
||||
blob, val);
|
||||
else
|
||||
err = ops->set_gain(tc_dev, val);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||
if (is_blob_supported)
|
||||
err = ops->set_exposure_ex(tc_dev,
|
||||
blob, val);
|
||||
else
|
||||
err = ops->set_exposure(tc_dev, val);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_FRAME_RATE:
|
||||
if (is_blob_supported)
|
||||
err = ops->set_frame_rate_ex(tc_dev,
|
||||
blob, val);
|
||||
else
|
||||
err = ops->set_frame_rate(tc_dev, val);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "%s: unsupported override %x\n",
|
||||
__func__, control.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
dev_err(dev, "%s: error to set %d override\n",
|
||||
__func__, control.id);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegracam_init_ctrl_ranges_by_mode(
|
||||
struct tegracam_ctrl_handler *handler,
|
||||
u32 modeidx)
|
||||
{
|
||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
struct sensor_control_properties *ctrlprops = NULL;
|
||||
s64 min_short_exp_time = 0;
|
||||
s64 max_short_exp_time = 0;
|
||||
s64 default_short_exp_time = 0;
|
||||
int i;
|
||||
|
||||
if (modeidx >= s_data->sensor_props.num_modes)
|
||||
return -EINVAL;
|
||||
|
||||
ctrlprops =
|
||||
&s_data->sensor_props.sensor_modes[modeidx].control_properties;
|
||||
|
||||
for (i = 0; i < handler->numctrls; i++) {
|
||||
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
||||
int err = 0;
|
||||
|
||||
switch (ctrl->id) {
|
||||
case TEGRA_CAMERA_CID_GAIN:
|
||||
case V4L2_CID_GAIN_RED:
|
||||
case V4L2_CID_GAIN_GREENR:
|
||||
case V4L2_CID_GAIN_GREENB:
|
||||
case V4L2_CID_GAIN_BLUE:
|
||||
err = v4l2_ctrl_modify_range(ctrl,
|
||||
ctrlprops->min_gain_val,
|
||||
ctrlprops->max_gain_val,
|
||||
ctrlprops->step_gain_val,
|
||||
ctrlprops->default_gain);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_FRAME_RATE:
|
||||
err = v4l2_ctrl_modify_range(ctrl,
|
||||
ctrlprops->min_framerate,
|
||||
ctrlprops->max_framerate,
|
||||
ctrlprops->step_framerate,
|
||||
ctrlprops->default_framerate);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||
err = v4l2_ctrl_modify_range(ctrl,
|
||||
ctrlprops->min_exp_time.val,
|
||||
ctrlprops->max_exp_time.val,
|
||||
ctrlprops->step_exp_time.val,
|
||||
ctrlprops->default_exp_time.val);
|
||||
break;
|
||||
case TEGRA_CAMERA_CID_EXPOSURE_SHORT:
|
||||
/*
|
||||
* min_hdr_ratio should be equal to max_hdr_ratio.
|
||||
* This will ensure consistent short exposure
|
||||
* limit calculations.
|
||||
*/
|
||||
min_short_exp_time =
|
||||
ctrlprops->min_exp_time.val /
|
||||
ctrlprops->min_hdr_ratio;
|
||||
max_short_exp_time =
|
||||
ctrlprops->max_exp_time.val /
|
||||
ctrlprops->min_hdr_ratio;
|
||||
default_short_exp_time =
|
||||
ctrlprops->default_exp_time.val /
|
||||
ctrlprops->min_hdr_ratio;
|
||||
err = v4l2_ctrl_modify_range(ctrl,
|
||||
min_short_exp_time,
|
||||
max_short_exp_time,
|
||||
ctrlprops->step_exp_time.val,
|
||||
default_short_exp_time);
|
||||
dev_dbg(s_data->dev,
|
||||
"%s:short_exp_limits[%lld,%lld], default_short_exp_time=%lld\n",
|
||||
__func__,
|
||||
min_short_exp_time,
|
||||
max_short_exp_time,
|
||||
default_short_exp_time);
|
||||
break;
|
||||
default:
|
||||
/* Not required to modify these control ranges */
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
dev_err(s_data->dev,
|
||||
"ctrl %s range update failed\n", ctrl->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegracam_init_ctrl_ranges_by_mode);
|
||||
|
||||
int tegracam_init_ctrl_ranges(struct tegracam_ctrl_handler *handler)
|
||||
{
|
||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||
struct camera_common_data *s_data = tc_dev->s_data;
|
||||
struct device *dev = tc_dev->dev;
|
||||
int i, err = 0;
|
||||
|
||||
/* Updating static control ranges */
|
||||
for (i = 0; i < handler->numctrls; i++) {
|
||||
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
||||
|
||||
switch (ctrl->id) {
|
||||
case TEGRA_CAMERA_CID_SENSOR_MODE_ID:
|
||||
err = v4l2_ctrl_modify_range(ctrl,
|
||||
CTRL_U32_MIN,
|
||||
(s64) s_data->sensor_props.num_modes,
|
||||
1,
|
||||
CTRL_U32_MIN);
|
||||
break;
|
||||
default:
|
||||
/* Not required to modify these control ranges */
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
dev_err(s_data->dev,
|
||||
"ctrl %s range update failed\n", ctrl->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use mode 0 control ranges as default */
|
||||
if (s_data->sensor_props.num_modes > 0) {
|
||||
err = tegracam_init_ctrl_ranges_by_mode(handler, 0);
|
||||
if (err) {
|
||||
dev_err(dev,
|
||||
"Error %d updating mode specific control ranges\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegracam_init_ctrl_ranges);
|
||||
|
||||
int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler)
|
||||
{
|
||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||
struct v4l2_ctrl *ctrl;
|
||||
struct v4l2_ctrl_config *ctrl_cfg;
|
||||
struct device *dev = tc_dev->dev;
|
||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||
const u32 *cids = ops->ctrl_cid_list;
|
||||
u32 numctrls = ops->numctrls + TEGRACAM_DEF_CTRLS;
|
||||
int i, j;
|
||||
int err = 0;
|
||||
|
||||
err = v4l2_ctrl_handler_init(&handler->ctrl_handler, numctrls);
|
||||
|
||||
for (i = 0, j = 0; i < numctrls; i++) {
|
||||
u32 cid = i < ops->numctrls ? cids[i] : tegracam_def_cids[j++];
|
||||
int index = tegracam_get_ctrl_index(cid);
|
||||
int size = 0;
|
||||
|
||||
if (index >= ARRAY_SIZE(ctrl_cfg_list)) {
|
||||
dev_err(dev, "unsupported control in the list\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
ctrl_cfg = &ctrl_cfg_list[index];
|
||||
if (ctrl_cfg->type == V4L2_CTRL_TYPE_STRING) {
|
||||
size = tegracam_get_string_ctrl_size(ctrl_cfg->id, ops);
|
||||
if (size < 0) {
|
||||
dev_err(dev, "Invalid string ctrl size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ctrl_cfg->max = size;
|
||||
}
|
||||
ctrl = v4l2_ctrl_new_custom(&handler->ctrl_handler,
|
||||
ctrl_cfg, NULL);
|
||||
if (ctrl == NULL) {
|
||||
dev_err(dev, "Failed to init %s ctrl\n",
|
||||
ctrl_cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctrl_cfg->type == V4L2_CTRL_TYPE_STRING &&
|
||||
ctrl_cfg->flags & V4L2_CTRL_FLAG_READ_ONLY) {
|
||||
ctrl->p_new.p_char = devm_kzalloc(tc_dev->dev,
|
||||
size + 1, GFP_KERNEL);
|
||||
}
|
||||
handler->ctrls[i] = ctrl;
|
||||
};
|
||||
|
||||
handler->numctrls = numctrls;
|
||||
err = v4l2_ctrl_handler_setup(&handler->ctrl_handler);
|
||||
if (err) {
|
||||
dev_err(dev, "Error %d in control hdl setup\n", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = handler->ctrl_handler.error;
|
||||
if (err) {
|
||||
dev_err(dev, "Error %d adding controls\n", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = tegracam_setup_string_ctrls(tc_dev, handler);
|
||||
if (err) {
|
||||
dev_err(dev, "setup string controls failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = tegracam_init_ctrl_ranges(handler);
|
||||
if (err) {
|
||||
dev_err(dev, "Error %d updating control ranges\n", err);
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
v4l2_ctrl_handler_free(&handler->ctrl_handler);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegracam_ctrl_handler_init);
|
|
@ -0,0 +1,413 @@
|
|||
/**
|
||||
* camera_common.h - utilities for tegra camera driver
|
||||
*
|
||||
* Copyright (c) 2015-2019, 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __camera_common__
|
||||
#define __camera_common__
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/camera_version_utils.h>
|
||||
#include <media/nvc_focus.h>
|
||||
#include <media/sensor_common.h>
|
||||
#include <media/soc_camera.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/tegracam_core.h>
|
||||
|
||||
/*
|
||||
* Scaling factor for converting a Q10.22 fixed point value
|
||||
* back to its original floating point value
|
||||
*/
|
||||
#define FIXED_POINT_SCALING_FACTOR (1ULL << 22)
|
||||
|
||||
struct reg_8 {
|
||||
u16 addr;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
struct reg_16 {
|
||||
u16 addr;
|
||||
u16 val;
|
||||
};
|
||||
|
||||
struct camera_common_power_rail {
|
||||
struct regulator *dvdd;
|
||||
struct regulator *avdd;
|
||||
struct regulator *iovdd;
|
||||
struct regulator *vcmvdd;
|
||||
struct clk *mclk;
|
||||
unsigned int pwdn_gpio;
|
||||
unsigned int reset_gpio;
|
||||
unsigned int af_gpio;
|
||||
bool state;
|
||||
};
|
||||
|
||||
struct camera_common_regulators {
|
||||
const char *avdd;
|
||||
const char *dvdd;
|
||||
const char *iovdd;
|
||||
const char *vcmvdd;
|
||||
};
|
||||
|
||||
struct camera_common_pdata {
|
||||
const char *mclk_name; /* NULL for default default_mclk */
|
||||
const char *parentclk_name; /* NULL for no parent clock*/
|
||||
unsigned int pwdn_gpio;
|
||||
unsigned int reset_gpio;
|
||||
unsigned int af_gpio;
|
||||
bool ext_reg;
|
||||
int (*power_on)(struct camera_common_power_rail *pw);
|
||||
int (*power_off)(struct camera_common_power_rail *pw);
|
||||
struct camera_common_regulators regulators;
|
||||
bool use_cam_gpio;
|
||||
bool has_eeprom;
|
||||
bool v_flip;
|
||||
bool h_mirror;
|
||||
unsigned int fuse_id_addr;
|
||||
};
|
||||
|
||||
struct camera_common_eeprom_data {
|
||||
struct i2c_client *i2c_client;
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_board_info brd;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
int
|
||||
regmap_util_write_table_8(struct regmap *regmap,
|
||||
const struct reg_8 table[],
|
||||
const struct reg_8 override_list[],
|
||||
int num_override_regs,
|
||||
u16 wait_ms_addr, u16 end_addr);
|
||||
|
||||
int
|
||||
regmap_util_write_table_16_as_8(struct regmap *regmap,
|
||||
const struct reg_16 table[],
|
||||
const struct reg_16 override_list[],
|
||||
int num_override_regs,
|
||||
u16 wait_ms_addr, u16 end_addr);
|
||||
|
||||
enum switch_state {
|
||||
SWITCH_OFF,
|
||||
SWITCH_ON,
|
||||
};
|
||||
|
||||
static const s64 switch_ctrl_qmenu[] = {
|
||||
SWITCH_OFF, SWITCH_ON
|
||||
};
|
||||
|
||||
/*
|
||||
* The memory buffers allocated from nvrm are aligned to
|
||||
* fullfill the hardware requirements:
|
||||
* - size in alignment with a multiple of 128K/64K bytes,
|
||||
* see CL http://git-master/r/256468 and bug 1321091.
|
||||
*/
|
||||
static const s64 size_align_ctrl_qmenu[] = {
|
||||
1, (64 * 1024), (128 * 1024),
|
||||
};
|
||||
|
||||
struct camera_common_frmfmt {
|
||||
struct v4l2_frmsize_discrete size;
|
||||
const int *framerates;
|
||||
int num_framerates;
|
||||
bool hdr_en;
|
||||
int mode;
|
||||
};
|
||||
|
||||
struct camera_common_colorfmt {
|
||||
unsigned int code;
|
||||
enum v4l2_colorspace colorspace;
|
||||
int pix_fmt;
|
||||
enum v4l2_xfer_func xfer_func;
|
||||
enum v4l2_ycbcr_encoding ycbcr_enc;
|
||||
enum v4l2_quantization quantization;
|
||||
};
|
||||
|
||||
struct camera_common_framesync {
|
||||
u32 inck; /* kHz */
|
||||
u32 xhs; /* in inck */
|
||||
u32 xvs; /* in xhs */
|
||||
u32 fps; /* frames in 1000 second */
|
||||
};
|
||||
|
||||
struct tegracam_device ;
|
||||
struct camera_common_data;
|
||||
|
||||
struct camera_common_sensor_ops {
|
||||
u32 numfrmfmts;
|
||||
const struct camera_common_frmfmt *frmfmt_table;
|
||||
int (*power_on)(struct camera_common_data *s_data);
|
||||
int (*power_off)(struct camera_common_data *s_data);
|
||||
int (*write_reg)(struct camera_common_data *s_data,
|
||||
u16 addr, u8 val);
|
||||
int (*read_reg)(struct camera_common_data *s_data,
|
||||
u16 addr, u8 *val);
|
||||
struct camera_common_pdata *(*parse_dt)(struct tegracam_device *tc_dev);
|
||||
int (*power_get)(struct tegracam_device *tc_dev);
|
||||
int (*power_put)(struct tegracam_device *tc_dev);
|
||||
int (*get_framesync)(struct camera_common_data *s_data,
|
||||
struct camera_common_framesync *vshs);
|
||||
int (*set_mode)(struct tegracam_device *tc_dev);
|
||||
int (*start_streaming)(struct tegracam_device *tc_dev);
|
||||
int (*stop_streaming)(struct tegracam_device *tc_dev);
|
||||
};
|
||||
|
||||
struct tegracam_sensor_data {
|
||||
struct sensor_blob mode_blob;
|
||||
struct sensor_blob ctrls_blob;
|
||||
};
|
||||
|
||||
struct tegracam_ctrl_ops {
|
||||
u32 numctrls;
|
||||
u32 string_ctrl_size[TEGRA_CAM_MAX_STRING_CONTROLS];
|
||||
const u32 *ctrl_cid_list;
|
||||
bool is_blob_supported;
|
||||
int (*set_gain)(struct tegracam_device *tc_dev, s64 val);
|
||||
int (*set_exposure)(struct tegracam_device *tc_dev, s64 val);
|
||||
int (*set_exposure_short)(struct tegracam_device *tc_dev, s64 val);
|
||||
int (*set_frame_rate)(struct tegracam_device *tc_dev, s64 val);
|
||||
int (*set_group_hold)(struct tegracam_device *tc_dev, bool val);
|
||||
int (*fill_string_ctrl)(struct tegracam_device *tc_dev,
|
||||
struct v4l2_ctrl *ctrl);
|
||||
int (*set_gain_ex)(struct tegracam_device *tc_dev,
|
||||
struct sensor_blob *blob, s64 val);
|
||||
int (*set_exposure_ex)(struct tegracam_device *tc_dev,
|
||||
struct sensor_blob *blob, s64 val);
|
||||
int (*set_frame_rate_ex)(struct tegracam_device *tc_dev,
|
||||
struct sensor_blob *blob, s64 val);
|
||||
int (*set_group_hold_ex)(struct tegracam_device *tc_dev,
|
||||
struct sensor_blob *blob, bool val);
|
||||
int (*set_analog_gain)(struct tegracam_device *tc_dev, s64 val);
|
||||
int (*set_digital_gain)(struct tegracam_device *tc_dev, s64 val,
|
||||
int id);
|
||||
int (*set_test_pattern)(struct tegracam_device *tc_dev, s32 val);
|
||||
int (*set_flash)(struct tegracam_device *tc_dev, s32 val);
|
||||
int (*set_flip)(struct tegracam_device *tc_dev, s32 val, int id);
|
||||
};
|
||||
|
||||
struct tegracam_ctrl_handler {
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
const struct tegracam_ctrl_ops *ctrl_ops;
|
||||
struct tegracam_device *tc_dev;
|
||||
struct tegracam_sensor_data sensor_data;
|
||||
|
||||
int numctrls;
|
||||
struct v4l2_ctrl *ctrls[MAX_CID_CONTROLS];
|
||||
};
|
||||
|
||||
struct camera_common_data {
|
||||
struct camera_common_sensor_ops *ops;
|
||||
struct v4l2_ctrl_handler *ctrl_handler;
|
||||
struct device *dev;
|
||||
const struct camera_common_frmfmt *frmfmt;
|
||||
const struct camera_common_colorfmt *colorfmt;
|
||||
struct dentry *debugdir;
|
||||
struct camera_common_power_rail *power;
|
||||
|
||||
struct v4l2_subdev subdev;
|
||||
struct v4l2_ctrl **ctrls;
|
||||
|
||||
struct sensor_properties sensor_props;
|
||||
/* TODO: cleanup neeeded once all the sensors adapt new framework */
|
||||
struct tegracam_ctrl_handler *tegracam_ctrl_hdl;
|
||||
struct regmap *regmap;
|
||||
struct camera_common_pdata *pdata;
|
||||
/* TODO: cleanup needed for priv once all the sensors adapt new framework */
|
||||
void *priv;
|
||||
int numctrls;
|
||||
int csi_port;
|
||||
int numlanes;
|
||||
int mode;
|
||||
int mode_prop_idx;
|
||||
int numfmts;
|
||||
int def_mode, def_width, def_height;
|
||||
int def_clk_freq;
|
||||
int fmt_width, fmt_height;
|
||||
int sensor_mode_id;
|
||||
bool use_sensor_mode_id;
|
||||
bool override_enable;
|
||||
u32 version;
|
||||
};
|
||||
|
||||
struct camera_common_focuser_data;
|
||||
|
||||
struct camera_common_focuser_ops {
|
||||
int (*power_on)(struct camera_common_focuser_data *s_data);
|
||||
int (*power_off)(struct camera_common_focuser_data *s_data);
|
||||
int (*load_config)(struct camera_common_focuser_data *s_data);
|
||||
int (*ctrls_init)(struct camera_common_focuser_data *s_data);
|
||||
};
|
||||
|
||||
struct camera_common_focuser_data {
|
||||
struct camera_common_focuser_ops *ops;
|
||||
struct v4l2_ctrl_handler *ctrl_handler;
|
||||
struct v4l2_subdev subdev;
|
||||
struct v4l2_ctrl **ctrls;
|
||||
struct device *dev;
|
||||
|
||||
struct nv_focuser_config config;
|
||||
void *priv;
|
||||
int pwr_dev;
|
||||
int def_position;
|
||||
};
|
||||
|
||||
static inline void msleep_range(unsigned int delay_base)
|
||||
{
|
||||
usleep_range(delay_base * 1000, delay_base * 1000 + 500);
|
||||
}
|
||||
|
||||
static inline struct camera_common_data *to_camera_common_data(
|
||||
const struct device *dev)
|
||||
{
|
||||
if (sensor_common_parse_num_modes(dev))
|
||||
return container_of(dev_get_drvdata(dev),
|
||||
struct camera_common_data, subdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct camera_common_focuser_data *to_camera_common_focuser_data(
|
||||
const struct device *dev)
|
||||
{
|
||||
return container_of(dev_get_drvdata(dev),
|
||||
struct camera_common_focuser_data, subdev);
|
||||
}
|
||||
|
||||
int camera_common_g_ctrl(struct camera_common_data *s_data,
|
||||
struct v4l2_control *control);
|
||||
|
||||
int camera_common_regulator_get(struct device *dev,
|
||||
struct regulator **vreg, const char *vreg_name);
|
||||
int camera_common_parse_clocks(struct device *dev,
|
||||
struct camera_common_pdata *pdata);
|
||||
int camera_common_parse_ports(struct device *dev,
|
||||
struct camera_common_data *s_data);
|
||||
int camera_common_mclk_enable(struct camera_common_data *s_data);
|
||||
void camera_common_mclk_disable(struct camera_common_data *s_data);
|
||||
|
||||
|
||||
int camera_common_debugfs_show(struct seq_file *s, void *unused);
|
||||
ssize_t camera_common_debugfs_write(
|
||||
struct file *file,
|
||||
char const __user *buf,
|
||||
size_t count,
|
||||
loff_t *offset);
|
||||
int camera_common_debugfs_open(struct inode *inode, struct file *file);
|
||||
void camera_common_remove_debugfs(struct camera_common_data *s_data);
|
||||
void camera_common_create_debugfs(struct camera_common_data *s_data,
|
||||
const char *name);
|
||||
|
||||
const struct camera_common_colorfmt *camera_common_find_datafmt(
|
||||
unsigned int code);
|
||||
int camera_common_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_mbus_code_enum *code);
|
||||
int camera_common_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
|
||||
unsigned int *code);
|
||||
int camera_common_try_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_mbus_framefmt *mf);
|
||||
int camera_common_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
|
||||
int camera_common_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
|
||||
int camera_common_enum_framesizes(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_frame_size_enum *fse);
|
||||
int camera_common_enum_frameintervals(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_frame_interval_enum *fie);
|
||||
int camera_common_set_power(struct camera_common_data *data, int on);
|
||||
int camera_common_s_power(struct v4l2_subdev *sd, int on);
|
||||
void camera_common_dpd_disable(struct camera_common_data *s_data);
|
||||
void camera_common_dpd_enable(struct camera_common_data *s_data);
|
||||
int camera_common_g_mbus_config(struct v4l2_subdev *sd,
|
||||
struct v4l2_mbus_config *cfg);
|
||||
int camera_common_get_framesync(struct v4l2_subdev *sd,
|
||||
struct camera_common_framesync *vshs);
|
||||
|
||||
/* Common initialize and cleanup for camera */
|
||||
int camera_common_initialize(struct camera_common_data *s_data,
|
||||
const char *dev_name);
|
||||
void camera_common_cleanup(struct camera_common_data *s_data);
|
||||
|
||||
/* Focuser */
|
||||
int camera_common_focuser_init(struct camera_common_focuser_data *s_data);
|
||||
int camera_common_focuser_s_power(struct v4l2_subdev *sd, int on);
|
||||
|
||||
const struct camera_common_colorfmt *camera_common_find_pixelfmt(
|
||||
unsigned int pix_fmt);
|
||||
|
||||
/* common control layer init */
|
||||
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *handler);
|
||||
int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler);
|
||||
int tegracam_init_ctrl_ranges(struct tegracam_ctrl_handler *handler);
|
||||
int tegracam_init_ctrl_ranges_by_mode(
|
||||
struct tegracam_ctrl_handler *handler,
|
||||
u32 modeidx);
|
||||
|
||||
/* Regmap / RTCPU I2C driver interface */
|
||||
struct tegra_i2c_rtcpu_sensor;
|
||||
struct tegra_i2c_rtcpu_config;
|
||||
|
||||
struct camera_common_i2c {
|
||||
struct regmap *regmap;
|
||||
struct tegra_i2c_rtcpu_sensor *rt_sensor;
|
||||
};
|
||||
|
||||
int camera_common_i2c_init(
|
||||
struct camera_common_i2c *sensor,
|
||||
struct i2c_client *client,
|
||||
struct regmap_config *regmap_config,
|
||||
const struct tegra_i2c_rtcpu_config *rtcpu_config);
|
||||
|
||||
int camera_common_i2c_aggregate(
|
||||
struct camera_common_i2c *sensor,
|
||||
bool start);
|
||||
|
||||
int camera_common_i2c_set_frame_id(
|
||||
struct camera_common_i2c *sensor,
|
||||
int frame_id);
|
||||
|
||||
int camera_common_i2c_read_reg8(
|
||||
struct camera_common_i2c *sensor,
|
||||
unsigned int addr,
|
||||
u8 *data,
|
||||
unsigned int count);
|
||||
|
||||
int camera_common_i2c_write_reg8(
|
||||
struct camera_common_i2c *sensor,
|
||||
unsigned int addr,
|
||||
const u8 *data,
|
||||
unsigned int count);
|
||||
|
||||
int camera_common_i2c_write_table_8(
|
||||
struct camera_common_i2c *sensor,
|
||||
const struct reg_8 table[],
|
||||
const struct reg_8 override_list[],
|
||||
int num_override_regs, u16 wait_ms_addr, u16 end_addr);
|
||||
|
||||
#endif /* __camera_common__ */
|
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
* TEGRA_V4L2_CAMERA.h - utilities for tegra camera driver
|
||||
*
|
||||
* Copyright (c) 2017-2019, 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TEGRA_V4L2_CAMERA__
|
||||
#define __TEGRA_V4L2_CAMERA__
|
||||
|
||||
#include <linux/v4l2-controls.h>
|
||||
|
||||
#define TEGRA_CAMERA_CID_BASE (V4L2_CTRL_CLASS_CAMERA | 0x2000)
|
||||
|
||||
#define TEGRA_CAMERA_CID_FRAME_LENGTH (TEGRA_CAMERA_CID_BASE+0)
|
||||
#define TEGRA_CAMERA_CID_COARSE_TIME (TEGRA_CAMERA_CID_BASE+1)
|
||||
#define TEGRA_CAMERA_CID_COARSE_TIME_SHORT (TEGRA_CAMERA_CID_BASE+2)
|
||||
#define TEGRA_CAMERA_CID_GROUP_HOLD (TEGRA_CAMERA_CID_BASE+3)
|
||||
#define TEGRA_CAMERA_CID_HDR_EN (TEGRA_CAMERA_CID_BASE+4)
|
||||
#define TEGRA_CAMERA_CID_EEPROM_DATA (TEGRA_CAMERA_CID_BASE+5)
|
||||
#define TEGRA_CAMERA_CID_OTP_DATA (TEGRA_CAMERA_CID_BASE+6)
|
||||
#define TEGRA_CAMERA_CID_FUSE_ID (TEGRA_CAMERA_CID_BASE+7)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_MODE_ID (TEGRA_CAMERA_CID_BASE+8)
|
||||
|
||||
#define TEGRA_CAMERA_CID_GAIN (TEGRA_CAMERA_CID_BASE+9)
|
||||
#define TEGRA_CAMERA_CID_EXPOSURE (TEGRA_CAMERA_CID_BASE+10)
|
||||
#define TEGRA_CAMERA_CID_FRAME_RATE (TEGRA_CAMERA_CID_BASE+11)
|
||||
#define TEGRA_CAMERA_CID_EXPOSURE_SHORT (TEGRA_CAMERA_CID_BASE+12)
|
||||
|
||||
#define TEGRA_CAMERA_CID_SENSOR_CONFIG (TEGRA_CAMERA_CID_BASE+50)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_MODE_BLOB (TEGRA_CAMERA_CID_BASE+51)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_CONTROL_BLOB (TEGRA_CAMERA_CID_BASE+52)
|
||||
|
||||
#define TEGRA_CAMERA_CID_VI_BYPASS_MODE (TEGRA_CAMERA_CID_BASE+100)
|
||||
#define TEGRA_CAMERA_CID_OVERRIDE_ENABLE (TEGRA_CAMERA_CID_BASE+101)
|
||||
#define TEGRA_CAMERA_CID_VI_HEIGHT_ALIGN (TEGRA_CAMERA_CID_BASE+102)
|
||||
#define TEGRA_CAMERA_CID_VI_SIZE_ALIGN (TEGRA_CAMERA_CID_BASE+103)
|
||||
#define TEGRA_CAMERA_CID_WRITE_ISPFORMAT (TEGRA_CAMERA_CID_BASE+104)
|
||||
|
||||
#define TEGRA_CAMERA_CID_SENSOR_SIGNAL_PROPERTIES (TEGRA_CAMERA_CID_BASE+105)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_IMAGE_PROPERTIES (TEGRA_CAMERA_CID_BASE+106)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_CONTROL_PROPERTIES (TEGRA_CAMERA_CID_BASE+107)
|
||||
#define TEGRA_CAMERA_CID_SENSOR_DV_TIMINGS (TEGRA_CAMERA_CID_BASE+108)
|
||||
#define TEGRA_CAMERA_CID_LOW_LATENCY (TEGRA_CAMERA_CID_BASE+109)
|
||||
|
||||
/* Custom Controls */
|
||||
#define V4L2_CID_GAIN_RED V4L2_CID_USER_BASE
|
||||
#define V4L2_CID_GAIN_GREENR V4L2_CID_USER_BASE + 1
|
||||
#define V4L2_CID_GAIN_GREENB V4L2_CID_USER_BASE + 2
|
||||
#define V4L2_CID_GAIN_BLUE V4L2_CID_USER_BASE + 3
|
||||
|
||||
/**
|
||||
* This is temporary with the current v4l2 infrastructure
|
||||
* currently discussing with upstream maintainers our proposals and
|
||||
* better approaches to resolve this
|
||||
*/
|
||||
#define TEGRA_CAMERA_CID_SENSOR_MODES (TEGRA_CAMERA_CID_BASE + 130)
|
||||
|
||||
#define MAX_BUFFER_SIZE 32
|
||||
#define MAX_CID_CONTROLS 32
|
||||
#define MAX_NUM_SENSOR_MODES 30
|
||||
#define OF_MAX_STR_LEN 256
|
||||
#define OF_SENSORMODE_PREFIX ("mode")
|
||||
|
||||
/*
|
||||
* Scaling factor for converting a Q10.22 fixed point value
|
||||
* back to its original floating point value
|
||||
*/
|
||||
#define FIXED_POINT_SCALING_FACTOR (1ULL << 22)
|
||||
|
||||
#define TEGRA_CAM_MAX_STRING_CONTROLS 8
|
||||
#define TEGRA_CAM_STRING_CTRL_EEPROM_INDEX 0
|
||||
#define TEGRA_CAM_STRING_CTRL_FUSEID_INDEX 1
|
||||
#define TEGRA_CAM_STRING_CTRL_OTP_INDEX 2
|
||||
|
||||
#define CSI_PHY_MODE_DPHY 0
|
||||
#define CSI_PHY_MODE_CPHY 1
|
||||
#define SLVS_EC 2
|
||||
|
||||
struct unpackedU64 {
|
||||
__u32 high;
|
||||
__u32 low;
|
||||
};
|
||||
|
||||
union __u64val {
|
||||
struct unpackedU64 unpacked;
|
||||
__u64 val;
|
||||
};
|
||||
|
||||
struct sensor_signal_properties {
|
||||
__u32 readout_orientation;
|
||||
__u32 num_lanes;
|
||||
__u32 mclk_freq;
|
||||
union __u64val pixel_clock;
|
||||
__u32 cil_settletime;
|
||||
__u32 discontinuous_clk;
|
||||
__u32 dpcm_enable;
|
||||
__u32 tegra_sinterface;
|
||||
__u32 phy_mode;
|
||||
__u32 deskew_initial_enable;
|
||||
__u32 deskew_periodic_enable;
|
||||
union __u64val serdes_pixel_clock;
|
||||
__u32 reserved[2];
|
||||
};
|
||||
|
||||
struct sensor_image_properties {
|
||||
__u32 width;
|
||||
__u32 height;
|
||||
__u32 line_length;
|
||||
__u32 pixel_format;
|
||||
__u32 embedded_metadata_height;
|
||||
__u32 reserved[11];
|
||||
};
|
||||
|
||||
struct sensor_dv_timings {
|
||||
__u32 hfrontporch;
|
||||
__u32 hsync;
|
||||
__u32 hbackporch;
|
||||
__u32 vfrontporch;
|
||||
__u32 vsync;
|
||||
__u32 vbackporch;
|
||||
__u32 reserved[10];
|
||||
};
|
||||
|
||||
struct sensor_control_properties {
|
||||
__u32 gain_factor;
|
||||
__u32 framerate_factor;
|
||||
__u32 inherent_gain;
|
||||
__u32 min_gain_val;
|
||||
__u32 max_gain_val;
|
||||
__u32 min_hdr_ratio;
|
||||
__u32 max_hdr_ratio;
|
||||
__u32 min_framerate;
|
||||
__u32 max_framerate;
|
||||
union __u64val min_exp_time;
|
||||
union __u64val max_exp_time;
|
||||
__u32 step_gain_val;
|
||||
__u32 step_framerate;
|
||||
__u32 exposure_factor;
|
||||
union __u64val step_exp_time;
|
||||
__u32 default_gain;
|
||||
__u32 default_framerate;
|
||||
union __u64val default_exp_time;
|
||||
__u32 reserved[10];
|
||||
};
|
||||
|
||||
struct sensor_mode_properties {
|
||||
struct sensor_signal_properties signal_properties;
|
||||
struct sensor_image_properties image_properties;
|
||||
struct sensor_control_properties control_properties;
|
||||
struct sensor_dv_timings dv_timings;
|
||||
};
|
||||
|
||||
#define SENSOR_SIGNAL_PROPERTIES_CID_SIZE \
|
||||
(sizeof(struct sensor_signal_properties) / sizeof(__u32))
|
||||
#define SENSOR_IMAGE_PROPERTIES_CID_SIZE \
|
||||
(sizeof(struct sensor_image_properties) / sizeof(__u32))
|
||||
#define SENSOR_CONTROL_PROPERTIES_CID_SIZE \
|
||||
(sizeof(struct sensor_control_properties) / sizeof(__u32))
|
||||
#define SENSOR_DV_TIMINGS_CID_SIZE \
|
||||
(sizeof(struct sensor_dv_timings) / sizeof(__u32))
|
||||
#define SENSOR_MODE_PROPERTIES_CID_SIZE \
|
||||
(sizeof(struct sensor_mode_properties) / sizeof(__u32))
|
||||
#define SENSOR_CONFIG_SIZE \
|
||||
(sizeof(struct sensor_cfg) / sizeof(__u32))
|
||||
#define SENSOR_MODE_BLOB_SIZE \
|
||||
(sizeof(struct sensor_blob) / sizeof(__u32))
|
||||
#define SENSOR_CTRL_BLOB_SIZE \
|
||||
(sizeof(struct sensor_blob) / sizeof(__u32))
|
||||
#endif /* __TEGRA_V4L2_CAMERA__ */
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
initial_gain=0
|
||||
initial_exposure_time=0
|
||||
|
||||
while true; do sleep 0.5;
|
||||
# Read center camera controls
|
||||
echo `v4l2-ctl -d /dev/video0 --get-ctrl=gain --get-ctrl=exposure` > controls
|
||||
awk '{print $2}' controls > get_control
|
||||
actual_gain=`cat get_control`
|
||||
awk '{print $4}' controls > get_control
|
||||
actual_exposure_time=`cat get_control`
|
||||
|
||||
# Print controls
|
||||
#echo -e "\n**Center Camera Controls**"
|
||||
#cat controls
|
||||
# Remove temp files
|
||||
rm controls get_control
|
||||
# Set R/L camera controls manually
|
||||
if [ $actual_gain -ne $initial_gain ]; then
|
||||
v4l2-ctl -d /dev/video1 --set-ctrl=gain=$actual_gain
|
||||
fi
|
||||
if [ $actual_exposure_time -ne $initial_exposure_time ]; then
|
||||
v4l2-ctl -d /dev/video1 --set-ctrl=exposure=$actual_exposure_time
|
||||
fi
|
||||
# Define new initial value
|
||||
initial_gain=$actual_gain
|
||||
initial_exposure_time=$actual_exposure_time
|
||||
done
|
Loading…
Reference in New Issue