From 35335a44b66e2e3e79a50381018d9657a053cbd9 Mon Sep 17 00:00:00 2001 From: Praveen AC Date: Wed, 30 Aug 2023 15:49:34 +0000 Subject: [PATCH] nv_hakw_owl: Add 4xHawk and 4xOwl support. Following changes are made to add support 4xHawk & 4xOwl on P3762 / P3783 GMSL board. 1) Driver changes to add i2c address translation. 2) Fix simultaneous streaming of Owl & Hawk. 3) Update ar0234 EEPROM Calibration. 4) Add support for 4xHawks. 5) Add internal Fsync support. 6) Add multiple link combinations for Hawk & Owl. 7) Enable EEPROM support for 4xHawk. Bug 3620984 Bug 3562348 Bug 3866131 Bug 3817827 Bug 3932004 Bug 4071347 Bug 4095571 Bug 4096788 Change-Id: Ic6289f60258d446f259277fdd1d6d52e687dc74e Signed-off-by: Praveen AC Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2971143 Reviewed-by: Laxman Dewangan Reviewed-by: Ankur Pawar GVS: Gerrit_Virtual_Submit --- drivers/media/i2c/Makefile | 1 + drivers/media/i2c/hawk_owl_mode_tbls.h | 1784 ++++++++++++++++++++++++ drivers/media/i2c/nv_hawk_owl.c | 1277 +++++++++++++++++ include/media/camera_common.h | 5 +- 4 files changed, 3065 insertions(+), 2 deletions(-) create mode 100644 drivers/media/i2c/hawk_owl_mode_tbls.h create mode 100644 drivers/media/i2c/nv_hawk_owl.c diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index e9d9e6b5..0982190c 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -18,4 +18,5 @@ obj-m += nv_imx477.o obj-m += nv_ov5693.o obj-m += nv_ar0234.o obj-m += pca9570.o +obj-m += nv_hawk_owl.o endif diff --git a/drivers/media/i2c/hawk_owl_mode_tbls.h b/drivers/media/i2c/hawk_owl_mode_tbls.h new file mode 100644 index 00000000..4ff99c99 --- /dev/null +++ b/drivers/media/i2c/hawk_owl_mode_tbls.h @@ -0,0 +1,1784 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */ +/* + * hawk_owl_mode_tbls.h - ar0234 sensor mode tables + */ + +#ifndef __AR0234_I2C_TABLES__ +#define __AR0234_I2C_TABLES__ +#include +#define AR0234_TABLE_WAIT_MS 0xff00 +#define AR0234_TABLE_END 0xff01 +#define AR0234_MAX_RETRIES 3 +#define AR0234_WAIT_MS_STOP 1 +#define AR0234_WAIT_MS_START 30 +#define AR0234_WAIT_MS_STREAM 210 +#define AR0234_GAIN_TABLE_SIZE 255 +#define AR0234_EEPROM_ADDRESS 0x38 +#define AR0234_EEPROM_ADDRESS_R 0x58 +#define AR0234_EEPROM_SIZE 512 +#define AR0234_EEPROM_STR_SIZE (AR0234_EEPROM_SIZE * 2) +#define AR0234_EEPROM_BLOCK_SIZE (1 << 8) +#define AR0234_EEPROM_NUM_BLOCKS \ + (AR0234_EEPROM_SIZE / AR0234_EEPROM_BLOCK_SIZE) +#define ar0234_reg struct reg_16 +struct index_reg_8 { + u16 source; + u16 addr; + u16 val; +}; +static struct index_reg_8 ar0234_start[] = { + {0x06,0x30ce, 0x0120}, + {0x06,0x301A, 0x295C}, // RESET_REGISTER + {0x00, AR0234_TABLE_END, 0x00} +}; +static struct index_reg_8 ar0234_stop[] = { + {0x06,0x301a, 0x2058}, + {0x00,AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_hawk_Single_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_hawk_Dual_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_hawk_Triple_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x52, 0x0006, 0x77}, + {0x80, 0x0000, 0x98}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_hawk_Quad_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x52, 0x0006, 0x77}, + {0x80, 0x0000, 0x98}, + {0x52, 0x0006, 0xff}, + {0x80, 0x0000, 0x9a}, + {0x00, AR0234_TABLE_END, 0x00} +}; +/* Deser/Ser I2C address translation */ +static struct index_reg_8 i2c_address_trans_Quad_hawk[] = { + /* HAWK1 0x10 -> 0x30, 0x18 -> 0x31 */ + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x20}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x30}, + /* HAWK2 0x10 -> 0x32, 0x18 -> 0x33 */ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x20}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x30}, + /* HAWK3 0x10 -> 0x34, 0x18 -> 0x35 */ + {0x98, 0x0042, 0x68}, + {0x98, 0x0043, 0x20}, + {0x98, 0x0044, 0x6a}, + {0x98, 0x0045, 0x30}, + /* HAWK4 0x10 -> 0x36, 0x18 -> 0x37 */ + {0x9a, 0x0042, 0x6c}, + {0x9a, 0x0043, 0x20}, + {0x9a, 0x0044, 0x6e}, + {0x9a, 0x0045, 0x30}, + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Triple_hawk[] = { + /* HAWK1 0x10 -> 0x30, 0x18 -> 0x31 */ + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x20}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x30}, + /* HAWK2 0x10 -> 0x32, 0x18 -> 0x33 */ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x20}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x30}, + /* HAWK3 0x10 -> 0x34, 0x18 -> 0x35 */ + {0x98, 0x0042, 0x68}, + {0x98, 0x0043, 0x20}, + {0x98, 0x0044, 0x6a}, + {0x98, 0x0045, 0x30}, + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Dual_hawk[] = { + /* HAWK1 0x10 -> 0x30, 0x18 -> 0x31 */ + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x20}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x30}, + /* HAWK2 0x10 -> 0x32, 0x18 -> 0x33 */ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x20}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x30}, + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Single_hawk[] = { + /* HAWK1 0x10 -> 0x30, 0x18 -> 0x31 */ + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x20}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x30}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +/* HAWK EEPROM i2c adddress translation */ +static struct index_reg_8 i2c_address_trans_Quad_hawk_eeprom[] = { + {0x94, 0x0042, 0x80}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x82}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x84}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x86}, + {0x96, 0x0045, 0xAA}, + {0x98, 0x0042, 0x88}, + {0x98, 0x0043, 0xA8}, + {0x98, 0x0044, 0x8A}, + {0x98, 0x0045, 0xAA}, + {0x9a, 0x0042, 0x8C}, + {0x9a, 0x0043, 0xA8}, + {0x9a, 0x0044, 0x8E}, + {0x9a, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Triple_hawk_eeprom[] = { + {0x94, 0x0042, 0x80}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x82}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x84}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x86}, + {0x96, 0x0045, 0xAA}, + {0x98, 0x0042, 0x88}, + {0x98, 0x0043, 0xA8}, + {0x98, 0x0044, 0x8A}, + {0x98, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Dual_hawk_eeprom[] = { + {0x94, 0x0042, 0x80}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x82}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x84}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x86}, + {0x96, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Single_hawk_eeprom[] = { + {0x94, 0x0042, 0x80}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x82}, + {0x94, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_owl_Single_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_owl_Dual_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_owl_Triple_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x52, 0x0006, 0x77}, + {0x80, 0x0000, 0x98}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_owl_Quad_ser[] = { + {0x52, 0x0006, 0x11}, + {0x80, 0x0000, 0x94}, + {0x52, 0x0006, 0x33}, + {0x80, 0x0000, 0x96}, + {0x52, 0x0006, 0x77}, + {0x80, 0x0000, 0x98}, + {0x52, 0x0006, 0xff}, + {0x80, 0x0000, 0x9a}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Quad_owl[] = { + /* OWL A 0x18 -> 0x30 0x43 -> 0x31 */ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x30}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x86}, + + /* OWL B 0x18 -> 0x32, 0x43 - > 0x33*/ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x30}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x86}, + + /* OWL C 0x18 -> 0x34, 0x43 -> 0x35 */ + {0x98, 0x0042, 0x68}, + {0x98, 0x0043, 0x30}, + {0x98, 0x0044, 0x6a}, + {0x98, 0x0045, 0x86}, + + /* OWL D 0x18 -> 0x36, 0x43 -> 0x37 */ + {0x9a, 0x0042, 0x6c}, + {0x9a, 0x0043, 0x30}, + {0x9a, 0x0044, 0x6e}, + {0x9a, 0x0045, 0x86}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Triple_owl[] = { + /* OWL A 0x18 -> 0x30 0x43 -> 0x31 */ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x30}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x86}, + + /* OWL B 0x18 -> 0x32, 0x43 - > 0x33*/ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x30}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x86}, + + /* OWL C 0x18 -> 0x34, 0x43 -> 0x35 */ + {0x98, 0x0042, 0x68}, + {0x98, 0x0043, 0x30}, + {0x98, 0x0044, 0x6a}, + {0x98, 0x0045, 0x86}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Dual_owl[] = { + /* OWL A 0x18 -> 0x30 0x43 -> 0x31 */ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x30}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x86}, + + /* OWL B 0x18 -> 0x32, 0x43 - > 0x33*/ + {0x96, 0x0042, 0x64}, + {0x96, 0x0043, 0x30}, + {0x96, 0x0044, 0x66}, + {0x96, 0x0045, 0x86}, + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Single_owl[] = { + /* OWL A 0x18 -> 0x30 0x43 -> 0x31 */ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0042, 0x60}, + {0x94, 0x0043, 0x30}, + {0x94, 0x0044, 0x62}, + {0x94, 0x0045, 0x86}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Single_owl_eeprom[] = { + {0x94, 0x0042, 0x70}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x72}, + {0x94, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Dual_owl_eeprom[] = { + {0x94, 0x0042, 0x70}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x72}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x74}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x76}, + {0x96, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Triple_owl_eeprom[] = { + {0x94, 0x0042, 0x70}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x72}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x74}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x76}, + {0x96, 0x0045, 0xAA}, + {0x98, 0x0042, 0x78}, + {0x98, 0x0043, 0xA8}, + {0x98, 0x0044, 0x7A}, + {0x98, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 i2c_address_trans_Quad_owl_eeprom[] = { + {0x94, 0x0042, 0x70}, + {0x94, 0x0043, 0xA8}, + {0x94, 0x0044, 0x72}, + {0x94, 0x0045, 0xAA}, + {0x96, 0x0042, 0x74}, + {0x96, 0x0043, 0xA8}, + {0x96, 0x0044, 0x76}, + {0x96, 0x0045, 0xAA}, + {0x98, 0x0042, 0x78}, + {0x98, 0x0043, 0xA8}, + {0x98, 0x0044, 0x7A}, + {0x98, 0x0045, 0xAA}, + {0x9a, 0x0042, 0x7C}, + {0x9a, 0x0043, 0xA8}, + {0x9a, 0x0044, 0x7E}, + {0x9a, 0x0045, 0xAA}, + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 ar0234_Hawk_SingleLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x52, 0x0018, 0x0F}, // Oneshot reset + {0x52, 0x0006, 0xFF}, // Enable links A, B, C & D + + {0x94, 0x0002, 0x33}, // Enable pipes X and Y + {0x94, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x94, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x94, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x94, 0x0314, 0x6b}, // RAW10 to pipe Y + + /*Tuned params to fix streaming issues */ + {0x52, 0x00F0, 0x01}, // Link A ID 0 to pipe 0 // Link A ID 1 to pipe 1 + {0x52, 0x00F1, 0x45}, // Link B ID 0 to pipe 2 // Link B ID 1 to pipe 3 + {0x52, 0x00F2, 0x89}, + {0x52, 0x00F3, 0Xcd}, + + {0x52, 0x08A0, 0x01}, // CSI output is 2x4 + {0x52, 0x08A3, 0x44}, // Default 4x2 lane mapping + {0x52, 0x08A4, 0x44}, // Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40}, // 2 lanes on port D + {0x52, 0x098A, 0x40}, // 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 2500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 2500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + + /* Set Video pipe to MIPI controller */ + /* For HAWK1 */ + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00}, // Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40}, // Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + {0x52, 0x08A2, 0xF0}, + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. + {0x94, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d7, 0x60}, // Enable sensor reset pin. + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02D9, 0x04}, //MFP9 for FSIN + {0x94, 0x02DB, 0x08}, + {0x94, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x94, 0x02De, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00,AR0234_TABLE_END,0x00} +}; + +static struct index_reg_8 ar0234_Hawk_DualLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x52, 0x0018, 0x0F}, // Oneshot reset + {0x52, 0x0006, 0xFF}, // Enable links A, B, C & D + + + {0x94, 0x0002, 0x33}, // Enable pipes X and Y + {0x94, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x94, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x94, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x94, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x96, 0x0002, 0x33}, // Enable pipes X and Y + {0x96, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x96, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x96, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x96, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x52, 0x00F4, 0xff}, // Enable pipe 0 + + /*Tuned params to fix streaming issues */ + {0x52, 0x00F0, 0x01}, // Link A ID 0 to pipe 0 // Link A ID 1 to pipe 1 + {0x52, 0x00F1, 0x45}, // Link B ID 0 to pipe 2 // Link B ID 1 to pipe 3 + {0x52, 0x00F2, 0x89}, + {0x52, 0x00F3, 0Xcd}, + + {0x52, 0x08A0, 0x01}, // CSI output is 2x4 + {0x52, 0x08A3, 0x44}, // Default 4x2 lane mapping + {0x52, 0x08A4, 0x44}, // Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40}, // 2 lanes on port D + {0x52, 0x098A, 0x40}, // 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 2500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 2500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + + /* Set Video pipe to MIPI controller */ + /* For HAWK1 */ + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00}, // Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40}, // Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + /* For HAWK2 */ + {0x52, 0x098B, 0x07}, // Enable 3 mappings Pipe 2 //video1 + {0x52, 0x09AD, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x098D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x098E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x098F, 0x00}, // Input FS, VC0 + {0x52, 0x0990, 0x00},// Output FS, VC0 + {0x52, 0x0991, 0x01}, // Input FE, VC0 + {0x52, 0x0992, 0x01}, // Output FE, VC0 + + {0x52, 0x09CB, 0x07}, // Enable 3 mappings Pipe 3 //video0 + {0x52, 0x09ED, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x09CD, 0x2B}, // Input RAW10, VC0 + {0x52, 0x09CE, 0x6B}, // Output RAW10, VC1 + {0x52, 0x09CF, 0x00}, // Input FS, VC0 + {0x52, 0x09D0, 0x40},// Output FS, VC1 + {0x52, 0x09D1, 0x01}, // Input FE, VC0 + {0x52, 0x09D2, 0x41}, // Output FE, VC1 + + {0x52, 0x08A2, 0xF0}, + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. + {0x94, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. + {0x96, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d7, 0x60}, // Enable sensor reset pin. + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02D9, 0x04}, //MFP9 for FSIN + {0x94, 0x02DB, 0x08}, + {0x94, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x94, 0x02De, 0x08}, + + {0x96, 0x02D9, 0x04}, //MFP9 for FSIN + {0x96, 0x02DB, 0x08}, + {0x96, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x96, 0x02De, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00,AR0234_TABLE_END,0x00} +}; + +static struct index_reg_8 ar0234_Hawk_TripleLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x52, 0x0018, 0x0F}, // Oneshot reset + {0x52, 0x0006, 0xFF}, // Enable links A, B, C & D + + {0x94, 0x0002, 0x33}, // Enable pipes X and Y + {0x94, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x94, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x94, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x94, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x96, 0x0002, 0x33}, // Enable pipes X and Y + {0x96, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x96, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x96, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x96, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x98, 0x0002, 0x33}, // Enable pipes X and Y + {0x98, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x98, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x98, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x98, 0x0314, 0x6b}, // RAW10 to pipe Y + + /*Tuned params to fix streaming issues */ + {0x52, 0x00F0, 0x01}, // Link A ID 0 to pipe 0 // Link A ID 1 to pipe 1 + {0x52, 0x00F1, 0x45}, // Link B ID 0 to pipe 2 // Link B ID 1 to pipe 3 + {0x52, 0x00F2, 0x89}, + {0x52, 0x00F3, 0Xcd}, + + {0x52, 0x08A0, 0x01}, // CSI output is 2x4 + {0x52, 0x08A3, 0x44}, // Default 4x2 lane mapping + {0x52, 0x08A4, 0x44}, // Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40}, // 2 lanes on port D + {0x52, 0x098A, 0x40}, // 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 2500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 2500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + + /* Set Video pipe to MIPI controller */ + /* For HAWK1 */ + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00}, // Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40}, // Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + /* For HAWK2 */ + {0x52, 0x098B, 0x07}, // Enable 3 mappings Pipe 2 //video1 + {0x52, 0x09AD, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x098D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x098E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x098F, 0x00}, // Input FS, VC0 + {0x52, 0x0990, 0x00},// Output FS, VC0 + {0x52, 0x0991, 0x01}, // Input FE, VC0 + {0x52, 0x0992, 0x01}, // Output FE, VC0 + + {0x52, 0x09CB, 0x07}, // Enable 3 mappings Pipe 3 //video0 + {0x52, 0x09ED, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x09CD, 0x2B}, // Input RAW10, VC0 + {0x52, 0x09CE, 0x6B}, // Output RAW10, VC1 + {0x52, 0x09CF, 0x00}, // Input FS, VC0 + {0x52, 0x09D0, 0x40},// Output FS, VC1 + {0x52, 0x09D1, 0x01}, // Input FE, VC0 + {0x52, 0x09D2, 0x41}, // Output FE, VC1 + + /* For HAWK3 */ + {0x52, 0x0A0B, 0x07}, // Enable 3 mappings Pipe 4 i.e RAW10, FS & FE mappings. + {0x52, 0x0A2D, 0x2A}, // Map all 3 mappings to controller 2 + {0x52, 0x0A0D, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0A0E, 0x2B}, // Output RAW10 on VC0 + {0x52, 0x0A0F, 0x00}, // Input FS on VC0 + {0x52, 0x0A10, 0x00}, // Output FS on VC0 + {0x52, 0x0A11, 0x01}, // Input FE on VC0 + {0x52, 0x0A12, 0x01}, // Output FE on VC0 + + {0x52, 0x0A4B, 0x07}, // Enable 3 mappings Pipe 5 i.e RAW10, FS & FE mappings. + {0x52, 0x0A6D, 0x2A}, // Map all 3 mappings to controller 2 + {0x52, 0x0A4D, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0A4E, 0x6B}, // Output RAW10 on VC1 + {0x52, 0x0A4F, 0x00}, // Input FS on VC0 + {0x52, 0x0A50, 0x40}, // Output FS on VC1 + {0x52, 0x0A51, 0x01}, // Input FE on VC0 + {0x52, 0x0A52, 0x41}, // Output FE on VC1 + + {0x52, 0x08A2, 0xF0}, + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. + {0x94, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. + {0x96, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x98, 0x02be, 0x90}, // Enable sensor power down pin. + {0x98, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x98, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x98, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x98, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x98, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x98, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x98, 0x02d7, 0x60}, // Enable sensor reset pin. + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02D9, 0x04}, //MFP9 for FSIN + {0x94, 0x02DB, 0x08}, + {0x94, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x94, 0x02De, 0x08}, + + {0x96, 0x02D9, 0x04}, //MFP9 for FSIN + {0x96, 0x02DB, 0x08}, + {0x96, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x96, 0x02De, 0x08}, + + {0x98, 0x02D9, 0x04}, //MFP9 for FSIN + {0x98, 0x02DB, 0x08}, + {0x98, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x98, 0x02De, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00,AR0234_TABLE_END,0x00} +}; + +static struct index_reg_8 ar0234_Hawk_QuadLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x52, 0x0018, 0x0F}, // Oneshot reset + {0x52, 0x0006, 0xFF}, // Enable links A, B, C & D + + + {0x94, 0x0002, 0x33}, // Enable pipes X and Y + {0x94, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x94, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x94, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x94, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x96, 0x0002, 0x33}, // Enable pipes X and Y + {0x96, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x96, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x96, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x96, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x98, 0x0002, 0x33}, // Enable pipes X and Y + {0x98, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x98, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x98, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x98, 0x0314, 0x6b}, // RAW10 to pipe Y + + {0x9a, 0x0002, 0x33}, // Enable pipes X and Y + {0x9a, 0x0308, 0x7E}, // Pipe X pulls clock from port A, pipe Y from port B + {0x9a, 0x0311, 0x21}, // Pipe X pulls data from port A, pipe Y from port B + {0x9a, 0x0316, 0x6b}, // RAW10 to pipe Y + {0x9a, 0x0314, 0x6b}, // RAW10 to pipe Y + {0x52, 0x00F4, 0xff}, // Enable pipe 0 + + /*Tuned params to fix streaming issues */ + {0x52, 0x00F0, 0x01}, // Link A ID 0 to pipe 0 // Link A ID 1 to pipe 1 + {0x52, 0x00F1, 0x45}, // Link B ID 0 to pipe 2 // Link B ID 1 to pipe 3 + {0x52, 0x00F2, 0x89}, + {0x52, 0x00F3, 0Xcd}, + + {0x52, 0x08A0, 0x01}, // CSI output is 2x4 + {0x52, 0x08A3, 0x44}, // Default 4x2 lane mapping + {0x52, 0x08A4, 0x44}, // Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40}, // 2 lanes on port D + {0x52, 0x098A, 0x40}, // 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 2500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 2500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + + /* Set Video pipe to MIPI controller */ + /* For HAWK1 */ + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00}, // Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00}, // All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40}, // Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + /* For HAWK2 */ + {0x52, 0x098B, 0x07}, // Enable 3 mappings Pipe 2 //video1 + {0x52, 0x09AD, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x098D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x098E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x098F, 0x00}, // Input FS, VC0 + {0x52, 0x0990, 0x00},// Output FS, VC0 + {0x52, 0x0991, 0x01}, // Input FE, VC0 + {0x52, 0x0992, 0x01}, // Output FE, VC0 + + {0x52, 0x09CB, 0x07}, // Enable 3 mappings Pipe 3 //video0 + {0x52, 0x09ED, 0x15}, // All mappings to controller 1 (port A) + {0x52, 0x09CD, 0x2B}, // Input RAW10, VC0 + {0x52, 0x09CE, 0x6B}, // Output RAW10, VC1 + {0x52, 0x09CF, 0x00}, // Input FS, VC0 + {0x52, 0x09D0, 0x40},// Output FS, VC1 + {0x52, 0x09D1, 0x01}, // Input FE, VC0 + {0x52, 0x09D2, 0x41}, // Output FE, VC1 + + /* For HAWK3 */ + {0x52, 0x0A0B, 0x07}, // Enable 3 mappings Pipe 4 i.e RAW10, FS & FE mappings. + {0x52, 0x0A2D, 0x2A}, // Map all 3 mappings to controller 2 + {0x52, 0x0A0D, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0A0E, 0x2B}, // Output RAW10 on VC0 + {0x52, 0x0A0F, 0x00}, // Input FS on VC0 + {0x52, 0x0A10, 0x00}, // Output FS on VC0 + {0x52, 0x0A11, 0x01}, // Input FE on VC0 + {0x52, 0x0A12, 0x01}, // Output FE on VC0 + + {0x52, 0x0A4B, 0x07}, // Enable 3 mappings Pipe 5 i.e RAW10, FS & FE mappings. + {0x52, 0x0A6D, 0x2A}, // Map all 3 mappings to controller 2 + {0x52, 0x0A4D, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0A4E, 0x6B}, // Output RAW10 on VC1 + {0x52, 0x0A4F, 0x00}, // Input FS on VC0 + {0x52, 0x0A50, 0x40}, // Output FS on VC1 + {0x52, 0x0A51, 0x01}, // Input FE on VC0 + {0x52, 0x0A52, 0x41}, // Output FE on VC1 + + /* For HAWK4 */ + {0x52, 0x0A8B, 0x07}, // Enable 3 mappings Pipe 6 i.e RAW10, FS & FE mappings. + {0x52, 0x0AAD, 0x3F}, // Map all 3 mappings to controller 3 + {0x52, 0x0A8D, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0A8E, 0x2B}, // Output RAW10 on VC0 + {0x52, 0x0A8F, 0x00}, // Input FS on VC0 + {0x52, 0x0A90, 0x00}, // Output FS on VC0 + {0x52, 0x0A91, 0x01}, // Input FE on VC0 + {0x52, 0x0A92, 0x01}, // Output FE on VC0 + + {0x52, 0x0ACB, 0x07}, // Enable 3 mappings Pipe 7 i.e RAW10, FS & FE mappings. + {0x52, 0x0AED, 0x3F}, // Map all 3 mappings to controller 3 + {0x52, 0x0ACD, 0x2B}, // Input RAW10 on VC0 + {0x52, 0x0ACE, 0x6B}, // Output RAW10 on VC1 + {0x52, 0x0ACF, 0x00}, // Input FS on VC0 + {0x52, 0x0AD0, 0x40}, // Output FS on VC1 + {0x52, 0x0AD1, 0x01}, // Input FE on VC0 + {0x52, 0x0AD2, 0x41}, // Output FE on VC1 + + {0x52, 0x08A2, 0xF0}, + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. + {0x94, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x94, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x94, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. + {0x96, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x96, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x96, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x98, 0x02be, 0x90}, // Enable sensor power down pin. + {0x98, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x98, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x98, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x98, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x98, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x98, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x98, 0x02d7, 0x60}, // Enable sensor reset pin. + {0x9a, 0x02be, 0x90}, // Enable sensor power down pin. + {0x9a, 0x02bf, 0x60}, // Enable sensor reset pin. + {0x9a, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x9a, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x9a, 0x02d3, 0x90}, // Enable sensor power down pin. + {0x9a, 0x02d4, 0x60}, // Enable sensor reset pin. + {0x9a, 0x02d6, 0x90}, // Enable sensor power down pin. + {0x9a, 0x02d7, 0x60}, // Enable sensor reset pin. + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02D9, 0x04}, //MFP9 for FSIN + {0x94, 0x02DB, 0x08}, + {0x94, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x94, 0x02De, 0x08}, + + {0x96, 0x02D9, 0x04}, //MFP9 for FSIN + {0x96, 0x02DB, 0x08}, + {0x96, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x96, 0x02De, 0x08}, + + {0x98, 0x02D9, 0x04}, //MFP9 for FSIN + {0x98, 0x02DB, 0x08}, + {0x98, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x98, 0x02De, 0x08}, + + {0x9a, 0x02D9, 0x04}, //MFP9 for FSIN + {0x9a, 0x02DB, 0x08}, + {0x9a, 0x02Dc, 0x04}, //MFP10 for FSIN + {0x9a, 0x02De, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00,AR0234_TABLE_END,0x00} +}; + +static struct index_reg_8 ar0234_Owl_SingleLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x94, 0x0010, 0x21}, + {0x52, 0x0006, 0xFF},// Enable links A, B, C, D + /* OWL 1*/ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0311, 0x20}, + {0x94, 0x0308, 0x62}, + {0x94, 0x0316, 0x6b}, + {0x94, 0x0002, 0x23}, + + {0x52, 0x00F4, 0x0f},// Enable pipe 0 -3 + {0x52, 0x00F0, 0x51},// Link A ID 1 to pipe 0 // Link B ID 1 to pipe 1 + {0x52, 0x00F1, 0xD9}, // Link c ID 1 to pipe 2 // Link D ID 1 to pipe 3 + + {0x52, 0x08A0, 0x01},// CSI output is 2x4 + {0x52, 0x08A3, 0x44},// Default 4x2 lane mapping + {0x52, 0x08A4, 0x44},// Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40},// 2 lanes on port D + {0x52, 0x098A, 0x40},// 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 1500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 1500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00},// Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x08A2, 0xF0}, + + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x03F1, 0x00}, + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02C7, 0x04}, //MFP3 for FSIN + {0x94, 0x02C9, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 ar0234_Owl_DualLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x94, 0x0010, 0x21}, + {0x96, 0x0010, 0x21}, + {0x52, 0x0006, 0xFF},// Enable links A, B, C, D + /* OWL 1*/ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0311, 0x20}, + {0x94, 0x0308, 0x62}, + {0x94, 0x0316, 0x6b}, + {0x94, 0x0002, 0x23}, + /* OWL 2*/ + {0x96, 0x0311, 0x20}, + {0x96, 0x0308, 0x62}, + {0x96, 0x0316, 0x6b}, + {0x96, 0x0002, 0x23}, + + {0x52, 0x00F4, 0x0f},// Enable pipe 0 -3 + {0x52, 0x00F0, 0x51},// Link A ID 1 to pipe 0 // Link B ID 1 to pipe 1 + {0x52, 0x00F1, 0xD9}, // Link c ID 1 to pipe 2 // Link D ID 1 to pipe 3 + + {0x52, 0x08A0, 0x01},// CSI output is 2x4 + {0x52, 0x08A3, 0x44},// Default 4x2 lane mapping + {0x52, 0x08A4, 0x44},// Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40},// 2 lanes on port D + {0x52, 0x098A, 0x40},// 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 1500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 1500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00},// Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40},// Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + {0x52, 0x08A2, 0xF0}, + + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x03F1, 0x00}, + + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x03F1, 0x00}, + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02C7, 0x04}, //MFP3 for FSIN + {0x94, 0x02C9, 0x08}, + + {0x96, 0x02C7, 0x04}, //MFP3 for FSIN + {0x96, 0x02C9, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + {0x00,AR0234_TABLE_END,0x00} +}; + +static struct index_reg_8 ar0234_Owl_TripleLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x94, 0x0010, 0x21}, + {0x96, 0x0010, 0x21}, + {0x98, 0x0010, 0x21}, + {0x52, 0x0006, 0xFF},// Enable links A, B, C, D + /* OWL 1*/ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0311, 0x20}, + {0x94, 0x0308, 0x62}, + {0x94, 0x0316, 0x6b}, + {0x94, 0x0002, 0x23}, + /* OWL 2*/ + {0x96, 0x0311, 0x20}, + {0x96, 0x0308, 0x62}, + {0x96, 0x0316, 0x6b}, + {0x96, 0x0002, 0x23}, + /* OWL 3*/ + {0x98, 0x0311, 0x20}, + {0x98, 0x0308, 0x62}, + {0x98, 0x0316, 0x6b}, + {0x98, 0x0002, 0x23}, + + {0x52, 0x00F4, 0x0f},// Enable pipe 0 -3 + {0x52, 0x00F0, 0x51},// Link A ID 1 to pipe 0 // Link B ID 1 to pipe 1 + {0x52, 0x00F1, 0xD9}, // Link c ID 1 to pipe 2 // Link D ID 1 to pipe 3 + + {0x52, 0x08A0, 0x01},// CSI output is 2x4 + {0x52, 0x08A3, 0x44},// Default 4x2 lane mapping + {0x52, 0x08A4, 0x44},// Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40},// 2 lanes on port D + {0x52, 0x098A, 0x40},// 2 lanes on port E + {0x52, 0x09CA, 0x40}, + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 1500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 1500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00},// Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40},// Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + {0x52, 0x098B, 0x07}, // Enable 3 mappings Pipe 2 //video1 + {0x52, 0x09AD, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x098D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x098E, 0xaB}, // Output RAW10, VC2 + {0x52, 0x098F, 0x00}, // Input FS, VC0 + {0x52, 0x0990, 0x80},// Output FS, VC2 + {0x52, 0x0991, 0x01}, // Input FE, VC0 + {0x52, 0x0992, 0x81}, // Output FE, VC2 + + {0x52, 0x08A2, 0xF0}, + + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x03F1, 0x00}, + + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x03F1, 0x00}, + + {0x98, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x98, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x98, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x98, 0x03F1, 0x00}, + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02C7, 0x04}, //MFP3 for FSIN + {0x94, 0x02C9, 0x08}, + + {0x96, 0x02C7, 0x04}, //MFP3 for FSIN + {0x96, 0x02C9, 0x08}, + + {0x98, 0x02C7, 0x04}, //MFP3 for FSIN + {0x98, 0x02C9, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00, AR0234_TABLE_END, 0x00} +}; + +static struct index_reg_8 ar0234_Owl_QuadLink_Dser_Ser[] = { + {0x52, 0x1458, 0x28}, + {0x52, 0x1459, 0x68}, + {0x52, 0x1558, 0x28}, + {0x52, 0x1559, 0x68}, + {0x52, 0x1658, 0x28}, + {0x52, 0x1659, 0x68}, + {0x52, 0x1758, 0x28}, + {0x52, 0x1759, 0x68}, + + {0x94, 0x0010, 0x21}, + {0x96, 0x0010, 0x21}, + {0x98, 0x0010, 0x21}, + {0x9A, 0x0010, 0x21}, + {0x52, 0x0006, 0xFF},// Enable links A, B, C, D + /* OWL 1*/ + {0x94, 0x02be, 0x1d}, + {0x94, 0x0311, 0x20}, + {0x94, 0x0308, 0x62}, + {0x94, 0x0316, 0x6b}, + {0x94, 0x0002, 0x23}, + /* OWL 2*/ + {0x96, 0x0311, 0x20}, + {0x96, 0x0308, 0x62}, + {0x96, 0x0316, 0x6b}, + {0x96, 0x0002, 0x23}, + /* OWL 3*/ + {0x98, 0x0311, 0x20}, + {0x98, 0x0308, 0x62}, + {0x98, 0x0316, 0x6b}, + {0x98, 0x0002, 0x23}, + /* OWL 4*/ + {0x9A, 0x0311, 0x20}, + {0x9A, 0x0308, 0x62}, + {0x9A, 0x0316, 0x6b}, + {0x9A, 0x0002, 0x23}, + + {0x52, 0x00F4, 0x0f},// Enable pipe 0 -3 + {0x52, 0x00F0, 0x51},// Link A ID 1 to pipe 0 // Link B ID 1 to pipe 1 + {0x52, 0x00F1, 0xD9}, // Link c ID 1 to pipe 2 // Link D ID 1 to pipe 3 + + {0x52, 0x08A0, 0x01},// CSI output is 2x4 + {0x52, 0x08A3, 0x44},// Default 4x2 lane mapping + {0x52, 0x08A4, 0x44},// Default 4x2 lane mapping + + {0x52, 0x090A, 0x40}, + {0x52, 0x094A, 0x40},// 2 lanes on port D + {0x52, 0x098A, 0x40},// 2 lanes on port E + {0x52, 0x09CA, 0x40}, + + {0x52, 0x1D00, 0xF4}, + {0x52, 0x1E00, 0xF4}, + + {0x52, 0x0415, 0x39}, + {0x52, 0x0418, 0x39},// 1500Mbps/lane on port D + {0x52, 0x041B, 0x39},// 1500Mbps/lane on port E + {0x52, 0x041E, 0x39}, + + {0x52, 0x1D00, 0xF5}, + {0x52, 0x1E00, 0xF5}, + {0x52, 0x090B, 0x07}, // Enable 3 mappings Pipe 0//video2 + {0x52, 0x092D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x090D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x090E, 0x2B}, // Output RAW10, VC0 + {0x52, 0x090F, 0x00}, // Input FS, VC0 + {0x52, 0x0910, 0x00},// Output FS, VC0 + {0x52, 0x0911, 0x01}, // Input FE, VC0 + {0x52, 0x0912, 0x01}, // Output FE, VC0 + + {0x52, 0x094B, 0x07}, // Enable 3 mappings Pipe 1 //video3 + {0x52, 0x096D, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x094D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x094E, 0x6B}, // Output RAW10, VC1 + {0x52, 0x094F, 0x00}, // Input FS, VC0 + {0x52, 0x0950, 0x40},// Output FS, VC1 + {0x52, 0x0951, 0x01}, // Input FE, VC0 + {0x52, 0x0952, 0x41}, // Output FE, VC1 + + {0x52, 0x098B, 0x07}, // Enable 3 mappings Pipe 2 //video1 + {0x52, 0x09AD, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x098D, 0x2B}, // Input RAW10, VC0 + {0x52, 0x098E, 0xaB}, // Output RAW10, VC2 + {0x52, 0x098F, 0x00}, // Input FS, VC0 + {0x52, 0x0990, 0x80},// Output FS, VC2 + {0x52, 0x0991, 0x01}, // Input FE, VC0 + {0x52, 0x0992, 0x81}, // Output FE, VC2 + + {0x52, 0x09CB, 0x07}, // Enable 3 mappings Pipe 3 //video0 + {0x52, 0x09ED, 0x00},// All mappings to controller 0 (port A) + {0x52, 0x09CD, 0x2B}, // Input RAW10, VC0 + {0x52, 0x09CE, 0xeB}, // Output RAW10, VC3 + {0x52, 0x09CF, 0x00}, // Input FS, VC0 + {0x52, 0x09D0, 0xc0},// Output FS, VC3 + {0x52, 0x09D1, 0x01}, // Input FE, VC0 + {0x52, 0x09D2, 0xc1}, // Output FE, VC3 + {0x52, 0x08A2, 0xF0}, + + {0x94, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x94, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x94, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x94, 0x03F1, 0x00}, + + {0x96, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x96, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x96, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x96, 0x03F1, 0x00}, + + {0x98, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x98, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x98, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x98, 0x03F1, 0x00}, + + {0x9A, 0x02be, 0x90}, // Enable sensor power down pin. Put imager in ,Active mode + {0x9A, 0x02ca, 0x80}, // Enable sensor power down pin. + {0x9A, 0x02cb, 0x60}, // Enable sensor reset pin. + {0x9A, 0x03F1, 0x00}, + + /* Enable internal Fsync */ + {0x52, 0x04AF, 0xC0}, // AUTO_FS_LINKS = 0, FS_USE_XTAL = 1, FS_LINK_[3:0] = 0 + {0x52, 0x04A0, 0x00}, // Manual frame sync, no pin output + {0x52, 0x04A2, 0x00}, // Turn off auto master link selection + {0x52, 0x04AA, 0x00}, // OVLP window = 0 + {0x52, 0x04AB, 0x00}, + {0x52, 0x04A5, 0x35}, // 30Hz FSYNC + {0x52, 0x04A6, 0xB7}, + {0x52, 0x04A7, 0x0C}, + + {0x94, 0x02C7, 0x04}, //MFP3 for FSIN + {0x94, 0x02C9, 0x08}, + + {0x96, 0x02C7, 0x04}, //MFP3 for FSIN + {0x96, 0x02C9, 0x08}, + + {0x98, 0x02C7, 0x04}, //MFP3 for FSIN + {0x98, 0x02C9, 0x08}, + + {0x9A, 0x02C7, 0x04}, //MFP3 for FSIN + {0x9A, 0x02C9, 0x08}, + + {0x52, 0x04B1, 0x40}, // FSYNC TX ID is 8 + + {0x00, AR0234_TABLE_END, 0x00 } +}; +static struct index_reg_8 ar0234_1920x1080_crop_30fps[] = { + {0x06, 0x301A, 0x00D9}, + {0x06, AR0234_TABLE_WAIT_MS, 100}, + {0x06, 0x3F4C, 0x121F}, + {0x06, 0x3F4E, 0x121F}, + {0x06, 0x3F50, 0x0B81}, + {0x06, 0x31E0, 0x0003}, + {0x06, 0x31E0, 0x0003}, + {0x06, 0x30B0, 0x0028}, + {0x06, 0x3088, 0x8000}, + {0x06, 0x3086, 0xC1AE}, + {0x06, 0x3086, 0x327F}, + {0x06, 0x3086, 0x5780}, + {0x06, 0x3086, 0x272F}, + {0x06, 0x3086, 0x7416}, + {0x06, 0x3086, 0x7E13}, + {0x06, 0x3086, 0x8000}, + {0x06, 0x3086, 0x307E}, + {0x06, 0x3086, 0xFF80}, + {0x06, 0x3086, 0x20C3}, + {0x06, 0x3086, 0xB00E}, + {0x06, 0x3086, 0x8190}, + {0x06, 0x3086, 0x1643}, + {0x06, 0x3086, 0x1651}, + {0x06, 0x3086, 0x9D3E}, + {0x06, 0x3086, 0x9545}, + {0x06, 0x3086, 0x2209}, + {0x06, 0x3086, 0x3781}, + {0x06, 0x3086, 0x9016}, + {0x06, 0x3086, 0x4316}, + {0x06, 0x3086, 0x7F90}, + {0x06, 0x3086, 0x8000}, + {0x06, 0x3086, 0x387F}, + {0x06, 0x3086, 0x1380}, + {0x06, 0x3086, 0x233B}, + {0x06, 0x3086, 0x7F93}, + {0x06, 0x3086, 0x4502}, + {0x06, 0x3086, 0x8000}, + {0x06, 0x3086, 0x7FB0}, + {0x06, 0x3086, 0x8D66}, + {0x06, 0x3086, 0x7F90}, + {0x06, 0x3086, 0x8192}, + {0x06, 0x3086, 0x3C16}, + {0x06, 0x3086, 0x357F}, + {0x06, 0x3086, 0x9345}, + {0x06, 0x3086, 0x0280}, + {0x06, 0x3086, 0x007F}, + {0x06, 0x3086, 0xB08D}, + {0x06, 0x3086, 0x667F}, + {0x06, 0x3086, 0x9081}, + {0x06, 0x3086, 0x8237}, + {0x06, 0x3086, 0x4502}, + {0x06, 0x3086, 0x3681}, + {0x06, 0x3086, 0x8044}, + {0x06, 0x3086, 0x1631}, + {0x06, 0x3086, 0x4374}, + {0x06, 0x3086, 0x1678}, + {0x06, 0x3086, 0x7B7D}, + {0x06, 0x3086, 0x4502}, + {0x06, 0x3086, 0x450A}, + {0x06, 0x3086, 0x7E12}, + {0x06, 0x3086, 0x8180}, + {0x06, 0x3086, 0x377F}, + {0x06, 0x3086, 0x1045}, + {0x06, 0x3086, 0x0A0E}, + {0x06, 0x3086, 0x7FD4}, + {0x06, 0x3086, 0x8024}, + {0x06, 0x3086, 0x0E82}, + {0x06, 0x3086, 0x9CC2}, + {0x06, 0x3086, 0xAFA8}, + {0x06, 0x3086, 0xAA03}, + {0x06, 0x3086, 0x430D}, + {0x06, 0x3086, 0x2D46}, + {0x06, 0x3086, 0x4316}, + {0x06, 0x3086, 0x5F16}, + {0x06, 0x3086, 0x530D}, + {0x06, 0x3086, 0x1660}, + {0x06, 0x3086, 0x401E}, + {0x06, 0x3086, 0x2904}, + {0x06, 0x3086, 0x2984}, + {0x06, 0x3086, 0x81E7}, + {0x06, 0x3086, 0x816F}, + {0x06, 0x3086, 0x1706}, + {0x06, 0x3086, 0x81E7}, + {0x06, 0x3086, 0x7F81}, + {0x06, 0x3086, 0x5C0D}, + {0x06, 0x3086, 0x5754}, + {0x06, 0x3086, 0x495F}, + {0x06, 0x3086, 0x5305}, + {0x06, 0x3086, 0x5307}, + {0x06, 0x3086, 0x4D2B}, + {0x06, 0x3086, 0xF810}, + {0x06, 0x3086, 0x164C}, + {0x06, 0x3086, 0x0755}, + {0x06, 0x3086, 0x562B}, + {0x06, 0x3086, 0xB82B}, + {0x06, 0x3086, 0x984E}, + {0x06, 0x3086, 0x1129}, + {0x06, 0x3086, 0x9460}, + {0x06, 0x3086, 0x5C09}, + {0x06, 0x3086, 0x5C1B}, + {0x06, 0x3086, 0x4002}, + {0x06, 0x3086, 0x4500}, + {0x06, 0x3086, 0x4580}, + {0x06, 0x3086, 0x29B6}, + {0x06, 0x3086, 0x7F80}, + {0x06, 0x3086, 0x4004}, + {0x06, 0x3086, 0x7F88}, + {0x06, 0x3086, 0x4109}, + {0x06, 0x3086, 0x5C0B}, + {0x06, 0x3086, 0x29B2}, + {0x06, 0x3086, 0x4115}, + {0x06, 0x3086, 0x5C03}, + {0x06, 0x3086, 0x4105}, + {0x06, 0x3086, 0x5F2B}, + {0x06, 0x3086, 0x902B}, + {0x06, 0x3086, 0x8081}, + {0x06, 0x3086, 0x6F40}, + {0x06, 0x3086, 0x1041}, + {0x06, 0x3086, 0x0160}, + {0x06, 0x3086, 0x29A2}, + {0x06, 0x3086, 0x29A3}, + {0x06, 0x3086, 0x5F4D}, + {0x06, 0x3086, 0x1C17}, + {0x06, 0x3086, 0x0281}, + {0x06, 0x3086, 0xE729}, + {0x06, 0x3086, 0x8345}, + {0x06, 0x3086, 0x8840}, + {0x06, 0x3086, 0x0F7F}, + {0x06, 0x3086, 0x8A40}, + {0x06, 0x3086, 0x2345}, + {0x06, 0x3086, 0x8024}, + {0x06, 0x3086, 0x4008}, + {0x06, 0x3086, 0x7F88}, + {0x06, 0x3086, 0x5D29}, + {0x06, 0x3086, 0x9288}, + {0x06, 0x3086, 0x102B}, + {0x06, 0x3086, 0x0489}, + {0x06, 0x3086, 0x165C}, + {0x06, 0x3086, 0x4386}, + {0x06, 0x3086, 0x170B}, + {0x06, 0x3086, 0x5C03}, + {0x06, 0x3086, 0x8A48}, + {0x06, 0x3086, 0x4D4E}, + {0x06, 0x3086, 0x2B80}, + {0x06, 0x3086, 0x4C09}, + {0x06, 0x3086, 0x4119}, + {0x06, 0x3086, 0x816F}, + {0x06, 0x3086, 0x4110}, + {0x06, 0x3086, 0x4001}, + {0x06, 0x3086, 0x6029}, + {0x06, 0x3086, 0x8229}, + {0x06, 0x3086, 0x8329}, + {0x06, 0x3086, 0x435C}, + {0x06, 0x3086, 0x055F}, + {0x06, 0x3086, 0x4D1C}, + {0x06, 0x3086, 0x81E7}, + {0x06, 0x3086, 0x4502}, + {0x06, 0x3086, 0x8180}, + {0x06, 0x3086, 0x7F80}, + {0x06, 0x3086, 0x410A}, + {0x06, 0x3086, 0x9144}, + {0x06, 0x3086, 0x1609}, + {0x06, 0x3086, 0x2FC3}, + {0x06, 0x3086, 0xB130}, + {0x06, 0x3086, 0xC3B1}, + {0x06, 0x3086, 0x0343}, + {0x06, 0x3086, 0x164A}, + {0x06, 0x3086, 0x0A43}, + {0x06, 0x3086, 0x160B}, + {0x06, 0x3086, 0x4316}, + {0x06, 0x3086, 0x8F43}, + {0x06, 0x3086, 0x1690}, + {0x06, 0x3086, 0x4316}, + {0x06, 0x3086, 0x7F81}, + {0x06, 0x3086, 0x450A}, + {0x06, 0x3086, 0x410F}, + {0x06, 0x3086, 0x7F83}, + {0x06, 0x3086, 0x5D29}, + {0x06, 0x3086, 0x4488}, + {0x06, 0x3086, 0x102B}, + {0x06, 0x3086, 0x0453}, + {0x06, 0x3086, 0x0D40}, + {0x06, 0x3086, 0x2345}, + {0x06, 0x3086, 0x0240}, + {0x06, 0x3086, 0x087F}, + {0x06, 0x3086, 0x8053}, + {0x06, 0x3086, 0x0D89}, + {0x06, 0x3086, 0x165C}, + {0x06, 0x3086, 0x4586}, + {0x06, 0x3086, 0x170B}, + {0x06, 0x3086, 0x5C05}, + {0x06, 0x3086, 0x8A60}, + {0x06, 0x3086, 0x4B91}, + {0x06, 0x3086, 0x4416}, + {0x06, 0x3086, 0x09C1}, + {0x06, 0x3086, 0x2CA9}, + {0x06, 0x3086, 0xAB30}, + {0x06, 0x3086, 0x51B3}, + {0x06, 0x3086, 0x3D5A}, + {0x06, 0x3086, 0x7E3D}, + {0x06, 0x3086, 0x7E19}, + {0x06, 0x3086, 0x8000}, + {0x06, 0x3086, 0x8B1F}, + {0x06, 0x3086, 0x2A1F}, + {0x06, 0x3086, 0x83A2}, + {0x06, 0x3086, 0x7516}, + {0x06, 0x3086, 0xAD33}, + {0x06, 0x3086, 0x450A}, + {0x06, 0x3086, 0x7F53}, + {0x06, 0x3086, 0x8023}, + {0x06, 0x3086, 0x8C66}, + {0x06, 0x3086, 0x7F13}, + {0x06, 0x3086, 0x8184}, + {0x06, 0x3086, 0x1481}, + {0x06, 0x3086, 0x8031}, + {0x06, 0x3086, 0x3D64}, + {0x06, 0x3086, 0x452A}, + {0x06, 0x3086, 0x9451}, + {0x06, 0x3086, 0x9E96}, + {0x06, 0x3086, 0x3D2B}, + {0x06, 0x3086, 0x3D1B}, + {0x06, 0x3086, 0x529F}, + {0x06, 0x3086, 0x0E3D}, + {0x06, 0x3086, 0x083D}, + {0x06, 0x3086, 0x167E}, + {0x06, 0x3086, 0x307E}, + {0x06, 0x3086, 0x1175}, + {0x06, 0x3086, 0x163E}, + {0x06, 0x3086, 0x970E}, + {0x06, 0x3086, 0x82B2}, + {0x06, 0x3086, 0x3D7F}, + {0x06, 0x3086, 0xAC3E}, + {0x06, 0x3086, 0x4502}, + {0x06, 0x3086, 0x7E11}, + {0x06, 0x3086, 0x7FD0}, + {0x06, 0x3086, 0x8000}, + {0x06, 0x3086, 0x8C66}, + {0x06, 0x3086, 0x7F90}, + {0x06, 0x3086, 0x8194}, + {0x06, 0x3086, 0x3F44}, + {0x06, 0x3086, 0x1681}, + {0x06, 0x3086, 0x8416}, + {0x06, 0x3086, 0x2C2C}, + {0x06, 0x3086, 0x2C2C}, + {0x06, 0x302A, 0x0005}, + {0x06, 0x302C, 0x0001}, + {0x06, 0x302E, 0x0003}, + {0x06, 0x3030, 0x0096}, // PLL multiplier + {0x06, 0x302E, 0x0006}, // PLL input pre-divider value + {0x06, 0x302C, 0x0004}, // P1 divider + {0x06, 0x302A, 0x0005}, // P2 divider + {0x06, 0x3038, 0x0004}, // P3 divider + {0x06, 0x3036, 0x000A}, // WCD divider + {0x06, 0x31B0, 0x002F}, // Frame preamble + {0x06, 0x31B2, 0x002C}, // Line preamble + {0x06, 0x31B4, 0x1144}, // MIPI timing 0 + {0x06, 0x31B6, 0x00C7}, // MIPI timing 1 + {0x06, 0x31B8, 0x3047}, // MIPI timing 2 + {0x06, 0x31BA, 0x0103}, // MIPI timing 3 + {0x06, 0x31BC, 0x8583}, // MIPI timing 4 + {0x06, 0x31AE, 0x0204}, // 4-lane MIPI + {0x06, 0x3002, 0x0008}, // Y_ADDR_START = 8 + {0x06, 0x3004, 0x0008}, // X_ADDR_START = 8 + {0x06, 0x3006, 0x04B7}, // Y_ADDR_END = 1207 + {0x06, 0x3008, 0x0787}, // X_ADDR_END = 1927 + {0x06, 0x300A, 0x04C6}, // FRAME_LENGTH_LINES = 1220 + {0x06, 0x300C, 0x0264}, // LINE_LENGTH_PCK = 612 + {0x06, 0x3012, 0x02DC}, // COARSE_INTEGRATION_TIME = 732 + {0x06, 0x31AC, 0x0A0A}, // DATA_FORMAT_BITS = 2570 + {0x06, 0x306E, 0x9010}, // DATAPATH_SELECT = 36880 + {0x06, 0x30A2, 0x0001}, // X_ODD_INC = 1 + {0x06, 0x30A6, 0x0001}, // Y_ODD_INC = 1 + {0x06, 0x3082, 0x0003}, // OPERATION_MODE_CTRL = 3 + {0x06, 0x3040, 0x0000}, // READ_MODE = 0 + {0x06, 0x31D0, 0x0000}, // COMPANDING = 0 + {0x06, 0x3044, 0x0410}, + {0x06, 0x3094, 0x03D4}, + {0x06, 0x3096, 0x0480}, + {0x06, 0x30BA, 0x7602}, + {0x06, 0x30B0, 0x0028}, + {0x06, 0x30FE, 0x002A}, + {0x06, 0x31DE, 0x0410}, + {0x06, 0x3ED6, 0x1435}, + {0x06, 0x3ED8, 0x9865}, + {0x06, 0x3EDA, 0x7698}, + {0x06, 0x3EDC, 0x99FF}, + {0x06, 0x3EE2, 0xBB88}, + {0x06, 0x3EE4, 0x8836}, + {0x06, 0x3EF0, 0x1CF0}, + {0x06, 0x3EF2, 0x0000}, + {0x06, 0x3EF8, 0x6166}, + {0x06, 0x3EFA, 0x3333}, + {0x06, 0x3EFC, 0x6634}, + {0x06, 0x3276, 0x05DC}, + {0x06, 0x3F00, 0x9D05}, + {0x06, 0x3ED2, 0xFA86}, + {0x06, 0x3EEE, 0xA4FE}, + {0x06, 0x30BA, 0x7602}, + {0x06, 0x3180, 0xC24F}, + {0x06, 0x3ECC, 0x6E42}, + {0x06, 0x3ECC, 0x0E42}, + {0x06, 0x3EEC, 0x0C0C}, + {0x06, 0x3EE8, 0xAAE4}, + {0x06, 0x3EE6, 0x3363}, + {0x06, 0x3EE6, 0x3363}, + {0x06, 0x3EE8, 0xAAE4}, + {0x06, 0x3EE8, 0xAAE4}, + {0x06, 0x3102, 0x5000}, + {0x06, 0x3060, 0x000D}, + {0x06, 0x3ED0, 0xFF44}, + {0x06, 0x3ED2, 0xAA86}, + {0x06, 0x3ED4, 0x031F}, + {0x06, 0x3EEE, 0xA4AA}, + {0x06, 0x301a, 0x2058}, + {0x00, AR0234_TABLE_END, 0x00}, +}; +static struct index_reg_8 tp_colorbars[] = { + {0x06,0x3070, 0x2}, + {0x00,AR0234_TABLE_END, 0x00}, +}; +enum { + AR0234_MODE_1920X1080_CROP_30FPS, + AR0234_MODE_START_STREAM, + AR0234_MODE_STOP_STREAM, + AR0234_MODE_HAWK_SINGLELINK_DSER_SER, + AR0234_MODE_OWL_SINGLELINK_DSER_SER, + AR0234_MODE_HAWK_DUALLINK_DSER_SER, + AR0234_MODE_OWL_DUALLINK_DSER_SER, + AR0234_MODE_HAWK_TRIPLELINK_DSER_SER, + AR0234_MODE_OWL_TRIPLELINK_DSER_SER, + AR0234_MODE_HAWK_QUADLINK_DSER_SER, + AR0234_MODE_OWL_QUADLINK_DSER_SER, + AR0234_MODE_TEST_PATTERN +}; +static struct index_reg_8 *mode_table[] = { + [AR0234_MODE_1920X1080_CROP_30FPS] + = ar0234_1920x1080_crop_30fps, + [AR0234_MODE_START_STREAM] + = ar0234_start, + [AR0234_MODE_STOP_STREAM] + = ar0234_stop, + [AR0234_MODE_HAWK_SINGLELINK_DSER_SER] = ar0234_Hawk_SingleLink_Dser_Ser, + [AR0234_MODE_OWL_SINGLELINK_DSER_SER] = ar0234_Owl_SingleLink_Dser_Ser, + [AR0234_MODE_HAWK_DUALLINK_DSER_SER] = ar0234_Hawk_DualLink_Dser_Ser, + [AR0234_MODE_OWL_DUALLINK_DSER_SER] = ar0234_Owl_DualLink_Dser_Ser, + [AR0234_MODE_HAWK_TRIPLELINK_DSER_SER] = ar0234_Hawk_TripleLink_Dser_Ser, + [AR0234_MODE_OWL_TRIPLELINK_DSER_SER] = ar0234_Owl_TripleLink_Dser_Ser, + [AR0234_MODE_HAWK_QUADLINK_DSER_SER] = ar0234_Hawk_QuadLink_Dser_Ser, + [AR0234_MODE_OWL_QUADLINK_DSER_SER] = ar0234_Owl_QuadLink_Dser_Ser, + [AR0234_MODE_TEST_PATTERN] = tp_colorbars, +}; +static const int ar0234_30fps[] = { + 30, +}; +static const int ar0234_60fps[] = { + 60, +}; +static const int ar0234_120fps[] = { + 120, +}; +static const struct camera_common_frmfmt ar0234_frmfmt[] = { + {{1920, 1200}, ar0234_30fps, 1, 0, AR0234_MODE_1920X1080_CROP_30FPS}, +}; +#endif /* __AR0234_I2C_TABLES__ */ diff --git a/drivers/media/i2c/nv_hawk_owl.c b/drivers/media/i2c/nv_hawk_owl.c new file mode 100644 index 00000000..05321c91 --- /dev/null +++ b/drivers/media/i2c/nv_hawk_owl.c @@ -0,0 +1,1277 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. +/* + * nv_hawk_owl.c.c - ar0234 sensor driver + */ + +#define DEBUG 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hawk_owl_mode_tbls.h" +#include +#define CHANNEL_N 13 +#define MAX_RADIAL_COEFFICIENTS 6 +#define MAX_TANGENTIAL_COEFFICIENTS 2 +#define MAX_FISHEYE_COEFFICIENTS 6 +#define CAMERA_MAX_SN_LENGTH 32 +#define MAX_RLS_COLOR_CHANNELS 4 +#define MAX_RLS_BREAKPOINTS 6 +#define OWL_CHANNEL 1 +#define HAWK_CHANNEL 0 + +extern int max96712_write_reg_Dser(int slaveAddr,int channel, + u16 addr, u8 val); +extern int max96712_read_reg_Dser(int slaveAddr,int channel, + u16 addr, unsigned int *val); +#define AR0234_MIN_GAIN (1) +#define AR0234_MAX_GAIN (8) +#define AR0234_MAX_GAIN_REG (0x40) +#define AR0234_DEFAULT_FRAME_LENGTH (1224) +#define AR0234_COARSE_TIME_SHS1_ADDR 0x3012 +#define AR0234_ANALOG_GAIN 0x3060 +static const struct of_device_id ar0234_of_match[] = { + {.compatible = "nvidia,ar0234_hawk_owl",}, + { }, +}; +MODULE_DEVICE_TABLE(of, ar0234_of_match); +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_EEPROM_DATA, + TEGRA_CAMERA_CID_HDR_EN, + TEGRA_CAMERA_CID_SENSOR_MODE_ID, + TEGRA_CAMERA_CID_STEREO_EEPROM, +}; +// Coefficients as per distortion model (wide FOV) being used +typedef struct +{ + // Radial coefficients count + u32 coeff_count; + // Radial coefficients + float k[MAX_FISHEYE_COEFFICIENTS]; + // 0 -> equidistant, 1 -> equisolid, 2 -> orthographic, 3 -> stereographic + u32 mapping_type; +} fisheye_lens_distortion_coeff; +// Coefficients as per distortion model being used +typedef struct +{ + // Radial coefficients count + u32 radial_coeff_count; + // Radial coefficients + float k[MAX_RADIAL_COEFFICIENTS]; + // Tangential coefficients count + u32 tangential_coeff_count; + // Tangential coefficients + float p[MAX_TANGENTIAL_COEFFICIENTS]; +} polynomial_lens_distortion_coeff; +/* + * Stereo Eeprom Data + */ +typedef struct +{ + // Width and height of image in pixels + u32 width, height; + // Focal length in pixels + float fx, fy; + float skew; + // Principal point (optical center) in pixels + float cx, cy; + /* + * Structure for distortion coefficients as per the model being used + * 0: pinhole, assuming polynomial distortion + * 1: fisheye, assuming fisheye distortion) + * 2: ocam (omini-directional) + */ + u32 distortion_type; + union distortion_coefficients { + polynomial_lens_distortion_coeff poly; + fisheye_lens_distortion_coeff fisheye; + } dist_coeff; +} camera_intrinsics; +/* + * Extrinsic parameters shared by camera and IMU. + * All rotation + translation with respect to the same reference point + */ +typedef struct +{ + /* + * Rotation parameter expressed in Rodrigues notation + * angle = sqrt(rx^2+ry^2+rz^2) + * unit axis = [rx,ry,rz]/angle + */ + float rx, ry, rz; + // Translation parameter from one camera to another parameter + float tx, ty, tz; +} camera_extrinsics; +typedef struct +{ + // 3D vector to add to accelerometer readings + float linear_acceleration_bias[3]; + // 3D vector to add to gyroscope readings + float angular_velocity_bias[3]; + // gravity acceleration + float gravity_acceleration[3]; + // Extrinsic structure for IMU device + camera_extrinsics extr; + // Noise model parameters + float update_rate; + float linear_acceleration_noise_density; + float linear_acceleration_random_walk; + float angular_velocity_noise_density; + float angular_velocity_random_walk; +} imu_params; + +typedef struct { + // Image height + u16 image_height; + // Image width + u16 image_width; + // Number of color channels + u8 n_channels; + // Coordinate x of center point + float rls_x0[MAX_RLS_COLOR_CHANNELS]; + // Coordinate y of center point + float rls_y0[MAX_RLS_COLOR_CHANNELS]; + // Ellipse xx parameter + double ekxx[MAX_RLS_COLOR_CHANNELS]; + // Ellipse xy parameter + double ekxy[MAX_RLS_COLOR_CHANNELS]; + // Ellipse yx parameter + double ekyx[MAX_RLS_COLOR_CHANNELS]; + // Ellipse yy parameter + double ekyy[MAX_RLS_COLOR_CHANNELS]; + // Number of breakpoints in LSC radial transfer function + u8 rls_n_points; + // LSC radial transfer function X + float rls_rad_tf_x[MAX_RLS_COLOR_CHANNELS][MAX_RLS_BREAKPOINTS]; + // LSC radial transfer function Y + float rls_rad_tf_y[MAX_RLS_COLOR_CHANNELS][MAX_RLS_BREAKPOINTS]; + // LSC radial transfer function slope + float rls_rad_tf_slope[MAX_RLS_COLOR_CHANNELS][MAX_RLS_BREAKPOINTS]; + // rScale parameter + u8 r_scale; +} radial_lsc_params; + + +typedef struct +{ + // Intrinsic structure for camera device + camera_intrinsics cam_intr; + // Extrinsic structure for camera device + camera_extrinsics cam_extr; + // Flag for IMU availability + u8 imu_present; + + // Intrinsic structure for IMU + imu_params imu; + + // HAWK module serial number + u8 serial_number[CAMERA_MAX_SN_LENGTH]; + + // Radial Lens Shading Correction parameters + radial_lsc_params rls; +} NvCamSyncSensorCalibData; +typedef struct +{ + /** + * EEPROM layout version + */ + u32 version; + /** + * Factory Blob Flag, to set when factory flashed and reset to 0 + * when user modified + */ + u32 factory_data; + /** + * Intrinsic structure for camera device + */ + camera_intrinsics left_cam_intr; + camera_intrinsics right_cam_intr; + /** + * Extrinsic structure for camera device + */ + camera_extrinsics cam_extr; + /** + * Flag for IMU 0-absent, 1-present + */ + u8 imu_present; + /** + * Intrinsic structure for IMU + */ + imu_params imu; + + // HAWK module serial number + u8 serial_number[CAMERA_MAX_SN_LENGTH]; + + // Radial Lens Shading Correction parameters + radial_lsc_params left_rls; + radial_lsc_params right_rls; +} LiEeprom_Content_Struct; +struct ar0234 { + struct camera_common_eeprom_data eeprom[AR0234_EEPROM_NUM_BLOCKS]; + u8 eeprom_buf[AR0234_EEPROM_SIZE]; + struct i2c_client *i2c_client; + const struct i2c_device_id *id; + struct v4l2_subdev *subdev; + u32 frame_length; + struct camera_common_data *s_data; + struct tegracam_device *tc_dev; + u32 channel; + u32 sync_sensor_index; + NvCamSyncSensorCalibData EepromCalib; +}; +static const struct regmap_config sensor_regmap_config = { + .reg_bits = 16, + .val_bits = 16, + .cache_type = REGCACHE_RBTREE, +}; +static inline void ar0234_get_coarse_time_regs_shs1(ar0234_reg *regs, + u16 coarse_time) +{ + regs->addr = AR0234_COARSE_TIME_SHS1_ADDR; + regs->val = (coarse_time) & 0xffff; +} +static inline void ar0234_get_gain_reg(ar0234_reg *regs, + u16 gain) +{ + regs->addr = AR0234_ANALOG_GAIN; + regs->val = (gain) & 0xffff; +} +static int test_mode; +module_param(test_mode, int, 0644); +static inline int ar0234_read_reg(struct camera_common_data *s_data, + u16 addr, u16 *val) +{ + int err = 0; + u32 reg_val = 0; + err = regmap_read(s_data->regmap, addr, ®_val); + *val = reg_val & 0xFFFF; + return err; +} +static int ar0234_write_reg(struct camera_common_data *s_data, + u16 addr, u16 val) +{ + int err; + struct device *dev = s_data->dev; + err = regmap_write(s_data->regmap, addr, val); + if (err) + dev_err(dev, "%s:i2c write failed, 0x%x = %x\n", + __func__, addr, val); + return err; +} +static int ar0234_write_table(struct ar0234 *priv, + const struct index_reg_8 table[]) +{ + struct tegracam_device *tc_dev = priv->tc_dev; + struct device *dev = tc_dev->dev; + int i = 0; + int ret = 0; + int retry = 5; + int retry_seraddr = 0x84; + dev_dbg(dev, "%s: channel %d, ", __func__, priv->channel); + while (table[i].source != 0x00) { + if (table[i].source == 0x06) { + retry = 1; + if (table[i].addr == AR0234_TABLE_WAIT_MS) + { + dev_err(dev, "%s: sleep 500\n", __func__); + msleep(table[i].val); + i++; + continue; + } +retry_sensor: + ret = ar0234_write_reg(priv->s_data, table[i].addr, table[i].val); + if (ret) { + retry--; + if (retry > 0) { + dev_warn(dev, "ar0234_write_reg: try %d\n", retry); + msleep(4); + goto retry_sensor; + } + return -1; + } else { + if (0x301a == table[i].addr || 0x3060 == table[i].addr) + msleep(100); + } + } else { + retry = 5; + if (priv->channel == CHANNEL_N) + { + i++; + continue; + } +retry_serdes: + /* To handle sync sensor i2c trans */ + if (2 == priv->sync_sensor_index) + ret = max96712_write_reg_Dser(table[i].source, + 0/*channel-num*/, table[i].addr, (u8)table[i].val); + else + ret = max96712_write_reg_Dser(table[i].source, + priv->channel, table[i].addr, (u8)table[i].val); + /* To handle ser address change from 0x80 to 0x84 + * after link enable at deser*/ + if (ret && (0x80 == table[i].source)) { + ret = max96712_write_reg_Dser(retry_seraddr, + priv->channel, table[i].addr, (u8)table[i].val); + } + if (ret && (table[i].addr != 0x0000)) + { + retry--; + if (retry > 0) { + dev_warn(dev, "max96712_write_reg_Dser: try %d\n", retry); + msleep(4); + goto retry_serdes; + } + return -1; + } + if (0x0010 == table[i].addr || 0x0000 == table[i].addr || + 0x0006 == table[i].addr || 0x0018 == table[i].addr) + msleep(300); + else + msleep(10); + } + i++; + } + return 0; +} + +static int ar0234_hawk_link_check(struct ar0234 *priv) +{ + unsigned int linkA = 0; + unsigned int linkB = 0; + unsigned int linkC = 0; + unsigned int linkD = 0; + + if ((1 == priv->channel)) { + max96712_read_reg_Dser(0x52, OWL_CHANNEL, 0x1A, &linkA); + max96712_read_reg_Dser(0x52, OWL_CHANNEL, 0x0A, &linkB); + max96712_read_reg_Dser(0x52, OWL_CHANNEL, 0x0B, &linkC); + max96712_read_reg_Dser(0x52, OWL_CHANNEL, 0x0C, &linkD); + + } else if ((!priv->channel) || (2 == priv->sync_sensor_index)) { + max96712_read_reg_Dser(0x52, HAWK_CHANNEL, 0x1A, &linkA); + max96712_read_reg_Dser(0x52, HAWK_CHANNEL, 0x0A, &linkB); + max96712_read_reg_Dser(0x52, HAWK_CHANNEL, 0x0B, &linkC); + max96712_read_reg_Dser(0x52, HAWK_CHANNEL, 0x0C, &linkD); + } + pr_info("%s: linA=%x, linB=%x, linC=%x, linD=%x\n",__func__, linkA, linkB, linkC, linkD); + if((linkB & 0x8) && (linkA & 0x8) && (linkC & 0x8) && (linkD & 0x8)) { + return 4; + } else if((linkB & 0x8) && (linkA & 0x8) && (linkC & 0x8) ){ + return 3; + } else if((linkB & 0x8) && (linkA & 0x8)){ + return 2; + } else if(linkA & 0x8) { + return 1; + } else { + return 0; + } +} + +static int ar0234_hawk_owl_i2ctrans(struct ar0234 *priv) +{ + int err = 0; + + if(ar0234_hawk_link_check(priv) == 4) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Quad_owl); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } else if ((!priv->channel) || (2 == priv->sync_sensor_index)) { + err = ar0234_write_table(priv, i2c_address_trans_Quad_hawk); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } + } else if(ar0234_hawk_link_check(priv) == 3) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Triple_owl); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } else if ((!priv->channel) || (2 == priv->sync_sensor_index)) { + err = ar0234_write_table(priv, i2c_address_trans_Triple_hawk); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } + } else if(ar0234_hawk_link_check(priv) == 2) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Dual_owl); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } else if ((!priv->channel) || (2 == priv->sync_sensor_index)) { + err = ar0234_write_table(priv, i2c_address_trans_Dual_hawk); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } + } else if(ar0234_hawk_link_check(priv) == 1) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Single_owl); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } else if ((!priv->channel) || (2 == priv->sync_sensor_index)) { + err = ar0234_write_table(priv, i2c_address_trans_Single_hawk); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + } + } + + return err; +} +static int ar0234_enable_pwdn_gpio(struct camera_common_data *s_data) +{ + int err = 0; + struct camera_common_power_rail *pw = s_data->power; + struct ar0234 *priv = (struct ar0234 *) s_data->priv; + static int haw_flag = 0, owl_flag = 0; + if (pw->pwdn_gpio > 0) + gpio_set_value(pw->pwdn_gpio, 1); + + msleep(100); + /* Serializer i2c address trans */ + if(ar0234_hawk_link_check(priv) == 4) { + if ((1 == priv->channel) && !owl_flag) { + err = ar0234_write_table(priv, i2c_address_trans_owl_Quad_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + owl_flag++; + + } else if ((!priv->channel) && !haw_flag) { + err = ar0234_write_table(priv, i2c_address_trans_hawk_Quad_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + haw_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 3) { + if ((1 == priv->channel) && !owl_flag) { + err = ar0234_write_table(priv, i2c_address_trans_owl_Triple_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + owl_flag++; + + } else if ((!priv->channel) && !haw_flag) { + err = ar0234_write_table(priv, i2c_address_trans_hawk_Triple_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + haw_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 2) { + if ((1 == priv->channel) && !owl_flag) { + err = ar0234_write_table(priv, i2c_address_trans_owl_Dual_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + owl_flag++; + + } else if ((!priv->channel) && !haw_flag) { + err = ar0234_write_table(priv, i2c_address_trans_hawk_Dual_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + haw_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 1) { + if ((1 == priv->channel) && !owl_flag) { + err = ar0234_write_table(priv, i2c_address_trans_owl_Single_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + owl_flag++; + + } else if ((!priv->channel) && !haw_flag) { + err = ar0234_write_table(priv, i2c_address_trans_hawk_Single_ser); + if (err) { + pr_err("%s: Failed to do i2c address trans..\n",__func__); + } else { + pr_err("%s: Successfully done I2c address trans..\n",__func__); + } + haw_flag++; + } + } + + return err; +} +static int ar0234_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; + struct ar0234 *priv = (struct ar0234 *) s_data->priv; + 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; + } + if (pw->reset_gpio > 0) + gpio_set_value(pw->reset_gpio, 1); + usleep_range(1000, 2000); + pw->state = SWITCH_ON; + /*i2c address trans for Hawk & Owl*/ + err = ar0234_hawk_owl_i2ctrans(priv); + return 0; +} +static int ar0234_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; + dev_err(dev, "%s:\n", __func__); + if (pdata && pdata->power_off) { + err = pdata->power_off(pw); + if (!err) + goto power_off_done; + else + dev_err(dev, "%s failed.\n", __func__); + return err; + } +power_off_done: + pw->state = SWITCH_OFF; + return 0; +} +static int ar0234_power_get(struct tegracam_device *tc_dev) +{ + struct device *dev = tc_dev->dev; + struct camera_common_data *s_data = tc_dev->s_data; + struct camera_common_power_rail *pw = s_data->power; + struct camera_common_pdata *pdata = s_data->pdata; + const char *mclk_name; + const char *parentclk_name; + struct clk *parent; + int err = 0; + mclk_name = pdata->mclk_name ? + pdata->mclk_name : "cam_mclk1"; + pw->mclk = devm_clk_get(dev, mclk_name); + if (IS_ERR(pw->mclk)) { + dev_err(dev, "unable to get clock %s\n", mclk_name); + return PTR_ERR(pw->mclk); + } + parentclk_name = pdata->parentclk_name; + if (parentclk_name) { + parent = devm_clk_get(dev, parentclk_name); + if (IS_ERR(parent)) { + dev_err(dev, "unable to get parent clcok %s", + parentclk_name); + } else + clk_set_parent(pw->mclk, parent); + } + if (!err) { + pw->reset_gpio = pdata->reset_gpio; + pw->af_gpio = pdata->af_gpio; + pw->pwdn_gpio = pdata->pwdn_gpio; + } + pw->state = SWITCH_OFF; + return err; +} +static int ar0234_power_put(struct tegracam_device *tc_dev) +{ + struct camera_common_data *s_data = tc_dev->s_data; + struct camera_common_power_rail *pw = s_data->power; + if (unlikely(!pw)) + return -EFAULT; + return 0; +} +static int ar0234_set_group_hold(struct tegracam_device *tc_dev, bool val) +{ + struct device *dev = tc_dev->dev; + int err = 0; + if (err) { + dev_err(dev, + "%s: Group hold control error\n", __func__); + return err; + } + return 0; +} +static int ar0234_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; + ar0234_reg reg_list[1]; + int err; + u16 gain = (u16)val; + u16 gain_reg = 0; + if (val < 200) { + gain_reg = (32 * (1000 - (100000/gain)))/1000; + } else if (val < 400 && val >= 200) { + gain = gain /2; + gain_reg = (16 * (1000 - (100000/gain)))/1000 * 2; + gain_reg = gain_reg + 0x10; + } else if (val < 800 && val >= 400) { + gain = gain / 4; + gain_reg = (32 * (1000 - (100000/gain)))/1000; + gain_reg = gain_reg + 0x20; + } else if (val < 1600 && val >= 800) { + gain = gain /8; + gain_reg = (16 * (1000 - (100000/gain)))/1000 * 2; + gain_reg = gain_reg + 0x30; + } else if (val >= 1600) { + gain_reg = 0x40; + } + if (gain > AR0234_MAX_GAIN_REG) + gain = AR0234_MAX_GAIN_REG; + ar0234_get_gain_reg(reg_list, gain_reg); + err = ar0234_write_reg(s_data, reg_list[0].addr, + reg_list[0].val); + if (err) + goto fail; + return 0; +fail: + dev_err(dev, "%s: GAIN control error\n", __func__); + return err; +} +static int ar0234_set_frame_rate(struct tegracam_device *tc_dev, s64 val) +{ + struct ar0234 *priv = (struct ar0234 *)tegracam_get_privdata(tc_dev); + if (val == 30000000) { //30fps full resolution + max96712_write_reg_Dser(0x52, priv->channel, 0x04A5, 0x35); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A6, 0xB7); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A7, 0x0C); + priv->frame_length = 0xC20; + } else if (val == 60000000) {//60fps full resolution + max96712_write_reg_Dser(0x52, priv->channel, 0x04A5, 0x9A); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A6, 0x5B); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A7, 0x06); + priv->frame_length = 0x610; + } else if (val == 120000000) {//120fps binning resolution + max96712_write_reg_Dser(0x52, priv->channel, 0x04A5, 0xCD); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A6, 0x2D); + max96712_write_reg_Dser(0x52, priv->channel, 0x04A7, 0x03); + priv->frame_length = 0x308; + } + return 0; +} +static int ar0234_set_exposure(struct tegracam_device *tc_dev, s64 val) +{ + struct ar0234 *priv = (struct ar0234 *)tegracam_get_privdata(tc_dev); + struct camera_common_data *s_data = tc_dev->s_data; + const struct sensor_mode_properties *mode = + &s_data->sensor_props.sensor_modes[s_data->mode]; + ar0234_reg reg_list[1]; + int err; + u32 coarse_time; + u32 shs1; + if (priv->frame_length == 0) + priv->frame_length = AR0234_DEFAULT_FRAME_LENGTH; + coarse_time = mode->signal_properties.pixel_clock.val * + val / mode->image_properties.line_length / + mode->control_properties.exposure_factor; + if (coarse_time > priv->frame_length) + coarse_time = priv->frame_length; + shs1 = coarse_time; + /* 0 and 1 are prohibited */ + if (shs1 < 2) + shs1 = 2; + ar0234_get_coarse_time_regs_shs1(reg_list, shs1); + err = ar0234_write_reg(priv->s_data, reg_list[0].addr, + reg_list[0].val); + if (err) + goto fail; + return 0; +fail: + dev_err(&priv->i2c_client->dev, + "%s: set coarse time error\n", __func__); + return err; +} +static int ar0234_fill_string_ctrl(struct tegracam_device *tc_dev, + struct v4l2_ctrl *ctrl) +{ + struct ar0234 *priv = tc_dev->priv; + int i, ret; + switch (ctrl->id) { + case TEGRA_CAMERA_CID_EEPROM_DATA: + for (i = 0; i < AR0234_EEPROM_SIZE; i++) { + ret = sprintf(&ctrl->p_new.p_char[i*2], "%02x", + priv->eeprom_buf[i]); + if (ret < 0) + return -EINVAL; + } + break; + default: + return -EINVAL; + } + ctrl->p_cur.p_char = ctrl->p_new.p_char; + return 0; +} +static int ar0234_fill_eeprom(struct tegracam_device *tc_dev, + struct v4l2_ctrl *ctrl) +{ + struct ar0234 *priv = tc_dev->priv; + LiEeprom_Content_Struct tmp; + u32 test = 0; + switch (ctrl->id) { + case TEGRA_CAMERA_CID_STEREO_EEPROM: + memset(&(priv->EepromCalib), 0, sizeof(NvCamSyncSensorCalibData)); + memset(ctrl->p_new.p, 0, sizeof(NvCamSyncSensorCalibData)); + memcpy(&tmp, priv->eeprom_buf, sizeof(LiEeprom_Content_Struct)); + if (priv->sync_sensor_index == 1) { + priv->EepromCalib.cam_intr = tmp.left_cam_intr; + } else if (priv->sync_sensor_index == 2) { + priv->EepromCalib.cam_intr = tmp.right_cam_intr; + } else { + priv->EepromCalib.cam_intr = tmp.left_cam_intr; + } + priv->EepromCalib.cam_extr = tmp.cam_extr; + priv->EepromCalib.imu_present = tmp.imu_present; + priv->EepromCalib.imu = tmp.imu; + memcpy(priv->EepromCalib.serial_number, tmp.serial_number, + CAMERA_MAX_SN_LENGTH); + + if (priv->sync_sensor_index == 1) + priv->EepromCalib.rls = tmp.left_rls; + else if (priv->sync_sensor_index == 2) + priv->EepromCalib.rls = tmp.right_rls; + else + priv->EepromCalib.rls = tmp.left_rls; + + memcpy(ctrl->p_new.p, (u8 *)&(priv->EepromCalib), + sizeof(NvCamSyncSensorCalibData)); + break; + default: + return -EINVAL; + } + memcpy(&test, &(priv->EepromCalib.cam_intr.fx), 4); + ctrl->p_cur.p = ctrl->p_new.p; + return 0; +} +static struct tegracam_ctrl_ops ar0234_ctrl_ops = { + .numctrls = ARRAY_SIZE(ctrl_cid_list), + .ctrl_cid_list = ctrl_cid_list, + .string_ctrl_size = {AR0234_EEPROM_STR_SIZE}, + .compound_ctrl_size = {sizeof(NvCamSyncSensorCalibData)}, + .set_gain = ar0234_set_gain, + .set_exposure = ar0234_set_exposure, + .set_exposure_short = ar0234_set_exposure, + .set_frame_rate = ar0234_set_frame_rate, + .set_group_hold = ar0234_set_group_hold, + .fill_string_ctrl = ar0234_fill_string_ctrl, + .fill_compound_ctrl = ar0234_fill_eeprom, +}; +static struct camera_common_pdata *ar0234_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; + int gpio = 0; + if (!node) + return NULL; + match = of_match_device(ar0234_of_match, dev); + if (!match) { + dev_err(dev, "Failed to find matching dt id\n"); + 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, "mclk not in DT\n"); + board_priv_pdata->reset_gpio = of_get_named_gpio(node, + "reset-gpios", 0); + gpio_direction_output(board_priv_pdata->reset_gpio, 1); + board_priv_pdata->pwdn_gpio = of_get_named_gpio(node, + "pwdn-gpios", 0); + gpio_direction_output(board_priv_pdata->pwdn_gpio, 1); + gpio = of_get_named_gpio(node, + "pwr-gpios", 0); + gpio_direction_output(gpio, 1); + board_priv_pdata->has_eeprom = + of_property_read_bool(node, "has-eeprom"); + + if (board_priv_pdata->has_eeprom) { + err = of_property_read_u32(node, "eeprom-addr", &board_priv_pdata->eeprom_id_addr); + if (err) + dev_err(dev, "Failed to read eeprom addr\n"); + } + return board_priv_pdata; +} +static int ar0234_set_mode(struct tegracam_device *tc_dev) +{ + struct ar0234 *priv = (struct ar0234 *)tegracam_get_privdata(tc_dev); + struct camera_common_data *s_data = tc_dev->s_data; + struct device *dev = tc_dev->dev; + const struct of_device_id *match; + int err; + match = of_match_device(ar0234_of_match, dev); + if (!match) { + dev_err(dev, "Failed to find matching dt id\n"); + return -EINVAL; + } + err = ar0234_write_table(priv, mode_table[AR0234_MODE_STOP_STREAM]); + if (err) + return err; + if (s_data->mode_prop_idx < 0) + return -EINVAL; + dev_err(dev, "%s: mode index:%d\n", __func__,s_data->mode_prop_idx); + err = ar0234_write_table(priv, mode_table[s_data->mode_prop_idx]); + if (err) + return err; + return 0; +} +static int ar0234_start_streaming(struct tegracam_device *tc_dev) +{ + struct ar0234 *priv = (struct ar0234 *)tegracam_get_privdata(tc_dev); + int err; + if (test_mode) { + err = ar0234_write_table(priv, + mode_table[AR0234_MODE_TEST_PATTERN]); + if (err) + return err; + } + err = ar0234_write_table(priv, + mode_table[AR0234_MODE_START_STREAM]); + if (err) + return err; + return 0; +} +static int ar0234_stop_streaming(struct tegracam_device *tc_dev) +{ + struct ar0234 *priv = (struct ar0234 *)tegracam_get_privdata(tc_dev); + int err; + err = ar0234_write_table(priv, mode_table[AR0234_MODE_STOP_STREAM]); + if (err) + return err; + return 0; +} +static struct camera_common_sensor_ops ar0234_common_ops = { + .numfrmfmts = ARRAY_SIZE(ar0234_frmfmt), + .frmfmt_table = ar0234_frmfmt, + .power_on = ar0234_power_on, + .power_off = ar0234_power_off, + .parse_dt = ar0234_parse_dt, + .power_get = ar0234_power_get, + .power_put = ar0234_power_put, + .set_mode = ar0234_set_mode, + .start_streaming = ar0234_start_streaming, + .stop_streaming = ar0234_stop_streaming, +}; +static int ar0234_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + dev_err(&client->dev, "%s:\n", __func__); + return 0; +} +static int ar0234_eeprom_device_release(struct ar0234 *priv) +{ + int i; + for (i = 0; i < AR0234_EEPROM_NUM_BLOCKS; i++) { + if (priv->eeprom[i].i2c_client != NULL) { + i2c_unregister_device(priv->eeprom[i].i2c_client); + priv->eeprom[i].i2c_client = NULL; + } + } + return 0; +} +static const struct v4l2_subdev_internal_ops ar0234_subdev_internal_ops = { + .open = ar0234_open, +}; +static int ar0234_eeprom_device_init(struct ar0234 *priv) +{ + struct camera_common_pdata *pdata = priv->s_data->pdata; + char *dev_name = "eeprom_ar0234"; + static struct regmap_config eeprom_regmap_config = { + .reg_bits = 8, + .val_bits = 8 + }; + int i; + int err; + + if (!pdata->has_eeprom) + return -EINVAL; + for (i = 0; i < AR0234_EEPROM_NUM_BLOCKS; i++) { + priv->eeprom[i].adap = i2c_get_adapter( + priv->i2c_client->adapter->nr); + memset(&priv->eeprom[i].brd, 0, sizeof(priv->eeprom[i].brd)); + strncpy(priv->eeprom[i].brd.type, dev_name, + sizeof(priv->eeprom[i].brd.type)); + + /* assign the EEPROM addrs which is read from DT */ + priv->eeprom[i].brd.addr = pdata->eeprom_id_addr + i; +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) + priv->eeprom[i].i2c_client = i2c_new_device( + priv->eeprom[i].adap, &priv->eeprom[i].brd); +#else + priv->eeprom[i].i2c_client = i2c_new_client_device( + priv->eeprom[i].adap, &priv->eeprom[i].brd); +#endif + if (!priv->eeprom[i].i2c_client) { + pr_err("%s: Failed to probe EEPORM at addr = 0x%x \n", + __func__, priv->eeprom[i].brd.addr); + return 0; + } + priv->eeprom[i].regmap = devm_regmap_init_i2c( + priv->eeprom[i].i2c_client, &eeprom_regmap_config); + if (IS_ERR(priv->eeprom[i].regmap)) { + err = PTR_ERR(priv->eeprom[i].regmap); + ar0234_eeprom_device_release(priv); + return err; + } + } + return 0; +} +static int ar0234_read_eeprom(struct ar0234 *priv) +{ + int err, i; + for (i = 0; i < AR0234_EEPROM_NUM_BLOCKS; i++) { + err = regmap_bulk_read(priv->eeprom[i].regmap, 0, + &priv->eeprom_buf[i * AR0234_EEPROM_BLOCK_SIZE], + AR0234_EEPROM_BLOCK_SIZE); + if (err) { + return err; + } + } +#if DEBUG + /* Print added, Remove later */ + for (i = 0; i < AR0234_EEPROM_BLOCK_SIZE; i+=8) { + pr_err("%02x %02x %02x %02x %02x %02x %02x %02x",priv->eeprom_buf[i+0],\ + priv->eeprom_buf[i+1],priv->eeprom_buf[i+2],priv->eeprom_buf[i+3],\ + priv->eeprom_buf[i+4],priv->eeprom_buf[i+5],priv->eeprom_buf[i+6], + priv->eeprom_buf[i+7]); + pr_err("\n"); + } +#endif + return 0; +} +static int ar0234_board_setup(struct ar0234 *priv) +{ + struct camera_common_data *s_data = priv->s_data; + struct device *dev = s_data->dev; + bool eeprom_ctrl = 0; + int err = 0; + dev_err(dev, "%s++\n", __func__); + /* eeprom interface */ + err = ar0234_eeprom_device_init(priv); + if (err && s_data->pdata->has_eeprom) + dev_err(dev, + "Failed to allocate eeprom reg map: %d\n", err); + eeprom_ctrl = !err; + err = camera_common_mclk_enable(s_data); + if (err) { + dev_err(dev, + "Error %d turning on mclk\n", err); + return err; + } + if (eeprom_ctrl) { + err = ar0234_read_eeprom(priv); + if (err) { + dev_err(dev, + "Error %d reading eeprom\n", err); + goto error; + } + } +error: + ar0234_power_off(s_data); + camera_common_mclk_disable(s_data); + return err; +} + +static int ar0234_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 ar0234 *priv; + const char *str; + int err; + static int hawk_flag = 0, owl_flag = 0; + dev_info(dev, "probing v4l2 sensor.\n"); + if (!IS_ENABLED(CONFIG_OF) || !node) + return -EINVAL; + priv = devm_kzalloc(dev, sizeof(struct ar0234), GFP_KERNEL); + if (!priv) { + dev_err(dev, "unable to allocate memory!\n"); + return -ENOMEM; + } + tc_dev = devm_kzalloc(dev, + sizeof(struct tegracam_device), GFP_KERNEL); + if (!tc_dev) + return -ENOMEM; + err = of_property_read_string(node, "channel", &str); + if (err) + dev_err(dev, "channel not found\n"); + priv->channel = str[0] - 'a'; + dev_err(dev, "%s: channel %d\n", __func__, priv->channel); + err = of_property_read_u32(node, "sync_sensor_index", + &priv->sync_sensor_index); + if (err) + dev_err(dev, "sync name index not in DT\n"); + priv->i2c_client = tc_dev->client = client; + tc_dev->dev = dev; + strncpy(tc_dev->name, "ar0234", sizeof(tc_dev->name)); + tc_dev->dev_regmap_config = &sensor_regmap_config; + tc_dev->sensor_ops = &ar0234_common_ops; + tc_dev->v4l2sd_internal_ops = &ar0234_subdev_internal_ops; + tc_dev->tcctrl_ops = &ar0234_ctrl_ops; + err = tegracam_device_register(tc_dev); + if (err) { + dev_err(dev, "tegra camera driver registration failed\n"); + 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); + /*Power down gpio enable */ + ar0234_enable_pwdn_gpio(tc_dev->s_data); + ar0234_power_on(tc_dev->s_data); + msleep(100); + err = ar0234_write_table(priv, mode_table[AR0234_MODE_STOP_STREAM]); + if (err) { + dev_err(&client->dev,"ar0234 detect error\n"); + return err; + } + msleep(100); + /* Deser/ser programming */ + if(ar0234_hawk_link_check(priv) == 4) { + if ((1 == priv->channel) && (!owl_flag)) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_OWL_QUADLINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do OWL mode table..\n",__func__); + else + pr_err("%s: Successfully done OWL mode table ..\n",__func__); + owl_flag++; + } + if ((!priv->channel) && !hawk_flag) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_HAWK_QUADLINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do Hawk mode table..\n",__func__); + else + pr_err("%s: Successfully done Hawk mode table ..\n",__func__); + hawk_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 3) { + if ((1 == priv->channel) && (!owl_flag)) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_OWL_TRIPLELINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do OWL mode table..\n",__func__); + else + pr_err("%s: Successfully done OWL mode table ..\n",__func__); + owl_flag++; + } + if ((!priv->channel) && !hawk_flag) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_HAWK_TRIPLELINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do Hawk mode table..\n",__func__); + else + pr_err("%s: Successfully done Hawk mode table ..\n",__func__); + hawk_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 2) { + if ((1 == priv->channel) && (!owl_flag)) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_OWL_DUALLINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do OWL mode table..\n",__func__); + else + pr_err("%s: Successfully done OWL mode table ..\n",__func__); + owl_flag++; + } + if ((!priv->channel) && !hawk_flag) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_HAWK_DUALLINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do Hawk mode table..\n",__func__); + else + pr_err("%s: Successfully done Hawk mode table ..\n",__func__); + hawk_flag++; + } + } else if(ar0234_hawk_link_check(priv) == 1) { + if ((1 == priv->channel) && (!owl_flag)) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_OWL_SINGLELINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do OWL mode table..\n",__func__); + else + pr_err("%s: Successfully done OWL mode table ..\n",__func__); + owl_flag++; + } + if ((!priv->channel) && !hawk_flag) { + err = ar0234_write_table(priv, mode_table[AR0234_MODE_HAWK_SINGLELINK_DSER_SER]); + if (err) + pr_err("%s: Failed to do Hawk mode table..\n",__func__); + else + pr_err("%s: Successfully done Hawk mode table ..\n",__func__); + hawk_flag++; + } + } + /* i2c address trans for EEPROM access */ + if(ar0234_hawk_link_check(priv) == 4) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Quad_owl_eeprom); + if (err) { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans success!!!\n"); + } + } else if ((!priv->channel) || (priv->sync_sensor_index == 2)) { + err = ar0234_write_table(priv, i2c_address_trans_Quad_hawk_eeprom); + if (err) { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans success!!!\n"); + } + } + } else if(ar0234_hawk_link_check(priv) == 3) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Triple_owl_eeprom); + if (err) { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans success!!!\n"); + } + } else if ((!priv->channel) || (priv->sync_sensor_index == 2)) { + err = ar0234_write_table(priv, i2c_address_trans_Triple_hawk_eeprom); + if (err) { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans success!!!\n"); + } + } + } else if(ar0234_hawk_link_check(priv) == 2) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Dual_owl_eeprom); + if (err) { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans success!!!\n"); + } + } else if ((!priv->channel) || (priv->sync_sensor_index == 2)) { + err = ar0234_write_table(priv, i2c_address_trans_Dual_hawk_eeprom); + if (err) { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans success!!!\n"); + } + } + } else if(ar0234_hawk_link_check(priv) == 1) { + if ((1 == priv->channel)) { + err = ar0234_write_table(priv, i2c_address_trans_Single_owl_eeprom); + if (err) { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Owl camera Eeprom i2c address trans success!!!\n"); + } + } else if ((!priv->channel) || (priv->sync_sensor_index == 2)) { + err = ar0234_write_table(priv, i2c_address_trans_Single_hawk_eeprom); + if (err) { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans error\n"); + return err; + } else { + dev_err(&client->dev,"Hawk camera Eeprom i2c address trans success!!!\n"); + } + } + } + + err = ar0234_board_setup(priv); + if (err) { + dev_err(dev, "board setup failed\n"); + return err; + } + + /* Un-register i2c client for EEPROM, + * so we can re-use i2c address for 2nd sensor of HAWK module */ + ar0234_eeprom_device_release(priv); + + /* re-i2c address trans for Hawk & Owl sensors */ + err = ar0234_hawk_owl_i2ctrans(priv); + if (err) { + dev_err(dev, "failed to do re-i2c address translation\n"); + return err; + } + err = tegracam_v4l2subdev_register(tc_dev, true); + if (err) { + dev_err(dev, "tegra camera subdev registration failed\n"); + return err; + } + dev_err(&client->dev, "Detected AR0234 sensor\n"); + return 0; +} +static int ar0234_remove(struct i2c_client *client) +{ + struct camera_common_data *s_data = to_camera_common_data(&client->dev); + struct ar0234 *priv = (struct ar0234 *)s_data->priv; + tegracam_v4l2subdev_unregister(priv->tc_dev); + tegracam_device_unregister(priv->tc_dev); + ar0234_eeprom_device_release(priv); + return 0; +} +static const struct i2c_device_id ar0234_id[] = { + { "ar0234", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ar0234_id); +static struct i2c_driver ar0234_i2c_driver = { + .driver = { + .name = "ar0234", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ar0234_of_match), + }, + .probe = ar0234_probe, + .remove = ar0234_remove, + .id_table = ar0234_id, +}; +module_i2c_driver(ar0234_i2c_driver); +MODULE_DESCRIPTION("Media Controller driver for Sony AR0234"); +MODULE_AUTHOR("NVIDIA Corporation"); +MODULE_AUTHOR("Praveen AC