18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (c) 2017 Intel Corporation. 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/acpi.h> 58c2ecf20Sopenharmony_ci#include <linux/i2c.h> 68c2ecf20Sopenharmony_ci#include <linux/module.h> 78c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 88c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 98c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 108c2ecf20Sopenharmony_ci#include <media/v4l2-fwnode.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define OV13858_REG_VALUE_08BIT 1 138c2ecf20Sopenharmony_ci#define OV13858_REG_VALUE_16BIT 2 148c2ecf20Sopenharmony_ci#define OV13858_REG_VALUE_24BIT 3 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define OV13858_REG_MODE_SELECT 0x0100 178c2ecf20Sopenharmony_ci#define OV13858_MODE_STANDBY 0x00 188c2ecf20Sopenharmony_ci#define OV13858_MODE_STREAMING 0x01 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define OV13858_REG_SOFTWARE_RST 0x0103 218c2ecf20Sopenharmony_ci#define OV13858_SOFTWARE_RST 0x01 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* PLL1 generates PCLK and MIPI_PHY_CLK */ 248c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_0 0x0300 258c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_1 0x0301 268c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_2 0x0302 278c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_3 0x0303 288c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_4 0x0304 298c2ecf20Sopenharmony_ci#define OV13858_REG_PLL1_CTRL_5 0x0305 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* PLL2 generates DAC_CLK, SCLK and SRAM_CLK */ 328c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_B 0x030b 338c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_C 0x030c 348c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_D 0x030d 358c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_E 0x030e 368c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_F 0x030f 378c2ecf20Sopenharmony_ci#define OV13858_REG_PLL2_CTRL_12 0x0312 388c2ecf20Sopenharmony_ci#define OV13858_REG_MIPI_SC_CTRL0 0x3016 398c2ecf20Sopenharmony_ci#define OV13858_REG_MIPI_SC_CTRL1 0x3022 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Chip ID */ 428c2ecf20Sopenharmony_ci#define OV13858_REG_CHIP_ID 0x300a 438c2ecf20Sopenharmony_ci#define OV13858_CHIP_ID 0x00d855 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* V_TIMING internal */ 468c2ecf20Sopenharmony_ci#define OV13858_REG_VTS 0x380e 478c2ecf20Sopenharmony_ci#define OV13858_VTS_30FPS 0x0c8e /* 30 fps */ 488c2ecf20Sopenharmony_ci#define OV13858_VTS_60FPS 0x0648 /* 60 fps */ 498c2ecf20Sopenharmony_ci#define OV13858_VTS_MAX 0x7fff 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* HBLANK control - read only */ 528c2ecf20Sopenharmony_ci#define OV13858_PPL_270MHZ 2244 538c2ecf20Sopenharmony_ci#define OV13858_PPL_540MHZ 4488 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* Exposure control */ 568c2ecf20Sopenharmony_ci#define OV13858_REG_EXPOSURE 0x3500 578c2ecf20Sopenharmony_ci#define OV13858_EXPOSURE_MIN 4 588c2ecf20Sopenharmony_ci#define OV13858_EXPOSURE_STEP 1 598c2ecf20Sopenharmony_ci#define OV13858_EXPOSURE_DEFAULT 0x640 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* Analog gain control */ 628c2ecf20Sopenharmony_ci#define OV13858_REG_ANALOG_GAIN 0x3508 638c2ecf20Sopenharmony_ci#define OV13858_ANA_GAIN_MIN 0 648c2ecf20Sopenharmony_ci#define OV13858_ANA_GAIN_MAX 0x1fff 658c2ecf20Sopenharmony_ci#define OV13858_ANA_GAIN_STEP 1 668c2ecf20Sopenharmony_ci#define OV13858_ANA_GAIN_DEFAULT 0x80 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Digital gain control */ 698c2ecf20Sopenharmony_ci#define OV13858_REG_B_MWB_GAIN 0x5100 708c2ecf20Sopenharmony_ci#define OV13858_REG_G_MWB_GAIN 0x5102 718c2ecf20Sopenharmony_ci#define OV13858_REG_R_MWB_GAIN 0x5104 728c2ecf20Sopenharmony_ci#define OV13858_DGTL_GAIN_MIN 0 738c2ecf20Sopenharmony_ci#define OV13858_DGTL_GAIN_MAX 16384 /* Max = 16 X */ 748c2ecf20Sopenharmony_ci#define OV13858_DGTL_GAIN_DEFAULT 1024 /* Default gain = 1 X */ 758c2ecf20Sopenharmony_ci#define OV13858_DGTL_GAIN_STEP 1 /* Each step = 1/1024 */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* Test Pattern Control */ 788c2ecf20Sopenharmony_ci#define OV13858_REG_TEST_PATTERN 0x4503 798c2ecf20Sopenharmony_ci#define OV13858_TEST_PATTERN_ENABLE BIT(7) 808c2ecf20Sopenharmony_ci#define OV13858_TEST_PATTERN_MASK 0xfc 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* Number of frames to skip */ 838c2ecf20Sopenharmony_ci#define OV13858_NUM_OF_SKIP_FRAMES 2 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct ov13858_reg { 868c2ecf20Sopenharmony_ci u16 address; 878c2ecf20Sopenharmony_ci u8 val; 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistruct ov13858_reg_list { 918c2ecf20Sopenharmony_ci u32 num_of_regs; 928c2ecf20Sopenharmony_ci const struct ov13858_reg *regs; 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* Link frequency config */ 968c2ecf20Sopenharmony_cistruct ov13858_link_freq_config { 978c2ecf20Sopenharmony_ci u32 pixels_per_line; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* PLL registers for this link frequency */ 1008c2ecf20Sopenharmony_ci struct ov13858_reg_list reg_list; 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* Mode : resolution and related config&values */ 1048c2ecf20Sopenharmony_cistruct ov13858_mode { 1058c2ecf20Sopenharmony_ci /* Frame width */ 1068c2ecf20Sopenharmony_ci u32 width; 1078c2ecf20Sopenharmony_ci /* Frame height */ 1088c2ecf20Sopenharmony_ci u32 height; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* V-timing */ 1118c2ecf20Sopenharmony_ci u32 vts_def; 1128c2ecf20Sopenharmony_ci u32 vts_min; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Index of Link frequency config to be used */ 1158c2ecf20Sopenharmony_ci u32 link_freq_index; 1168c2ecf20Sopenharmony_ci /* Default register values */ 1178c2ecf20Sopenharmony_ci struct ov13858_reg_list reg_list; 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* 4224x3136 needs 1080Mbps/lane, 4 lanes */ 1218c2ecf20Sopenharmony_cistatic const struct ov13858_reg mipi_data_rate_1080mbps[] = { 1228c2ecf20Sopenharmony_ci /* PLL1 registers */ 1238c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_0, 0x07}, 1248c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_1, 0x01}, 1258c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_2, 0xc2}, 1268c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_3, 0x00}, 1278c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_4, 0x00}, 1288c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_5, 0x01}, 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* PLL2 registers */ 1318c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_B, 0x05}, 1328c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_C, 0x01}, 1338c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_D, 0x0e}, 1348c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_E, 0x05}, 1358c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_F, 0x01}, 1368c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_12, 0x01}, 1378c2ecf20Sopenharmony_ci {OV13858_REG_MIPI_SC_CTRL0, 0x72}, 1388c2ecf20Sopenharmony_ci {OV13858_REG_MIPI_SC_CTRL1, 0x01}, 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* 1428c2ecf20Sopenharmony_ci * 2112x1568, 2112x1188, 1056x784 need 540Mbps/lane, 1438c2ecf20Sopenharmony_ci * 4 lanes 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_cistatic const struct ov13858_reg mipi_data_rate_540mbps[] = { 1468c2ecf20Sopenharmony_ci /* PLL1 registers */ 1478c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_0, 0x07}, 1488c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_1, 0x01}, 1498c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_2, 0xc2}, 1508c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_3, 0x01}, 1518c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_4, 0x00}, 1528c2ecf20Sopenharmony_ci {OV13858_REG_PLL1_CTRL_5, 0x01}, 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* PLL2 registers */ 1558c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_B, 0x05}, 1568c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_C, 0x01}, 1578c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_D, 0x0e}, 1588c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_E, 0x05}, 1598c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_F, 0x01}, 1608c2ecf20Sopenharmony_ci {OV13858_REG_PLL2_CTRL_12, 0x01}, 1618c2ecf20Sopenharmony_ci {OV13858_REG_MIPI_SC_CTRL0, 0x72}, 1628c2ecf20Sopenharmony_ci {OV13858_REG_MIPI_SC_CTRL1, 0x01}, 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic const struct ov13858_reg mode_4224x3136_regs[] = { 1668c2ecf20Sopenharmony_ci {0x3013, 0x32}, 1678c2ecf20Sopenharmony_ci {0x301b, 0xf0}, 1688c2ecf20Sopenharmony_ci {0x301f, 0xd0}, 1698c2ecf20Sopenharmony_ci {0x3106, 0x15}, 1708c2ecf20Sopenharmony_ci {0x3107, 0x23}, 1718c2ecf20Sopenharmony_ci {0x350a, 0x00}, 1728c2ecf20Sopenharmony_ci {0x350e, 0x00}, 1738c2ecf20Sopenharmony_ci {0x3510, 0x00}, 1748c2ecf20Sopenharmony_ci {0x3511, 0x02}, 1758c2ecf20Sopenharmony_ci {0x3512, 0x00}, 1768c2ecf20Sopenharmony_ci {0x3600, 0x2b}, 1778c2ecf20Sopenharmony_ci {0x3601, 0x52}, 1788c2ecf20Sopenharmony_ci {0x3602, 0x60}, 1798c2ecf20Sopenharmony_ci {0x3612, 0x05}, 1808c2ecf20Sopenharmony_ci {0x3613, 0xa4}, 1818c2ecf20Sopenharmony_ci {0x3620, 0x80}, 1828c2ecf20Sopenharmony_ci {0x3621, 0x10}, 1838c2ecf20Sopenharmony_ci {0x3622, 0x30}, 1848c2ecf20Sopenharmony_ci {0x3624, 0x1c}, 1858c2ecf20Sopenharmony_ci {0x3640, 0x10}, 1868c2ecf20Sopenharmony_ci {0x3641, 0x70}, 1878c2ecf20Sopenharmony_ci {0x3660, 0x04}, 1888c2ecf20Sopenharmony_ci {0x3661, 0x80}, 1898c2ecf20Sopenharmony_ci {0x3662, 0x12}, 1908c2ecf20Sopenharmony_ci {0x3664, 0x73}, 1918c2ecf20Sopenharmony_ci {0x3665, 0xa7}, 1928c2ecf20Sopenharmony_ci {0x366e, 0xff}, 1938c2ecf20Sopenharmony_ci {0x366f, 0xf4}, 1948c2ecf20Sopenharmony_ci {0x3674, 0x00}, 1958c2ecf20Sopenharmony_ci {0x3679, 0x0c}, 1968c2ecf20Sopenharmony_ci {0x367f, 0x01}, 1978c2ecf20Sopenharmony_ci {0x3680, 0x0c}, 1988c2ecf20Sopenharmony_ci {0x3681, 0x50}, 1998c2ecf20Sopenharmony_ci {0x3682, 0x50}, 2008c2ecf20Sopenharmony_ci {0x3683, 0xa9}, 2018c2ecf20Sopenharmony_ci {0x3684, 0xa9}, 2028c2ecf20Sopenharmony_ci {0x3709, 0x5f}, 2038c2ecf20Sopenharmony_ci {0x3714, 0x24}, 2048c2ecf20Sopenharmony_ci {0x371a, 0x3e}, 2058c2ecf20Sopenharmony_ci {0x3737, 0x04}, 2068c2ecf20Sopenharmony_ci {0x3738, 0xcc}, 2078c2ecf20Sopenharmony_ci {0x3739, 0x12}, 2088c2ecf20Sopenharmony_ci {0x373d, 0x26}, 2098c2ecf20Sopenharmony_ci {0x3764, 0x20}, 2108c2ecf20Sopenharmony_ci {0x3765, 0x20}, 2118c2ecf20Sopenharmony_ci {0x37a1, 0x36}, 2128c2ecf20Sopenharmony_ci {0x37a8, 0x3b}, 2138c2ecf20Sopenharmony_ci {0x37ab, 0x31}, 2148c2ecf20Sopenharmony_ci {0x37c2, 0x04}, 2158c2ecf20Sopenharmony_ci {0x37c3, 0xf1}, 2168c2ecf20Sopenharmony_ci {0x37c5, 0x00}, 2178c2ecf20Sopenharmony_ci {0x37d8, 0x03}, 2188c2ecf20Sopenharmony_ci {0x37d9, 0x0c}, 2198c2ecf20Sopenharmony_ci {0x37da, 0xc2}, 2208c2ecf20Sopenharmony_ci {0x37dc, 0x02}, 2218c2ecf20Sopenharmony_ci {0x37e0, 0x00}, 2228c2ecf20Sopenharmony_ci {0x37e1, 0x0a}, 2238c2ecf20Sopenharmony_ci {0x37e2, 0x14}, 2248c2ecf20Sopenharmony_ci {0x37e3, 0x04}, 2258c2ecf20Sopenharmony_ci {0x37e4, 0x2a}, 2268c2ecf20Sopenharmony_ci {0x37e5, 0x03}, 2278c2ecf20Sopenharmony_ci {0x37e6, 0x04}, 2288c2ecf20Sopenharmony_ci {0x3800, 0x00}, 2298c2ecf20Sopenharmony_ci {0x3801, 0x00}, 2308c2ecf20Sopenharmony_ci {0x3802, 0x00}, 2318c2ecf20Sopenharmony_ci {0x3803, 0x08}, 2328c2ecf20Sopenharmony_ci {0x3804, 0x10}, 2338c2ecf20Sopenharmony_ci {0x3805, 0x9f}, 2348c2ecf20Sopenharmony_ci {0x3806, 0x0c}, 2358c2ecf20Sopenharmony_ci {0x3807, 0x57}, 2368c2ecf20Sopenharmony_ci {0x3808, 0x10}, 2378c2ecf20Sopenharmony_ci {0x3809, 0x80}, 2388c2ecf20Sopenharmony_ci {0x380a, 0x0c}, 2398c2ecf20Sopenharmony_ci {0x380b, 0x40}, 2408c2ecf20Sopenharmony_ci {0x380c, 0x04}, 2418c2ecf20Sopenharmony_ci {0x380d, 0x62}, 2428c2ecf20Sopenharmony_ci {0x380e, 0x0c}, 2438c2ecf20Sopenharmony_ci {0x380f, 0x8e}, 2448c2ecf20Sopenharmony_ci {0x3811, 0x04}, 2458c2ecf20Sopenharmony_ci {0x3813, 0x05}, 2468c2ecf20Sopenharmony_ci {0x3814, 0x01}, 2478c2ecf20Sopenharmony_ci {0x3815, 0x01}, 2488c2ecf20Sopenharmony_ci {0x3816, 0x01}, 2498c2ecf20Sopenharmony_ci {0x3817, 0x01}, 2508c2ecf20Sopenharmony_ci {0x3820, 0xa8}, 2518c2ecf20Sopenharmony_ci {0x3821, 0x00}, 2528c2ecf20Sopenharmony_ci {0x3822, 0xc2}, 2538c2ecf20Sopenharmony_ci {0x3823, 0x18}, 2548c2ecf20Sopenharmony_ci {0x3826, 0x11}, 2558c2ecf20Sopenharmony_ci {0x3827, 0x1c}, 2568c2ecf20Sopenharmony_ci {0x3829, 0x03}, 2578c2ecf20Sopenharmony_ci {0x3832, 0x00}, 2588c2ecf20Sopenharmony_ci {0x3c80, 0x00}, 2598c2ecf20Sopenharmony_ci {0x3c87, 0x01}, 2608c2ecf20Sopenharmony_ci {0x3c8c, 0x19}, 2618c2ecf20Sopenharmony_ci {0x3c8d, 0x1c}, 2628c2ecf20Sopenharmony_ci {0x3c90, 0x00}, 2638c2ecf20Sopenharmony_ci {0x3c91, 0x00}, 2648c2ecf20Sopenharmony_ci {0x3c92, 0x00}, 2658c2ecf20Sopenharmony_ci {0x3c93, 0x00}, 2668c2ecf20Sopenharmony_ci {0x3c94, 0x40}, 2678c2ecf20Sopenharmony_ci {0x3c95, 0x54}, 2688c2ecf20Sopenharmony_ci {0x3c96, 0x34}, 2698c2ecf20Sopenharmony_ci {0x3c97, 0x04}, 2708c2ecf20Sopenharmony_ci {0x3c98, 0x00}, 2718c2ecf20Sopenharmony_ci {0x3d8c, 0x73}, 2728c2ecf20Sopenharmony_ci {0x3d8d, 0xc0}, 2738c2ecf20Sopenharmony_ci {0x3f00, 0x0b}, 2748c2ecf20Sopenharmony_ci {0x3f03, 0x00}, 2758c2ecf20Sopenharmony_ci {0x4001, 0xe0}, 2768c2ecf20Sopenharmony_ci {0x4008, 0x00}, 2778c2ecf20Sopenharmony_ci {0x4009, 0x0f}, 2788c2ecf20Sopenharmony_ci {0x4011, 0xf0}, 2798c2ecf20Sopenharmony_ci {0x4017, 0x08}, 2808c2ecf20Sopenharmony_ci {0x4050, 0x04}, 2818c2ecf20Sopenharmony_ci {0x4051, 0x0b}, 2828c2ecf20Sopenharmony_ci {0x4052, 0x00}, 2838c2ecf20Sopenharmony_ci {0x4053, 0x80}, 2848c2ecf20Sopenharmony_ci {0x4054, 0x00}, 2858c2ecf20Sopenharmony_ci {0x4055, 0x80}, 2868c2ecf20Sopenharmony_ci {0x4056, 0x00}, 2878c2ecf20Sopenharmony_ci {0x4057, 0x80}, 2888c2ecf20Sopenharmony_ci {0x4058, 0x00}, 2898c2ecf20Sopenharmony_ci {0x4059, 0x80}, 2908c2ecf20Sopenharmony_ci {0x405e, 0x20}, 2918c2ecf20Sopenharmony_ci {0x4500, 0x07}, 2928c2ecf20Sopenharmony_ci {0x4503, 0x00}, 2938c2ecf20Sopenharmony_ci {0x450a, 0x04}, 2948c2ecf20Sopenharmony_ci {0x4809, 0x04}, 2958c2ecf20Sopenharmony_ci {0x480c, 0x12}, 2968c2ecf20Sopenharmony_ci {0x481f, 0x30}, 2978c2ecf20Sopenharmony_ci {0x4833, 0x10}, 2988c2ecf20Sopenharmony_ci {0x4837, 0x0e}, 2998c2ecf20Sopenharmony_ci {0x4902, 0x01}, 3008c2ecf20Sopenharmony_ci {0x4d00, 0x03}, 3018c2ecf20Sopenharmony_ci {0x4d01, 0xc9}, 3028c2ecf20Sopenharmony_ci {0x4d02, 0xbc}, 3038c2ecf20Sopenharmony_ci {0x4d03, 0xd7}, 3048c2ecf20Sopenharmony_ci {0x4d04, 0xf0}, 3058c2ecf20Sopenharmony_ci {0x4d05, 0xa2}, 3068c2ecf20Sopenharmony_ci {0x5000, 0xfd}, 3078c2ecf20Sopenharmony_ci {0x5001, 0x01}, 3088c2ecf20Sopenharmony_ci {0x5040, 0x39}, 3098c2ecf20Sopenharmony_ci {0x5041, 0x10}, 3108c2ecf20Sopenharmony_ci {0x5042, 0x10}, 3118c2ecf20Sopenharmony_ci {0x5043, 0x84}, 3128c2ecf20Sopenharmony_ci {0x5044, 0x62}, 3138c2ecf20Sopenharmony_ci {0x5180, 0x00}, 3148c2ecf20Sopenharmony_ci {0x5181, 0x10}, 3158c2ecf20Sopenharmony_ci {0x5182, 0x02}, 3168c2ecf20Sopenharmony_ci {0x5183, 0x0f}, 3178c2ecf20Sopenharmony_ci {0x5200, 0x1b}, 3188c2ecf20Sopenharmony_ci {0x520b, 0x07}, 3198c2ecf20Sopenharmony_ci {0x520c, 0x0f}, 3208c2ecf20Sopenharmony_ci {0x5300, 0x04}, 3218c2ecf20Sopenharmony_ci {0x5301, 0x0c}, 3228c2ecf20Sopenharmony_ci {0x5302, 0x0c}, 3238c2ecf20Sopenharmony_ci {0x5303, 0x0f}, 3248c2ecf20Sopenharmony_ci {0x5304, 0x00}, 3258c2ecf20Sopenharmony_ci {0x5305, 0x70}, 3268c2ecf20Sopenharmony_ci {0x5306, 0x00}, 3278c2ecf20Sopenharmony_ci {0x5307, 0x80}, 3288c2ecf20Sopenharmony_ci {0x5308, 0x00}, 3298c2ecf20Sopenharmony_ci {0x5309, 0xa5}, 3308c2ecf20Sopenharmony_ci {0x530a, 0x00}, 3318c2ecf20Sopenharmony_ci {0x530b, 0xd3}, 3328c2ecf20Sopenharmony_ci {0x530c, 0x00}, 3338c2ecf20Sopenharmony_ci {0x530d, 0xf0}, 3348c2ecf20Sopenharmony_ci {0x530e, 0x01}, 3358c2ecf20Sopenharmony_ci {0x530f, 0x10}, 3368c2ecf20Sopenharmony_ci {0x5310, 0x01}, 3378c2ecf20Sopenharmony_ci {0x5311, 0x20}, 3388c2ecf20Sopenharmony_ci {0x5312, 0x01}, 3398c2ecf20Sopenharmony_ci {0x5313, 0x20}, 3408c2ecf20Sopenharmony_ci {0x5314, 0x01}, 3418c2ecf20Sopenharmony_ci {0x5315, 0x20}, 3428c2ecf20Sopenharmony_ci {0x5316, 0x08}, 3438c2ecf20Sopenharmony_ci {0x5317, 0x08}, 3448c2ecf20Sopenharmony_ci {0x5318, 0x10}, 3458c2ecf20Sopenharmony_ci {0x5319, 0x88}, 3468c2ecf20Sopenharmony_ci {0x531a, 0x88}, 3478c2ecf20Sopenharmony_ci {0x531b, 0xa9}, 3488c2ecf20Sopenharmony_ci {0x531c, 0xaa}, 3498c2ecf20Sopenharmony_ci {0x531d, 0x0a}, 3508c2ecf20Sopenharmony_ci {0x5405, 0x02}, 3518c2ecf20Sopenharmony_ci {0x5406, 0x67}, 3528c2ecf20Sopenharmony_ci {0x5407, 0x01}, 3538c2ecf20Sopenharmony_ci {0x5408, 0x4a}, 3548c2ecf20Sopenharmony_ci}; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic const struct ov13858_reg mode_2112x1568_regs[] = { 3578c2ecf20Sopenharmony_ci {0x3013, 0x32}, 3588c2ecf20Sopenharmony_ci {0x301b, 0xf0}, 3598c2ecf20Sopenharmony_ci {0x301f, 0xd0}, 3608c2ecf20Sopenharmony_ci {0x3106, 0x15}, 3618c2ecf20Sopenharmony_ci {0x3107, 0x23}, 3628c2ecf20Sopenharmony_ci {0x350a, 0x00}, 3638c2ecf20Sopenharmony_ci {0x350e, 0x00}, 3648c2ecf20Sopenharmony_ci {0x3510, 0x00}, 3658c2ecf20Sopenharmony_ci {0x3511, 0x02}, 3668c2ecf20Sopenharmony_ci {0x3512, 0x00}, 3678c2ecf20Sopenharmony_ci {0x3600, 0x2b}, 3688c2ecf20Sopenharmony_ci {0x3601, 0x52}, 3698c2ecf20Sopenharmony_ci {0x3602, 0x60}, 3708c2ecf20Sopenharmony_ci {0x3612, 0x05}, 3718c2ecf20Sopenharmony_ci {0x3613, 0xa4}, 3728c2ecf20Sopenharmony_ci {0x3620, 0x80}, 3738c2ecf20Sopenharmony_ci {0x3621, 0x10}, 3748c2ecf20Sopenharmony_ci {0x3622, 0x30}, 3758c2ecf20Sopenharmony_ci {0x3624, 0x1c}, 3768c2ecf20Sopenharmony_ci {0x3640, 0x10}, 3778c2ecf20Sopenharmony_ci {0x3641, 0x70}, 3788c2ecf20Sopenharmony_ci {0x3660, 0x04}, 3798c2ecf20Sopenharmony_ci {0x3661, 0x80}, 3808c2ecf20Sopenharmony_ci {0x3662, 0x10}, 3818c2ecf20Sopenharmony_ci {0x3664, 0x73}, 3828c2ecf20Sopenharmony_ci {0x3665, 0xa7}, 3838c2ecf20Sopenharmony_ci {0x366e, 0xff}, 3848c2ecf20Sopenharmony_ci {0x366f, 0xf4}, 3858c2ecf20Sopenharmony_ci {0x3674, 0x00}, 3868c2ecf20Sopenharmony_ci {0x3679, 0x0c}, 3878c2ecf20Sopenharmony_ci {0x367f, 0x01}, 3888c2ecf20Sopenharmony_ci {0x3680, 0x0c}, 3898c2ecf20Sopenharmony_ci {0x3681, 0x50}, 3908c2ecf20Sopenharmony_ci {0x3682, 0x50}, 3918c2ecf20Sopenharmony_ci {0x3683, 0xa9}, 3928c2ecf20Sopenharmony_ci {0x3684, 0xa9}, 3938c2ecf20Sopenharmony_ci {0x3709, 0x5f}, 3948c2ecf20Sopenharmony_ci {0x3714, 0x28}, 3958c2ecf20Sopenharmony_ci {0x371a, 0x3e}, 3968c2ecf20Sopenharmony_ci {0x3737, 0x08}, 3978c2ecf20Sopenharmony_ci {0x3738, 0xcc}, 3988c2ecf20Sopenharmony_ci {0x3739, 0x20}, 3998c2ecf20Sopenharmony_ci {0x373d, 0x26}, 4008c2ecf20Sopenharmony_ci {0x3764, 0x20}, 4018c2ecf20Sopenharmony_ci {0x3765, 0x20}, 4028c2ecf20Sopenharmony_ci {0x37a1, 0x36}, 4038c2ecf20Sopenharmony_ci {0x37a8, 0x3b}, 4048c2ecf20Sopenharmony_ci {0x37ab, 0x31}, 4058c2ecf20Sopenharmony_ci {0x37c2, 0x14}, 4068c2ecf20Sopenharmony_ci {0x37c3, 0xf1}, 4078c2ecf20Sopenharmony_ci {0x37c5, 0x00}, 4088c2ecf20Sopenharmony_ci {0x37d8, 0x03}, 4098c2ecf20Sopenharmony_ci {0x37d9, 0x0c}, 4108c2ecf20Sopenharmony_ci {0x37da, 0xc2}, 4118c2ecf20Sopenharmony_ci {0x37dc, 0x02}, 4128c2ecf20Sopenharmony_ci {0x37e0, 0x00}, 4138c2ecf20Sopenharmony_ci {0x37e1, 0x0a}, 4148c2ecf20Sopenharmony_ci {0x37e2, 0x14}, 4158c2ecf20Sopenharmony_ci {0x37e3, 0x08}, 4168c2ecf20Sopenharmony_ci {0x37e4, 0x38}, 4178c2ecf20Sopenharmony_ci {0x37e5, 0x03}, 4188c2ecf20Sopenharmony_ci {0x37e6, 0x08}, 4198c2ecf20Sopenharmony_ci {0x3800, 0x00}, 4208c2ecf20Sopenharmony_ci {0x3801, 0x00}, 4218c2ecf20Sopenharmony_ci {0x3802, 0x00}, 4228c2ecf20Sopenharmony_ci {0x3803, 0x00}, 4238c2ecf20Sopenharmony_ci {0x3804, 0x10}, 4248c2ecf20Sopenharmony_ci {0x3805, 0x9f}, 4258c2ecf20Sopenharmony_ci {0x3806, 0x0c}, 4268c2ecf20Sopenharmony_ci {0x3807, 0x5f}, 4278c2ecf20Sopenharmony_ci {0x3808, 0x08}, 4288c2ecf20Sopenharmony_ci {0x3809, 0x40}, 4298c2ecf20Sopenharmony_ci {0x380a, 0x06}, 4308c2ecf20Sopenharmony_ci {0x380b, 0x20}, 4318c2ecf20Sopenharmony_ci {0x380c, 0x04}, 4328c2ecf20Sopenharmony_ci {0x380d, 0x62}, 4338c2ecf20Sopenharmony_ci {0x380e, 0x0c}, 4348c2ecf20Sopenharmony_ci {0x380f, 0x8e}, 4358c2ecf20Sopenharmony_ci {0x3811, 0x04}, 4368c2ecf20Sopenharmony_ci {0x3813, 0x05}, 4378c2ecf20Sopenharmony_ci {0x3814, 0x03}, 4388c2ecf20Sopenharmony_ci {0x3815, 0x01}, 4398c2ecf20Sopenharmony_ci {0x3816, 0x03}, 4408c2ecf20Sopenharmony_ci {0x3817, 0x01}, 4418c2ecf20Sopenharmony_ci {0x3820, 0xab}, 4428c2ecf20Sopenharmony_ci {0x3821, 0x00}, 4438c2ecf20Sopenharmony_ci {0x3822, 0xc2}, 4448c2ecf20Sopenharmony_ci {0x3823, 0x18}, 4458c2ecf20Sopenharmony_ci {0x3826, 0x04}, 4468c2ecf20Sopenharmony_ci {0x3827, 0x90}, 4478c2ecf20Sopenharmony_ci {0x3829, 0x07}, 4488c2ecf20Sopenharmony_ci {0x3832, 0x00}, 4498c2ecf20Sopenharmony_ci {0x3c80, 0x00}, 4508c2ecf20Sopenharmony_ci {0x3c87, 0x01}, 4518c2ecf20Sopenharmony_ci {0x3c8c, 0x19}, 4528c2ecf20Sopenharmony_ci {0x3c8d, 0x1c}, 4538c2ecf20Sopenharmony_ci {0x3c90, 0x00}, 4548c2ecf20Sopenharmony_ci {0x3c91, 0x00}, 4558c2ecf20Sopenharmony_ci {0x3c92, 0x00}, 4568c2ecf20Sopenharmony_ci {0x3c93, 0x00}, 4578c2ecf20Sopenharmony_ci {0x3c94, 0x40}, 4588c2ecf20Sopenharmony_ci {0x3c95, 0x54}, 4598c2ecf20Sopenharmony_ci {0x3c96, 0x34}, 4608c2ecf20Sopenharmony_ci {0x3c97, 0x04}, 4618c2ecf20Sopenharmony_ci {0x3c98, 0x00}, 4628c2ecf20Sopenharmony_ci {0x3d8c, 0x73}, 4638c2ecf20Sopenharmony_ci {0x3d8d, 0xc0}, 4648c2ecf20Sopenharmony_ci {0x3f00, 0x0b}, 4658c2ecf20Sopenharmony_ci {0x3f03, 0x00}, 4668c2ecf20Sopenharmony_ci {0x4001, 0xe0}, 4678c2ecf20Sopenharmony_ci {0x4008, 0x00}, 4688c2ecf20Sopenharmony_ci {0x4009, 0x0d}, 4698c2ecf20Sopenharmony_ci {0x4011, 0xf0}, 4708c2ecf20Sopenharmony_ci {0x4017, 0x08}, 4718c2ecf20Sopenharmony_ci {0x4050, 0x04}, 4728c2ecf20Sopenharmony_ci {0x4051, 0x0b}, 4738c2ecf20Sopenharmony_ci {0x4052, 0x00}, 4748c2ecf20Sopenharmony_ci {0x4053, 0x80}, 4758c2ecf20Sopenharmony_ci {0x4054, 0x00}, 4768c2ecf20Sopenharmony_ci {0x4055, 0x80}, 4778c2ecf20Sopenharmony_ci {0x4056, 0x00}, 4788c2ecf20Sopenharmony_ci {0x4057, 0x80}, 4798c2ecf20Sopenharmony_ci {0x4058, 0x00}, 4808c2ecf20Sopenharmony_ci {0x4059, 0x80}, 4818c2ecf20Sopenharmony_ci {0x405e, 0x20}, 4828c2ecf20Sopenharmony_ci {0x4500, 0x07}, 4838c2ecf20Sopenharmony_ci {0x4503, 0x00}, 4848c2ecf20Sopenharmony_ci {0x450a, 0x04}, 4858c2ecf20Sopenharmony_ci {0x4809, 0x04}, 4868c2ecf20Sopenharmony_ci {0x480c, 0x12}, 4878c2ecf20Sopenharmony_ci {0x481f, 0x30}, 4888c2ecf20Sopenharmony_ci {0x4833, 0x10}, 4898c2ecf20Sopenharmony_ci {0x4837, 0x1c}, 4908c2ecf20Sopenharmony_ci {0x4902, 0x01}, 4918c2ecf20Sopenharmony_ci {0x4d00, 0x03}, 4928c2ecf20Sopenharmony_ci {0x4d01, 0xc9}, 4938c2ecf20Sopenharmony_ci {0x4d02, 0xbc}, 4948c2ecf20Sopenharmony_ci {0x4d03, 0xd7}, 4958c2ecf20Sopenharmony_ci {0x4d04, 0xf0}, 4968c2ecf20Sopenharmony_ci {0x4d05, 0xa2}, 4978c2ecf20Sopenharmony_ci {0x5000, 0xfd}, 4988c2ecf20Sopenharmony_ci {0x5001, 0x01}, 4998c2ecf20Sopenharmony_ci {0x5040, 0x39}, 5008c2ecf20Sopenharmony_ci {0x5041, 0x10}, 5018c2ecf20Sopenharmony_ci {0x5042, 0x10}, 5028c2ecf20Sopenharmony_ci {0x5043, 0x84}, 5038c2ecf20Sopenharmony_ci {0x5044, 0x62}, 5048c2ecf20Sopenharmony_ci {0x5180, 0x00}, 5058c2ecf20Sopenharmony_ci {0x5181, 0x10}, 5068c2ecf20Sopenharmony_ci {0x5182, 0x02}, 5078c2ecf20Sopenharmony_ci {0x5183, 0x0f}, 5088c2ecf20Sopenharmony_ci {0x5200, 0x1b}, 5098c2ecf20Sopenharmony_ci {0x520b, 0x07}, 5108c2ecf20Sopenharmony_ci {0x520c, 0x0f}, 5118c2ecf20Sopenharmony_ci {0x5300, 0x04}, 5128c2ecf20Sopenharmony_ci {0x5301, 0x0c}, 5138c2ecf20Sopenharmony_ci {0x5302, 0x0c}, 5148c2ecf20Sopenharmony_ci {0x5303, 0x0f}, 5158c2ecf20Sopenharmony_ci {0x5304, 0x00}, 5168c2ecf20Sopenharmony_ci {0x5305, 0x70}, 5178c2ecf20Sopenharmony_ci {0x5306, 0x00}, 5188c2ecf20Sopenharmony_ci {0x5307, 0x80}, 5198c2ecf20Sopenharmony_ci {0x5308, 0x00}, 5208c2ecf20Sopenharmony_ci {0x5309, 0xa5}, 5218c2ecf20Sopenharmony_ci {0x530a, 0x00}, 5228c2ecf20Sopenharmony_ci {0x530b, 0xd3}, 5238c2ecf20Sopenharmony_ci {0x530c, 0x00}, 5248c2ecf20Sopenharmony_ci {0x530d, 0xf0}, 5258c2ecf20Sopenharmony_ci {0x530e, 0x01}, 5268c2ecf20Sopenharmony_ci {0x530f, 0x10}, 5278c2ecf20Sopenharmony_ci {0x5310, 0x01}, 5288c2ecf20Sopenharmony_ci {0x5311, 0x20}, 5298c2ecf20Sopenharmony_ci {0x5312, 0x01}, 5308c2ecf20Sopenharmony_ci {0x5313, 0x20}, 5318c2ecf20Sopenharmony_ci {0x5314, 0x01}, 5328c2ecf20Sopenharmony_ci {0x5315, 0x20}, 5338c2ecf20Sopenharmony_ci {0x5316, 0x08}, 5348c2ecf20Sopenharmony_ci {0x5317, 0x08}, 5358c2ecf20Sopenharmony_ci {0x5318, 0x10}, 5368c2ecf20Sopenharmony_ci {0x5319, 0x88}, 5378c2ecf20Sopenharmony_ci {0x531a, 0x88}, 5388c2ecf20Sopenharmony_ci {0x531b, 0xa9}, 5398c2ecf20Sopenharmony_ci {0x531c, 0xaa}, 5408c2ecf20Sopenharmony_ci {0x531d, 0x0a}, 5418c2ecf20Sopenharmony_ci {0x5405, 0x02}, 5428c2ecf20Sopenharmony_ci {0x5406, 0x67}, 5438c2ecf20Sopenharmony_ci {0x5407, 0x01}, 5448c2ecf20Sopenharmony_ci {0x5408, 0x4a}, 5458c2ecf20Sopenharmony_ci}; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic const struct ov13858_reg mode_2112x1188_regs[] = { 5488c2ecf20Sopenharmony_ci {0x3013, 0x32}, 5498c2ecf20Sopenharmony_ci {0x301b, 0xf0}, 5508c2ecf20Sopenharmony_ci {0x301f, 0xd0}, 5518c2ecf20Sopenharmony_ci {0x3106, 0x15}, 5528c2ecf20Sopenharmony_ci {0x3107, 0x23}, 5538c2ecf20Sopenharmony_ci {0x350a, 0x00}, 5548c2ecf20Sopenharmony_ci {0x350e, 0x00}, 5558c2ecf20Sopenharmony_ci {0x3510, 0x00}, 5568c2ecf20Sopenharmony_ci {0x3511, 0x02}, 5578c2ecf20Sopenharmony_ci {0x3512, 0x00}, 5588c2ecf20Sopenharmony_ci {0x3600, 0x2b}, 5598c2ecf20Sopenharmony_ci {0x3601, 0x52}, 5608c2ecf20Sopenharmony_ci {0x3602, 0x60}, 5618c2ecf20Sopenharmony_ci {0x3612, 0x05}, 5628c2ecf20Sopenharmony_ci {0x3613, 0xa4}, 5638c2ecf20Sopenharmony_ci {0x3620, 0x80}, 5648c2ecf20Sopenharmony_ci {0x3621, 0x10}, 5658c2ecf20Sopenharmony_ci {0x3622, 0x30}, 5668c2ecf20Sopenharmony_ci {0x3624, 0x1c}, 5678c2ecf20Sopenharmony_ci {0x3640, 0x10}, 5688c2ecf20Sopenharmony_ci {0x3641, 0x70}, 5698c2ecf20Sopenharmony_ci {0x3660, 0x04}, 5708c2ecf20Sopenharmony_ci {0x3661, 0x80}, 5718c2ecf20Sopenharmony_ci {0x3662, 0x10}, 5728c2ecf20Sopenharmony_ci {0x3664, 0x73}, 5738c2ecf20Sopenharmony_ci {0x3665, 0xa7}, 5748c2ecf20Sopenharmony_ci {0x366e, 0xff}, 5758c2ecf20Sopenharmony_ci {0x366f, 0xf4}, 5768c2ecf20Sopenharmony_ci {0x3674, 0x00}, 5778c2ecf20Sopenharmony_ci {0x3679, 0x0c}, 5788c2ecf20Sopenharmony_ci {0x367f, 0x01}, 5798c2ecf20Sopenharmony_ci {0x3680, 0x0c}, 5808c2ecf20Sopenharmony_ci {0x3681, 0x50}, 5818c2ecf20Sopenharmony_ci {0x3682, 0x50}, 5828c2ecf20Sopenharmony_ci {0x3683, 0xa9}, 5838c2ecf20Sopenharmony_ci {0x3684, 0xa9}, 5848c2ecf20Sopenharmony_ci {0x3709, 0x5f}, 5858c2ecf20Sopenharmony_ci {0x3714, 0x28}, 5868c2ecf20Sopenharmony_ci {0x371a, 0x3e}, 5878c2ecf20Sopenharmony_ci {0x3737, 0x08}, 5888c2ecf20Sopenharmony_ci {0x3738, 0xcc}, 5898c2ecf20Sopenharmony_ci {0x3739, 0x20}, 5908c2ecf20Sopenharmony_ci {0x373d, 0x26}, 5918c2ecf20Sopenharmony_ci {0x3764, 0x20}, 5928c2ecf20Sopenharmony_ci {0x3765, 0x20}, 5938c2ecf20Sopenharmony_ci {0x37a1, 0x36}, 5948c2ecf20Sopenharmony_ci {0x37a8, 0x3b}, 5958c2ecf20Sopenharmony_ci {0x37ab, 0x31}, 5968c2ecf20Sopenharmony_ci {0x37c2, 0x14}, 5978c2ecf20Sopenharmony_ci {0x37c3, 0xf1}, 5988c2ecf20Sopenharmony_ci {0x37c5, 0x00}, 5998c2ecf20Sopenharmony_ci {0x37d8, 0x03}, 6008c2ecf20Sopenharmony_ci {0x37d9, 0x0c}, 6018c2ecf20Sopenharmony_ci {0x37da, 0xc2}, 6028c2ecf20Sopenharmony_ci {0x37dc, 0x02}, 6038c2ecf20Sopenharmony_ci {0x37e0, 0x00}, 6048c2ecf20Sopenharmony_ci {0x37e1, 0x0a}, 6058c2ecf20Sopenharmony_ci {0x37e2, 0x14}, 6068c2ecf20Sopenharmony_ci {0x37e3, 0x08}, 6078c2ecf20Sopenharmony_ci {0x37e4, 0x38}, 6088c2ecf20Sopenharmony_ci {0x37e5, 0x03}, 6098c2ecf20Sopenharmony_ci {0x37e6, 0x08}, 6108c2ecf20Sopenharmony_ci {0x3800, 0x00}, 6118c2ecf20Sopenharmony_ci {0x3801, 0x00}, 6128c2ecf20Sopenharmony_ci {0x3802, 0x01}, 6138c2ecf20Sopenharmony_ci {0x3803, 0x84}, 6148c2ecf20Sopenharmony_ci {0x3804, 0x10}, 6158c2ecf20Sopenharmony_ci {0x3805, 0x9f}, 6168c2ecf20Sopenharmony_ci {0x3806, 0x0a}, 6178c2ecf20Sopenharmony_ci {0x3807, 0xd3}, 6188c2ecf20Sopenharmony_ci {0x3808, 0x08}, 6198c2ecf20Sopenharmony_ci {0x3809, 0x40}, 6208c2ecf20Sopenharmony_ci {0x380a, 0x04}, 6218c2ecf20Sopenharmony_ci {0x380b, 0xa4}, 6228c2ecf20Sopenharmony_ci {0x380c, 0x04}, 6238c2ecf20Sopenharmony_ci {0x380d, 0x62}, 6248c2ecf20Sopenharmony_ci {0x380e, 0x0c}, 6258c2ecf20Sopenharmony_ci {0x380f, 0x8e}, 6268c2ecf20Sopenharmony_ci {0x3811, 0x08}, 6278c2ecf20Sopenharmony_ci {0x3813, 0x03}, 6288c2ecf20Sopenharmony_ci {0x3814, 0x03}, 6298c2ecf20Sopenharmony_ci {0x3815, 0x01}, 6308c2ecf20Sopenharmony_ci {0x3816, 0x03}, 6318c2ecf20Sopenharmony_ci {0x3817, 0x01}, 6328c2ecf20Sopenharmony_ci {0x3820, 0xab}, 6338c2ecf20Sopenharmony_ci {0x3821, 0x00}, 6348c2ecf20Sopenharmony_ci {0x3822, 0xc2}, 6358c2ecf20Sopenharmony_ci {0x3823, 0x18}, 6368c2ecf20Sopenharmony_ci {0x3826, 0x04}, 6378c2ecf20Sopenharmony_ci {0x3827, 0x90}, 6388c2ecf20Sopenharmony_ci {0x3829, 0x07}, 6398c2ecf20Sopenharmony_ci {0x3832, 0x00}, 6408c2ecf20Sopenharmony_ci {0x3c80, 0x00}, 6418c2ecf20Sopenharmony_ci {0x3c87, 0x01}, 6428c2ecf20Sopenharmony_ci {0x3c8c, 0x19}, 6438c2ecf20Sopenharmony_ci {0x3c8d, 0x1c}, 6448c2ecf20Sopenharmony_ci {0x3c90, 0x00}, 6458c2ecf20Sopenharmony_ci {0x3c91, 0x00}, 6468c2ecf20Sopenharmony_ci {0x3c92, 0x00}, 6478c2ecf20Sopenharmony_ci {0x3c93, 0x00}, 6488c2ecf20Sopenharmony_ci {0x3c94, 0x40}, 6498c2ecf20Sopenharmony_ci {0x3c95, 0x54}, 6508c2ecf20Sopenharmony_ci {0x3c96, 0x34}, 6518c2ecf20Sopenharmony_ci {0x3c97, 0x04}, 6528c2ecf20Sopenharmony_ci {0x3c98, 0x00}, 6538c2ecf20Sopenharmony_ci {0x3d8c, 0x73}, 6548c2ecf20Sopenharmony_ci {0x3d8d, 0xc0}, 6558c2ecf20Sopenharmony_ci {0x3f00, 0x0b}, 6568c2ecf20Sopenharmony_ci {0x3f03, 0x00}, 6578c2ecf20Sopenharmony_ci {0x4001, 0xe0}, 6588c2ecf20Sopenharmony_ci {0x4008, 0x00}, 6598c2ecf20Sopenharmony_ci {0x4009, 0x0d}, 6608c2ecf20Sopenharmony_ci {0x4011, 0xf0}, 6618c2ecf20Sopenharmony_ci {0x4017, 0x08}, 6628c2ecf20Sopenharmony_ci {0x4050, 0x04}, 6638c2ecf20Sopenharmony_ci {0x4051, 0x0b}, 6648c2ecf20Sopenharmony_ci {0x4052, 0x00}, 6658c2ecf20Sopenharmony_ci {0x4053, 0x80}, 6668c2ecf20Sopenharmony_ci {0x4054, 0x00}, 6678c2ecf20Sopenharmony_ci {0x4055, 0x80}, 6688c2ecf20Sopenharmony_ci {0x4056, 0x00}, 6698c2ecf20Sopenharmony_ci {0x4057, 0x80}, 6708c2ecf20Sopenharmony_ci {0x4058, 0x00}, 6718c2ecf20Sopenharmony_ci {0x4059, 0x80}, 6728c2ecf20Sopenharmony_ci {0x405e, 0x20}, 6738c2ecf20Sopenharmony_ci {0x4500, 0x07}, 6748c2ecf20Sopenharmony_ci {0x4503, 0x00}, 6758c2ecf20Sopenharmony_ci {0x450a, 0x04}, 6768c2ecf20Sopenharmony_ci {0x4809, 0x04}, 6778c2ecf20Sopenharmony_ci {0x480c, 0x12}, 6788c2ecf20Sopenharmony_ci {0x481f, 0x30}, 6798c2ecf20Sopenharmony_ci {0x4833, 0x10}, 6808c2ecf20Sopenharmony_ci {0x4837, 0x1c}, 6818c2ecf20Sopenharmony_ci {0x4902, 0x01}, 6828c2ecf20Sopenharmony_ci {0x4d00, 0x03}, 6838c2ecf20Sopenharmony_ci {0x4d01, 0xc9}, 6848c2ecf20Sopenharmony_ci {0x4d02, 0xbc}, 6858c2ecf20Sopenharmony_ci {0x4d03, 0xd7}, 6868c2ecf20Sopenharmony_ci {0x4d04, 0xf0}, 6878c2ecf20Sopenharmony_ci {0x4d05, 0xa2}, 6888c2ecf20Sopenharmony_ci {0x5000, 0xfd}, 6898c2ecf20Sopenharmony_ci {0x5001, 0x01}, 6908c2ecf20Sopenharmony_ci {0x5040, 0x39}, 6918c2ecf20Sopenharmony_ci {0x5041, 0x10}, 6928c2ecf20Sopenharmony_ci {0x5042, 0x10}, 6938c2ecf20Sopenharmony_ci {0x5043, 0x84}, 6948c2ecf20Sopenharmony_ci {0x5044, 0x62}, 6958c2ecf20Sopenharmony_ci {0x5180, 0x00}, 6968c2ecf20Sopenharmony_ci {0x5181, 0x10}, 6978c2ecf20Sopenharmony_ci {0x5182, 0x02}, 6988c2ecf20Sopenharmony_ci {0x5183, 0x0f}, 6998c2ecf20Sopenharmony_ci {0x5200, 0x1b}, 7008c2ecf20Sopenharmony_ci {0x520b, 0x07}, 7018c2ecf20Sopenharmony_ci {0x520c, 0x0f}, 7028c2ecf20Sopenharmony_ci {0x5300, 0x04}, 7038c2ecf20Sopenharmony_ci {0x5301, 0x0c}, 7048c2ecf20Sopenharmony_ci {0x5302, 0x0c}, 7058c2ecf20Sopenharmony_ci {0x5303, 0x0f}, 7068c2ecf20Sopenharmony_ci {0x5304, 0x00}, 7078c2ecf20Sopenharmony_ci {0x5305, 0x70}, 7088c2ecf20Sopenharmony_ci {0x5306, 0x00}, 7098c2ecf20Sopenharmony_ci {0x5307, 0x80}, 7108c2ecf20Sopenharmony_ci {0x5308, 0x00}, 7118c2ecf20Sopenharmony_ci {0x5309, 0xa5}, 7128c2ecf20Sopenharmony_ci {0x530a, 0x00}, 7138c2ecf20Sopenharmony_ci {0x530b, 0xd3}, 7148c2ecf20Sopenharmony_ci {0x530c, 0x00}, 7158c2ecf20Sopenharmony_ci {0x530d, 0xf0}, 7168c2ecf20Sopenharmony_ci {0x530e, 0x01}, 7178c2ecf20Sopenharmony_ci {0x530f, 0x10}, 7188c2ecf20Sopenharmony_ci {0x5310, 0x01}, 7198c2ecf20Sopenharmony_ci {0x5311, 0x20}, 7208c2ecf20Sopenharmony_ci {0x5312, 0x01}, 7218c2ecf20Sopenharmony_ci {0x5313, 0x20}, 7228c2ecf20Sopenharmony_ci {0x5314, 0x01}, 7238c2ecf20Sopenharmony_ci {0x5315, 0x20}, 7248c2ecf20Sopenharmony_ci {0x5316, 0x08}, 7258c2ecf20Sopenharmony_ci {0x5317, 0x08}, 7268c2ecf20Sopenharmony_ci {0x5318, 0x10}, 7278c2ecf20Sopenharmony_ci {0x5319, 0x88}, 7288c2ecf20Sopenharmony_ci {0x531a, 0x88}, 7298c2ecf20Sopenharmony_ci {0x531b, 0xa9}, 7308c2ecf20Sopenharmony_ci {0x531c, 0xaa}, 7318c2ecf20Sopenharmony_ci {0x531d, 0x0a}, 7328c2ecf20Sopenharmony_ci {0x5405, 0x02}, 7338c2ecf20Sopenharmony_ci {0x5406, 0x67}, 7348c2ecf20Sopenharmony_ci {0x5407, 0x01}, 7358c2ecf20Sopenharmony_ci {0x5408, 0x4a}, 7368c2ecf20Sopenharmony_ci}; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic const struct ov13858_reg mode_1056x784_regs[] = { 7398c2ecf20Sopenharmony_ci {0x3013, 0x32}, 7408c2ecf20Sopenharmony_ci {0x301b, 0xf0}, 7418c2ecf20Sopenharmony_ci {0x301f, 0xd0}, 7428c2ecf20Sopenharmony_ci {0x3106, 0x15}, 7438c2ecf20Sopenharmony_ci {0x3107, 0x23}, 7448c2ecf20Sopenharmony_ci {0x350a, 0x00}, 7458c2ecf20Sopenharmony_ci {0x350e, 0x00}, 7468c2ecf20Sopenharmony_ci {0x3510, 0x00}, 7478c2ecf20Sopenharmony_ci {0x3511, 0x02}, 7488c2ecf20Sopenharmony_ci {0x3512, 0x00}, 7498c2ecf20Sopenharmony_ci {0x3600, 0x2b}, 7508c2ecf20Sopenharmony_ci {0x3601, 0x52}, 7518c2ecf20Sopenharmony_ci {0x3602, 0x60}, 7528c2ecf20Sopenharmony_ci {0x3612, 0x05}, 7538c2ecf20Sopenharmony_ci {0x3613, 0xa4}, 7548c2ecf20Sopenharmony_ci {0x3620, 0x80}, 7558c2ecf20Sopenharmony_ci {0x3621, 0x10}, 7568c2ecf20Sopenharmony_ci {0x3622, 0x30}, 7578c2ecf20Sopenharmony_ci {0x3624, 0x1c}, 7588c2ecf20Sopenharmony_ci {0x3640, 0x10}, 7598c2ecf20Sopenharmony_ci {0x3641, 0x70}, 7608c2ecf20Sopenharmony_ci {0x3660, 0x04}, 7618c2ecf20Sopenharmony_ci {0x3661, 0x80}, 7628c2ecf20Sopenharmony_ci {0x3662, 0x08}, 7638c2ecf20Sopenharmony_ci {0x3664, 0x73}, 7648c2ecf20Sopenharmony_ci {0x3665, 0xa7}, 7658c2ecf20Sopenharmony_ci {0x366e, 0xff}, 7668c2ecf20Sopenharmony_ci {0x366f, 0xf4}, 7678c2ecf20Sopenharmony_ci {0x3674, 0x00}, 7688c2ecf20Sopenharmony_ci {0x3679, 0x0c}, 7698c2ecf20Sopenharmony_ci {0x367f, 0x01}, 7708c2ecf20Sopenharmony_ci {0x3680, 0x0c}, 7718c2ecf20Sopenharmony_ci {0x3681, 0x50}, 7728c2ecf20Sopenharmony_ci {0x3682, 0x50}, 7738c2ecf20Sopenharmony_ci {0x3683, 0xa9}, 7748c2ecf20Sopenharmony_ci {0x3684, 0xa9}, 7758c2ecf20Sopenharmony_ci {0x3709, 0x5f}, 7768c2ecf20Sopenharmony_ci {0x3714, 0x30}, 7778c2ecf20Sopenharmony_ci {0x371a, 0x3e}, 7788c2ecf20Sopenharmony_ci {0x3737, 0x08}, 7798c2ecf20Sopenharmony_ci {0x3738, 0xcc}, 7808c2ecf20Sopenharmony_ci {0x3739, 0x20}, 7818c2ecf20Sopenharmony_ci {0x373d, 0x26}, 7828c2ecf20Sopenharmony_ci {0x3764, 0x20}, 7838c2ecf20Sopenharmony_ci {0x3765, 0x20}, 7848c2ecf20Sopenharmony_ci {0x37a1, 0x36}, 7858c2ecf20Sopenharmony_ci {0x37a8, 0x3b}, 7868c2ecf20Sopenharmony_ci {0x37ab, 0x31}, 7878c2ecf20Sopenharmony_ci {0x37c2, 0x2c}, 7888c2ecf20Sopenharmony_ci {0x37c3, 0xf1}, 7898c2ecf20Sopenharmony_ci {0x37c5, 0x00}, 7908c2ecf20Sopenharmony_ci {0x37d8, 0x03}, 7918c2ecf20Sopenharmony_ci {0x37d9, 0x06}, 7928c2ecf20Sopenharmony_ci {0x37da, 0xc2}, 7938c2ecf20Sopenharmony_ci {0x37dc, 0x02}, 7948c2ecf20Sopenharmony_ci {0x37e0, 0x00}, 7958c2ecf20Sopenharmony_ci {0x37e1, 0x0a}, 7968c2ecf20Sopenharmony_ci {0x37e2, 0x14}, 7978c2ecf20Sopenharmony_ci {0x37e3, 0x08}, 7988c2ecf20Sopenharmony_ci {0x37e4, 0x36}, 7998c2ecf20Sopenharmony_ci {0x37e5, 0x03}, 8008c2ecf20Sopenharmony_ci {0x37e6, 0x08}, 8018c2ecf20Sopenharmony_ci {0x3800, 0x00}, 8028c2ecf20Sopenharmony_ci {0x3801, 0x00}, 8038c2ecf20Sopenharmony_ci {0x3802, 0x00}, 8048c2ecf20Sopenharmony_ci {0x3803, 0x00}, 8058c2ecf20Sopenharmony_ci {0x3804, 0x10}, 8068c2ecf20Sopenharmony_ci {0x3805, 0x9f}, 8078c2ecf20Sopenharmony_ci {0x3806, 0x0c}, 8088c2ecf20Sopenharmony_ci {0x3807, 0x5f}, 8098c2ecf20Sopenharmony_ci {0x3808, 0x04}, 8108c2ecf20Sopenharmony_ci {0x3809, 0x20}, 8118c2ecf20Sopenharmony_ci {0x380a, 0x03}, 8128c2ecf20Sopenharmony_ci {0x380b, 0x10}, 8138c2ecf20Sopenharmony_ci {0x380c, 0x04}, 8148c2ecf20Sopenharmony_ci {0x380d, 0x62}, 8158c2ecf20Sopenharmony_ci {0x380e, 0x0c}, 8168c2ecf20Sopenharmony_ci {0x380f, 0x8e}, 8178c2ecf20Sopenharmony_ci {0x3811, 0x04}, 8188c2ecf20Sopenharmony_ci {0x3813, 0x05}, 8198c2ecf20Sopenharmony_ci {0x3814, 0x07}, 8208c2ecf20Sopenharmony_ci {0x3815, 0x01}, 8218c2ecf20Sopenharmony_ci {0x3816, 0x07}, 8228c2ecf20Sopenharmony_ci {0x3817, 0x01}, 8238c2ecf20Sopenharmony_ci {0x3820, 0xac}, 8248c2ecf20Sopenharmony_ci {0x3821, 0x00}, 8258c2ecf20Sopenharmony_ci {0x3822, 0xc2}, 8268c2ecf20Sopenharmony_ci {0x3823, 0x18}, 8278c2ecf20Sopenharmony_ci {0x3826, 0x04}, 8288c2ecf20Sopenharmony_ci {0x3827, 0x48}, 8298c2ecf20Sopenharmony_ci {0x3829, 0x03}, 8308c2ecf20Sopenharmony_ci {0x3832, 0x00}, 8318c2ecf20Sopenharmony_ci {0x3c80, 0x00}, 8328c2ecf20Sopenharmony_ci {0x3c87, 0x01}, 8338c2ecf20Sopenharmony_ci {0x3c8c, 0x19}, 8348c2ecf20Sopenharmony_ci {0x3c8d, 0x1c}, 8358c2ecf20Sopenharmony_ci {0x3c90, 0x00}, 8368c2ecf20Sopenharmony_ci {0x3c91, 0x00}, 8378c2ecf20Sopenharmony_ci {0x3c92, 0x00}, 8388c2ecf20Sopenharmony_ci {0x3c93, 0x00}, 8398c2ecf20Sopenharmony_ci {0x3c94, 0x40}, 8408c2ecf20Sopenharmony_ci {0x3c95, 0x54}, 8418c2ecf20Sopenharmony_ci {0x3c96, 0x34}, 8428c2ecf20Sopenharmony_ci {0x3c97, 0x04}, 8438c2ecf20Sopenharmony_ci {0x3c98, 0x00}, 8448c2ecf20Sopenharmony_ci {0x3d8c, 0x73}, 8458c2ecf20Sopenharmony_ci {0x3d8d, 0xc0}, 8468c2ecf20Sopenharmony_ci {0x3f00, 0x0b}, 8478c2ecf20Sopenharmony_ci {0x3f03, 0x00}, 8488c2ecf20Sopenharmony_ci {0x4001, 0xe0}, 8498c2ecf20Sopenharmony_ci {0x4008, 0x00}, 8508c2ecf20Sopenharmony_ci {0x4009, 0x05}, 8518c2ecf20Sopenharmony_ci {0x4011, 0xf0}, 8528c2ecf20Sopenharmony_ci {0x4017, 0x08}, 8538c2ecf20Sopenharmony_ci {0x4050, 0x02}, 8548c2ecf20Sopenharmony_ci {0x4051, 0x05}, 8558c2ecf20Sopenharmony_ci {0x4052, 0x00}, 8568c2ecf20Sopenharmony_ci {0x4053, 0x80}, 8578c2ecf20Sopenharmony_ci {0x4054, 0x00}, 8588c2ecf20Sopenharmony_ci {0x4055, 0x80}, 8598c2ecf20Sopenharmony_ci {0x4056, 0x00}, 8608c2ecf20Sopenharmony_ci {0x4057, 0x80}, 8618c2ecf20Sopenharmony_ci {0x4058, 0x00}, 8628c2ecf20Sopenharmony_ci {0x4059, 0x80}, 8638c2ecf20Sopenharmony_ci {0x405e, 0x20}, 8648c2ecf20Sopenharmony_ci {0x4500, 0x07}, 8658c2ecf20Sopenharmony_ci {0x4503, 0x00}, 8668c2ecf20Sopenharmony_ci {0x450a, 0x04}, 8678c2ecf20Sopenharmony_ci {0x4809, 0x04}, 8688c2ecf20Sopenharmony_ci {0x480c, 0x12}, 8698c2ecf20Sopenharmony_ci {0x481f, 0x30}, 8708c2ecf20Sopenharmony_ci {0x4833, 0x10}, 8718c2ecf20Sopenharmony_ci {0x4837, 0x1e}, 8728c2ecf20Sopenharmony_ci {0x4902, 0x02}, 8738c2ecf20Sopenharmony_ci {0x4d00, 0x03}, 8748c2ecf20Sopenharmony_ci {0x4d01, 0xc9}, 8758c2ecf20Sopenharmony_ci {0x4d02, 0xbc}, 8768c2ecf20Sopenharmony_ci {0x4d03, 0xd7}, 8778c2ecf20Sopenharmony_ci {0x4d04, 0xf0}, 8788c2ecf20Sopenharmony_ci {0x4d05, 0xa2}, 8798c2ecf20Sopenharmony_ci {0x5000, 0xfd}, 8808c2ecf20Sopenharmony_ci {0x5001, 0x01}, 8818c2ecf20Sopenharmony_ci {0x5040, 0x39}, 8828c2ecf20Sopenharmony_ci {0x5041, 0x10}, 8838c2ecf20Sopenharmony_ci {0x5042, 0x10}, 8848c2ecf20Sopenharmony_ci {0x5043, 0x84}, 8858c2ecf20Sopenharmony_ci {0x5044, 0x62}, 8868c2ecf20Sopenharmony_ci {0x5180, 0x00}, 8878c2ecf20Sopenharmony_ci {0x5181, 0x10}, 8888c2ecf20Sopenharmony_ci {0x5182, 0x02}, 8898c2ecf20Sopenharmony_ci {0x5183, 0x0f}, 8908c2ecf20Sopenharmony_ci {0x5200, 0x1b}, 8918c2ecf20Sopenharmony_ci {0x520b, 0x07}, 8928c2ecf20Sopenharmony_ci {0x520c, 0x0f}, 8938c2ecf20Sopenharmony_ci {0x5300, 0x04}, 8948c2ecf20Sopenharmony_ci {0x5301, 0x0c}, 8958c2ecf20Sopenharmony_ci {0x5302, 0x0c}, 8968c2ecf20Sopenharmony_ci {0x5303, 0x0f}, 8978c2ecf20Sopenharmony_ci {0x5304, 0x00}, 8988c2ecf20Sopenharmony_ci {0x5305, 0x70}, 8998c2ecf20Sopenharmony_ci {0x5306, 0x00}, 9008c2ecf20Sopenharmony_ci {0x5307, 0x80}, 9018c2ecf20Sopenharmony_ci {0x5308, 0x00}, 9028c2ecf20Sopenharmony_ci {0x5309, 0xa5}, 9038c2ecf20Sopenharmony_ci {0x530a, 0x00}, 9048c2ecf20Sopenharmony_ci {0x530b, 0xd3}, 9058c2ecf20Sopenharmony_ci {0x530c, 0x00}, 9068c2ecf20Sopenharmony_ci {0x530d, 0xf0}, 9078c2ecf20Sopenharmony_ci {0x530e, 0x01}, 9088c2ecf20Sopenharmony_ci {0x530f, 0x10}, 9098c2ecf20Sopenharmony_ci {0x5310, 0x01}, 9108c2ecf20Sopenharmony_ci {0x5311, 0x20}, 9118c2ecf20Sopenharmony_ci {0x5312, 0x01}, 9128c2ecf20Sopenharmony_ci {0x5313, 0x20}, 9138c2ecf20Sopenharmony_ci {0x5314, 0x01}, 9148c2ecf20Sopenharmony_ci {0x5315, 0x20}, 9158c2ecf20Sopenharmony_ci {0x5316, 0x08}, 9168c2ecf20Sopenharmony_ci {0x5317, 0x08}, 9178c2ecf20Sopenharmony_ci {0x5318, 0x10}, 9188c2ecf20Sopenharmony_ci {0x5319, 0x88}, 9198c2ecf20Sopenharmony_ci {0x531a, 0x88}, 9208c2ecf20Sopenharmony_ci {0x531b, 0xa9}, 9218c2ecf20Sopenharmony_ci {0x531c, 0xaa}, 9228c2ecf20Sopenharmony_ci {0x531d, 0x0a}, 9238c2ecf20Sopenharmony_ci {0x5405, 0x02}, 9248c2ecf20Sopenharmony_ci {0x5406, 0x67}, 9258c2ecf20Sopenharmony_ci {0x5407, 0x01}, 9268c2ecf20Sopenharmony_ci {0x5408, 0x4a}, 9278c2ecf20Sopenharmony_ci}; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_cistatic const char * const ov13858_test_pattern_menu[] = { 9308c2ecf20Sopenharmony_ci "Disabled", 9318c2ecf20Sopenharmony_ci "Vertical Color Bar Type 1", 9328c2ecf20Sopenharmony_ci "Vertical Color Bar Type 2", 9338c2ecf20Sopenharmony_ci "Vertical Color Bar Type 3", 9348c2ecf20Sopenharmony_ci "Vertical Color Bar Type 4" 9358c2ecf20Sopenharmony_ci}; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci/* Configurations for supported link frequencies */ 9388c2ecf20Sopenharmony_ci#define OV13858_NUM_OF_LINK_FREQS 2 9398c2ecf20Sopenharmony_ci#define OV13858_LINK_FREQ_540MHZ 540000000ULL 9408c2ecf20Sopenharmony_ci#define OV13858_LINK_FREQ_270MHZ 270000000ULL 9418c2ecf20Sopenharmony_ci#define OV13858_LINK_FREQ_INDEX_0 0 9428c2ecf20Sopenharmony_ci#define OV13858_LINK_FREQ_INDEX_1 1 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci/* 9458c2ecf20Sopenharmony_ci * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample 9468c2ecf20Sopenharmony_ci * data rate => double data rate; number of lanes => 4; bits per pixel => 10 9478c2ecf20Sopenharmony_ci */ 9488c2ecf20Sopenharmony_cistatic u64 link_freq_to_pixel_rate(u64 f) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci f *= 2 * 4; 9518c2ecf20Sopenharmony_ci do_div(f, 10); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci return f; 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci/* Menu items for LINK_FREQ V4L2 control */ 9578c2ecf20Sopenharmony_cistatic const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = { 9588c2ecf20Sopenharmony_ci OV13858_LINK_FREQ_540MHZ, 9598c2ecf20Sopenharmony_ci OV13858_LINK_FREQ_270MHZ 9608c2ecf20Sopenharmony_ci}; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci/* Link frequency configs */ 9638c2ecf20Sopenharmony_cistatic const struct ov13858_link_freq_config 9648c2ecf20Sopenharmony_ci link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = { 9658c2ecf20Sopenharmony_ci { 9668c2ecf20Sopenharmony_ci .pixels_per_line = OV13858_PPL_540MHZ, 9678c2ecf20Sopenharmony_ci .reg_list = { 9688c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps), 9698c2ecf20Sopenharmony_ci .regs = mipi_data_rate_1080mbps, 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci }, 9728c2ecf20Sopenharmony_ci { 9738c2ecf20Sopenharmony_ci .pixels_per_line = OV13858_PPL_270MHZ, 9748c2ecf20Sopenharmony_ci .reg_list = { 9758c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps), 9768c2ecf20Sopenharmony_ci .regs = mipi_data_rate_540mbps, 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci}; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci/* Mode configs */ 9828c2ecf20Sopenharmony_cistatic const struct ov13858_mode supported_modes[] = { 9838c2ecf20Sopenharmony_ci { 9848c2ecf20Sopenharmony_ci .width = 4224, 9858c2ecf20Sopenharmony_ci .height = 3136, 9868c2ecf20Sopenharmony_ci .vts_def = OV13858_VTS_30FPS, 9878c2ecf20Sopenharmony_ci .vts_min = OV13858_VTS_30FPS, 9888c2ecf20Sopenharmony_ci .reg_list = { 9898c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mode_4224x3136_regs), 9908c2ecf20Sopenharmony_ci .regs = mode_4224x3136_regs, 9918c2ecf20Sopenharmony_ci }, 9928c2ecf20Sopenharmony_ci .link_freq_index = OV13858_LINK_FREQ_INDEX_0, 9938c2ecf20Sopenharmony_ci }, 9948c2ecf20Sopenharmony_ci { 9958c2ecf20Sopenharmony_ci .width = 2112, 9968c2ecf20Sopenharmony_ci .height = 1568, 9978c2ecf20Sopenharmony_ci .vts_def = OV13858_VTS_30FPS, 9988c2ecf20Sopenharmony_ci .vts_min = 1608, 9998c2ecf20Sopenharmony_ci .reg_list = { 10008c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mode_2112x1568_regs), 10018c2ecf20Sopenharmony_ci .regs = mode_2112x1568_regs, 10028c2ecf20Sopenharmony_ci }, 10038c2ecf20Sopenharmony_ci .link_freq_index = OV13858_LINK_FREQ_INDEX_1, 10048c2ecf20Sopenharmony_ci }, 10058c2ecf20Sopenharmony_ci { 10068c2ecf20Sopenharmony_ci .width = 2112, 10078c2ecf20Sopenharmony_ci .height = 1188, 10088c2ecf20Sopenharmony_ci .vts_def = OV13858_VTS_30FPS, 10098c2ecf20Sopenharmony_ci .vts_min = 1608, 10108c2ecf20Sopenharmony_ci .reg_list = { 10118c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mode_2112x1188_regs), 10128c2ecf20Sopenharmony_ci .regs = mode_2112x1188_regs, 10138c2ecf20Sopenharmony_ci }, 10148c2ecf20Sopenharmony_ci .link_freq_index = OV13858_LINK_FREQ_INDEX_1, 10158c2ecf20Sopenharmony_ci }, 10168c2ecf20Sopenharmony_ci { 10178c2ecf20Sopenharmony_ci .width = 1056, 10188c2ecf20Sopenharmony_ci .height = 784, 10198c2ecf20Sopenharmony_ci .vts_def = OV13858_VTS_30FPS, 10208c2ecf20Sopenharmony_ci .vts_min = 804, 10218c2ecf20Sopenharmony_ci .reg_list = { 10228c2ecf20Sopenharmony_ci .num_of_regs = ARRAY_SIZE(mode_1056x784_regs), 10238c2ecf20Sopenharmony_ci .regs = mode_1056x784_regs, 10248c2ecf20Sopenharmony_ci }, 10258c2ecf20Sopenharmony_ci .link_freq_index = OV13858_LINK_FREQ_INDEX_1, 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci}; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_cistruct ov13858 { 10308c2ecf20Sopenharmony_ci struct v4l2_subdev sd; 10318c2ecf20Sopenharmony_ci struct media_pad pad; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler ctrl_handler; 10348c2ecf20Sopenharmony_ci /* V4L2 Controls */ 10358c2ecf20Sopenharmony_ci struct v4l2_ctrl *link_freq; 10368c2ecf20Sopenharmony_ci struct v4l2_ctrl *pixel_rate; 10378c2ecf20Sopenharmony_ci struct v4l2_ctrl *vblank; 10388c2ecf20Sopenharmony_ci struct v4l2_ctrl *hblank; 10398c2ecf20Sopenharmony_ci struct v4l2_ctrl *exposure; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci /* Current mode */ 10428c2ecf20Sopenharmony_ci const struct ov13858_mode *cur_mode; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci /* Mutex for serialized access */ 10458c2ecf20Sopenharmony_ci struct mutex mutex; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* Streaming on/off */ 10488c2ecf20Sopenharmony_ci bool streaming; 10498c2ecf20Sopenharmony_ci}; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci#define to_ov13858(_sd) container_of(_sd, struct ov13858, sd) 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci/* Read registers up to 4 at a time */ 10548c2ecf20Sopenharmony_cistatic int ov13858_read_reg(struct ov13858 *ov13858, u16 reg, u32 len, 10558c2ecf20Sopenharmony_ci u32 *val) 10568c2ecf20Sopenharmony_ci{ 10578c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 10588c2ecf20Sopenharmony_ci struct i2c_msg msgs[2]; 10598c2ecf20Sopenharmony_ci u8 *data_be_p; 10608c2ecf20Sopenharmony_ci int ret; 10618c2ecf20Sopenharmony_ci __be32 data_be = 0; 10628c2ecf20Sopenharmony_ci __be16 reg_addr_be = cpu_to_be16(reg); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (len > 4) 10658c2ecf20Sopenharmony_ci return -EINVAL; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci data_be_p = (u8 *)&data_be; 10688c2ecf20Sopenharmony_ci /* Write register address */ 10698c2ecf20Sopenharmony_ci msgs[0].addr = client->addr; 10708c2ecf20Sopenharmony_ci msgs[0].flags = 0; 10718c2ecf20Sopenharmony_ci msgs[0].len = 2; 10728c2ecf20Sopenharmony_ci msgs[0].buf = (u8 *)®_addr_be; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci /* Read data from register */ 10758c2ecf20Sopenharmony_ci msgs[1].addr = client->addr; 10768c2ecf20Sopenharmony_ci msgs[1].flags = I2C_M_RD; 10778c2ecf20Sopenharmony_ci msgs[1].len = len; 10788c2ecf20Sopenharmony_ci msgs[1].buf = &data_be_p[4 - len]; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 10818c2ecf20Sopenharmony_ci if (ret != ARRAY_SIZE(msgs)) 10828c2ecf20Sopenharmony_ci return -EIO; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci *val = be32_to_cpu(data_be); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci return 0; 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci/* Write registers up to 4 at a time */ 10908c2ecf20Sopenharmony_cistatic int ov13858_write_reg(struct ov13858 *ov13858, u16 reg, u32 len, 10918c2ecf20Sopenharmony_ci u32 __val) 10928c2ecf20Sopenharmony_ci{ 10938c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 10948c2ecf20Sopenharmony_ci int buf_i, val_i; 10958c2ecf20Sopenharmony_ci u8 buf[6], *val_p; 10968c2ecf20Sopenharmony_ci __be32 val; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci if (len > 4) 10998c2ecf20Sopenharmony_ci return -EINVAL; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci buf[0] = reg >> 8; 11028c2ecf20Sopenharmony_ci buf[1] = reg & 0xff; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci val = cpu_to_be32(__val); 11058c2ecf20Sopenharmony_ci val_p = (u8 *)&val; 11068c2ecf20Sopenharmony_ci buf_i = 2; 11078c2ecf20Sopenharmony_ci val_i = 4 - len; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci while (val_i < 4) 11108c2ecf20Sopenharmony_ci buf[buf_i++] = val_p[val_i++]; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci if (i2c_master_send(client, buf, len + 2) != len + 2) 11138c2ecf20Sopenharmony_ci return -EIO; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci return 0; 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci/* Write a list of registers */ 11198c2ecf20Sopenharmony_cistatic int ov13858_write_regs(struct ov13858 *ov13858, 11208c2ecf20Sopenharmony_ci const struct ov13858_reg *regs, u32 len) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 11238c2ecf20Sopenharmony_ci int ret; 11248c2ecf20Sopenharmony_ci u32 i; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 11278c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, regs[i].address, 1, 11288c2ecf20Sopenharmony_ci regs[i].val); 11298c2ecf20Sopenharmony_ci if (ret) { 11308c2ecf20Sopenharmony_ci dev_err_ratelimited( 11318c2ecf20Sopenharmony_ci &client->dev, 11328c2ecf20Sopenharmony_ci "Failed to write reg 0x%4.4x. error = %d\n", 11338c2ecf20Sopenharmony_ci regs[i].address, ret); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return ret; 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci return 0; 11408c2ecf20Sopenharmony_ci} 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic int ov13858_write_reg_list(struct ov13858 *ov13858, 11438c2ecf20Sopenharmony_ci const struct ov13858_reg_list *r_list) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci return ov13858_write_regs(ov13858, r_list->regs, r_list->num_of_regs); 11468c2ecf20Sopenharmony_ci} 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci/* Open sub-device */ 11498c2ecf20Sopenharmony_cistatic int ov13858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 11508c2ecf20Sopenharmony_ci{ 11518c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 11528c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd, 11538c2ecf20Sopenharmony_ci fh->pad, 11548c2ecf20Sopenharmony_ci 0); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci mutex_lock(&ov13858->mutex); 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci /* Initialize try_fmt */ 11598c2ecf20Sopenharmony_ci try_fmt->width = ov13858->cur_mode->width; 11608c2ecf20Sopenharmony_ci try_fmt->height = ov13858->cur_mode->height; 11618c2ecf20Sopenharmony_ci try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; 11628c2ecf20Sopenharmony_ci try_fmt->field = V4L2_FIELD_NONE; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci /* No crop or compose */ 11658c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci return 0; 11688c2ecf20Sopenharmony_ci} 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_cistatic int ov13858_update_digital_gain(struct ov13858 *ov13858, u32 d_gain) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci int ret; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_B_MWB_GAIN, 11758c2ecf20Sopenharmony_ci OV13858_REG_VALUE_16BIT, d_gain); 11768c2ecf20Sopenharmony_ci if (ret) 11778c2ecf20Sopenharmony_ci return ret; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_G_MWB_GAIN, 11808c2ecf20Sopenharmony_ci OV13858_REG_VALUE_16BIT, d_gain); 11818c2ecf20Sopenharmony_ci if (ret) 11828c2ecf20Sopenharmony_ci return ret; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_R_MWB_GAIN, 11858c2ecf20Sopenharmony_ci OV13858_REG_VALUE_16BIT, d_gain); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci return ret; 11888c2ecf20Sopenharmony_ci} 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_cistatic int ov13858_enable_test_pattern(struct ov13858 *ov13858, u32 pattern) 11918c2ecf20Sopenharmony_ci{ 11928c2ecf20Sopenharmony_ci int ret; 11938c2ecf20Sopenharmony_ci u32 val; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci ret = ov13858_read_reg(ov13858, OV13858_REG_TEST_PATTERN, 11968c2ecf20Sopenharmony_ci OV13858_REG_VALUE_08BIT, &val); 11978c2ecf20Sopenharmony_ci if (ret) 11988c2ecf20Sopenharmony_ci return ret; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci if (pattern) { 12018c2ecf20Sopenharmony_ci val &= OV13858_TEST_PATTERN_MASK; 12028c2ecf20Sopenharmony_ci val |= (pattern - 1) | OV13858_TEST_PATTERN_ENABLE; 12038c2ecf20Sopenharmony_ci } else { 12048c2ecf20Sopenharmony_ci val &= ~OV13858_TEST_PATTERN_ENABLE; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci return ov13858_write_reg(ov13858, OV13858_REG_TEST_PATTERN, 12088c2ecf20Sopenharmony_ci OV13858_REG_VALUE_08BIT, val); 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_cistatic int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) 12128c2ecf20Sopenharmony_ci{ 12138c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = container_of(ctrl->handler, 12148c2ecf20Sopenharmony_ci struct ov13858, ctrl_handler); 12158c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 12168c2ecf20Sopenharmony_ci s64 max; 12178c2ecf20Sopenharmony_ci int ret; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci /* Propagate change of current control to all related controls */ 12208c2ecf20Sopenharmony_ci switch (ctrl->id) { 12218c2ecf20Sopenharmony_ci case V4L2_CID_VBLANK: 12228c2ecf20Sopenharmony_ci /* Update max exposure while meeting expected vblanking */ 12238c2ecf20Sopenharmony_ci max = ov13858->cur_mode->height + ctrl->val - 8; 12248c2ecf20Sopenharmony_ci __v4l2_ctrl_modify_range(ov13858->exposure, 12258c2ecf20Sopenharmony_ci ov13858->exposure->minimum, 12268c2ecf20Sopenharmony_ci max, ov13858->exposure->step, max); 12278c2ecf20Sopenharmony_ci break; 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci /* 12318c2ecf20Sopenharmony_ci * Applying V4L2 control value only happens 12328c2ecf20Sopenharmony_ci * when power is up for streaming 12338c2ecf20Sopenharmony_ci */ 12348c2ecf20Sopenharmony_ci if (!pm_runtime_get_if_in_use(&client->dev)) 12358c2ecf20Sopenharmony_ci return 0; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci ret = 0; 12388c2ecf20Sopenharmony_ci switch (ctrl->id) { 12398c2ecf20Sopenharmony_ci case V4L2_CID_ANALOGUE_GAIN: 12408c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_ANALOG_GAIN, 12418c2ecf20Sopenharmony_ci OV13858_REG_VALUE_16BIT, ctrl->val); 12428c2ecf20Sopenharmony_ci break; 12438c2ecf20Sopenharmony_ci case V4L2_CID_DIGITAL_GAIN: 12448c2ecf20Sopenharmony_ci ret = ov13858_update_digital_gain(ov13858, ctrl->val); 12458c2ecf20Sopenharmony_ci break; 12468c2ecf20Sopenharmony_ci case V4L2_CID_EXPOSURE: 12478c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_EXPOSURE, 12488c2ecf20Sopenharmony_ci OV13858_REG_VALUE_24BIT, 12498c2ecf20Sopenharmony_ci ctrl->val << 4); 12508c2ecf20Sopenharmony_ci break; 12518c2ecf20Sopenharmony_ci case V4L2_CID_VBLANK: 12528c2ecf20Sopenharmony_ci /* Update VTS that meets expected vertical blanking */ 12538c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_VTS, 12548c2ecf20Sopenharmony_ci OV13858_REG_VALUE_16BIT, 12558c2ecf20Sopenharmony_ci ov13858->cur_mode->height 12568c2ecf20Sopenharmony_ci + ctrl->val); 12578c2ecf20Sopenharmony_ci break; 12588c2ecf20Sopenharmony_ci case V4L2_CID_TEST_PATTERN: 12598c2ecf20Sopenharmony_ci ret = ov13858_enable_test_pattern(ov13858, ctrl->val); 12608c2ecf20Sopenharmony_ci break; 12618c2ecf20Sopenharmony_ci default: 12628c2ecf20Sopenharmony_ci dev_info(&client->dev, 12638c2ecf20Sopenharmony_ci "ctrl(id:0x%x,val:0x%x) is not handled\n", 12648c2ecf20Sopenharmony_ci ctrl->id, ctrl->val); 12658c2ecf20Sopenharmony_ci break; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci pm_runtime_put(&client->dev); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci return ret; 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops ov13858_ctrl_ops = { 12748c2ecf20Sopenharmony_ci .s_ctrl = ov13858_set_ctrl, 12758c2ecf20Sopenharmony_ci}; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_cistatic int ov13858_enum_mbus_code(struct v4l2_subdev *sd, 12788c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 12798c2ecf20Sopenharmony_ci struct v4l2_subdev_mbus_code_enum *code) 12808c2ecf20Sopenharmony_ci{ 12818c2ecf20Sopenharmony_ci /* Only one bayer order(GRBG) is supported */ 12828c2ecf20Sopenharmony_ci if (code->index > 0) 12838c2ecf20Sopenharmony_ci return -EINVAL; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci code->code = MEDIA_BUS_FMT_SGRBG10_1X10; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci return 0; 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cistatic int ov13858_enum_frame_size(struct v4l2_subdev *sd, 12918c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 12928c2ecf20Sopenharmony_ci struct v4l2_subdev_frame_size_enum *fse) 12938c2ecf20Sopenharmony_ci{ 12948c2ecf20Sopenharmony_ci if (fse->index >= ARRAY_SIZE(supported_modes)) 12958c2ecf20Sopenharmony_ci return -EINVAL; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) 12988c2ecf20Sopenharmony_ci return -EINVAL; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci fse->min_width = supported_modes[fse->index].width; 13018c2ecf20Sopenharmony_ci fse->max_width = fse->min_width; 13028c2ecf20Sopenharmony_ci fse->min_height = supported_modes[fse->index].height; 13038c2ecf20Sopenharmony_ci fse->max_height = fse->min_height; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci return 0; 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_cistatic void ov13858_update_pad_format(const struct ov13858_mode *mode, 13098c2ecf20Sopenharmony_ci struct v4l2_subdev_format *fmt) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci fmt->format.width = mode->width; 13128c2ecf20Sopenharmony_ci fmt->format.height = mode->height; 13138c2ecf20Sopenharmony_ci fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 13148c2ecf20Sopenharmony_ci fmt->format.field = V4L2_FIELD_NONE; 13158c2ecf20Sopenharmony_ci} 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_cistatic int ov13858_do_get_pad_format(struct ov13858 *ov13858, 13188c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 13198c2ecf20Sopenharmony_ci struct v4l2_subdev_format *fmt) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt *framefmt; 13228c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = &ov13858->sd; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 13258c2ecf20Sopenharmony_ci framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 13268c2ecf20Sopenharmony_ci fmt->format = *framefmt; 13278c2ecf20Sopenharmony_ci } else { 13288c2ecf20Sopenharmony_ci ov13858_update_pad_format(ov13858->cur_mode, fmt); 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci return 0; 13328c2ecf20Sopenharmony_ci} 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_cistatic int ov13858_get_pad_format(struct v4l2_subdev *sd, 13358c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 13368c2ecf20Sopenharmony_ci struct v4l2_subdev_format *fmt) 13378c2ecf20Sopenharmony_ci{ 13388c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 13398c2ecf20Sopenharmony_ci int ret; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci mutex_lock(&ov13858->mutex); 13428c2ecf20Sopenharmony_ci ret = ov13858_do_get_pad_format(ov13858, cfg, fmt); 13438c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci return ret; 13468c2ecf20Sopenharmony_ci} 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_cistatic int 13498c2ecf20Sopenharmony_ciov13858_set_pad_format(struct v4l2_subdev *sd, 13508c2ecf20Sopenharmony_ci struct v4l2_subdev_pad_config *cfg, 13518c2ecf20Sopenharmony_ci struct v4l2_subdev_format *fmt) 13528c2ecf20Sopenharmony_ci{ 13538c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 13548c2ecf20Sopenharmony_ci const struct ov13858_mode *mode; 13558c2ecf20Sopenharmony_ci struct v4l2_mbus_framefmt *framefmt; 13568c2ecf20Sopenharmony_ci s32 vblank_def; 13578c2ecf20Sopenharmony_ci s32 vblank_min; 13588c2ecf20Sopenharmony_ci s64 h_blank; 13598c2ecf20Sopenharmony_ci s64 pixel_rate; 13608c2ecf20Sopenharmony_ci s64 link_freq; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci mutex_lock(&ov13858->mutex); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci /* Only one raw bayer(GRBG) order is supported */ 13658c2ecf20Sopenharmony_ci if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10) 13668c2ecf20Sopenharmony_ci fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci mode = v4l2_find_nearest_size(supported_modes, 13698c2ecf20Sopenharmony_ci ARRAY_SIZE(supported_modes), 13708c2ecf20Sopenharmony_ci width, height, 13718c2ecf20Sopenharmony_ci fmt->format.width, fmt->format.height); 13728c2ecf20Sopenharmony_ci ov13858_update_pad_format(mode, fmt); 13738c2ecf20Sopenharmony_ci if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 13748c2ecf20Sopenharmony_ci framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 13758c2ecf20Sopenharmony_ci *framefmt = fmt->format; 13768c2ecf20Sopenharmony_ci } else { 13778c2ecf20Sopenharmony_ci ov13858->cur_mode = mode; 13788c2ecf20Sopenharmony_ci __v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index); 13798c2ecf20Sopenharmony_ci link_freq = link_freq_menu_items[mode->link_freq_index]; 13808c2ecf20Sopenharmony_ci pixel_rate = link_freq_to_pixel_rate(link_freq); 13818c2ecf20Sopenharmony_ci __v4l2_ctrl_s_ctrl_int64(ov13858->pixel_rate, pixel_rate); 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci /* Update limits and set FPS to default */ 13848c2ecf20Sopenharmony_ci vblank_def = ov13858->cur_mode->vts_def - 13858c2ecf20Sopenharmony_ci ov13858->cur_mode->height; 13868c2ecf20Sopenharmony_ci vblank_min = ov13858->cur_mode->vts_min - 13878c2ecf20Sopenharmony_ci ov13858->cur_mode->height; 13888c2ecf20Sopenharmony_ci __v4l2_ctrl_modify_range( 13898c2ecf20Sopenharmony_ci ov13858->vblank, vblank_min, 13908c2ecf20Sopenharmony_ci OV13858_VTS_MAX - ov13858->cur_mode->height, 1, 13918c2ecf20Sopenharmony_ci vblank_def); 13928c2ecf20Sopenharmony_ci __v4l2_ctrl_s_ctrl(ov13858->vblank, vblank_def); 13938c2ecf20Sopenharmony_ci h_blank = 13948c2ecf20Sopenharmony_ci link_freq_configs[mode->link_freq_index].pixels_per_line 13958c2ecf20Sopenharmony_ci - ov13858->cur_mode->width; 13968c2ecf20Sopenharmony_ci __v4l2_ctrl_modify_range(ov13858->hblank, h_blank, 13978c2ecf20Sopenharmony_ci h_blank, 1, h_blank); 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci return 0; 14038c2ecf20Sopenharmony_ci} 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_cistatic int ov13858_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) 14068c2ecf20Sopenharmony_ci{ 14078c2ecf20Sopenharmony_ci *frames = OV13858_NUM_OF_SKIP_FRAMES; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci return 0; 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci/* Start streaming */ 14138c2ecf20Sopenharmony_cistatic int ov13858_start_streaming(struct ov13858 *ov13858) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 14168c2ecf20Sopenharmony_ci const struct ov13858_reg_list *reg_list; 14178c2ecf20Sopenharmony_ci int ret, link_freq_index; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci /* Get out of from software reset */ 14208c2ecf20Sopenharmony_ci ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST, 14218c2ecf20Sopenharmony_ci OV13858_REG_VALUE_08BIT, OV13858_SOFTWARE_RST); 14228c2ecf20Sopenharmony_ci if (ret) { 14238c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s failed to set powerup registers\n", 14248c2ecf20Sopenharmony_ci __func__); 14258c2ecf20Sopenharmony_ci return ret; 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci /* Setup PLL */ 14298c2ecf20Sopenharmony_ci link_freq_index = ov13858->cur_mode->link_freq_index; 14308c2ecf20Sopenharmony_ci reg_list = &link_freq_configs[link_freq_index].reg_list; 14318c2ecf20Sopenharmony_ci ret = ov13858_write_reg_list(ov13858, reg_list); 14328c2ecf20Sopenharmony_ci if (ret) { 14338c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s failed to set plls\n", __func__); 14348c2ecf20Sopenharmony_ci return ret; 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* Apply default values of current mode */ 14388c2ecf20Sopenharmony_ci reg_list = &ov13858->cur_mode->reg_list; 14398c2ecf20Sopenharmony_ci ret = ov13858_write_reg_list(ov13858, reg_list); 14408c2ecf20Sopenharmony_ci if (ret) { 14418c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s failed to set mode\n", __func__); 14428c2ecf20Sopenharmony_ci return ret; 14438c2ecf20Sopenharmony_ci } 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci /* Apply customized values from user */ 14468c2ecf20Sopenharmony_ci ret = __v4l2_ctrl_handler_setup(ov13858->sd.ctrl_handler); 14478c2ecf20Sopenharmony_ci if (ret) 14488c2ecf20Sopenharmony_ci return ret; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT, 14518c2ecf20Sopenharmony_ci OV13858_REG_VALUE_08BIT, 14528c2ecf20Sopenharmony_ci OV13858_MODE_STREAMING); 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci/* Stop streaming */ 14568c2ecf20Sopenharmony_cistatic int ov13858_stop_streaming(struct ov13858 *ov13858) 14578c2ecf20Sopenharmony_ci{ 14588c2ecf20Sopenharmony_ci return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT, 14598c2ecf20Sopenharmony_ci OV13858_REG_VALUE_08BIT, OV13858_MODE_STANDBY); 14608c2ecf20Sopenharmony_ci} 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_cistatic int ov13858_set_stream(struct v4l2_subdev *sd, int enable) 14638c2ecf20Sopenharmony_ci{ 14648c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 14658c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(sd); 14668c2ecf20Sopenharmony_ci int ret = 0; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci mutex_lock(&ov13858->mutex); 14698c2ecf20Sopenharmony_ci if (ov13858->streaming == enable) { 14708c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 14718c2ecf20Sopenharmony_ci return 0; 14728c2ecf20Sopenharmony_ci } 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci if (enable) { 14758c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(&client->dev); 14768c2ecf20Sopenharmony_ci if (ret < 0) { 14778c2ecf20Sopenharmony_ci pm_runtime_put_noidle(&client->dev); 14788c2ecf20Sopenharmony_ci goto err_unlock; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci /* 14828c2ecf20Sopenharmony_ci * Apply default & customized values 14838c2ecf20Sopenharmony_ci * and then start streaming. 14848c2ecf20Sopenharmony_ci */ 14858c2ecf20Sopenharmony_ci ret = ov13858_start_streaming(ov13858); 14868c2ecf20Sopenharmony_ci if (ret) 14878c2ecf20Sopenharmony_ci goto err_rpm_put; 14888c2ecf20Sopenharmony_ci } else { 14898c2ecf20Sopenharmony_ci ov13858_stop_streaming(ov13858); 14908c2ecf20Sopenharmony_ci pm_runtime_put(&client->dev); 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci ov13858->streaming = enable; 14948c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci return ret; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_cierr_rpm_put: 14998c2ecf20Sopenharmony_ci pm_runtime_put(&client->dev); 15008c2ecf20Sopenharmony_cierr_unlock: 15018c2ecf20Sopenharmony_ci mutex_unlock(&ov13858->mutex); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci return ret; 15048c2ecf20Sopenharmony_ci} 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_cistatic int __maybe_unused ov13858_suspend(struct device *dev) 15078c2ecf20Sopenharmony_ci{ 15088c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 15098c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = i2c_get_clientdata(client); 15108c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (ov13858->streaming) 15138c2ecf20Sopenharmony_ci ov13858_stop_streaming(ov13858); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci return 0; 15168c2ecf20Sopenharmony_ci} 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_cistatic int __maybe_unused ov13858_resume(struct device *dev) 15198c2ecf20Sopenharmony_ci{ 15208c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 15218c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = i2c_get_clientdata(client); 15228c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 15238c2ecf20Sopenharmony_ci int ret; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (ov13858->streaming) { 15268c2ecf20Sopenharmony_ci ret = ov13858_start_streaming(ov13858); 15278c2ecf20Sopenharmony_ci if (ret) 15288c2ecf20Sopenharmony_ci goto error; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci return 0; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_cierror: 15348c2ecf20Sopenharmony_ci ov13858_stop_streaming(ov13858); 15358c2ecf20Sopenharmony_ci ov13858->streaming = false; 15368c2ecf20Sopenharmony_ci return ret; 15378c2ecf20Sopenharmony_ci} 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci/* Verify chip ID */ 15408c2ecf20Sopenharmony_cistatic int ov13858_identify_module(struct ov13858 *ov13858) 15418c2ecf20Sopenharmony_ci{ 15428c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 15438c2ecf20Sopenharmony_ci int ret; 15448c2ecf20Sopenharmony_ci u32 val; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci ret = ov13858_read_reg(ov13858, OV13858_REG_CHIP_ID, 15478c2ecf20Sopenharmony_ci OV13858_REG_VALUE_24BIT, &val); 15488c2ecf20Sopenharmony_ci if (ret) 15498c2ecf20Sopenharmony_ci return ret; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci if (val != OV13858_CHIP_ID) { 15528c2ecf20Sopenharmony_ci dev_err(&client->dev, "chip id mismatch: %x!=%x\n", 15538c2ecf20Sopenharmony_ci OV13858_CHIP_ID, val); 15548c2ecf20Sopenharmony_ci return -EIO; 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci return 0; 15588c2ecf20Sopenharmony_ci} 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_video_ops ov13858_video_ops = { 15618c2ecf20Sopenharmony_ci .s_stream = ov13858_set_stream, 15628c2ecf20Sopenharmony_ci}; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_pad_ops ov13858_pad_ops = { 15658c2ecf20Sopenharmony_ci .enum_mbus_code = ov13858_enum_mbus_code, 15668c2ecf20Sopenharmony_ci .get_fmt = ov13858_get_pad_format, 15678c2ecf20Sopenharmony_ci .set_fmt = ov13858_set_pad_format, 15688c2ecf20Sopenharmony_ci .enum_frame_size = ov13858_enum_frame_size, 15698c2ecf20Sopenharmony_ci}; 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_sensor_ops ov13858_sensor_ops = { 15728c2ecf20Sopenharmony_ci .g_skip_frames = ov13858_get_skip_frames, 15738c2ecf20Sopenharmony_ci}; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_ops ov13858_subdev_ops = { 15768c2ecf20Sopenharmony_ci .video = &ov13858_video_ops, 15778c2ecf20Sopenharmony_ci .pad = &ov13858_pad_ops, 15788c2ecf20Sopenharmony_ci .sensor = &ov13858_sensor_ops, 15798c2ecf20Sopenharmony_ci}; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_cistatic const struct media_entity_operations ov13858_subdev_entity_ops = { 15828c2ecf20Sopenharmony_ci .link_validate = v4l2_subdev_link_validate, 15838c2ecf20Sopenharmony_ci}; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_internal_ops ov13858_internal_ops = { 15868c2ecf20Sopenharmony_ci .open = ov13858_open, 15878c2ecf20Sopenharmony_ci}; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci/* Initialize control handlers */ 15908c2ecf20Sopenharmony_cistatic int ov13858_init_controls(struct ov13858 *ov13858) 15918c2ecf20Sopenharmony_ci{ 15928c2ecf20Sopenharmony_ci struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd); 15938c2ecf20Sopenharmony_ci struct v4l2_fwnode_device_properties props; 15948c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler *ctrl_hdlr; 15958c2ecf20Sopenharmony_ci s64 exposure_max; 15968c2ecf20Sopenharmony_ci s64 vblank_def; 15978c2ecf20Sopenharmony_ci s64 vblank_min; 15988c2ecf20Sopenharmony_ci s64 hblank; 15998c2ecf20Sopenharmony_ci s64 pixel_rate_min; 16008c2ecf20Sopenharmony_ci s64 pixel_rate_max; 16018c2ecf20Sopenharmony_ci const struct ov13858_mode *mode; 16028c2ecf20Sopenharmony_ci int ret; 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci ctrl_hdlr = &ov13858->ctrl_handler; 16058c2ecf20Sopenharmony_ci ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); 16068c2ecf20Sopenharmony_ci if (ret) 16078c2ecf20Sopenharmony_ci return ret; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci mutex_init(&ov13858->mutex); 16108c2ecf20Sopenharmony_ci ctrl_hdlr->lock = &ov13858->mutex; 16118c2ecf20Sopenharmony_ci ov13858->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, 16128c2ecf20Sopenharmony_ci &ov13858_ctrl_ops, 16138c2ecf20Sopenharmony_ci V4L2_CID_LINK_FREQ, 16148c2ecf20Sopenharmony_ci OV13858_NUM_OF_LINK_FREQS - 1, 16158c2ecf20Sopenharmony_ci 0, 16168c2ecf20Sopenharmony_ci link_freq_menu_items); 16178c2ecf20Sopenharmony_ci if (ov13858->link_freq) 16188c2ecf20Sopenharmony_ci ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]); 16218c2ecf20Sopenharmony_ci pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]); 16228c2ecf20Sopenharmony_ci /* By default, PIXEL_RATE is read only */ 16238c2ecf20Sopenharmony_ci ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, 16248c2ecf20Sopenharmony_ci V4L2_CID_PIXEL_RATE, 16258c2ecf20Sopenharmony_ci pixel_rate_min, pixel_rate_max, 16268c2ecf20Sopenharmony_ci 1, pixel_rate_max); 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci mode = ov13858->cur_mode; 16298c2ecf20Sopenharmony_ci vblank_def = mode->vts_def - mode->height; 16308c2ecf20Sopenharmony_ci vblank_min = mode->vts_min - mode->height; 16318c2ecf20Sopenharmony_ci ov13858->vblank = v4l2_ctrl_new_std( 16328c2ecf20Sopenharmony_ci ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK, 16338c2ecf20Sopenharmony_ci vblank_min, OV13858_VTS_MAX - mode->height, 1, 16348c2ecf20Sopenharmony_ci vblank_def); 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci hblank = link_freq_configs[mode->link_freq_index].pixels_per_line - 16378c2ecf20Sopenharmony_ci mode->width; 16388c2ecf20Sopenharmony_ci ov13858->hblank = v4l2_ctrl_new_std( 16398c2ecf20Sopenharmony_ci ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK, 16408c2ecf20Sopenharmony_ci hblank, hblank, 1, hblank); 16418c2ecf20Sopenharmony_ci if (ov13858->hblank) 16428c2ecf20Sopenharmony_ci ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci exposure_max = mode->vts_def - 8; 16458c2ecf20Sopenharmony_ci ov13858->exposure = v4l2_ctrl_new_std( 16468c2ecf20Sopenharmony_ci ctrl_hdlr, &ov13858_ctrl_ops, 16478c2ecf20Sopenharmony_ci V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN, 16488c2ecf20Sopenharmony_ci exposure_max, OV13858_EXPOSURE_STEP, 16498c2ecf20Sopenharmony_ci OV13858_EXPOSURE_DEFAULT); 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, 16528c2ecf20Sopenharmony_ci OV13858_ANA_GAIN_MIN, OV13858_ANA_GAIN_MAX, 16538c2ecf20Sopenharmony_ci OV13858_ANA_GAIN_STEP, OV13858_ANA_GAIN_DEFAULT); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci /* Digital gain */ 16568c2ecf20Sopenharmony_ci v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_DIGITAL_GAIN, 16578c2ecf20Sopenharmony_ci OV13858_DGTL_GAIN_MIN, OV13858_DGTL_GAIN_MAX, 16588c2ecf20Sopenharmony_ci OV13858_DGTL_GAIN_STEP, OV13858_DGTL_GAIN_DEFAULT); 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov13858_ctrl_ops, 16618c2ecf20Sopenharmony_ci V4L2_CID_TEST_PATTERN, 16628c2ecf20Sopenharmony_ci ARRAY_SIZE(ov13858_test_pattern_menu) - 1, 16638c2ecf20Sopenharmony_ci 0, 0, ov13858_test_pattern_menu); 16648c2ecf20Sopenharmony_ci if (ctrl_hdlr->error) { 16658c2ecf20Sopenharmony_ci ret = ctrl_hdlr->error; 16668c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s control init failed (%d)\n", 16678c2ecf20Sopenharmony_ci __func__, ret); 16688c2ecf20Sopenharmony_ci goto error; 16698c2ecf20Sopenharmony_ci } 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci ret = v4l2_fwnode_device_parse(&client->dev, &props); 16728c2ecf20Sopenharmony_ci if (ret) 16738c2ecf20Sopenharmony_ci goto error; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov13858_ctrl_ops, 16768c2ecf20Sopenharmony_ci &props); 16778c2ecf20Sopenharmony_ci if (ret) 16788c2ecf20Sopenharmony_ci goto error; 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci ov13858->sd.ctrl_handler = ctrl_hdlr; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci return 0; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_cierror: 16858c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(ctrl_hdlr); 16868c2ecf20Sopenharmony_ci mutex_destroy(&ov13858->mutex); 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci return ret; 16898c2ecf20Sopenharmony_ci} 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_cistatic void ov13858_free_controls(struct ov13858 *ov13858) 16928c2ecf20Sopenharmony_ci{ 16938c2ecf20Sopenharmony_ci v4l2_ctrl_handler_free(ov13858->sd.ctrl_handler); 16948c2ecf20Sopenharmony_ci mutex_destroy(&ov13858->mutex); 16958c2ecf20Sopenharmony_ci} 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_cistatic int ov13858_probe(struct i2c_client *client, 16988c2ecf20Sopenharmony_ci const struct i2c_device_id *devid) 16998c2ecf20Sopenharmony_ci{ 17008c2ecf20Sopenharmony_ci struct ov13858 *ov13858; 17018c2ecf20Sopenharmony_ci int ret; 17028c2ecf20Sopenharmony_ci u32 val = 0; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci device_property_read_u32(&client->dev, "clock-frequency", &val); 17058c2ecf20Sopenharmony_ci if (val != 19200000) 17068c2ecf20Sopenharmony_ci return -EINVAL; 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci ov13858 = devm_kzalloc(&client->dev, sizeof(*ov13858), GFP_KERNEL); 17098c2ecf20Sopenharmony_ci if (!ov13858) 17108c2ecf20Sopenharmony_ci return -ENOMEM; 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci /* Initialize subdev */ 17138c2ecf20Sopenharmony_ci v4l2_i2c_subdev_init(&ov13858->sd, client, &ov13858_subdev_ops); 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci /* Check module identity */ 17168c2ecf20Sopenharmony_ci ret = ov13858_identify_module(ov13858); 17178c2ecf20Sopenharmony_ci if (ret) { 17188c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to find sensor: %d\n", ret); 17198c2ecf20Sopenharmony_ci return ret; 17208c2ecf20Sopenharmony_ci } 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci /* Set default mode to max resolution */ 17238c2ecf20Sopenharmony_ci ov13858->cur_mode = &supported_modes[0]; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci ret = ov13858_init_controls(ov13858); 17268c2ecf20Sopenharmony_ci if (ret) 17278c2ecf20Sopenharmony_ci return ret; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci /* Initialize subdev */ 17308c2ecf20Sopenharmony_ci ov13858->sd.internal_ops = &ov13858_internal_ops; 17318c2ecf20Sopenharmony_ci ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 17328c2ecf20Sopenharmony_ci ov13858->sd.entity.ops = &ov13858_subdev_entity_ops; 17338c2ecf20Sopenharmony_ci ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci /* Initialize source pad */ 17368c2ecf20Sopenharmony_ci ov13858->pad.flags = MEDIA_PAD_FL_SOURCE; 17378c2ecf20Sopenharmony_ci ret = media_entity_pads_init(&ov13858->sd.entity, 1, &ov13858->pad); 17388c2ecf20Sopenharmony_ci if (ret) { 17398c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s failed:%d\n", __func__, ret); 17408c2ecf20Sopenharmony_ci goto error_handler_free; 17418c2ecf20Sopenharmony_ci } 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci ret = v4l2_async_register_subdev_sensor_common(&ov13858->sd); 17448c2ecf20Sopenharmony_ci if (ret < 0) 17458c2ecf20Sopenharmony_ci goto error_media_entity; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci /* 17488c2ecf20Sopenharmony_ci * Device is already turned on by i2c-core with ACPI domain PM. 17498c2ecf20Sopenharmony_ci * Enable runtime PM and turn off the device. 17508c2ecf20Sopenharmony_ci */ 17518c2ecf20Sopenharmony_ci pm_runtime_set_active(&client->dev); 17528c2ecf20Sopenharmony_ci pm_runtime_enable(&client->dev); 17538c2ecf20Sopenharmony_ci pm_runtime_idle(&client->dev); 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci return 0; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_cierror_media_entity: 17588c2ecf20Sopenharmony_ci media_entity_cleanup(&ov13858->sd.entity); 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_cierror_handler_free: 17618c2ecf20Sopenharmony_ci ov13858_free_controls(ov13858); 17628c2ecf20Sopenharmony_ci dev_err(&client->dev, "%s failed:%d\n", __func__, ret); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci return ret; 17658c2ecf20Sopenharmony_ci} 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_cistatic int ov13858_remove(struct i2c_client *client) 17688c2ecf20Sopenharmony_ci{ 17698c2ecf20Sopenharmony_ci struct v4l2_subdev *sd = i2c_get_clientdata(client); 17708c2ecf20Sopenharmony_ci struct ov13858 *ov13858 = to_ov13858(sd); 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci v4l2_async_unregister_subdev(sd); 17738c2ecf20Sopenharmony_ci media_entity_cleanup(&sd->entity); 17748c2ecf20Sopenharmony_ci ov13858_free_controls(ov13858); 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci pm_runtime_disable(&client->dev); 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci return 0; 17798c2ecf20Sopenharmony_ci} 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_cistatic const struct i2c_device_id ov13858_id_table[] = { 17828c2ecf20Sopenharmony_ci {"ov13858", 0}, 17838c2ecf20Sopenharmony_ci {}, 17848c2ecf20Sopenharmony_ci}; 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ov13858_id_table); 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_cistatic const struct dev_pm_ops ov13858_pm_ops = { 17898c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(ov13858_suspend, ov13858_resume) 17908c2ecf20Sopenharmony_ci}; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 17938c2ecf20Sopenharmony_cistatic const struct acpi_device_id ov13858_acpi_ids[] = { 17948c2ecf20Sopenharmony_ci {"OVTID858"}, 17958c2ecf20Sopenharmony_ci { /* sentinel */ } 17968c2ecf20Sopenharmony_ci}; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids); 17998c2ecf20Sopenharmony_ci#endif 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_cistatic struct i2c_driver ov13858_i2c_driver = { 18028c2ecf20Sopenharmony_ci .driver = { 18038c2ecf20Sopenharmony_ci .name = "ov13858", 18048c2ecf20Sopenharmony_ci .pm = &ov13858_pm_ops, 18058c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), 18068c2ecf20Sopenharmony_ci }, 18078c2ecf20Sopenharmony_ci .probe = ov13858_probe, 18088c2ecf20Sopenharmony_ci .remove = ov13858_remove, 18098c2ecf20Sopenharmony_ci .id_table = ov13858_id_table, 18108c2ecf20Sopenharmony_ci}; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_cimodule_i2c_driver(ov13858_i2c_driver); 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kan, Chris <chris.kan@intel.com>"); 18158c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>"); 18168c2ecf20Sopenharmony_ciMODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>"); 18178c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Omnivision ov13858 sensor driver"); 18188c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1819