1e43ccb0aSPaul Kocialkowski // SPDX-License-Identifier: GPL-2.0-or-later 2e43ccb0aSPaul Kocialkowski /* 3e43ccb0aSPaul Kocialkowski * Copyright (C) 2020 Bootlin 4e43ccb0aSPaul Kocialkowski * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com> 5e43ccb0aSPaul Kocialkowski */ 6e43ccb0aSPaul Kocialkowski 7e43ccb0aSPaul Kocialkowski #include <linux/clk.h> 8e43ccb0aSPaul Kocialkowski #include <linux/delay.h> 9e43ccb0aSPaul Kocialkowski #include <linux/device.h> 10e43ccb0aSPaul Kocialkowski #include <linux/i2c.h> 11e43ccb0aSPaul Kocialkowski #include <linux/module.h> 12e43ccb0aSPaul Kocialkowski #include <linux/of_graph.h> 13e43ccb0aSPaul Kocialkowski #include <linux/pm_runtime.h> 14e43ccb0aSPaul Kocialkowski #include <linux/regulator/consumer.h> 15e43ccb0aSPaul Kocialkowski #include <linux/videodev2.h> 16e43ccb0aSPaul Kocialkowski #include <media/v4l2-ctrls.h> 17e43ccb0aSPaul Kocialkowski #include <media/v4l2-device.h> 18e43ccb0aSPaul Kocialkowski #include <media/v4l2-fwnode.h> 19e43ccb0aSPaul Kocialkowski #include <media/v4l2-image-sizes.h> 20e43ccb0aSPaul Kocialkowski #include <media/v4l2-mediabus.h> 21e43ccb0aSPaul Kocialkowski 22e43ccb0aSPaul Kocialkowski /* Clock rate */ 23e43ccb0aSPaul Kocialkowski 24e43ccb0aSPaul Kocialkowski #define OV5648_XVCLK_RATE 24000000 25e43ccb0aSPaul Kocialkowski 26e43ccb0aSPaul Kocialkowski /* Register definitions */ 27e43ccb0aSPaul Kocialkowski 28e43ccb0aSPaul Kocialkowski /* System */ 29e43ccb0aSPaul Kocialkowski 30e43ccb0aSPaul Kocialkowski #define OV5648_SW_STANDBY_REG 0x100 31e43ccb0aSPaul Kocialkowski #define OV5648_SW_STANDBY_STREAM_ON BIT(0) 32e43ccb0aSPaul Kocialkowski 33e43ccb0aSPaul Kocialkowski #define OV5648_SW_RESET_REG 0x103 34e43ccb0aSPaul Kocialkowski #define OV5648_SW_RESET_RESET BIT(0) 35e43ccb0aSPaul Kocialkowski 36e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OEN0_REG 0x3000 37e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OEN1_REG 0x3001 38e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OEN2_REG 0x3002 39e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OUT0_REG 0x3008 40e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OUT1_REG 0x3009 41e43ccb0aSPaul Kocialkowski 42e43ccb0aSPaul Kocialkowski #define OV5648_CHIP_ID_H_REG 0x300a 43e43ccb0aSPaul Kocialkowski #define OV5648_CHIP_ID_H_VALUE 0x56 44e43ccb0aSPaul Kocialkowski #define OV5648_CHIP_ID_L_REG 0x300b 45e43ccb0aSPaul Kocialkowski #define OV5648_CHIP_ID_L_VALUE 0x48 46e43ccb0aSPaul Kocialkowski 47e43ccb0aSPaul Kocialkowski #define OV5648_PAD_OUT2_REG 0x300d 48e43ccb0aSPaul Kocialkowski #define OV5648_PAD_SEL0_REG 0x300e 49e43ccb0aSPaul Kocialkowski #define OV5648_PAD_SEL1_REG 0x300f 50e43ccb0aSPaul Kocialkowski #define OV5648_PAD_SEL2_REG 0x3010 51e43ccb0aSPaul Kocialkowski #define OV5648_PAD_PK_REG 0x3011 52e43ccb0aSPaul Kocialkowski #define OV5648_PAD_PK_PD_DATO_EN BIT(7) 53e43ccb0aSPaul Kocialkowski #define OV5648_PAD_PK_DRIVE_STRENGTH_1X (0 << 5) 54e43ccb0aSPaul Kocialkowski #define OV5648_PAD_PK_DRIVE_STRENGTH_2X (2 << 5) 55e43ccb0aSPaul Kocialkowski #define OV5648_PAD_PK_FREX_N BIT(1) 56e43ccb0aSPaul Kocialkowski 57e43ccb0aSPaul Kocialkowski #define OV5648_A_PWC_PK_O0_REG 0x3013 58e43ccb0aSPaul Kocialkowski #define OV5648_A_PWC_PK_O0_BP_REGULATOR_N BIT(3) 59e43ccb0aSPaul Kocialkowski #define OV5648_A_PWC_PK_O1_REG 0x3014 60e43ccb0aSPaul Kocialkowski 61e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_PHY0_REG 0x3016 62e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_PHY1_REG 0x3017 63e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_REG 0x3018 64e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_MIPI_LANES(v) (((v) << 5) & GENMASK(7, 5)) 65e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_PHY_HS_TX_PD BIT(4) 66e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_PHY_LP_RX_PD BIT(3) 67e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_MIPI_EN BIT(2) 68e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_MIPI_SUSP BIT(1) 69e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL0_LANE_DIS_OP BIT(0) 70e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL1_REG 0x3019 71e43ccb0aSPaul Kocialkowski #define OV5648_MISC_CTRL0_REG 0x3021 72e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SC_CTRL2_REG 0x3022 73e43ccb0aSPaul Kocialkowski #define OV5648_SUB_ID_REG 0x302a 74e43ccb0aSPaul Kocialkowski 75e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL0_REG 0x3034 76e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL0_PLL_CHARGE_PUMP(v) (((v) << 4) & GENMASK(6, 4)) 77e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL0_BITS(v) ((v) & GENMASK(3, 0)) 78e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL1_REG 0x3035 79e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL1_SYS_DIV(v) (((v) << 4) & GENMASK(7, 4)) 80e43ccb0aSPaul Kocialkowski #define OV5648_PLL_CTRL1_MIPI_DIV(v) ((v) & GENMASK(3, 0)) 81e43ccb0aSPaul Kocialkowski #define OV5648_PLL_MUL_REG 0x3036 82e43ccb0aSPaul Kocialkowski #define OV5648_PLL_MUL(v) ((v) & GENMASK(7, 0)) 83e43ccb0aSPaul Kocialkowski #define OV5648_PLL_DIV_REG 0x3037 84e43ccb0aSPaul Kocialkowski #define OV5648_PLL_DIV_ROOT_DIV(v) ((((v) - 1) << 4) & BIT(4)) 85e43ccb0aSPaul Kocialkowski #define OV5648_PLL_DIV_PLL_PRE_DIV(v) ((v) & GENMASK(3, 0)) 86e43ccb0aSPaul Kocialkowski #define OV5648_PLL_DEBUG_REG 0x3038 87e43ccb0aSPaul Kocialkowski #define OV5648_PLL_BYPASS_REG 0x3039 88e43ccb0aSPaul Kocialkowski 89e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_BYPASS_REG 0x303a 90e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_MUL_REG 0x303b 91e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_MUL(v) ((v) & GENMASK(4, 0)) 92e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_CTRL_REG 0x303c 93e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_CTRL_PLL_CHARGE_PUMP(v) (((v) << 4) & GENMASK(6, 4)) 94e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_CTRL_SYS_DIV(v) ((v) & GENMASK(3, 0)) 95e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_DIV_REG 0x303d 96e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_DIV_PLLS_PRE_DIV(v) (((v) << 4) & GENMASK(5, 4)) 97e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_DIV_PLLS_DIV_R(v) ((((v) - 1) << 2) & BIT(2)) 98e43ccb0aSPaul Kocialkowski #define OV5648_PLLS_DIV_PLLS_SEL_DIV(v) ((v) & GENMASK(1, 0)) 99e43ccb0aSPaul Kocialkowski 100e43ccb0aSPaul Kocialkowski #define OV5648_SRB_CTRL_REG 0x3106 101e43ccb0aSPaul Kocialkowski #define OV5648_SRB_CTRL_SCLK_DIV(v) (((v) << 2) & GENMASK(3, 2)) 102e43ccb0aSPaul Kocialkowski #define OV5648_SRB_CTRL_RESET_ARBITER_EN BIT(1) 103e43ccb0aSPaul Kocialkowski #define OV5648_SRB_CTRL_SCLK_ARBITER_EN BIT(0) 104e43ccb0aSPaul Kocialkowski 105e43ccb0aSPaul Kocialkowski /* Group Hold */ 106e43ccb0aSPaul Kocialkowski 107e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_ADR0_REG 0x3200 108e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_ADR1_REG 0x3201 109e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_ADR2_REG 0x3202 110e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_ADR3_REG 0x3203 111e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_LEN0_REG 0x3204 112e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_LEN1_REG 0x3205 113e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_LEN2_REG 0x3206 114e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_LEN3_REG 0x3207 115e43ccb0aSPaul Kocialkowski #define OV5648_GROUP_ACCESS_REG 0x3208 116e43ccb0aSPaul Kocialkowski 117e43ccb0aSPaul Kocialkowski /* Exposure/gain/banding */ 118e43ccb0aSPaul Kocialkowski 119e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_HH_REG 0x3500 120e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_HH(v) (((v) & GENMASK(19, 16)) >> 16) 121e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_HH_VALUE(v) (((v) << 16) & GENMASK(19, 16)) 122e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_H_REG 0x3501 123e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_H(v) (((v) & GENMASK(15, 8)) >> 8) 124e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_H_VALUE(v) (((v) << 8) & GENMASK(15, 8)) 125e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_L_REG 0x3502 126e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0)) 127e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_CTRL_L_VALUE(v) ((v) & GENMASK(7, 0)) 128e43ccb0aSPaul Kocialkowski #define OV5648_MANUAL_CTRL_REG 0x3503 129e43ccb0aSPaul Kocialkowski #define OV5648_MANUAL_CTRL_FRAME_DELAY(v) (((v) << 4) & GENMASK(5, 4)) 130e43ccb0aSPaul Kocialkowski #define OV5648_MANUAL_CTRL_AGC_MANUAL_EN BIT(1) 131e43ccb0aSPaul Kocialkowski #define OV5648_MANUAL_CTRL_AEC_MANUAL_EN BIT(0) 132e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_H_REG 0x350a 133e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_H(v) (((v) & GENMASK(9, 8)) >> 8) 134e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_H_VALUE(v) (((v) << 8) & GENMASK(9, 8)) 135e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_L_REG 0x350b 136e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_L(v) ((v) & GENMASK(7, 0)) 137e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_CTRL_L_VALUE(v) ((v) & GENMASK(7, 0)) 138e43ccb0aSPaul Kocialkowski 139e43ccb0aSPaul Kocialkowski #define OV5648_ANALOG_CTRL0_REG_BASE 0x3600 140e43ccb0aSPaul Kocialkowski #define OV5648_ANALOG_CTRL1_REG_BASE 0x3700 141e43ccb0aSPaul Kocialkowski 142e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_REG 0x3a00 143e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_DEBUG BIT(6) 144e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_DEBAND_EN BIT(5) 145e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_DEBAND_LOW_LIMIT_EN BIT(4) 146e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_START_SEL_EN BIT(3) 147e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_NIGHT_MODE_EN BIT(2) 148e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL0_FREEZE_EN BIT(0) 149e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_MIN_REG 0x3a01 150e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_MAX_60_H_REG 0x3a02 151e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_MAX_60_L_REG 0x3a03 152e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL5_REG 0x3a05 153e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL6_REG 0x3a06 154e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL7_REG 0x3a07 155e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_STEP_50_H_REG 0x3a08 156e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_STEP_50_L_REG 0x3a09 157e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_STEP_60_H_REG 0x3a0a 158e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_STEP_60_L_REG 0x3a0b 159e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRLC_REG 0x3a0c 160e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_MAX_60_REG 0x3a0d 161e43ccb0aSPaul Kocialkowski #define OV5648_BANDING_MAX_50_REG 0x3a0e 162e43ccb0aSPaul Kocialkowski #define OV5648_WPT_REG 0x3a0f 163e43ccb0aSPaul Kocialkowski #define OV5648_BPT_REG 0x3a10 164e43ccb0aSPaul Kocialkowski #define OV5648_VPT_HIGH_REG 0x3a11 165e43ccb0aSPaul Kocialkowski #define OV5648_AVG_MANUAL_REG 0x3a12 166e43ccb0aSPaul Kocialkowski #define OV5648_PRE_GAIN_REG 0x3a13 167e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_MAX_50_H_REG 0x3a14 168e43ccb0aSPaul Kocialkowski #define OV5648_EXPOSURE_MAX_50_L_REG 0x3a15 169e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BASE_NIGHT_REG 0x3a17 170e43ccb0aSPaul Kocialkowski #define OV5648_AEC_GAIN_CEILING_H_REG 0x3a18 171e43ccb0aSPaul Kocialkowski #define OV5648_AEC_GAIN_CEILING_L_REG 0x3a19 172e43ccb0aSPaul Kocialkowski #define OV5648_DIFF_MAX_REG 0x3a1a 173e43ccb0aSPaul Kocialkowski #define OV5648_WPT2_REG 0x3a1b 174e43ccb0aSPaul Kocialkowski #define OV5648_LED_ADD_ROW_H_REG 0x3a1c 175e43ccb0aSPaul Kocialkowski #define OV5648_LED_ADD_ROW_L_REG 0x3a1d 176e43ccb0aSPaul Kocialkowski #define OV5648_BPT2_REG 0x3a1e 177e43ccb0aSPaul Kocialkowski #define OV5648_VPT_LOW_REG 0x3a1f 178e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL20_REG 0x3a20 179e43ccb0aSPaul Kocialkowski #define OV5648_AEC_CTRL21_REG 0x3a21 180e43ccb0aSPaul Kocialkowski 181e43ccb0aSPaul Kocialkowski #define OV5648_AVG_START_X_H_REG 0x5680 182e43ccb0aSPaul Kocialkowski #define OV5648_AVG_START_X_L_REG 0x5681 183e43ccb0aSPaul Kocialkowski #define OV5648_AVG_START_Y_H_REG 0x5682 184e43ccb0aSPaul Kocialkowski #define OV5648_AVG_START_Y_L_REG 0x5683 185e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WINDOW_X_H_REG 0x5684 186e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WINDOW_X_L_REG 0x5685 187e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WINDOW_Y_H_REG 0x5686 188e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WINDOW_Y_L_REG 0x5687 189e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT00_REG 0x5688 190e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT01_REG 0x5689 191e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT02_REG 0x568a 192e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT03_REG 0x568b 193e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT04_REG 0x568c 194e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT05_REG 0x568d 195e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT06_REG 0x568e 196e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT07_REG 0x568f 197e43ccb0aSPaul Kocialkowski #define OV5648_AVG_CTRL10_REG 0x5690 198e43ccb0aSPaul Kocialkowski #define OV5648_AVG_WEIGHT_SUM_REG 0x5691 199e43ccb0aSPaul Kocialkowski #define OV5648_AVG_READOUT_REG 0x5693 200e43ccb0aSPaul Kocialkowski 201e43ccb0aSPaul Kocialkowski #define OV5648_DIG_CTRL0_REG 0x5a00 202e43ccb0aSPaul Kocialkowski #define OV5648_DIG_COMP_MAN_H_REG 0x5a02 203e43ccb0aSPaul Kocialkowski #define OV5648_DIG_COMP_MAN_L_REG 0x5a03 204e43ccb0aSPaul Kocialkowski 205e43ccb0aSPaul Kocialkowski #define OV5648_GAINC_MAN_H_REG 0x5a20 206e43ccb0aSPaul Kocialkowski #define OV5648_GAINC_MAN_L_REG 0x5a21 207e43ccb0aSPaul Kocialkowski #define OV5648_GAINC_DGC_MAN_H_REG 0x5a22 208e43ccb0aSPaul Kocialkowski #define OV5648_GAINC_DGC_MAN_L_REG 0x5a23 209e43ccb0aSPaul Kocialkowski #define OV5648_GAINC_CTRL0_REG 0x5a24 210e43ccb0aSPaul Kocialkowski 211e43ccb0aSPaul Kocialkowski #define OV5648_GAINF_ANA_NUM_REG 0x5a40 212e43ccb0aSPaul Kocialkowski #define OV5648_GAINF_DIG_GAIN_REG 0x5a41 213e43ccb0aSPaul Kocialkowski 214e43ccb0aSPaul Kocialkowski /* Timing */ 215e43ccb0aSPaul Kocialkowski 216e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_X_H_REG 0x3800 217e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_X_H(v) (((v) & GENMASK(11, 8)) >> 8) 218e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_X_L_REG 0x3801 219e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_X_L(v) ((v) & GENMASK(7, 0)) 220e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_Y_H_REG 0x3802 221e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) 222e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_Y_L_REG 0x3803 223e43ccb0aSPaul Kocialkowski #define OV5648_CROP_START_Y_L(v) ((v) & GENMASK(7, 0)) 224e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_X_H_REG 0x3804 225e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_X_H(v) (((v) & GENMASK(11, 8)) >> 8) 226e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_X_L_REG 0x3805 227e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_X_L(v) ((v) & GENMASK(7, 0)) 228e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_Y_H_REG 0x3806 229e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) 230e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_Y_L_REG 0x3807 231e43ccb0aSPaul Kocialkowski #define OV5648_CROP_END_Y_L(v) ((v) & GENMASK(7, 0)) 232e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_X_H_REG 0x3808 233e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_X_H(v) (((v) & GENMASK(11, 8)) >> 8) 234e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_X_L_REG 0x3809 235e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_X_L(v) ((v) & GENMASK(7, 0)) 236e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_Y_H_REG 0x380a 237e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) 238e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_Y_L_REG 0x380b 239e43ccb0aSPaul Kocialkowski #define OV5648_OUTPUT_SIZE_Y_L(v) ((v) & GENMASK(7, 0)) 240e43ccb0aSPaul Kocialkowski #define OV5648_HTS_H_REG 0x380c 241e43ccb0aSPaul Kocialkowski #define OV5648_HTS_H(v) (((v) & GENMASK(12, 8)) >> 8) 242e43ccb0aSPaul Kocialkowski #define OV5648_HTS_L_REG 0x380d 243e43ccb0aSPaul Kocialkowski #define OV5648_HTS_L(v) ((v) & GENMASK(7, 0)) 244e43ccb0aSPaul Kocialkowski #define OV5648_VTS_H_REG 0x380e 245e43ccb0aSPaul Kocialkowski #define OV5648_VTS_H(v) (((v) & GENMASK(15, 8)) >> 8) 246e43ccb0aSPaul Kocialkowski #define OV5648_VTS_L_REG 0x380f 247e43ccb0aSPaul Kocialkowski #define OV5648_VTS_L(v) ((v) & GENMASK(7, 0)) 248e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_X_H_REG 0x3810 249e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_X_H(v) (((v) & GENMASK(11, 8)) >> 8) 250e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_X_L_REG 0x3811 251e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_X_L(v) ((v) & GENMASK(7, 0)) 252e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_Y_H_REG 0x3812 253e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_Y_H(v) (((v) & GENMASK(11, 8)) >> 8) 254e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_Y_L_REG 0x3813 255e43ccb0aSPaul Kocialkowski #define OV5648_OFFSET_Y_L(v) ((v) & GENMASK(7, 0)) 256e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_X_REG 0x3814 257e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_X_ODD(v) (((v) << 4) & GENMASK(7, 4)) 258e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_X_EVEN(v) ((v) & GENMASK(3, 0)) 259e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_Y_REG 0x3815 260e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_Y_ODD(v) (((v) << 4) & GENMASK(7, 4)) 261e43ccb0aSPaul Kocialkowski #define OV5648_SUB_INC_Y_EVEN(v) ((v) & GENMASK(3, 0)) 262e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCST_H_REG 0x3816 263e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCST_H(v) (((v) >> 8) & 0xf) 264e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCST_L_REG 0x3817 265e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCST_L(v) ((v) & GENMASK(7, 0)) 266e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCW_H_REG 0x3818 267e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCW_H(v) (((v) >> 8) & 0xf) 268e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCW_L_REG 0x3819 269e43ccb0aSPaul Kocialkowski #define OV5648_HSYNCW_L(v) ((v) & GENMASK(7, 0)) 270e43ccb0aSPaul Kocialkowski 271e43ccb0aSPaul Kocialkowski #define OV5648_TC20_REG 0x3820 272e43ccb0aSPaul Kocialkowski #define OV5648_TC20_DEBUG BIT(6) 273e43ccb0aSPaul Kocialkowski #define OV5648_TC20_FLIP_VERT_ISP_EN BIT(2) 274e43ccb0aSPaul Kocialkowski #define OV5648_TC20_FLIP_VERT_SENSOR_EN BIT(1) 275e43ccb0aSPaul Kocialkowski #define OV5648_TC20_BINNING_VERT_EN BIT(0) 276e43ccb0aSPaul Kocialkowski #define OV5648_TC21_REG 0x3821 277e43ccb0aSPaul Kocialkowski #define OV5648_TC21_FLIP_HORZ_ISP_EN BIT(2) 278e43ccb0aSPaul Kocialkowski #define OV5648_TC21_FLIP_HORZ_SENSOR_EN BIT(1) 279e43ccb0aSPaul Kocialkowski #define OV5648_TC21_BINNING_HORZ_EN BIT(0) 280e43ccb0aSPaul Kocialkowski 281e43ccb0aSPaul Kocialkowski /* Strobe/exposure */ 282e43ccb0aSPaul Kocialkowski 283e43ccb0aSPaul Kocialkowski #define OV5648_STROBE_REG 0x3b00 284e43ccb0aSPaul Kocialkowski #define OV5648_FREX_EXP_HH_REG 0x3b01 285e43ccb0aSPaul Kocialkowski #define OV5648_SHUTTER_DLY_H_REG 0x3b02 286e43ccb0aSPaul Kocialkowski #define OV5648_SHUTTER_DLY_L_REG 0x3b03 287e43ccb0aSPaul Kocialkowski #define OV5648_FREX_EXP_H_REG 0x3b04 288e43ccb0aSPaul Kocialkowski #define OV5648_FREX_EXP_L_REG 0x3b05 289e43ccb0aSPaul Kocialkowski #define OV5648_FREX_CTRL_REG 0x3b06 290e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_REG 0x3b07 291e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_FREX_SA1 BIT(4) 292e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_FX1_FM_EN BIT(3) 293e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_FREX_INV BIT(2) 294e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_MODE1 0x0 295e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_MODE2 0x1 296e43ccb0aSPaul Kocialkowski #define OV5648_FREX_MODE_SEL_ROLLING 0x2 297e43ccb0aSPaul Kocialkowski #define OV5648_FREX_EXP_REQ_REG 0x3b08 298e43ccb0aSPaul Kocialkowski #define OV5648_FREX_SHUTTER_DLY_REG 0x3b09 299e43ccb0aSPaul Kocialkowski #define OV5648_FREX_RST_LEN_REG 0x3b0a 300e43ccb0aSPaul Kocialkowski #define OV5648_STROBE_WIDTH_HH_REG 0x3b0b 301e43ccb0aSPaul Kocialkowski #define OV5648_STROBE_WIDTH_H_REG 0x3b0c 302e43ccb0aSPaul Kocialkowski 303e43ccb0aSPaul Kocialkowski /* OTP */ 304e43ccb0aSPaul Kocialkowski 305e43ccb0aSPaul Kocialkowski #define OV5648_OTP_DATA_REG_BASE 0x3d00 306e43ccb0aSPaul Kocialkowski #define OV5648_OTP_PROGRAM_CTRL_REG 0x3d80 307e43ccb0aSPaul Kocialkowski #define OV5648_OTP_LOAD_CTRL_REG 0x3d81 308e43ccb0aSPaul Kocialkowski 309e43ccb0aSPaul Kocialkowski /* PSRAM */ 310e43ccb0aSPaul Kocialkowski 311e43ccb0aSPaul Kocialkowski #define OV5648_PSRAM_CTRL1_REG 0x3f01 312e43ccb0aSPaul Kocialkowski #define OV5648_PSRAM_CTRLF_REG 0x3f0f 313e43ccb0aSPaul Kocialkowski 314e43ccb0aSPaul Kocialkowski /* Black Level */ 315e43ccb0aSPaul Kocialkowski 316e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL0_REG 0x4000 317e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL1_REG 0x4001 318e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL1_START_LINE(v) ((v) & GENMASK(5, 0)) 319e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL2_REG 0x4002 320e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL2_AUTO_EN BIT(6) 321e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL2_RESET_FRAME_NUM(v) ((v) & GENMASK(5, 0)) 322e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL3_REG 0x4003 323e43ccb0aSPaul Kocialkowski #define OV5648_BLC_LINE_NUM_REG 0x4004 324e43ccb0aSPaul Kocialkowski #define OV5648_BLC_LINE_NUM(v) ((v) & GENMASK(7, 0)) 325e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL5_REG 0x4005 326e43ccb0aSPaul Kocialkowski #define OV5648_BLC_CTRL5_UPDATE_EN BIT(1) 327e43ccb0aSPaul Kocialkowski #define OV5648_BLC_LEVEL_REG 0x4009 328e43ccb0aSPaul Kocialkowski 329e43ccb0aSPaul Kocialkowski /* Frame */ 330e43ccb0aSPaul Kocialkowski 331e43ccb0aSPaul Kocialkowski #define OV5648_FRAME_CTRL_REG 0x4200 332e43ccb0aSPaul Kocialkowski #define OV5648_FRAME_ON_NUM_REG 0x4201 333e43ccb0aSPaul Kocialkowski #define OV5648_FRAME_OFF_NUM_REG 0x4202 334e43ccb0aSPaul Kocialkowski 335e43ccb0aSPaul Kocialkowski /* MIPI CSI-2 */ 336e43ccb0aSPaul Kocialkowski 337e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_REG 0x4800 338e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_CLK_LANE_AUTOGATE BIT(5) 339e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_LANE_SYNC_EN BIT(4) 340e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_LANE_SELECT_LANE1 0 341e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_LANE_SELECT_LANE2 BIT(3) 342e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_IDLE_LP00 0 343e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL0_IDLE_LP11 BIT(2) 344e43ccb0aSPaul Kocialkowski 345e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL1_REG 0x4801 346e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL2_REG 0x4802 347e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL3_REG 0x4803 348e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL4_REG 0x4804 349e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL5_REG 0x4805 350e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_MAX_FRAME_COUNT_H_REG 0x4810 351e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_MAX_FRAME_COUNT_L_REG 0x4811 352e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CTRL14_REG 0x4814 353e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_DT_SPKT_REG 0x4815 354e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_ZERO_MIN_H_REG 0x4818 355e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_ZERO_MIN_L_REG 0x4819 356e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_TRAIN_MIN_H_REG 0x481a 357e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_TRAIN_MIN_L_REG 0x481b 358e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_ZERO_MIN_H_REG 0x481c 359e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_ZERO_MIN_L_REG 0x481d 360e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_PREPARE_MIN_H_REG 0x481e 361e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_PREPARE_MIN_L_REG 0x481f 362e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_POST_MIN_H_REG 0x4820 363e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_POST_MIN_L_REG 0x4821 364e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_TRAIL_MIN_H_REG 0x4822 365e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_TRAIL_MIN_L_REG 0x4823 366e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_LPX_P_MIN_H_REG 0x4824 367e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_LPX_P_MIN_L_REG 0x4825 368e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_PREPARE_MIN_H_REG 0x4826 369e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_PREPARE_MIN_L_REG 0x4827 370e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_EXIT_MIN_H_REG 0x4828 371e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_EXIT_MIN_L_REG 0x4829 372e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_ZERO_MIN_UI_REG 0x482a 373e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_TRAIL_MIN_UI_REG 0x482b 374e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_ZERO_MIN_UI_REG 0x482c 375e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_PREPARE_MIN_UI_REG 0x482d 376e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_POST_MIN_UI_REG 0x482e 377e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_CLK_TRAIL_MIN_UI_REG 0x482f 378e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_LPX_P_MIN_UI_REG 0x4830 379e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_PREPARE_MIN_UI_REG 0x4831 380e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_HS_EXIT_MIN_UI_REG 0x4832 381e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_REG_MIN_H_REG 0x4833 382e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_REG_MIN_L_REG 0x4834 383e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_REG_MAX_H_REG 0x4835 384e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_REG_MAX_L_REG 0x4836 385e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_PCLK_PERIOD_REG 0x4837 386e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_WKUP_DLY_REG 0x4838 387e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_LP_GPIO_REG 0x483b 388e43ccb0aSPaul Kocialkowski #define OV5648_MIPI_SNR_PCLK_DIV_REG 0x4843 389e43ccb0aSPaul Kocialkowski 390e43ccb0aSPaul Kocialkowski /* ISP */ 391e43ccb0aSPaul Kocialkowski 392e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL0_REG 0x5000 393e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL0_BLACK_CORRECT_EN BIT(2) 394e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL0_WHITE_CORRECT_EN BIT(1) 395e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1_REG 0x5001 396e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1_AWB_EN BIT(0) 397e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL2_REG 0x5002 398e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL2_WIN_EN BIT(6) 399e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL2_OTP_EN BIT(1) 400e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL2_AWB_GAIN_EN BIT(0) 401e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3_REG 0x5003 402e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3_BUF_EN BIT(3) 403e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3_BIN_MAN_SET BIT(2) 404e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3_BIN_AUTO_EN BIT(1) 405e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL4_REG 0x5004 406e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL5_REG 0x5005 407e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL6_REG 0x5006 408e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL7_REG 0x5007 409e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_OFFSET_X_H_REG 0x5008 410e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_OFFSET_X_L_REG 0x5009 411e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_OFFSET_Y_H_REG 0x500a 412e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_OFFSET_Y_L_REG 0x500b 413e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OFFSET_X_H_REG 0x500c 414e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OFFSET_X_L_REG 0x500d 415e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OFFSET_Y_H_REG 0x500e 416e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OFFSET_Y_L_REG 0x500f 417e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OUTPUT_X_H_REG 0x5010 418e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OUTPUT_X_L_REG 0x5011 419e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OUTPUT_Y_H_REG 0x5012 420e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_WIN_OUTPUT_Y_L_REG 0x5013 421e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_INPUT_X_H_REG 0x5014 422e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_INPUT_X_L_REG 0x5015 423e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_INPUT_Y_H_REG 0x5016 424e43ccb0aSPaul Kocialkowski #define OV5648_ISP_MAN_INPUT_Y_L_REG 0x5017 425e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL18_REG 0x5018 426e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL19_REG 0x5019 427e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1A_REG 0x501a 428e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1D_REG 0x501d 429e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1F_REG 0x501f 430e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL1F_OUTPUT_EN 3 431e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL25_REG 0x5025 432e43ccb0aSPaul Kocialkowski 433e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_REG 0x503d 434e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_PATTERN_EN BIT(7) 435e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_ROLLING_BAR_EN BIT(6) 436e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_TRANSPARENT_MODE BIT(5) 437e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_SQUARES_BW_MODE BIT(4) 438e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS 0 439e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_PATTERN_RANDOM_DATA 1 440e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES 2 441e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3D_PATTERN_INPUT 3 442e43ccb0aSPaul Kocialkowski 443e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL3E_REG 0x503e 444e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL4B_REG 0x504b 445e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL4B_POST_BIN_H_EN BIT(5) 446e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL4B_POST_BIN_V_EN BIT(4) 447e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL4C_REG 0x504c 448e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL57_REG 0x5057 449e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL58_REG 0x5058 450e43ccb0aSPaul Kocialkowski #define OV5648_ISP_CTRL59_REG 0x5059 451e43ccb0aSPaul Kocialkowski 452e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_START_X_H_REG 0x5980 453e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_START_X_L_REG 0x5981 454e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_START_Y_H_REG 0x5982 455e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_START_Y_L_REG 0x5983 456e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_WIN_X_H_REG 0x5984 457e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_WIN_X_L_REG 0x5985 458e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_WIN_Y_H_REG 0x5986 459e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_WIN_Y_L_REG 0x5987 460e43ccb0aSPaul Kocialkowski #define OV5648_ISP_WINDOW_MAN_REG 0x5988 461e43ccb0aSPaul Kocialkowski 462e43ccb0aSPaul Kocialkowski /* White Balance */ 463e43ccb0aSPaul Kocialkowski 464e43ccb0aSPaul Kocialkowski #define OV5648_AWB_CTRL_REG 0x5180 465e43ccb0aSPaul Kocialkowski #define OV5648_AWB_CTRL_FAST_AWB BIT(6) 466e43ccb0aSPaul Kocialkowski #define OV5648_AWB_CTRL_GAIN_FREEZE_EN BIT(5) 467e43ccb0aSPaul Kocialkowski #define OV5648_AWB_CTRL_SUM_FREEZE_EN BIT(4) 468e43ccb0aSPaul Kocialkowski #define OV5648_AWB_CTRL_GAIN_MANUAL_EN BIT(3) 469e43ccb0aSPaul Kocialkowski 470e43ccb0aSPaul Kocialkowski #define OV5648_AWB_DELTA_REG 0x5181 471e43ccb0aSPaul Kocialkowski #define OV5648_AWB_STABLE_RANGE_REG 0x5182 472e43ccb0aSPaul Kocialkowski #define OV5648_AWB_STABLE_RANGE_WIDE_REG 0x5183 473e43ccb0aSPaul Kocialkowski #define OV5648_HSIZE_MAN_REG 0x5185 474e43ccb0aSPaul Kocialkowski 475e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_RED_MAN_H_REG 0x5186 476e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_RED_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) 477e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_RED_MAN_L_REG 0x5187 478e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_RED_MAN_L(v) ((v) & GENMASK(7, 0)) 479e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_GREEN_MAN_H_REG 0x5188 480e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_GREEN_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) 481e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_GREEN_MAN_L_REG 0x5189 482e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_GREEN_MAN_L(v) ((v) & GENMASK(7, 0)) 483e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BLUE_MAN_H_REG 0x518a 484e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BLUE_MAN_H(v) (((v) & GENMASK(11, 8)) >> 8) 485e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BLUE_MAN_L_REG 0x518b 486e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BLUE_MAN_L(v) ((v) & GENMASK(7, 0)) 487e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_RED_LIMIT_REG 0x518c 488e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_GREEN_LIMIT_REG 0x518d 489e43ccb0aSPaul Kocialkowski #define OV5648_GAIN_BLUE_LIMIT_REG 0x518e 490e43ccb0aSPaul Kocialkowski #define OV5648_AWB_FRAME_COUNT_REG 0x518f 491e43ccb0aSPaul Kocialkowski #define OV5648_AWB_BASE_MAN_REG 0x51df 492e43ccb0aSPaul Kocialkowski 493e43ccb0aSPaul Kocialkowski /* Macros */ 494e43ccb0aSPaul Kocialkowski 495e43ccb0aSPaul Kocialkowski #define ov5648_subdev_sensor(s) \ 496e43ccb0aSPaul Kocialkowski container_of(s, struct ov5648_sensor, subdev) 497e43ccb0aSPaul Kocialkowski 498e43ccb0aSPaul Kocialkowski #define ov5648_ctrl_subdev(c) \ 49936e4f2b2SPaul Kocialkowski (&container_of((c)->handler, struct ov5648_sensor, \ 50036e4f2b2SPaul Kocialkowski ctrls.handler)->subdev) 501e43ccb0aSPaul Kocialkowski 502e43ccb0aSPaul Kocialkowski /* Data structures */ 503e43ccb0aSPaul Kocialkowski 504e43ccb0aSPaul Kocialkowski struct ov5648_register_value { 505e43ccb0aSPaul Kocialkowski u16 address; 506e43ccb0aSPaul Kocialkowski u8 value; 507e43ccb0aSPaul Kocialkowski unsigned int delay_ms; 508e43ccb0aSPaul Kocialkowski }; 509e43ccb0aSPaul Kocialkowski 510e43ccb0aSPaul Kocialkowski /* 511e43ccb0aSPaul Kocialkowski * PLL1 Clock Tree: 512e43ccb0aSPaul Kocialkowski * 513e43ccb0aSPaul Kocialkowski * +-< XVCLK 514e43ccb0aSPaul Kocialkowski * | 515e43ccb0aSPaul Kocialkowski * +-+ pll_pre_div (0x3037 [3:0], special values: 5: 1.5, 7: 2.5) 516e43ccb0aSPaul Kocialkowski * | 517e43ccb0aSPaul Kocialkowski * +-+ pll_mul (0x3036 [7:0]) 518e43ccb0aSPaul Kocialkowski * | 519e43ccb0aSPaul Kocialkowski * +-+ sys_div (0x3035 [7:4]) 520e43ccb0aSPaul Kocialkowski * | 521e43ccb0aSPaul Kocialkowski * +-+ mipi_div (0x3035 [3:0]) 522e43ccb0aSPaul Kocialkowski * | | 523e43ccb0aSPaul Kocialkowski * | +-> MIPI_SCLK 524e43ccb0aSPaul Kocialkowski * | | 525e43ccb0aSPaul Kocialkowski * | +-+ mipi_phy_div (2) 526e43ccb0aSPaul Kocialkowski * | | 527e43ccb0aSPaul Kocialkowski * | +-> MIPI_CLK 528e43ccb0aSPaul Kocialkowski * | 529e43ccb0aSPaul Kocialkowski * +-+ root_div (0x3037 [4]) 530e43ccb0aSPaul Kocialkowski * | 531e43ccb0aSPaul Kocialkowski * +-+ bit_div (0x3034 [3:0], 8 bits: 2, 10 bits: 2.5, other: 1) 532e43ccb0aSPaul Kocialkowski * | 533e43ccb0aSPaul Kocialkowski * +-+ sclk_div (0x3106 [3:2]) 534e43ccb0aSPaul Kocialkowski * | 535e43ccb0aSPaul Kocialkowski * +-> SCLK 536e43ccb0aSPaul Kocialkowski * | 537e43ccb0aSPaul Kocialkowski * +-+ mipi_div (0x3035, 1: PCLK = SCLK) 538e43ccb0aSPaul Kocialkowski * | 539e43ccb0aSPaul Kocialkowski * +-> PCLK 540e43ccb0aSPaul Kocialkowski */ 541e43ccb0aSPaul Kocialkowski 542e43ccb0aSPaul Kocialkowski struct ov5648_pll1_config { 543e43ccb0aSPaul Kocialkowski unsigned int pll_pre_div; 544e43ccb0aSPaul Kocialkowski unsigned int pll_mul; 545e43ccb0aSPaul Kocialkowski unsigned int sys_div; 546e43ccb0aSPaul Kocialkowski unsigned int root_div; 547e43ccb0aSPaul Kocialkowski unsigned int sclk_div; 548e43ccb0aSPaul Kocialkowski unsigned int mipi_div; 549e43ccb0aSPaul Kocialkowski }; 550e43ccb0aSPaul Kocialkowski 551e43ccb0aSPaul Kocialkowski /* 552e43ccb0aSPaul Kocialkowski * PLL2 Clock Tree: 553e43ccb0aSPaul Kocialkowski * 554e43ccb0aSPaul Kocialkowski * +-< XVCLK 555e43ccb0aSPaul Kocialkowski * | 556e43ccb0aSPaul Kocialkowski * +-+ plls_pre_div (0x303d [5:4], special values: 0: 1, 1: 1.5) 557e43ccb0aSPaul Kocialkowski * | 558e43ccb0aSPaul Kocialkowski * +-+ plls_div_r (0x303d [2]) 559e43ccb0aSPaul Kocialkowski * | 560e43ccb0aSPaul Kocialkowski * +-+ plls_mul (0x303b [4:0]) 561e43ccb0aSPaul Kocialkowski * | 562e43ccb0aSPaul Kocialkowski * +-+ sys_div (0x303c [3:0]) 563e43ccb0aSPaul Kocialkowski * | 564e43ccb0aSPaul Kocialkowski * +-+ sel_div (0x303d [1:0], special values: 0: 1, 3: 2.5) 565e43ccb0aSPaul Kocialkowski * | 566e43ccb0aSPaul Kocialkowski * +-> ADCLK 567e43ccb0aSPaul Kocialkowski */ 568e43ccb0aSPaul Kocialkowski 569e43ccb0aSPaul Kocialkowski struct ov5648_pll2_config { 570e43ccb0aSPaul Kocialkowski unsigned int plls_pre_div; 571e43ccb0aSPaul Kocialkowski unsigned int plls_div_r; 572e43ccb0aSPaul Kocialkowski unsigned int plls_mul; 573e43ccb0aSPaul Kocialkowski unsigned int sys_div; 574e43ccb0aSPaul Kocialkowski unsigned int sel_div; 575e43ccb0aSPaul Kocialkowski }; 576e43ccb0aSPaul Kocialkowski 577e43ccb0aSPaul Kocialkowski /* 578e43ccb0aSPaul Kocialkowski * General formulas for (array-centered) mode calculation: 579e43ccb0aSPaul Kocialkowski * - photo_array_width = 2624 580e43ccb0aSPaul Kocialkowski * - crop_start_x = (photo_array_width - output_size_x) / 2 581e43ccb0aSPaul Kocialkowski * - crop_end_x = crop_start_x + offset_x + output_size_x - 1 582e43ccb0aSPaul Kocialkowski * 583e43ccb0aSPaul Kocialkowski * - photo_array_height = 1956 584e43ccb0aSPaul Kocialkowski * - crop_start_y = (photo_array_height - output_size_y) / 2 585e43ccb0aSPaul Kocialkowski * - crop_end_y = crop_start_y + offset_y + output_size_y - 1 586e43ccb0aSPaul Kocialkowski */ 587e43ccb0aSPaul Kocialkowski 588e43ccb0aSPaul Kocialkowski struct ov5648_mode { 589e43ccb0aSPaul Kocialkowski unsigned int crop_start_x; 590e43ccb0aSPaul Kocialkowski unsigned int offset_x; 591e43ccb0aSPaul Kocialkowski unsigned int output_size_x; 592e43ccb0aSPaul Kocialkowski unsigned int crop_end_x; 593e43ccb0aSPaul Kocialkowski unsigned int hts; 594e43ccb0aSPaul Kocialkowski 595e43ccb0aSPaul Kocialkowski unsigned int crop_start_y; 596e43ccb0aSPaul Kocialkowski unsigned int offset_y; 597e43ccb0aSPaul Kocialkowski unsigned int output_size_y; 598e43ccb0aSPaul Kocialkowski unsigned int crop_end_y; 599e43ccb0aSPaul Kocialkowski unsigned int vts; 600e43ccb0aSPaul Kocialkowski 601e43ccb0aSPaul Kocialkowski bool binning_x; 602e43ccb0aSPaul Kocialkowski bool binning_y; 603e43ccb0aSPaul Kocialkowski 604e43ccb0aSPaul Kocialkowski unsigned int inc_x_odd; 605e43ccb0aSPaul Kocialkowski unsigned int inc_x_even; 606e43ccb0aSPaul Kocialkowski unsigned int inc_y_odd; 607e43ccb0aSPaul Kocialkowski unsigned int inc_y_even; 608e43ccb0aSPaul Kocialkowski 609e43ccb0aSPaul Kocialkowski /* 8-bit frame interval followed by 10-bit frame interval. */ 610e43ccb0aSPaul Kocialkowski struct v4l2_fract frame_interval[2]; 611e43ccb0aSPaul Kocialkowski 612e43ccb0aSPaul Kocialkowski /* 8-bit config followed by 10-bit config. */ 613e43ccb0aSPaul Kocialkowski const struct ov5648_pll1_config *pll1_config[2]; 614e43ccb0aSPaul Kocialkowski const struct ov5648_pll2_config *pll2_config; 615e43ccb0aSPaul Kocialkowski 616e43ccb0aSPaul Kocialkowski const struct ov5648_register_value *register_values; 617e43ccb0aSPaul Kocialkowski unsigned int register_values_count; 618e43ccb0aSPaul Kocialkowski }; 619e43ccb0aSPaul Kocialkowski 620e43ccb0aSPaul Kocialkowski struct ov5648_state { 621e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode; 622e43ccb0aSPaul Kocialkowski u32 mbus_code; 623e43ccb0aSPaul Kocialkowski 624e43ccb0aSPaul Kocialkowski bool streaming; 625e43ccb0aSPaul Kocialkowski }; 626e43ccb0aSPaul Kocialkowski 627e43ccb0aSPaul Kocialkowski struct ov5648_ctrls { 628e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *exposure_auto; 629e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *exposure; 630e43ccb0aSPaul Kocialkowski 631e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *gain_auto; 632e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *gain; 633e43ccb0aSPaul Kocialkowski 634e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *white_balance_auto; 635e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *red_balance; 636e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *blue_balance; 637e43ccb0aSPaul Kocialkowski 638e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *link_freq; 639e43ccb0aSPaul Kocialkowski struct v4l2_ctrl *pixel_rate; 640e43ccb0aSPaul Kocialkowski 641e43ccb0aSPaul Kocialkowski struct v4l2_ctrl_handler handler; 642e43ccb0aSPaul Kocialkowski } __packed; 643e43ccb0aSPaul Kocialkowski 644e43ccb0aSPaul Kocialkowski struct ov5648_sensor { 645e43ccb0aSPaul Kocialkowski struct device *dev; 646e43ccb0aSPaul Kocialkowski struct i2c_client *i2c_client; 647e43ccb0aSPaul Kocialkowski struct gpio_desc *reset; 648e43ccb0aSPaul Kocialkowski struct gpio_desc *powerdown; 649e43ccb0aSPaul Kocialkowski struct regulator *avdd; 650e43ccb0aSPaul Kocialkowski struct regulator *dvdd; 651e43ccb0aSPaul Kocialkowski struct regulator *dovdd; 652e43ccb0aSPaul Kocialkowski struct clk *xvclk; 653e43ccb0aSPaul Kocialkowski 654e43ccb0aSPaul Kocialkowski struct v4l2_fwnode_endpoint endpoint; 655e43ccb0aSPaul Kocialkowski struct v4l2_subdev subdev; 656e43ccb0aSPaul Kocialkowski struct media_pad pad; 657e43ccb0aSPaul Kocialkowski 658e43ccb0aSPaul Kocialkowski struct mutex mutex; 659e43ccb0aSPaul Kocialkowski 660e43ccb0aSPaul Kocialkowski struct ov5648_state state; 661e43ccb0aSPaul Kocialkowski struct ov5648_ctrls ctrls; 662e43ccb0aSPaul Kocialkowski }; 663e43ccb0aSPaul Kocialkowski 664e43ccb0aSPaul Kocialkowski /* Static definitions */ 665e43ccb0aSPaul Kocialkowski 666e43ccb0aSPaul Kocialkowski /* 667e43ccb0aSPaul Kocialkowski * XVCLK = 24 MHz 668e43ccb0aSPaul Kocialkowski * SCLK = 84 MHz 669e43ccb0aSPaul Kocialkowski * PCLK = 84 MHz 670e43ccb0aSPaul Kocialkowski */ 671e43ccb0aSPaul Kocialkowski static const struct ov5648_pll1_config ov5648_pll1_config_native_8_bits = { 672e43ccb0aSPaul Kocialkowski .pll_pre_div = 3, 673e43ccb0aSPaul Kocialkowski .pll_mul = 84, 674e43ccb0aSPaul Kocialkowski .sys_div = 2, 675e43ccb0aSPaul Kocialkowski .root_div = 1, 676e43ccb0aSPaul Kocialkowski .sclk_div = 1, 677e43ccb0aSPaul Kocialkowski .mipi_div = 1, 678e43ccb0aSPaul Kocialkowski }; 679e43ccb0aSPaul Kocialkowski 680e43ccb0aSPaul Kocialkowski /* 681e43ccb0aSPaul Kocialkowski * XVCLK = 24 MHz 682e43ccb0aSPaul Kocialkowski * SCLK = 84 MHz 683e43ccb0aSPaul Kocialkowski * PCLK = 84 MHz 684e43ccb0aSPaul Kocialkowski */ 685e43ccb0aSPaul Kocialkowski static const struct ov5648_pll1_config ov5648_pll1_config_native_10_bits = { 686e43ccb0aSPaul Kocialkowski .pll_pre_div = 3, 687e43ccb0aSPaul Kocialkowski .pll_mul = 105, 688e43ccb0aSPaul Kocialkowski .sys_div = 2, 689e43ccb0aSPaul Kocialkowski .root_div = 1, 690e43ccb0aSPaul Kocialkowski .sclk_div = 1, 691e43ccb0aSPaul Kocialkowski .mipi_div = 1, 692e43ccb0aSPaul Kocialkowski }; 693e43ccb0aSPaul Kocialkowski 694e43ccb0aSPaul Kocialkowski /* 695e43ccb0aSPaul Kocialkowski * XVCLK = 24 MHz 696e43ccb0aSPaul Kocialkowski * ADCLK = 200 MHz 697e43ccb0aSPaul Kocialkowski */ 698e43ccb0aSPaul Kocialkowski static const struct ov5648_pll2_config ov5648_pll2_config_native = { 699e43ccb0aSPaul Kocialkowski .plls_pre_div = 3, 700e43ccb0aSPaul Kocialkowski .plls_div_r = 1, 701e43ccb0aSPaul Kocialkowski .plls_mul = 25, 702e43ccb0aSPaul Kocialkowski .sys_div = 1, 703e43ccb0aSPaul Kocialkowski .sel_div = 1, 704e43ccb0aSPaul Kocialkowski }; 705e43ccb0aSPaul Kocialkowski 706e43ccb0aSPaul Kocialkowski static const struct ov5648_mode ov5648_modes[] = { 707e43ccb0aSPaul Kocialkowski /* 2592x1944 */ 708e43ccb0aSPaul Kocialkowski { 709e43ccb0aSPaul Kocialkowski /* Horizontal */ 710e43ccb0aSPaul Kocialkowski .crop_start_x = 16, 711e43ccb0aSPaul Kocialkowski .offset_x = 0, 712e43ccb0aSPaul Kocialkowski .output_size_x = 2592, 713e43ccb0aSPaul Kocialkowski .crop_end_x = 2607, 714e43ccb0aSPaul Kocialkowski .hts = 2816, 715e43ccb0aSPaul Kocialkowski 716e43ccb0aSPaul Kocialkowski /* Vertical */ 717e43ccb0aSPaul Kocialkowski .crop_start_y = 6, 718e43ccb0aSPaul Kocialkowski .offset_y = 0, 719e43ccb0aSPaul Kocialkowski .output_size_y = 1944, 720e43ccb0aSPaul Kocialkowski .crop_end_y = 1949, 721e43ccb0aSPaul Kocialkowski .vts = 1984, 722e43ccb0aSPaul Kocialkowski 723e43ccb0aSPaul Kocialkowski /* Subsample increase */ 724e43ccb0aSPaul Kocialkowski .inc_x_odd = 1, 725e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 726e43ccb0aSPaul Kocialkowski .inc_y_odd = 1, 727e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 728e43ccb0aSPaul Kocialkowski 729e43ccb0aSPaul Kocialkowski /* Frame Interval */ 730e43ccb0aSPaul Kocialkowski .frame_interval = { 731e43ccb0aSPaul Kocialkowski { 1, 15 }, 732e43ccb0aSPaul Kocialkowski { 1, 15 }, 733e43ccb0aSPaul Kocialkowski }, 734e43ccb0aSPaul Kocialkowski 735e43ccb0aSPaul Kocialkowski /* PLL */ 736e43ccb0aSPaul Kocialkowski .pll1_config = { 737e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 738e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 739e43ccb0aSPaul Kocialkowski }, 740e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 741e43ccb0aSPaul Kocialkowski }, 742e43ccb0aSPaul Kocialkowski /* 1600x1200 (UXGA) */ 743e43ccb0aSPaul Kocialkowski { 744e43ccb0aSPaul Kocialkowski /* Horizontal */ 745e43ccb0aSPaul Kocialkowski .crop_start_x = 512, 746e43ccb0aSPaul Kocialkowski .offset_x = 0, 747e43ccb0aSPaul Kocialkowski .output_size_x = 1600, 748e43ccb0aSPaul Kocialkowski .crop_end_x = 2111, 749e43ccb0aSPaul Kocialkowski .hts = 2816, 750e43ccb0aSPaul Kocialkowski 751e43ccb0aSPaul Kocialkowski /* Vertical */ 752e43ccb0aSPaul Kocialkowski .crop_start_y = 378, 753e43ccb0aSPaul Kocialkowski .offset_y = 0, 754e43ccb0aSPaul Kocialkowski .output_size_y = 1200, 755e43ccb0aSPaul Kocialkowski .crop_end_y = 1577, 756e43ccb0aSPaul Kocialkowski .vts = 1984, 757e43ccb0aSPaul Kocialkowski 758e43ccb0aSPaul Kocialkowski /* Subsample increase */ 759e43ccb0aSPaul Kocialkowski .inc_x_odd = 1, 760e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 761e43ccb0aSPaul Kocialkowski .inc_y_odd = 1, 762e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 763e43ccb0aSPaul Kocialkowski 764e43ccb0aSPaul Kocialkowski /* Frame Interval */ 765e43ccb0aSPaul Kocialkowski .frame_interval = { 766e43ccb0aSPaul Kocialkowski { 1, 15 }, 767e43ccb0aSPaul Kocialkowski { 1, 15 }, 768e43ccb0aSPaul Kocialkowski }, 769e43ccb0aSPaul Kocialkowski 770e43ccb0aSPaul Kocialkowski /* PLL */ 771e43ccb0aSPaul Kocialkowski .pll1_config = { 772e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 773e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 774e43ccb0aSPaul Kocialkowski }, 775e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 776e43ccb0aSPaul Kocialkowski }, 777e43ccb0aSPaul Kocialkowski /* 1920x1080 (Full HD) */ 778e43ccb0aSPaul Kocialkowski { 779e43ccb0aSPaul Kocialkowski /* Horizontal */ 780e43ccb0aSPaul Kocialkowski .crop_start_x = 352, 781e43ccb0aSPaul Kocialkowski .offset_x = 0, 782e43ccb0aSPaul Kocialkowski .output_size_x = 1920, 783e43ccb0aSPaul Kocialkowski .crop_end_x = 2271, 784e43ccb0aSPaul Kocialkowski .hts = 2816, 785e43ccb0aSPaul Kocialkowski 786e43ccb0aSPaul Kocialkowski /* Vertical */ 787e43ccb0aSPaul Kocialkowski .crop_start_y = 438, 788e43ccb0aSPaul Kocialkowski .offset_y = 0, 789e43ccb0aSPaul Kocialkowski .output_size_y = 1080, 790e43ccb0aSPaul Kocialkowski .crop_end_y = 1517, 791e43ccb0aSPaul Kocialkowski .vts = 1984, 792e43ccb0aSPaul Kocialkowski 793e43ccb0aSPaul Kocialkowski /* Subsample increase */ 794e43ccb0aSPaul Kocialkowski .inc_x_odd = 1, 795e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 796e43ccb0aSPaul Kocialkowski .inc_y_odd = 1, 797e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 798e43ccb0aSPaul Kocialkowski 799e43ccb0aSPaul Kocialkowski /* Frame Interval */ 800e43ccb0aSPaul Kocialkowski .frame_interval = { 801e43ccb0aSPaul Kocialkowski { 1, 15 }, 802e43ccb0aSPaul Kocialkowski { 1, 15 }, 803e43ccb0aSPaul Kocialkowski }, 804e43ccb0aSPaul Kocialkowski 805e43ccb0aSPaul Kocialkowski /* PLL */ 806e43ccb0aSPaul Kocialkowski .pll1_config = { 807e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 808e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 809e43ccb0aSPaul Kocialkowski }, 810e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 811e43ccb0aSPaul Kocialkowski }, 812e43ccb0aSPaul Kocialkowski /* 1280x960 */ 813e43ccb0aSPaul Kocialkowski { 814e43ccb0aSPaul Kocialkowski /* Horizontal */ 815e43ccb0aSPaul Kocialkowski .crop_start_x = 16, 816e43ccb0aSPaul Kocialkowski .offset_x = 8, 817e43ccb0aSPaul Kocialkowski .output_size_x = 1280, 818e43ccb0aSPaul Kocialkowski .crop_end_x = 2607, 819e43ccb0aSPaul Kocialkowski .hts = 1912, 820e43ccb0aSPaul Kocialkowski 821e43ccb0aSPaul Kocialkowski /* Vertical */ 822e43ccb0aSPaul Kocialkowski .crop_start_y = 6, 823e43ccb0aSPaul Kocialkowski .offset_y = 6, 824e43ccb0aSPaul Kocialkowski .output_size_y = 960, 825e43ccb0aSPaul Kocialkowski .crop_end_y = 1949, 826e43ccb0aSPaul Kocialkowski .vts = 1496, 827e43ccb0aSPaul Kocialkowski 828e43ccb0aSPaul Kocialkowski /* Binning */ 829e43ccb0aSPaul Kocialkowski .binning_x = true, 830e43ccb0aSPaul Kocialkowski 831e43ccb0aSPaul Kocialkowski /* Subsample increase */ 832e43ccb0aSPaul Kocialkowski .inc_x_odd = 3, 833e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 834e43ccb0aSPaul Kocialkowski .inc_y_odd = 3, 835e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 836e43ccb0aSPaul Kocialkowski 837e43ccb0aSPaul Kocialkowski /* Frame Interval */ 838e43ccb0aSPaul Kocialkowski .frame_interval = { 839e43ccb0aSPaul Kocialkowski { 1, 30 }, 840e43ccb0aSPaul Kocialkowski { 1, 30 }, 841e43ccb0aSPaul Kocialkowski }, 842e43ccb0aSPaul Kocialkowski 843e43ccb0aSPaul Kocialkowski /* PLL */ 844e43ccb0aSPaul Kocialkowski .pll1_config = { 845e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 846e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 847e43ccb0aSPaul Kocialkowski }, 848e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 849e43ccb0aSPaul Kocialkowski }, 850e43ccb0aSPaul Kocialkowski /* 1280x720 (HD) */ 851e43ccb0aSPaul Kocialkowski { 852e43ccb0aSPaul Kocialkowski /* Horizontal */ 853e43ccb0aSPaul Kocialkowski .crop_start_x = 16, 854e43ccb0aSPaul Kocialkowski .offset_x = 8, 855e43ccb0aSPaul Kocialkowski .output_size_x = 1280, 856e43ccb0aSPaul Kocialkowski .crop_end_x = 2607, 857e43ccb0aSPaul Kocialkowski .hts = 1912, 858e43ccb0aSPaul Kocialkowski 859e43ccb0aSPaul Kocialkowski /* Vertical */ 860e43ccb0aSPaul Kocialkowski .crop_start_y = 254, 861e43ccb0aSPaul Kocialkowski .offset_y = 2, 862e43ccb0aSPaul Kocialkowski .output_size_y = 720, 863e43ccb0aSPaul Kocialkowski .crop_end_y = 1701, 864e43ccb0aSPaul Kocialkowski .vts = 1496, 865e43ccb0aSPaul Kocialkowski 866e43ccb0aSPaul Kocialkowski /* Binning */ 867e43ccb0aSPaul Kocialkowski .binning_x = true, 868e43ccb0aSPaul Kocialkowski 869e43ccb0aSPaul Kocialkowski /* Subsample increase */ 870e43ccb0aSPaul Kocialkowski .inc_x_odd = 3, 871e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 872e43ccb0aSPaul Kocialkowski .inc_y_odd = 3, 873e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 874e43ccb0aSPaul Kocialkowski 875e43ccb0aSPaul Kocialkowski /* Frame Interval */ 876e43ccb0aSPaul Kocialkowski .frame_interval = { 877e43ccb0aSPaul Kocialkowski { 1, 30 }, 878e43ccb0aSPaul Kocialkowski { 1, 30 }, 879e43ccb0aSPaul Kocialkowski }, 880e43ccb0aSPaul Kocialkowski 881e43ccb0aSPaul Kocialkowski /* PLL */ 882e43ccb0aSPaul Kocialkowski .pll1_config = { 883e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 884e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 885e43ccb0aSPaul Kocialkowski }, 886e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 887e43ccb0aSPaul Kocialkowski }, 888e43ccb0aSPaul Kocialkowski /* 640x480 (VGA) */ 889e43ccb0aSPaul Kocialkowski { 890e43ccb0aSPaul Kocialkowski /* Horizontal */ 891e43ccb0aSPaul Kocialkowski .crop_start_x = 0, 892e43ccb0aSPaul Kocialkowski .offset_x = 8, 893e43ccb0aSPaul Kocialkowski .output_size_x = 640, 894e43ccb0aSPaul Kocialkowski .crop_end_x = 2623, 895e43ccb0aSPaul Kocialkowski .hts = 1896, 896e43ccb0aSPaul Kocialkowski 897e43ccb0aSPaul Kocialkowski /* Vertical */ 898e43ccb0aSPaul Kocialkowski .crop_start_y = 0, 899e43ccb0aSPaul Kocialkowski .offset_y = 2, 900e43ccb0aSPaul Kocialkowski .output_size_y = 480, 901e43ccb0aSPaul Kocialkowski .crop_end_y = 1953, 902e43ccb0aSPaul Kocialkowski .vts = 984, 903e43ccb0aSPaul Kocialkowski 904e43ccb0aSPaul Kocialkowski /* Binning */ 905e43ccb0aSPaul Kocialkowski .binning_x = true, 906e43ccb0aSPaul Kocialkowski 907e43ccb0aSPaul Kocialkowski /* Subsample increase */ 908e43ccb0aSPaul Kocialkowski .inc_x_odd = 7, 909e43ccb0aSPaul Kocialkowski .inc_x_even = 1, 910e43ccb0aSPaul Kocialkowski .inc_y_odd = 7, 911e43ccb0aSPaul Kocialkowski .inc_y_even = 1, 912e43ccb0aSPaul Kocialkowski 913e43ccb0aSPaul Kocialkowski /* Frame Interval */ 914e43ccb0aSPaul Kocialkowski .frame_interval = { 915e43ccb0aSPaul Kocialkowski { 1, 30 }, 916e43ccb0aSPaul Kocialkowski { 1, 30 }, 917e43ccb0aSPaul Kocialkowski }, 918e43ccb0aSPaul Kocialkowski 919e43ccb0aSPaul Kocialkowski /* PLL */ 920e43ccb0aSPaul Kocialkowski .pll1_config = { 921e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_8_bits, 922e43ccb0aSPaul Kocialkowski &ov5648_pll1_config_native_10_bits, 923e43ccb0aSPaul Kocialkowski }, 924e43ccb0aSPaul Kocialkowski .pll2_config = &ov5648_pll2_config_native, 925e43ccb0aSPaul Kocialkowski }, 926e43ccb0aSPaul Kocialkowski }; 927e43ccb0aSPaul Kocialkowski 928e43ccb0aSPaul Kocialkowski static const u32 ov5648_mbus_codes[] = { 929e43ccb0aSPaul Kocialkowski MEDIA_BUS_FMT_SBGGR8_1X8, 930e43ccb0aSPaul Kocialkowski MEDIA_BUS_FMT_SBGGR10_1X10, 931e43ccb0aSPaul Kocialkowski }; 932e43ccb0aSPaul Kocialkowski 933e43ccb0aSPaul Kocialkowski static const struct ov5648_register_value ov5648_init_sequence[] = { 934e43ccb0aSPaul Kocialkowski /* PSRAM */ 935e43ccb0aSPaul Kocialkowski { OV5648_PSRAM_CTRL1_REG, 0x0d }, 936e43ccb0aSPaul Kocialkowski { OV5648_PSRAM_CTRLF_REG, 0xf5 }, 937e43ccb0aSPaul Kocialkowski }; 938e43ccb0aSPaul Kocialkowski 939e43ccb0aSPaul Kocialkowski static const s64 ov5648_link_freq_menu[] = { 940e43ccb0aSPaul Kocialkowski 210000000, 941e43ccb0aSPaul Kocialkowski 168000000, 942e43ccb0aSPaul Kocialkowski }; 943e43ccb0aSPaul Kocialkowski 944e43ccb0aSPaul Kocialkowski static const char *const ov5648_test_pattern_menu[] = { 945e43ccb0aSPaul Kocialkowski "Disabled", 946e43ccb0aSPaul Kocialkowski "Random data", 947e43ccb0aSPaul Kocialkowski "Color bars", 948e43ccb0aSPaul Kocialkowski "Color bars with rolling bar", 949e43ccb0aSPaul Kocialkowski "Color squares", 950e43ccb0aSPaul Kocialkowski "Color squares with rolling bar" 951e43ccb0aSPaul Kocialkowski }; 952e43ccb0aSPaul Kocialkowski 953e43ccb0aSPaul Kocialkowski static const u8 ov5648_test_pattern_bits[] = { 954e43ccb0aSPaul Kocialkowski 0, 955e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_RANDOM_DATA, 956e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS, 957e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_ROLLING_BAR_EN | 958e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_COLOR_BARS, 959e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES, 960e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_EN | OV5648_ISP_CTRL3D_ROLLING_BAR_EN | 961e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3D_PATTERN_COLOR_SQUARES, 962e43ccb0aSPaul Kocialkowski }; 963e43ccb0aSPaul Kocialkowski 964e43ccb0aSPaul Kocialkowski /* Input/Output */ 965e43ccb0aSPaul Kocialkowski 966e43ccb0aSPaul Kocialkowski static int ov5648_read(struct ov5648_sensor *sensor, u16 address, u8 *value) 967e43ccb0aSPaul Kocialkowski { 968e43ccb0aSPaul Kocialkowski unsigned char data[2] = { address >> 8, address & 0xff }; 969e43ccb0aSPaul Kocialkowski struct i2c_client *client = sensor->i2c_client; 970e43ccb0aSPaul Kocialkowski int ret; 971e43ccb0aSPaul Kocialkowski 972e43ccb0aSPaul Kocialkowski ret = i2c_master_send(client, data, sizeof(data)); 973e43ccb0aSPaul Kocialkowski if (ret < 0) { 974e43ccb0aSPaul Kocialkowski dev_dbg(&client->dev, "i2c send error at address %#04x\n", 975e43ccb0aSPaul Kocialkowski address); 976e43ccb0aSPaul Kocialkowski return ret; 977e43ccb0aSPaul Kocialkowski } 978e43ccb0aSPaul Kocialkowski 979e43ccb0aSPaul Kocialkowski ret = i2c_master_recv(client, value, 1); 980e43ccb0aSPaul Kocialkowski if (ret < 0) { 981e43ccb0aSPaul Kocialkowski dev_dbg(&client->dev, "i2c recv error at address %#04x\n", 982e43ccb0aSPaul Kocialkowski address); 983e43ccb0aSPaul Kocialkowski return ret; 984e43ccb0aSPaul Kocialkowski } 985e43ccb0aSPaul Kocialkowski 986e43ccb0aSPaul Kocialkowski return 0; 987e43ccb0aSPaul Kocialkowski } 988e43ccb0aSPaul Kocialkowski 989e43ccb0aSPaul Kocialkowski static int ov5648_write(struct ov5648_sensor *sensor, u16 address, u8 value) 990e43ccb0aSPaul Kocialkowski { 991e43ccb0aSPaul Kocialkowski unsigned char data[3] = { address >> 8, address & 0xff, value }; 992e43ccb0aSPaul Kocialkowski struct i2c_client *client = sensor->i2c_client; 993e43ccb0aSPaul Kocialkowski int ret; 994e43ccb0aSPaul Kocialkowski 995e43ccb0aSPaul Kocialkowski ret = i2c_master_send(client, data, sizeof(data)); 996e43ccb0aSPaul Kocialkowski if (ret < 0) { 997e43ccb0aSPaul Kocialkowski dev_dbg(&client->dev, "i2c send error at address %#04x\n", 998e43ccb0aSPaul Kocialkowski address); 999e43ccb0aSPaul Kocialkowski return ret; 1000e43ccb0aSPaul Kocialkowski } 1001e43ccb0aSPaul Kocialkowski 1002e43ccb0aSPaul Kocialkowski return 0; 1003e43ccb0aSPaul Kocialkowski } 1004e43ccb0aSPaul Kocialkowski 1005e43ccb0aSPaul Kocialkowski static int ov5648_write_sequence(struct ov5648_sensor *sensor, 1006e43ccb0aSPaul Kocialkowski const struct ov5648_register_value *sequence, 1007e43ccb0aSPaul Kocialkowski unsigned int sequence_count) 1008e43ccb0aSPaul Kocialkowski { 1009e43ccb0aSPaul Kocialkowski unsigned int i; 1010e43ccb0aSPaul Kocialkowski int ret = 0; 1011e43ccb0aSPaul Kocialkowski 1012e43ccb0aSPaul Kocialkowski for (i = 0; i < sequence_count; i++) { 1013e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, sequence[i].address, 1014e43ccb0aSPaul Kocialkowski sequence[i].value); 1015e43ccb0aSPaul Kocialkowski if (ret) 1016e43ccb0aSPaul Kocialkowski break; 1017e43ccb0aSPaul Kocialkowski 1018e43ccb0aSPaul Kocialkowski if (sequence[i].delay_ms) 1019e43ccb0aSPaul Kocialkowski msleep(sequence[i].delay_ms); 1020e43ccb0aSPaul Kocialkowski } 1021e43ccb0aSPaul Kocialkowski 1022e43ccb0aSPaul Kocialkowski return ret; 1023e43ccb0aSPaul Kocialkowski } 1024e43ccb0aSPaul Kocialkowski 1025e43ccb0aSPaul Kocialkowski static int ov5648_update_bits(struct ov5648_sensor *sensor, u16 address, 1026e43ccb0aSPaul Kocialkowski u8 mask, u8 bits) 1027e43ccb0aSPaul Kocialkowski { 1028e43ccb0aSPaul Kocialkowski u8 value = 0; 1029e43ccb0aSPaul Kocialkowski int ret; 1030e43ccb0aSPaul Kocialkowski 1031e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, address, &value); 1032e43ccb0aSPaul Kocialkowski if (ret) 1033e43ccb0aSPaul Kocialkowski return ret; 1034e43ccb0aSPaul Kocialkowski 1035e43ccb0aSPaul Kocialkowski value &= ~mask; 1036e43ccb0aSPaul Kocialkowski value |= bits; 1037e43ccb0aSPaul Kocialkowski 1038e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, address, value); 1039e43ccb0aSPaul Kocialkowski if (ret) 1040e43ccb0aSPaul Kocialkowski return ret; 1041e43ccb0aSPaul Kocialkowski 1042e43ccb0aSPaul Kocialkowski return 0; 1043e43ccb0aSPaul Kocialkowski } 1044e43ccb0aSPaul Kocialkowski 1045e43ccb0aSPaul Kocialkowski /* Sensor */ 1046e43ccb0aSPaul Kocialkowski 1047e43ccb0aSPaul Kocialkowski static int ov5648_sw_reset(struct ov5648_sensor *sensor) 1048e43ccb0aSPaul Kocialkowski { 1049e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_SW_RESET_REG, OV5648_SW_RESET_RESET); 1050e43ccb0aSPaul Kocialkowski } 1051e43ccb0aSPaul Kocialkowski 1052e43ccb0aSPaul Kocialkowski static int ov5648_sw_standby(struct ov5648_sensor *sensor, int standby) 1053e43ccb0aSPaul Kocialkowski { 1054e43ccb0aSPaul Kocialkowski u8 value = 0; 1055e43ccb0aSPaul Kocialkowski 1056e43ccb0aSPaul Kocialkowski if (!standby) 1057e43ccb0aSPaul Kocialkowski value = OV5648_SW_STANDBY_STREAM_ON; 1058e43ccb0aSPaul Kocialkowski 1059e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_SW_STANDBY_REG, value); 1060e43ccb0aSPaul Kocialkowski } 1061e43ccb0aSPaul Kocialkowski 1062e43ccb0aSPaul Kocialkowski static int ov5648_chip_id_check(struct ov5648_sensor *sensor) 1063e43ccb0aSPaul Kocialkowski { 1064e43ccb0aSPaul Kocialkowski u16 regs[] = { OV5648_CHIP_ID_H_REG, OV5648_CHIP_ID_L_REG }; 1065e43ccb0aSPaul Kocialkowski u8 values[] = { OV5648_CHIP_ID_H_VALUE, OV5648_CHIP_ID_L_VALUE }; 1066e43ccb0aSPaul Kocialkowski unsigned int i; 1067e43ccb0aSPaul Kocialkowski u8 value; 1068e43ccb0aSPaul Kocialkowski int ret; 1069e43ccb0aSPaul Kocialkowski 1070e43ccb0aSPaul Kocialkowski for (i = 0; i < ARRAY_SIZE(regs); i++) { 1071e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, regs[i], &value); 1072e43ccb0aSPaul Kocialkowski if (ret < 0) 1073e43ccb0aSPaul Kocialkowski return ret; 1074e43ccb0aSPaul Kocialkowski 1075e43ccb0aSPaul Kocialkowski if (value != values[i]) { 1076e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1077e43ccb0aSPaul Kocialkowski "chip id value mismatch: %#x instead of %#x\n", 1078e43ccb0aSPaul Kocialkowski value, values[i]); 1079e43ccb0aSPaul Kocialkowski return -EINVAL; 1080e43ccb0aSPaul Kocialkowski } 1081e43ccb0aSPaul Kocialkowski } 1082e43ccb0aSPaul Kocialkowski 1083e43ccb0aSPaul Kocialkowski return 0; 1084e43ccb0aSPaul Kocialkowski } 1085e43ccb0aSPaul Kocialkowski 1086e43ccb0aSPaul Kocialkowski static int ov5648_avdd_internal_power(struct ov5648_sensor *sensor, int on) 1087e43ccb0aSPaul Kocialkowski { 1088e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_A_PWC_PK_O0_REG, 1089e43ccb0aSPaul Kocialkowski on ? 0 : OV5648_A_PWC_PK_O0_BP_REGULATOR_N); 1090e43ccb0aSPaul Kocialkowski } 1091e43ccb0aSPaul Kocialkowski 1092e43ccb0aSPaul Kocialkowski static int ov5648_pad_configure(struct ov5648_sensor *sensor) 1093e43ccb0aSPaul Kocialkowski { 1094e43ccb0aSPaul Kocialkowski int ret; 1095e43ccb0aSPaul Kocialkowski 1096e43ccb0aSPaul Kocialkowski /* Configure pads as input. */ 1097e43ccb0aSPaul Kocialkowski 1098e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PAD_OEN1_REG, 0); 1099e43ccb0aSPaul Kocialkowski if (ret) 1100e43ccb0aSPaul Kocialkowski return ret; 1101e43ccb0aSPaul Kocialkowski 1102e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PAD_OEN2_REG, 0); 1103e43ccb0aSPaul Kocialkowski if (ret) 1104e43ccb0aSPaul Kocialkowski return ret; 1105e43ccb0aSPaul Kocialkowski 1106e43ccb0aSPaul Kocialkowski /* Disable FREX pin. */ 1107e43ccb0aSPaul Kocialkowski 1108e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_PAD_PK_REG, 1109e43ccb0aSPaul Kocialkowski OV5648_PAD_PK_DRIVE_STRENGTH_1X | 1110e43ccb0aSPaul Kocialkowski OV5648_PAD_PK_FREX_N); 1111e43ccb0aSPaul Kocialkowski } 1112e43ccb0aSPaul Kocialkowski 1113e43ccb0aSPaul Kocialkowski static int ov5648_mipi_configure(struct ov5648_sensor *sensor) 1114e43ccb0aSPaul Kocialkowski { 1115e43ccb0aSPaul Kocialkowski struct v4l2_fwnode_bus_mipi_csi2 *bus_mipi_csi2 = 1116e43ccb0aSPaul Kocialkowski &sensor->endpoint.bus.mipi_csi2; 1117e43ccb0aSPaul Kocialkowski unsigned int lanes_count = bus_mipi_csi2->num_data_lanes; 1118e43ccb0aSPaul Kocialkowski int ret; 1119e43ccb0aSPaul Kocialkowski 1120e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_MIPI_CTRL0_REG, 1121e43ccb0aSPaul Kocialkowski OV5648_MIPI_CTRL0_CLK_LANE_AUTOGATE | 1122e43ccb0aSPaul Kocialkowski OV5648_MIPI_CTRL0_LANE_SELECT_LANE1 | 1123e43ccb0aSPaul Kocialkowski OV5648_MIPI_CTRL0_IDLE_LP11); 1124e43ccb0aSPaul Kocialkowski if (ret) 1125e43ccb0aSPaul Kocialkowski return ret; 1126e43ccb0aSPaul Kocialkowski 1127e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_MIPI_SC_CTRL0_REG, 1128e43ccb0aSPaul Kocialkowski OV5648_MIPI_SC_CTRL0_MIPI_LANES(lanes_count) | 1129e43ccb0aSPaul Kocialkowski OV5648_MIPI_SC_CTRL0_PHY_LP_RX_PD | 1130e43ccb0aSPaul Kocialkowski OV5648_MIPI_SC_CTRL0_MIPI_EN); 1131e43ccb0aSPaul Kocialkowski } 1132e43ccb0aSPaul Kocialkowski 1133e43ccb0aSPaul Kocialkowski static int ov5648_black_level_configure(struct ov5648_sensor *sensor) 1134e43ccb0aSPaul Kocialkowski { 1135e43ccb0aSPaul Kocialkowski int ret; 1136e43ccb0aSPaul Kocialkowski 1137e43ccb0aSPaul Kocialkowski /* Up to 6 lines are available for black level calibration. */ 1138e43ccb0aSPaul Kocialkowski 1139e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_BLC_CTRL1_REG, 1140e43ccb0aSPaul Kocialkowski OV5648_BLC_CTRL1_START_LINE(2)); 1141e43ccb0aSPaul Kocialkowski if (ret) 1142e43ccb0aSPaul Kocialkowski return ret; 1143e43ccb0aSPaul Kocialkowski 1144e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_BLC_CTRL2_REG, 1145e43ccb0aSPaul Kocialkowski OV5648_BLC_CTRL2_AUTO_EN | 1146e43ccb0aSPaul Kocialkowski OV5648_BLC_CTRL2_RESET_FRAME_NUM(5)); 1147e43ccb0aSPaul Kocialkowski if (ret) 1148e43ccb0aSPaul Kocialkowski return ret; 1149e43ccb0aSPaul Kocialkowski 1150e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_BLC_LINE_NUM_REG, 1151e43ccb0aSPaul Kocialkowski OV5648_BLC_LINE_NUM(4)); 1152e43ccb0aSPaul Kocialkowski if (ret) 1153e43ccb0aSPaul Kocialkowski return ret; 1154e43ccb0aSPaul Kocialkowski 1155e43ccb0aSPaul Kocialkowski return ov5648_update_bits(sensor, OV5648_BLC_CTRL5_REG, 1156e43ccb0aSPaul Kocialkowski OV5648_BLC_CTRL5_UPDATE_EN, 1157e43ccb0aSPaul Kocialkowski OV5648_BLC_CTRL5_UPDATE_EN); 1158e43ccb0aSPaul Kocialkowski } 1159e43ccb0aSPaul Kocialkowski 1160e43ccb0aSPaul Kocialkowski static int ov5648_isp_configure(struct ov5648_sensor *sensor) 1161e43ccb0aSPaul Kocialkowski { 1162e43ccb0aSPaul Kocialkowski u8 bits; 1163e43ccb0aSPaul Kocialkowski int ret; 1164e43ccb0aSPaul Kocialkowski 1165e43ccb0aSPaul Kocialkowski /* Enable black and white level correction. */ 1166e43ccb0aSPaul Kocialkowski bits = OV5648_ISP_CTRL0_BLACK_CORRECT_EN | 1167e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL0_WHITE_CORRECT_EN; 1168e43ccb0aSPaul Kocialkowski 1169e43ccb0aSPaul Kocialkowski ret = ov5648_update_bits(sensor, OV5648_ISP_CTRL0_REG, bits, bits); 1170e43ccb0aSPaul Kocialkowski if (ret) 1171e43ccb0aSPaul Kocialkowski return ret; 1172e43ccb0aSPaul Kocialkowski 1173e43ccb0aSPaul Kocialkowski /* Enable AWB. */ 1174e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL1_REG, 1175e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL1_AWB_EN); 1176e43ccb0aSPaul Kocialkowski if (ret) 1177e43ccb0aSPaul Kocialkowski return ret; 1178e43ccb0aSPaul Kocialkowski 1179e43ccb0aSPaul Kocialkowski /* Enable AWB gain and windowing. */ 1180e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL2_REG, 1181e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL2_WIN_EN | 1182e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL2_AWB_GAIN_EN); 1183e43ccb0aSPaul Kocialkowski if (ret) 1184e43ccb0aSPaul Kocialkowski return ret; 1185e43ccb0aSPaul Kocialkowski 1186e43ccb0aSPaul Kocialkowski /* Enable buffering and auto-binning. */ 1187e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL3_REG, 1188e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3_BUF_EN | 1189e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL3_BIN_AUTO_EN); 1190e43ccb0aSPaul Kocialkowski if (ret) 1191e43ccb0aSPaul Kocialkowski return ret; 1192e43ccb0aSPaul Kocialkowski 1193e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL4_REG, 0); 1194e43ccb0aSPaul Kocialkowski if (ret) 1195e43ccb0aSPaul Kocialkowski return ret; 1196e43ccb0aSPaul Kocialkowski 1197e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL1F_REG, 1198e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL1F_OUTPUT_EN); 1199e43ccb0aSPaul Kocialkowski if (ret) 1200e43ccb0aSPaul Kocialkowski return ret; 1201e43ccb0aSPaul Kocialkowski 1202e43ccb0aSPaul Kocialkowski /* Enable post-binning filters. */ 1203e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_ISP_CTRL4B_REG, 1204e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL4B_POST_BIN_H_EN | 1205e43ccb0aSPaul Kocialkowski OV5648_ISP_CTRL4B_POST_BIN_V_EN); 1206e43ccb0aSPaul Kocialkowski if (ret) 1207e43ccb0aSPaul Kocialkowski return ret; 1208e43ccb0aSPaul Kocialkowski 1209e43ccb0aSPaul Kocialkowski /* Disable debanding and night mode. Debug bit seems necessary. */ 1210e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_AEC_CTRL0_REG, 1211e43ccb0aSPaul Kocialkowski OV5648_AEC_CTRL0_DEBUG | 1212e43ccb0aSPaul Kocialkowski OV5648_AEC_CTRL0_START_SEL_EN); 1213e43ccb0aSPaul Kocialkowski if (ret) 1214e43ccb0aSPaul Kocialkowski return ret; 1215e43ccb0aSPaul Kocialkowski 1216e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_MANUAL_CTRL_REG, 1217e43ccb0aSPaul Kocialkowski OV5648_MANUAL_CTRL_FRAME_DELAY(1)); 1218e43ccb0aSPaul Kocialkowski } 1219e43ccb0aSPaul Kocialkowski 1220e43ccb0aSPaul Kocialkowski static unsigned long ov5648_mode_pll1_rate(struct ov5648_sensor *sensor, 1221e43ccb0aSPaul Kocialkowski const struct ov5648_pll1_config *config) 1222e43ccb0aSPaul Kocialkowski { 1223e43ccb0aSPaul Kocialkowski unsigned long xvclk_rate; 1224e43ccb0aSPaul Kocialkowski unsigned long pll1_rate; 1225e43ccb0aSPaul Kocialkowski 1226e43ccb0aSPaul Kocialkowski xvclk_rate = clk_get_rate(sensor->xvclk); 1227e43ccb0aSPaul Kocialkowski pll1_rate = xvclk_rate * config->pll_mul; 1228e43ccb0aSPaul Kocialkowski 1229e43ccb0aSPaul Kocialkowski switch (config->pll_pre_div) { 1230e43ccb0aSPaul Kocialkowski case 5: 1231e43ccb0aSPaul Kocialkowski pll1_rate *= 3; 1232e43ccb0aSPaul Kocialkowski pll1_rate /= 2; 1233e43ccb0aSPaul Kocialkowski break; 1234e43ccb0aSPaul Kocialkowski case 7: 1235e43ccb0aSPaul Kocialkowski pll1_rate *= 5; 1236e43ccb0aSPaul Kocialkowski pll1_rate /= 2; 1237e43ccb0aSPaul Kocialkowski break; 1238e43ccb0aSPaul Kocialkowski default: 1239e43ccb0aSPaul Kocialkowski pll1_rate /= config->pll_pre_div; 1240e43ccb0aSPaul Kocialkowski break; 1241e43ccb0aSPaul Kocialkowski } 1242e43ccb0aSPaul Kocialkowski 1243e43ccb0aSPaul Kocialkowski return pll1_rate; 1244e43ccb0aSPaul Kocialkowski } 1245e43ccb0aSPaul Kocialkowski 1246e43ccb0aSPaul Kocialkowski static int ov5648_mode_pll1_configure(struct ov5648_sensor *sensor, 1247e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode, 1248e43ccb0aSPaul Kocialkowski u32 mbus_code) 1249e43ccb0aSPaul Kocialkowski { 1250e43ccb0aSPaul Kocialkowski const struct ov5648_pll1_config *config; 1251e43ccb0aSPaul Kocialkowski u8 value; 1252e43ccb0aSPaul Kocialkowski int ret; 1253e43ccb0aSPaul Kocialkowski 1254e43ccb0aSPaul Kocialkowski value = OV5648_PLL_CTRL0_PLL_CHARGE_PUMP(1); 1255e43ccb0aSPaul Kocialkowski 1256e43ccb0aSPaul Kocialkowski switch (mbus_code) { 1257e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR8_1X8: 1258e43ccb0aSPaul Kocialkowski config = mode->pll1_config[0]; 1259e43ccb0aSPaul Kocialkowski value |= OV5648_PLL_CTRL0_BITS(8); 1260e43ccb0aSPaul Kocialkowski break; 1261e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR10_1X10: 1262e43ccb0aSPaul Kocialkowski config = mode->pll1_config[1]; 1263e43ccb0aSPaul Kocialkowski value |= OV5648_PLL_CTRL0_BITS(10); 1264e43ccb0aSPaul Kocialkowski break; 1265e43ccb0aSPaul Kocialkowski default: 1266e43ccb0aSPaul Kocialkowski return -EINVAL; 1267e43ccb0aSPaul Kocialkowski } 1268e43ccb0aSPaul Kocialkowski 1269e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLL_CTRL0_REG, value); 1270e43ccb0aSPaul Kocialkowski if (ret) 1271e43ccb0aSPaul Kocialkowski return ret; 1272e43ccb0aSPaul Kocialkowski 1273e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLL_DIV_REG, 1274e43ccb0aSPaul Kocialkowski OV5648_PLL_DIV_ROOT_DIV(config->root_div) | 1275e43ccb0aSPaul Kocialkowski OV5648_PLL_DIV_PLL_PRE_DIV(config->pll_pre_div)); 1276e43ccb0aSPaul Kocialkowski if (ret) 1277e43ccb0aSPaul Kocialkowski return ret; 1278e43ccb0aSPaul Kocialkowski 1279e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLL_MUL_REG, 1280e43ccb0aSPaul Kocialkowski OV5648_PLL_MUL(config->pll_mul)); 1281e43ccb0aSPaul Kocialkowski if (ret) 1282e43ccb0aSPaul Kocialkowski return ret; 1283e43ccb0aSPaul Kocialkowski 1284e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLL_CTRL1_REG, 1285e43ccb0aSPaul Kocialkowski OV5648_PLL_CTRL1_SYS_DIV(config->sys_div) | 1286e43ccb0aSPaul Kocialkowski OV5648_PLL_CTRL1_MIPI_DIV(config->mipi_div)); 1287e43ccb0aSPaul Kocialkowski if (ret) 1288e43ccb0aSPaul Kocialkowski return ret; 1289e43ccb0aSPaul Kocialkowski 1290e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_SRB_CTRL_REG, 1291e43ccb0aSPaul Kocialkowski OV5648_SRB_CTRL_SCLK_DIV(config->sclk_div) | 1292e43ccb0aSPaul Kocialkowski OV5648_SRB_CTRL_SCLK_ARBITER_EN); 1293e43ccb0aSPaul Kocialkowski } 1294e43ccb0aSPaul Kocialkowski 1295e43ccb0aSPaul Kocialkowski static int ov5648_mode_pll2_configure(struct ov5648_sensor *sensor, 1296e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode) 1297e43ccb0aSPaul Kocialkowski { 1298e43ccb0aSPaul Kocialkowski const struct ov5648_pll2_config *config = mode->pll2_config; 1299e43ccb0aSPaul Kocialkowski int ret; 1300e43ccb0aSPaul Kocialkowski 1301e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLLS_DIV_REG, 1302e43ccb0aSPaul Kocialkowski OV5648_PLLS_DIV_PLLS_PRE_DIV(config->plls_pre_div) | 1303e43ccb0aSPaul Kocialkowski OV5648_PLLS_DIV_PLLS_DIV_R(config->plls_div_r) | 1304e43ccb0aSPaul Kocialkowski OV5648_PLLS_DIV_PLLS_SEL_DIV(config->sel_div)); 1305e43ccb0aSPaul Kocialkowski if (ret) 1306e43ccb0aSPaul Kocialkowski return ret; 1307e43ccb0aSPaul Kocialkowski 1308e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_PLLS_MUL_REG, 1309e43ccb0aSPaul Kocialkowski OV5648_PLLS_MUL(config->plls_mul)); 1310e43ccb0aSPaul Kocialkowski if (ret) 1311e43ccb0aSPaul Kocialkowski return ret; 1312e43ccb0aSPaul Kocialkowski 1313e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_PLLS_CTRL_REG, 1314e43ccb0aSPaul Kocialkowski OV5648_PLLS_CTRL_PLL_CHARGE_PUMP(1) | 1315e43ccb0aSPaul Kocialkowski OV5648_PLLS_CTRL_SYS_DIV(config->sys_div)); 1316e43ccb0aSPaul Kocialkowski } 1317e43ccb0aSPaul Kocialkowski 1318e43ccb0aSPaul Kocialkowski static int ov5648_mode_configure(struct ov5648_sensor *sensor, 1319e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode, u32 mbus_code) 1320e43ccb0aSPaul Kocialkowski { 1321e43ccb0aSPaul Kocialkowski int ret; 1322e43ccb0aSPaul Kocialkowski 1323e43ccb0aSPaul Kocialkowski /* Crop Start X */ 1324e43ccb0aSPaul Kocialkowski 1325e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_START_X_H_REG, 1326e43ccb0aSPaul Kocialkowski OV5648_CROP_START_X_H(mode->crop_start_x)); 1327e43ccb0aSPaul Kocialkowski if (ret) 1328e43ccb0aSPaul Kocialkowski return ret; 1329e43ccb0aSPaul Kocialkowski 1330e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_START_X_L_REG, 1331e43ccb0aSPaul Kocialkowski OV5648_CROP_START_X_L(mode->crop_start_x)); 1332e43ccb0aSPaul Kocialkowski if (ret) 1333e43ccb0aSPaul Kocialkowski return ret; 1334e43ccb0aSPaul Kocialkowski 1335e43ccb0aSPaul Kocialkowski /* Offset X */ 1336e43ccb0aSPaul Kocialkowski 1337e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OFFSET_X_H_REG, 1338e43ccb0aSPaul Kocialkowski OV5648_OFFSET_X_H(mode->offset_x)); 1339e43ccb0aSPaul Kocialkowski if (ret) 1340e43ccb0aSPaul Kocialkowski return ret; 1341e43ccb0aSPaul Kocialkowski 1342e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OFFSET_X_L_REG, 1343e43ccb0aSPaul Kocialkowski OV5648_OFFSET_X_L(mode->offset_x)); 1344e43ccb0aSPaul Kocialkowski if (ret) 1345e43ccb0aSPaul Kocialkowski return ret; 1346e43ccb0aSPaul Kocialkowski 1347e43ccb0aSPaul Kocialkowski /* Output Size X */ 1348e43ccb0aSPaul Kocialkowski 1349e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_X_H_REG, 1350e43ccb0aSPaul Kocialkowski OV5648_OUTPUT_SIZE_X_H(mode->output_size_x)); 1351e43ccb0aSPaul Kocialkowski if (ret) 1352e43ccb0aSPaul Kocialkowski return ret; 1353e43ccb0aSPaul Kocialkowski 1354e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_X_L_REG, 1355e43ccb0aSPaul Kocialkowski OV5648_OUTPUT_SIZE_X_L(mode->output_size_x)); 1356e43ccb0aSPaul Kocialkowski if (ret) 1357e43ccb0aSPaul Kocialkowski return ret; 1358e43ccb0aSPaul Kocialkowski 1359e43ccb0aSPaul Kocialkowski /* Crop End X */ 1360e43ccb0aSPaul Kocialkowski 1361e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_END_X_H_REG, 1362e43ccb0aSPaul Kocialkowski OV5648_CROP_END_X_H(mode->crop_end_x)); 1363e43ccb0aSPaul Kocialkowski if (ret) 1364e43ccb0aSPaul Kocialkowski return ret; 1365e43ccb0aSPaul Kocialkowski 1366e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_END_X_L_REG, 1367e43ccb0aSPaul Kocialkowski OV5648_CROP_END_X_L(mode->crop_end_x)); 1368e43ccb0aSPaul Kocialkowski if (ret) 1369e43ccb0aSPaul Kocialkowski return ret; 1370e43ccb0aSPaul Kocialkowski 1371e43ccb0aSPaul Kocialkowski /* Horizontal Total Size */ 1372e43ccb0aSPaul Kocialkowski 1373e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_HTS_H_REG, OV5648_HTS_H(mode->hts)); 1374e43ccb0aSPaul Kocialkowski if (ret) 1375e43ccb0aSPaul Kocialkowski return ret; 1376e43ccb0aSPaul Kocialkowski 1377e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_HTS_L_REG, OV5648_HTS_L(mode->hts)); 1378e43ccb0aSPaul Kocialkowski if (ret) 1379e43ccb0aSPaul Kocialkowski return ret; 1380e43ccb0aSPaul Kocialkowski 1381e43ccb0aSPaul Kocialkowski /* Crop Start Y */ 1382e43ccb0aSPaul Kocialkowski 1383e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_START_Y_H_REG, 1384e43ccb0aSPaul Kocialkowski OV5648_CROP_START_Y_H(mode->crop_start_y)); 1385e43ccb0aSPaul Kocialkowski if (ret) 1386e43ccb0aSPaul Kocialkowski return ret; 1387e43ccb0aSPaul Kocialkowski 1388e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_START_Y_L_REG, 1389e43ccb0aSPaul Kocialkowski OV5648_CROP_START_Y_L(mode->crop_start_y)); 1390e43ccb0aSPaul Kocialkowski if (ret) 1391e43ccb0aSPaul Kocialkowski return ret; 1392e43ccb0aSPaul Kocialkowski 1393e43ccb0aSPaul Kocialkowski /* Offset Y */ 1394e43ccb0aSPaul Kocialkowski 1395e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OFFSET_Y_H_REG, 1396e43ccb0aSPaul Kocialkowski OV5648_OFFSET_Y_H(mode->offset_y)); 1397e43ccb0aSPaul Kocialkowski if (ret) 1398e43ccb0aSPaul Kocialkowski return ret; 1399e43ccb0aSPaul Kocialkowski 1400e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OFFSET_Y_L_REG, 1401e43ccb0aSPaul Kocialkowski OV5648_OFFSET_Y_L(mode->offset_y)); 1402e43ccb0aSPaul Kocialkowski if (ret) 1403e43ccb0aSPaul Kocialkowski return ret; 1404e43ccb0aSPaul Kocialkowski 1405e43ccb0aSPaul Kocialkowski /* Output Size Y */ 1406e43ccb0aSPaul Kocialkowski 1407e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_Y_H_REG, 1408e43ccb0aSPaul Kocialkowski OV5648_OUTPUT_SIZE_Y_H(mode->output_size_y)); 1409e43ccb0aSPaul Kocialkowski if (ret) 1410e43ccb0aSPaul Kocialkowski return ret; 1411e43ccb0aSPaul Kocialkowski 1412e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_OUTPUT_SIZE_Y_L_REG, 1413e43ccb0aSPaul Kocialkowski OV5648_OUTPUT_SIZE_Y_L(mode->output_size_y)); 1414e43ccb0aSPaul Kocialkowski if (ret) 1415e43ccb0aSPaul Kocialkowski return ret; 1416e43ccb0aSPaul Kocialkowski 1417e43ccb0aSPaul Kocialkowski /* Crop End Y */ 1418e43ccb0aSPaul Kocialkowski 1419e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_END_Y_H_REG, 1420e43ccb0aSPaul Kocialkowski OV5648_CROP_END_Y_H(mode->crop_end_y)); 1421e43ccb0aSPaul Kocialkowski if (ret) 1422e43ccb0aSPaul Kocialkowski return ret; 1423e43ccb0aSPaul Kocialkowski 1424e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_CROP_END_Y_L_REG, 1425e43ccb0aSPaul Kocialkowski OV5648_CROP_END_Y_L(mode->crop_end_y)); 1426e43ccb0aSPaul Kocialkowski if (ret) 1427e43ccb0aSPaul Kocialkowski return ret; 1428e43ccb0aSPaul Kocialkowski 1429e43ccb0aSPaul Kocialkowski /* Vertical Total Size */ 1430e43ccb0aSPaul Kocialkowski 1431e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_VTS_H_REG, OV5648_VTS_H(mode->vts)); 1432e43ccb0aSPaul Kocialkowski if (ret) 1433e43ccb0aSPaul Kocialkowski return ret; 1434e43ccb0aSPaul Kocialkowski 1435e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_VTS_L_REG, OV5648_VTS_L(mode->vts)); 1436e43ccb0aSPaul Kocialkowski if (ret) 1437e43ccb0aSPaul Kocialkowski return ret; 1438e43ccb0aSPaul Kocialkowski 1439e43ccb0aSPaul Kocialkowski /* Flip/Mirror/Binning */ 1440e43ccb0aSPaul Kocialkowski 1441e43ccb0aSPaul Kocialkowski /* 1442e43ccb0aSPaul Kocialkowski * A debug bit is enabled by default and needs to be cleared for 1443e43ccb0aSPaul Kocialkowski * subsampling to work. 1444e43ccb0aSPaul Kocialkowski */ 1445e43ccb0aSPaul Kocialkowski ret = ov5648_update_bits(sensor, OV5648_TC20_REG, 1446e43ccb0aSPaul Kocialkowski OV5648_TC20_DEBUG | 1447e43ccb0aSPaul Kocialkowski OV5648_TC20_BINNING_VERT_EN, 1448e43ccb0aSPaul Kocialkowski mode->binning_y ? OV5648_TC20_BINNING_VERT_EN : 1449e43ccb0aSPaul Kocialkowski 0); 1450e43ccb0aSPaul Kocialkowski if (ret) 1451e43ccb0aSPaul Kocialkowski return ret; 1452e43ccb0aSPaul Kocialkowski 1453e43ccb0aSPaul Kocialkowski ret = ov5648_update_bits(sensor, OV5648_TC21_REG, 1454e43ccb0aSPaul Kocialkowski OV5648_TC21_BINNING_HORZ_EN, 1455e43ccb0aSPaul Kocialkowski mode->binning_x ? OV5648_TC21_BINNING_HORZ_EN : 1456e43ccb0aSPaul Kocialkowski 0); 1457e43ccb0aSPaul Kocialkowski if (ret) 1458e43ccb0aSPaul Kocialkowski return ret; 1459e43ccb0aSPaul Kocialkowski 1460e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_SUB_INC_X_REG, 1461e43ccb0aSPaul Kocialkowski OV5648_SUB_INC_X_ODD(mode->inc_x_odd) | 1462e43ccb0aSPaul Kocialkowski OV5648_SUB_INC_X_EVEN(mode->inc_x_even)); 1463e43ccb0aSPaul Kocialkowski if (ret) 1464e43ccb0aSPaul Kocialkowski return ret; 1465e43ccb0aSPaul Kocialkowski 1466e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_SUB_INC_Y_REG, 1467e43ccb0aSPaul Kocialkowski OV5648_SUB_INC_Y_ODD(mode->inc_y_odd) | 1468e43ccb0aSPaul Kocialkowski OV5648_SUB_INC_Y_EVEN(mode->inc_y_even)); 1469e43ccb0aSPaul Kocialkowski if (ret) 1470e43ccb0aSPaul Kocialkowski return ret; 1471e43ccb0aSPaul Kocialkowski 1472e43ccb0aSPaul Kocialkowski /* PLLs */ 1473e43ccb0aSPaul Kocialkowski 1474e43ccb0aSPaul Kocialkowski ret = ov5648_mode_pll1_configure(sensor, mode, mbus_code); 1475e43ccb0aSPaul Kocialkowski if (ret) 1476e43ccb0aSPaul Kocialkowski return ret; 1477e43ccb0aSPaul Kocialkowski 1478e43ccb0aSPaul Kocialkowski ret = ov5648_mode_pll2_configure(sensor, mode); 1479e43ccb0aSPaul Kocialkowski if (ret) 1480e43ccb0aSPaul Kocialkowski return ret; 1481e43ccb0aSPaul Kocialkowski 1482e43ccb0aSPaul Kocialkowski /* Extra registers */ 1483e43ccb0aSPaul Kocialkowski 1484e43ccb0aSPaul Kocialkowski if (mode->register_values) { 1485e43ccb0aSPaul Kocialkowski ret = ov5648_write_sequence(sensor, mode->register_values, 1486e43ccb0aSPaul Kocialkowski mode->register_values_count); 1487e43ccb0aSPaul Kocialkowski if (ret) 1488e43ccb0aSPaul Kocialkowski return ret; 1489e43ccb0aSPaul Kocialkowski } 1490e43ccb0aSPaul Kocialkowski 1491e43ccb0aSPaul Kocialkowski return 0; 1492e43ccb0aSPaul Kocialkowski } 1493e43ccb0aSPaul Kocialkowski 1494e43ccb0aSPaul Kocialkowski static unsigned long ov5648_mode_mipi_clk_rate(struct ov5648_sensor *sensor, 1495e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode, 1496e43ccb0aSPaul Kocialkowski u32 mbus_code) 1497e43ccb0aSPaul Kocialkowski { 1498e43ccb0aSPaul Kocialkowski const struct ov5648_pll1_config *config; 1499e43ccb0aSPaul Kocialkowski unsigned long pll1_rate; 1500e43ccb0aSPaul Kocialkowski 1501e43ccb0aSPaul Kocialkowski switch (mbus_code) { 1502e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR8_1X8: 1503e43ccb0aSPaul Kocialkowski config = mode->pll1_config[0]; 1504e43ccb0aSPaul Kocialkowski break; 1505e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR10_1X10: 1506e43ccb0aSPaul Kocialkowski config = mode->pll1_config[1]; 1507e43ccb0aSPaul Kocialkowski break; 1508e43ccb0aSPaul Kocialkowski default: 1509e43ccb0aSPaul Kocialkowski return 0; 1510e43ccb0aSPaul Kocialkowski } 1511e43ccb0aSPaul Kocialkowski 1512e43ccb0aSPaul Kocialkowski pll1_rate = ov5648_mode_pll1_rate(sensor, config); 1513e43ccb0aSPaul Kocialkowski 1514e43ccb0aSPaul Kocialkowski return pll1_rate / config->sys_div / config->mipi_div / 2; 1515e43ccb0aSPaul Kocialkowski } 1516e43ccb0aSPaul Kocialkowski 1517e43ccb0aSPaul Kocialkowski /* Exposure */ 1518e43ccb0aSPaul Kocialkowski 1519e43ccb0aSPaul Kocialkowski static int ov5648_exposure_auto_configure(struct ov5648_sensor *sensor, 1520e43ccb0aSPaul Kocialkowski bool enable) 1521e43ccb0aSPaul Kocialkowski { 1522e43ccb0aSPaul Kocialkowski return ov5648_update_bits(sensor, OV5648_MANUAL_CTRL_REG, 1523e43ccb0aSPaul Kocialkowski OV5648_MANUAL_CTRL_AEC_MANUAL_EN, 1524e43ccb0aSPaul Kocialkowski enable ? 0 : OV5648_MANUAL_CTRL_AEC_MANUAL_EN); 1525e43ccb0aSPaul Kocialkowski } 1526e43ccb0aSPaul Kocialkowski 1527e43ccb0aSPaul Kocialkowski static int ov5648_exposure_configure(struct ov5648_sensor *sensor, u32 exposure) 1528e43ccb0aSPaul Kocialkowski { 1529e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1530e43ccb0aSPaul Kocialkowski int ret; 1531e43ccb0aSPaul Kocialkowski 1532e43ccb0aSPaul Kocialkowski if (ctrls->exposure_auto->val != V4L2_EXPOSURE_MANUAL) 1533e43ccb0aSPaul Kocialkowski return -EINVAL; 1534e43ccb0aSPaul Kocialkowski 1535e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_EXPOSURE_CTRL_HH_REG, 1536e43ccb0aSPaul Kocialkowski OV5648_EXPOSURE_CTRL_HH(exposure)); 1537e43ccb0aSPaul Kocialkowski if (ret) 1538e43ccb0aSPaul Kocialkowski return ret; 1539e43ccb0aSPaul Kocialkowski 1540e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_EXPOSURE_CTRL_H_REG, 1541e43ccb0aSPaul Kocialkowski OV5648_EXPOSURE_CTRL_H(exposure)); 1542e43ccb0aSPaul Kocialkowski if (ret) 1543e43ccb0aSPaul Kocialkowski return ret; 1544e43ccb0aSPaul Kocialkowski 1545e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_EXPOSURE_CTRL_L_REG, 1546e43ccb0aSPaul Kocialkowski OV5648_EXPOSURE_CTRL_L(exposure)); 1547e43ccb0aSPaul Kocialkowski } 1548e43ccb0aSPaul Kocialkowski 1549e43ccb0aSPaul Kocialkowski static int ov5648_exposure_value(struct ov5648_sensor *sensor, 1550e43ccb0aSPaul Kocialkowski u32 *exposure) 1551e43ccb0aSPaul Kocialkowski { 1552e43ccb0aSPaul Kocialkowski u8 exposure_hh = 0, exposure_h = 0, exposure_l = 0; 1553e43ccb0aSPaul Kocialkowski int ret; 1554e43ccb0aSPaul Kocialkowski 1555e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_HH_REG, &exposure_hh); 1556e43ccb0aSPaul Kocialkowski if (ret) 1557e43ccb0aSPaul Kocialkowski return ret; 1558e43ccb0aSPaul Kocialkowski 1559e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_H_REG, &exposure_h); 1560e43ccb0aSPaul Kocialkowski if (ret) 1561e43ccb0aSPaul Kocialkowski return ret; 1562e43ccb0aSPaul Kocialkowski 1563e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, OV5648_EXPOSURE_CTRL_L_REG, &exposure_l); 1564e43ccb0aSPaul Kocialkowski if (ret) 1565e43ccb0aSPaul Kocialkowski return ret; 1566e43ccb0aSPaul Kocialkowski 1567e43ccb0aSPaul Kocialkowski *exposure = OV5648_EXPOSURE_CTRL_HH_VALUE((u32)exposure_hh) | 1568e43ccb0aSPaul Kocialkowski OV5648_EXPOSURE_CTRL_H_VALUE((u32)exposure_h) | 1569e43ccb0aSPaul Kocialkowski OV5648_EXPOSURE_CTRL_L_VALUE((u32)exposure_l); 1570e43ccb0aSPaul Kocialkowski 1571e43ccb0aSPaul Kocialkowski return 0; 1572e43ccb0aSPaul Kocialkowski } 1573e43ccb0aSPaul Kocialkowski 1574e43ccb0aSPaul Kocialkowski /* Gain */ 1575e43ccb0aSPaul Kocialkowski 1576e43ccb0aSPaul Kocialkowski static int ov5648_gain_auto_configure(struct ov5648_sensor *sensor, bool enable) 1577e43ccb0aSPaul Kocialkowski { 1578e43ccb0aSPaul Kocialkowski return ov5648_update_bits(sensor, OV5648_MANUAL_CTRL_REG, 1579e43ccb0aSPaul Kocialkowski OV5648_MANUAL_CTRL_AGC_MANUAL_EN, 1580e43ccb0aSPaul Kocialkowski enable ? 0 : OV5648_MANUAL_CTRL_AGC_MANUAL_EN); 1581e43ccb0aSPaul Kocialkowski } 1582e43ccb0aSPaul Kocialkowski 1583e43ccb0aSPaul Kocialkowski static int ov5648_gain_configure(struct ov5648_sensor *sensor, u32 gain) 1584e43ccb0aSPaul Kocialkowski { 1585e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1586e43ccb0aSPaul Kocialkowski int ret; 1587e43ccb0aSPaul Kocialkowski 1588e43ccb0aSPaul Kocialkowski if (ctrls->gain_auto->val) 1589e43ccb0aSPaul Kocialkowski return -EINVAL; 1590e43ccb0aSPaul Kocialkowski 1591e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_GAIN_CTRL_H_REG, 1592e43ccb0aSPaul Kocialkowski OV5648_GAIN_CTRL_H(gain)); 1593e43ccb0aSPaul Kocialkowski if (ret) 1594e43ccb0aSPaul Kocialkowski return ret; 1595e43ccb0aSPaul Kocialkowski 1596e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_GAIN_CTRL_L_REG, 1597e43ccb0aSPaul Kocialkowski OV5648_GAIN_CTRL_L(gain)); 1598e43ccb0aSPaul Kocialkowski } 1599e43ccb0aSPaul Kocialkowski 1600e43ccb0aSPaul Kocialkowski static int ov5648_gain_value(struct ov5648_sensor *sensor, u32 *gain) 1601e43ccb0aSPaul Kocialkowski { 1602e43ccb0aSPaul Kocialkowski u8 gain_h = 0, gain_l = 0; 1603e43ccb0aSPaul Kocialkowski int ret; 1604e43ccb0aSPaul Kocialkowski 1605e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, OV5648_GAIN_CTRL_H_REG, &gain_h); 1606e43ccb0aSPaul Kocialkowski if (ret) 1607e43ccb0aSPaul Kocialkowski return ret; 1608e43ccb0aSPaul Kocialkowski 1609e43ccb0aSPaul Kocialkowski ret = ov5648_read(sensor, OV5648_GAIN_CTRL_L_REG, &gain_l); 1610e43ccb0aSPaul Kocialkowski if (ret) 1611e43ccb0aSPaul Kocialkowski return ret; 1612e43ccb0aSPaul Kocialkowski 1613e43ccb0aSPaul Kocialkowski *gain = OV5648_GAIN_CTRL_H_VALUE((u32)gain_h) | 1614e43ccb0aSPaul Kocialkowski OV5648_GAIN_CTRL_L_VALUE((u32)gain_l); 1615e43ccb0aSPaul Kocialkowski 1616e43ccb0aSPaul Kocialkowski return 0; 1617e43ccb0aSPaul Kocialkowski } 1618e43ccb0aSPaul Kocialkowski 1619e43ccb0aSPaul Kocialkowski /* White Balance */ 1620e43ccb0aSPaul Kocialkowski 1621e43ccb0aSPaul Kocialkowski static int ov5648_white_balance_auto_configure(struct ov5648_sensor *sensor, 1622e43ccb0aSPaul Kocialkowski bool enable) 1623e43ccb0aSPaul Kocialkowski { 1624e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_AWB_CTRL_REG, 1625e43ccb0aSPaul Kocialkowski enable ? 0 : OV5648_AWB_CTRL_GAIN_MANUAL_EN); 1626e43ccb0aSPaul Kocialkowski } 1627e43ccb0aSPaul Kocialkowski 1628e43ccb0aSPaul Kocialkowski static int ov5648_white_balance_configure(struct ov5648_sensor *sensor, 1629e43ccb0aSPaul Kocialkowski u32 red_balance, u32 blue_balance) 1630e43ccb0aSPaul Kocialkowski { 1631e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1632e43ccb0aSPaul Kocialkowski int ret; 1633e43ccb0aSPaul Kocialkowski 1634e43ccb0aSPaul Kocialkowski if (ctrls->white_balance_auto->val) 1635e43ccb0aSPaul Kocialkowski return -EINVAL; 1636e43ccb0aSPaul Kocialkowski 1637e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_GAIN_RED_MAN_H_REG, 1638e43ccb0aSPaul Kocialkowski OV5648_GAIN_RED_MAN_H(red_balance)); 1639e43ccb0aSPaul Kocialkowski if (ret) 1640e43ccb0aSPaul Kocialkowski return ret; 1641e43ccb0aSPaul Kocialkowski 1642e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_GAIN_RED_MAN_L_REG, 1643e43ccb0aSPaul Kocialkowski OV5648_GAIN_RED_MAN_L(red_balance)); 1644e43ccb0aSPaul Kocialkowski if (ret) 1645e43ccb0aSPaul Kocialkowski return ret; 1646e43ccb0aSPaul Kocialkowski 1647e43ccb0aSPaul Kocialkowski ret = ov5648_write(sensor, OV5648_GAIN_BLUE_MAN_H_REG, 1648e43ccb0aSPaul Kocialkowski OV5648_GAIN_BLUE_MAN_H(blue_balance)); 1649e43ccb0aSPaul Kocialkowski if (ret) 1650e43ccb0aSPaul Kocialkowski return ret; 1651e43ccb0aSPaul Kocialkowski 1652e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_GAIN_BLUE_MAN_L_REG, 1653e43ccb0aSPaul Kocialkowski OV5648_GAIN_BLUE_MAN_L(blue_balance)); 1654e43ccb0aSPaul Kocialkowski } 1655e43ccb0aSPaul Kocialkowski 1656e43ccb0aSPaul Kocialkowski /* Flip */ 1657e43ccb0aSPaul Kocialkowski 1658e43ccb0aSPaul Kocialkowski static int ov5648_flip_vert_configure(struct ov5648_sensor *sensor, bool enable) 1659e43ccb0aSPaul Kocialkowski { 1660e43ccb0aSPaul Kocialkowski u8 bits = OV5648_TC20_FLIP_VERT_ISP_EN | 1661e43ccb0aSPaul Kocialkowski OV5648_TC20_FLIP_VERT_SENSOR_EN; 1662e43ccb0aSPaul Kocialkowski 1663e43ccb0aSPaul Kocialkowski return ov5648_update_bits(sensor, OV5648_TC20_REG, bits, 1664e43ccb0aSPaul Kocialkowski enable ? bits : 0); 1665e43ccb0aSPaul Kocialkowski } 1666e43ccb0aSPaul Kocialkowski 1667e43ccb0aSPaul Kocialkowski static int ov5648_flip_horz_configure(struct ov5648_sensor *sensor, bool enable) 1668e43ccb0aSPaul Kocialkowski { 1669e43ccb0aSPaul Kocialkowski u8 bits = OV5648_TC21_FLIP_HORZ_ISP_EN | 1670e43ccb0aSPaul Kocialkowski OV5648_TC21_FLIP_HORZ_SENSOR_EN; 1671e43ccb0aSPaul Kocialkowski 1672e43ccb0aSPaul Kocialkowski return ov5648_update_bits(sensor, OV5648_TC21_REG, bits, 1673e43ccb0aSPaul Kocialkowski enable ? bits : 0); 1674e43ccb0aSPaul Kocialkowski } 1675e43ccb0aSPaul Kocialkowski 1676e43ccb0aSPaul Kocialkowski /* Test Pattern */ 1677e43ccb0aSPaul Kocialkowski 1678e43ccb0aSPaul Kocialkowski static int ov5648_test_pattern_configure(struct ov5648_sensor *sensor, 1679e43ccb0aSPaul Kocialkowski unsigned int index) 1680e43ccb0aSPaul Kocialkowski { 1681e43ccb0aSPaul Kocialkowski if (index >= ARRAY_SIZE(ov5648_test_pattern_bits)) 1682e43ccb0aSPaul Kocialkowski return -EINVAL; 1683e43ccb0aSPaul Kocialkowski 1684e43ccb0aSPaul Kocialkowski return ov5648_write(sensor, OV5648_ISP_CTRL3D_REG, 1685e43ccb0aSPaul Kocialkowski ov5648_test_pattern_bits[index]); 1686e43ccb0aSPaul Kocialkowski } 1687e43ccb0aSPaul Kocialkowski 1688e43ccb0aSPaul Kocialkowski /* State */ 1689e43ccb0aSPaul Kocialkowski 1690e43ccb0aSPaul Kocialkowski static int ov5648_state_mipi_configure(struct ov5648_sensor *sensor, 1691e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode, 1692e43ccb0aSPaul Kocialkowski u32 mbus_code) 1693e43ccb0aSPaul Kocialkowski { 1694e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1695e43ccb0aSPaul Kocialkowski struct v4l2_fwnode_bus_mipi_csi2 *bus_mipi_csi2 = 1696e43ccb0aSPaul Kocialkowski &sensor->endpoint.bus.mipi_csi2; 1697e43ccb0aSPaul Kocialkowski unsigned long mipi_clk_rate; 1698e43ccb0aSPaul Kocialkowski unsigned int bits_per_sample; 1699e43ccb0aSPaul Kocialkowski unsigned int lanes_count; 1700e43ccb0aSPaul Kocialkowski unsigned int i, j; 1701e43ccb0aSPaul Kocialkowski s64 mipi_pixel_rate; 1702e43ccb0aSPaul Kocialkowski 1703e43ccb0aSPaul Kocialkowski mipi_clk_rate = ov5648_mode_mipi_clk_rate(sensor, mode, mbus_code); 1704e43ccb0aSPaul Kocialkowski if (!mipi_clk_rate) 1705e43ccb0aSPaul Kocialkowski return -EINVAL; 1706e43ccb0aSPaul Kocialkowski 1707e43ccb0aSPaul Kocialkowski for (i = 0; i < ARRAY_SIZE(ov5648_link_freq_menu); i++) { 1708e43ccb0aSPaul Kocialkowski s64 freq = ov5648_link_freq_menu[i]; 1709e43ccb0aSPaul Kocialkowski 1710e43ccb0aSPaul Kocialkowski if (freq == mipi_clk_rate) 1711e43ccb0aSPaul Kocialkowski break; 1712e43ccb0aSPaul Kocialkowski } 1713e43ccb0aSPaul Kocialkowski 1714e43ccb0aSPaul Kocialkowski for (j = 0; j < sensor->endpoint.nr_of_link_frequencies; j++) { 1715e43ccb0aSPaul Kocialkowski u64 freq = sensor->endpoint.link_frequencies[j]; 1716e43ccb0aSPaul Kocialkowski 1717e43ccb0aSPaul Kocialkowski if (freq == mipi_clk_rate) 1718e43ccb0aSPaul Kocialkowski break; 1719e43ccb0aSPaul Kocialkowski } 1720e43ccb0aSPaul Kocialkowski 1721e43ccb0aSPaul Kocialkowski if (i == ARRAY_SIZE(ov5648_link_freq_menu)) { 1722e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1723e43ccb0aSPaul Kocialkowski "failed to find %lu clk rate in link freq\n", 1724e43ccb0aSPaul Kocialkowski mipi_clk_rate); 1725e43ccb0aSPaul Kocialkowski } else if (j == sensor->endpoint.nr_of_link_frequencies) { 1726e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1727e43ccb0aSPaul Kocialkowski "failed to find %lu clk rate in endpoint link-frequencies\n", 1728e43ccb0aSPaul Kocialkowski mipi_clk_rate); 1729e43ccb0aSPaul Kocialkowski } else { 1730e43ccb0aSPaul Kocialkowski __v4l2_ctrl_s_ctrl(ctrls->link_freq, i); 1731e43ccb0aSPaul Kocialkowski } 1732e43ccb0aSPaul Kocialkowski 1733e43ccb0aSPaul Kocialkowski switch (mbus_code) { 1734e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR8_1X8: 1735e43ccb0aSPaul Kocialkowski bits_per_sample = 8; 1736e43ccb0aSPaul Kocialkowski break; 1737e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR10_1X10: 1738e43ccb0aSPaul Kocialkowski bits_per_sample = 10; 1739e43ccb0aSPaul Kocialkowski break; 1740e43ccb0aSPaul Kocialkowski default: 1741e43ccb0aSPaul Kocialkowski return -EINVAL; 1742e43ccb0aSPaul Kocialkowski } 1743e43ccb0aSPaul Kocialkowski 1744e43ccb0aSPaul Kocialkowski lanes_count = bus_mipi_csi2->num_data_lanes; 1745e43ccb0aSPaul Kocialkowski mipi_pixel_rate = mipi_clk_rate * 2 * lanes_count / bits_per_sample; 1746e43ccb0aSPaul Kocialkowski 1747e43ccb0aSPaul Kocialkowski __v4l2_ctrl_s_ctrl_int64(ctrls->pixel_rate, mipi_pixel_rate); 1748e43ccb0aSPaul Kocialkowski 1749e43ccb0aSPaul Kocialkowski return 0; 1750e43ccb0aSPaul Kocialkowski } 1751e43ccb0aSPaul Kocialkowski 1752e43ccb0aSPaul Kocialkowski static int ov5648_state_configure(struct ov5648_sensor *sensor, 1753e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode, 1754e43ccb0aSPaul Kocialkowski u32 mbus_code) 1755e43ccb0aSPaul Kocialkowski { 1756e43ccb0aSPaul Kocialkowski int ret; 1757e43ccb0aSPaul Kocialkowski 1758e43ccb0aSPaul Kocialkowski if (sensor->state.streaming) 1759e43ccb0aSPaul Kocialkowski return -EBUSY; 1760e43ccb0aSPaul Kocialkowski 1761e43ccb0aSPaul Kocialkowski /* State will be configured at first power on otherwise. */ 1762e43ccb0aSPaul Kocialkowski if (pm_runtime_enabled(sensor->dev) && 1763e43ccb0aSPaul Kocialkowski !pm_runtime_suspended(sensor->dev)) { 1764e43ccb0aSPaul Kocialkowski ret = ov5648_mode_configure(sensor, mode, mbus_code); 1765e43ccb0aSPaul Kocialkowski if (ret) 1766e43ccb0aSPaul Kocialkowski return ret; 1767e43ccb0aSPaul Kocialkowski } 1768e43ccb0aSPaul Kocialkowski 1769e43ccb0aSPaul Kocialkowski ret = ov5648_state_mipi_configure(sensor, mode, mbus_code); 1770e43ccb0aSPaul Kocialkowski if (ret) 1771e43ccb0aSPaul Kocialkowski return ret; 1772e43ccb0aSPaul Kocialkowski 1773e43ccb0aSPaul Kocialkowski sensor->state.mode = mode; 1774e43ccb0aSPaul Kocialkowski sensor->state.mbus_code = mbus_code; 1775e43ccb0aSPaul Kocialkowski 1776e43ccb0aSPaul Kocialkowski return 0; 1777e43ccb0aSPaul Kocialkowski } 1778e43ccb0aSPaul Kocialkowski 1779e43ccb0aSPaul Kocialkowski static int ov5648_state_init(struct ov5648_sensor *sensor) 1780e43ccb0aSPaul Kocialkowski { 1781e43ccb0aSPaul Kocialkowski return ov5648_state_configure(sensor, &ov5648_modes[0], 1782e43ccb0aSPaul Kocialkowski ov5648_mbus_codes[0]); 1783e43ccb0aSPaul Kocialkowski } 1784e43ccb0aSPaul Kocialkowski 1785e43ccb0aSPaul Kocialkowski /* Sensor Base */ 1786e43ccb0aSPaul Kocialkowski 1787e43ccb0aSPaul Kocialkowski static int ov5648_sensor_init(struct ov5648_sensor *sensor) 1788e43ccb0aSPaul Kocialkowski { 1789e43ccb0aSPaul Kocialkowski int ret; 1790e43ccb0aSPaul Kocialkowski 1791e43ccb0aSPaul Kocialkowski ret = ov5648_sw_reset(sensor); 1792e43ccb0aSPaul Kocialkowski if (ret) { 1793e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to perform sw reset\n"); 1794e43ccb0aSPaul Kocialkowski return ret; 1795e43ccb0aSPaul Kocialkowski } 1796e43ccb0aSPaul Kocialkowski 1797e43ccb0aSPaul Kocialkowski ret = ov5648_sw_standby(sensor, 1); 1798e43ccb0aSPaul Kocialkowski if (ret) { 1799e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to set sensor standby\n"); 1800e43ccb0aSPaul Kocialkowski return ret; 1801e43ccb0aSPaul Kocialkowski } 1802e43ccb0aSPaul Kocialkowski 1803e43ccb0aSPaul Kocialkowski ret = ov5648_chip_id_check(sensor); 1804e43ccb0aSPaul Kocialkowski if (ret) { 1805e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to check sensor chip id\n"); 1806e43ccb0aSPaul Kocialkowski return ret; 1807e43ccb0aSPaul Kocialkowski } 1808e43ccb0aSPaul Kocialkowski 1809e43ccb0aSPaul Kocialkowski ret = ov5648_avdd_internal_power(sensor, !sensor->avdd); 1810e43ccb0aSPaul Kocialkowski if (ret) { 1811e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to set internal avdd power\n"); 1812e43ccb0aSPaul Kocialkowski return ret; 1813e43ccb0aSPaul Kocialkowski } 1814e43ccb0aSPaul Kocialkowski 1815e43ccb0aSPaul Kocialkowski ret = ov5648_write_sequence(sensor, ov5648_init_sequence, 1816e43ccb0aSPaul Kocialkowski ARRAY_SIZE(ov5648_init_sequence)); 1817e43ccb0aSPaul Kocialkowski if (ret) { 1818e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to write init sequence\n"); 1819e43ccb0aSPaul Kocialkowski return ret; 1820e43ccb0aSPaul Kocialkowski } 1821e43ccb0aSPaul Kocialkowski 1822e43ccb0aSPaul Kocialkowski ret = ov5648_pad_configure(sensor); 1823e43ccb0aSPaul Kocialkowski if (ret) { 1824e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to configure pad\n"); 1825e43ccb0aSPaul Kocialkowski return ret; 1826e43ccb0aSPaul Kocialkowski } 1827e43ccb0aSPaul Kocialkowski 1828e43ccb0aSPaul Kocialkowski ret = ov5648_mipi_configure(sensor); 1829e43ccb0aSPaul Kocialkowski if (ret) { 1830e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to configure MIPI\n"); 1831e43ccb0aSPaul Kocialkowski return ret; 1832e43ccb0aSPaul Kocialkowski } 1833e43ccb0aSPaul Kocialkowski 1834e43ccb0aSPaul Kocialkowski ret = ov5648_isp_configure(sensor); 1835e43ccb0aSPaul Kocialkowski if (ret) { 1836e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to configure ISP\n"); 1837e43ccb0aSPaul Kocialkowski return ret; 1838e43ccb0aSPaul Kocialkowski } 1839e43ccb0aSPaul Kocialkowski 1840e43ccb0aSPaul Kocialkowski ret = ov5648_black_level_configure(sensor); 1841e43ccb0aSPaul Kocialkowski if (ret) { 1842e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to configure black level\n"); 1843e43ccb0aSPaul Kocialkowski return ret; 1844e43ccb0aSPaul Kocialkowski } 1845e43ccb0aSPaul Kocialkowski 1846e43ccb0aSPaul Kocialkowski /* Configure current mode. */ 1847e43ccb0aSPaul Kocialkowski ret = ov5648_state_configure(sensor, sensor->state.mode, 1848e43ccb0aSPaul Kocialkowski sensor->state.mbus_code); 1849e43ccb0aSPaul Kocialkowski if (ret) { 1850e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to configure state\n"); 1851e43ccb0aSPaul Kocialkowski return ret; 1852e43ccb0aSPaul Kocialkowski } 1853e43ccb0aSPaul Kocialkowski 1854e43ccb0aSPaul Kocialkowski return 0; 1855e43ccb0aSPaul Kocialkowski } 1856e43ccb0aSPaul Kocialkowski 1857e43ccb0aSPaul Kocialkowski static int ov5648_sensor_power(struct ov5648_sensor *sensor, bool on) 1858e43ccb0aSPaul Kocialkowski { 1859e43ccb0aSPaul Kocialkowski /* Keep initialized to zero for disable label. */ 1860e43ccb0aSPaul Kocialkowski int ret = 0; 1861e43ccb0aSPaul Kocialkowski 1862e43ccb0aSPaul Kocialkowski /* 1863e43ccb0aSPaul Kocialkowski * General notes about the power sequence: 1864e43ccb0aSPaul Kocialkowski * - power-down GPIO must be active (low) during power-on; 1865e43ccb0aSPaul Kocialkowski * - reset GPIO state does not matter during power-on; 1866e43ccb0aSPaul Kocialkowski * - XVCLK must be provided 1 ms before register access; 1867e43ccb0aSPaul Kocialkowski * - 10 ms are needed between power-down deassert and register access. 1868e43ccb0aSPaul Kocialkowski */ 1869e43ccb0aSPaul Kocialkowski 1870e43ccb0aSPaul Kocialkowski /* Note that regulator-and-GPIO-based power is untested. */ 1871e43ccb0aSPaul Kocialkowski if (on) { 1872e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->reset, 1); 1873e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->powerdown, 1); 1874e43ccb0aSPaul Kocialkowski 1875e43ccb0aSPaul Kocialkowski ret = regulator_enable(sensor->dovdd); 1876e43ccb0aSPaul Kocialkowski if (ret) { 1877e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1878e43ccb0aSPaul Kocialkowski "failed to enable DOVDD regulator\n"); 1879e43ccb0aSPaul Kocialkowski goto disable; 1880e43ccb0aSPaul Kocialkowski } 1881e43ccb0aSPaul Kocialkowski 1882e43ccb0aSPaul Kocialkowski if (sensor->avdd) { 1883e43ccb0aSPaul Kocialkowski ret = regulator_enable(sensor->avdd); 1884e43ccb0aSPaul Kocialkowski if (ret) { 1885e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1886e43ccb0aSPaul Kocialkowski "failed to enable AVDD regulator\n"); 1887e43ccb0aSPaul Kocialkowski goto disable; 1888e43ccb0aSPaul Kocialkowski } 1889e43ccb0aSPaul Kocialkowski } 1890e43ccb0aSPaul Kocialkowski 1891e43ccb0aSPaul Kocialkowski ret = regulator_enable(sensor->dvdd); 1892e43ccb0aSPaul Kocialkowski if (ret) { 1893e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, 1894e43ccb0aSPaul Kocialkowski "failed to enable DVDD regulator\n"); 1895e43ccb0aSPaul Kocialkowski goto disable; 1896e43ccb0aSPaul Kocialkowski } 1897e43ccb0aSPaul Kocialkowski 1898e43ccb0aSPaul Kocialkowski /* According to OV5648 power up diagram. */ 1899e43ccb0aSPaul Kocialkowski usleep_range(5000, 10000); 1900e43ccb0aSPaul Kocialkowski 1901e43ccb0aSPaul Kocialkowski ret = clk_prepare_enable(sensor->xvclk); 1902e43ccb0aSPaul Kocialkowski if (ret) { 1903e43ccb0aSPaul Kocialkowski dev_err(sensor->dev, "failed to enable XVCLK clock\n"); 1904e43ccb0aSPaul Kocialkowski goto disable; 1905e43ccb0aSPaul Kocialkowski } 1906e43ccb0aSPaul Kocialkowski 1907e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->reset, 0); 1908e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->powerdown, 0); 1909e43ccb0aSPaul Kocialkowski 1910e43ccb0aSPaul Kocialkowski usleep_range(20000, 25000); 1911e43ccb0aSPaul Kocialkowski } else { 1912e43ccb0aSPaul Kocialkowski disable: 1913e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->powerdown, 1); 1914e43ccb0aSPaul Kocialkowski gpiod_set_value_cansleep(sensor->reset, 1); 1915e43ccb0aSPaul Kocialkowski 1916e43ccb0aSPaul Kocialkowski clk_disable_unprepare(sensor->xvclk); 1917e43ccb0aSPaul Kocialkowski 1918e43ccb0aSPaul Kocialkowski regulator_disable(sensor->dvdd); 1919e43ccb0aSPaul Kocialkowski 1920e43ccb0aSPaul Kocialkowski if (sensor->avdd) 1921e43ccb0aSPaul Kocialkowski regulator_disable(sensor->avdd); 1922e43ccb0aSPaul Kocialkowski 1923e43ccb0aSPaul Kocialkowski regulator_disable(sensor->dovdd); 1924e43ccb0aSPaul Kocialkowski } 1925e43ccb0aSPaul Kocialkowski 1926e43ccb0aSPaul Kocialkowski return ret; 1927e43ccb0aSPaul Kocialkowski } 1928e43ccb0aSPaul Kocialkowski 1929e43ccb0aSPaul Kocialkowski /* Controls */ 1930e43ccb0aSPaul Kocialkowski 1931e43ccb0aSPaul Kocialkowski static int ov5648_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 1932e43ccb0aSPaul Kocialkowski { 1933e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev = ov5648_ctrl_subdev(ctrl); 1934e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 1935e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1936e43ccb0aSPaul Kocialkowski int ret; 1937e43ccb0aSPaul Kocialkowski 1938e43ccb0aSPaul Kocialkowski switch (ctrl->id) { 1939e43ccb0aSPaul Kocialkowski case V4L2_CID_EXPOSURE_AUTO: 1940e43ccb0aSPaul Kocialkowski ret = ov5648_exposure_value(sensor, &ctrls->exposure->val); 1941e43ccb0aSPaul Kocialkowski if (ret) 1942e43ccb0aSPaul Kocialkowski return ret; 1943e43ccb0aSPaul Kocialkowski break; 1944e43ccb0aSPaul Kocialkowski case V4L2_CID_AUTOGAIN: 1945e43ccb0aSPaul Kocialkowski ret = ov5648_gain_value(sensor, &ctrls->gain->val); 1946e43ccb0aSPaul Kocialkowski if (ret) 1947e43ccb0aSPaul Kocialkowski return ret; 1948e43ccb0aSPaul Kocialkowski break; 1949e43ccb0aSPaul Kocialkowski default: 1950e43ccb0aSPaul Kocialkowski return -EINVAL; 1951e43ccb0aSPaul Kocialkowski } 1952e43ccb0aSPaul Kocialkowski 1953e43ccb0aSPaul Kocialkowski return 0; 1954e43ccb0aSPaul Kocialkowski } 1955e43ccb0aSPaul Kocialkowski 1956e43ccb0aSPaul Kocialkowski static int ov5648_s_ctrl(struct v4l2_ctrl *ctrl) 1957e43ccb0aSPaul Kocialkowski { 1958e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev = ov5648_ctrl_subdev(ctrl); 1959e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 1960e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 1961e43ccb0aSPaul Kocialkowski unsigned int index; 1962e43ccb0aSPaul Kocialkowski bool enable; 1963e43ccb0aSPaul Kocialkowski int ret; 1964e43ccb0aSPaul Kocialkowski 1965e43ccb0aSPaul Kocialkowski /* Wait for the sensor to be on before setting controls. */ 1966e43ccb0aSPaul Kocialkowski if (pm_runtime_suspended(sensor->dev)) 1967e43ccb0aSPaul Kocialkowski return 0; 1968e43ccb0aSPaul Kocialkowski 1969e43ccb0aSPaul Kocialkowski switch (ctrl->id) { 1970e43ccb0aSPaul Kocialkowski case V4L2_CID_EXPOSURE_AUTO: 1971e43ccb0aSPaul Kocialkowski enable = ctrl->val == V4L2_EXPOSURE_AUTO; 1972e43ccb0aSPaul Kocialkowski 1973e43ccb0aSPaul Kocialkowski ret = ov5648_exposure_auto_configure(sensor, enable); 1974e43ccb0aSPaul Kocialkowski if (ret) 1975e43ccb0aSPaul Kocialkowski return ret; 1976e43ccb0aSPaul Kocialkowski 1977e43ccb0aSPaul Kocialkowski if (!enable && ctrls->exposure->is_new) { 1978e43ccb0aSPaul Kocialkowski ret = ov5648_exposure_configure(sensor, 1979e43ccb0aSPaul Kocialkowski ctrls->exposure->val); 1980e43ccb0aSPaul Kocialkowski if (ret) 1981e43ccb0aSPaul Kocialkowski return ret; 1982e43ccb0aSPaul Kocialkowski } 1983e43ccb0aSPaul Kocialkowski break; 1984e43ccb0aSPaul Kocialkowski case V4L2_CID_AUTOGAIN: 1985e43ccb0aSPaul Kocialkowski enable = !!ctrl->val; 1986e43ccb0aSPaul Kocialkowski 1987e43ccb0aSPaul Kocialkowski ret = ov5648_gain_auto_configure(sensor, enable); 1988e43ccb0aSPaul Kocialkowski if (ret) 1989e43ccb0aSPaul Kocialkowski return ret; 1990e43ccb0aSPaul Kocialkowski 1991e43ccb0aSPaul Kocialkowski if (!enable) { 1992e43ccb0aSPaul Kocialkowski ret = ov5648_gain_configure(sensor, ctrls->gain->val); 1993e43ccb0aSPaul Kocialkowski if (ret) 1994e43ccb0aSPaul Kocialkowski return ret; 1995e43ccb0aSPaul Kocialkowski } 1996e43ccb0aSPaul Kocialkowski break; 1997e43ccb0aSPaul Kocialkowski case V4L2_CID_AUTO_WHITE_BALANCE: 1998e43ccb0aSPaul Kocialkowski enable = !!ctrl->val; 1999e43ccb0aSPaul Kocialkowski 2000e43ccb0aSPaul Kocialkowski ret = ov5648_white_balance_auto_configure(sensor, enable); 2001e43ccb0aSPaul Kocialkowski if (ret) 2002e43ccb0aSPaul Kocialkowski return ret; 2003e43ccb0aSPaul Kocialkowski 2004e43ccb0aSPaul Kocialkowski if (!enable) { 2005e43ccb0aSPaul Kocialkowski ret = ov5648_white_balance_configure(sensor, 2006e43ccb0aSPaul Kocialkowski ctrls->red_balance->val, 2007e43ccb0aSPaul Kocialkowski ctrls->blue_balance->val); 2008e43ccb0aSPaul Kocialkowski if (ret) 2009e43ccb0aSPaul Kocialkowski return ret; 2010e43ccb0aSPaul Kocialkowski } 2011e43ccb0aSPaul Kocialkowski break; 2012e43ccb0aSPaul Kocialkowski case V4L2_CID_HFLIP: 2013e43ccb0aSPaul Kocialkowski enable = !!ctrl->val; 2014e43ccb0aSPaul Kocialkowski return ov5648_flip_horz_configure(sensor, enable); 2015e43ccb0aSPaul Kocialkowski case V4L2_CID_VFLIP: 2016e43ccb0aSPaul Kocialkowski enable = !!ctrl->val; 2017e43ccb0aSPaul Kocialkowski return ov5648_flip_vert_configure(sensor, enable); 2018e43ccb0aSPaul Kocialkowski case V4L2_CID_TEST_PATTERN: 2019e43ccb0aSPaul Kocialkowski index = (unsigned int)ctrl->val; 2020e43ccb0aSPaul Kocialkowski return ov5648_test_pattern_configure(sensor, index); 2021e43ccb0aSPaul Kocialkowski default: 2022e43ccb0aSPaul Kocialkowski return -EINVAL; 2023e43ccb0aSPaul Kocialkowski } 2024e43ccb0aSPaul Kocialkowski 2025e43ccb0aSPaul Kocialkowski return 0; 2026e43ccb0aSPaul Kocialkowski } 2027e43ccb0aSPaul Kocialkowski 2028e43ccb0aSPaul Kocialkowski static const struct v4l2_ctrl_ops ov5648_ctrl_ops = { 2029e43ccb0aSPaul Kocialkowski .g_volatile_ctrl = ov5648_g_volatile_ctrl, 2030e43ccb0aSPaul Kocialkowski .s_ctrl = ov5648_s_ctrl, 2031e43ccb0aSPaul Kocialkowski }; 2032e43ccb0aSPaul Kocialkowski 2033e43ccb0aSPaul Kocialkowski static int ov5648_ctrls_init(struct ov5648_sensor *sensor) 2034e43ccb0aSPaul Kocialkowski { 2035e43ccb0aSPaul Kocialkowski struct ov5648_ctrls *ctrls = &sensor->ctrls; 2036e43ccb0aSPaul Kocialkowski struct v4l2_ctrl_handler *handler = &ctrls->handler; 2037e43ccb0aSPaul Kocialkowski const struct v4l2_ctrl_ops *ops = &ov5648_ctrl_ops; 2038e43ccb0aSPaul Kocialkowski int ret; 2039e43ccb0aSPaul Kocialkowski 2040e43ccb0aSPaul Kocialkowski v4l2_ctrl_handler_init(handler, 32); 2041e43ccb0aSPaul Kocialkowski 2042e43ccb0aSPaul Kocialkowski /* Use our mutex for ctrl locking. */ 2043e43ccb0aSPaul Kocialkowski handler->lock = &sensor->mutex; 2044e43ccb0aSPaul Kocialkowski 2045e43ccb0aSPaul Kocialkowski /* Exposure */ 2046e43ccb0aSPaul Kocialkowski 2047e43ccb0aSPaul Kocialkowski ctrls->exposure_auto = v4l2_ctrl_new_std_menu(handler, ops, 2048e43ccb0aSPaul Kocialkowski V4L2_CID_EXPOSURE_AUTO, 2049e43ccb0aSPaul Kocialkowski V4L2_EXPOSURE_MANUAL, 0, 2050e43ccb0aSPaul Kocialkowski V4L2_EXPOSURE_AUTO); 2051e43ccb0aSPaul Kocialkowski 2052e43ccb0aSPaul Kocialkowski ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 2053e43ccb0aSPaul Kocialkowski 16, 1048575, 16, 512); 2054e43ccb0aSPaul Kocialkowski 2055e43ccb0aSPaul Kocialkowski v4l2_ctrl_auto_cluster(2, &ctrls->exposure_auto, 1, true); 2056e43ccb0aSPaul Kocialkowski 2057e43ccb0aSPaul Kocialkowski /* Gain */ 2058e43ccb0aSPaul Kocialkowski 2059e43ccb0aSPaul Kocialkowski ctrls->gain_auto = 2060e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std(handler, ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 2061e43ccb0aSPaul Kocialkowski 2062e43ccb0aSPaul Kocialkowski ctrls->gain = v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 16, 1023, 2063e43ccb0aSPaul Kocialkowski 16, 16); 2064e43ccb0aSPaul Kocialkowski 2065e43ccb0aSPaul Kocialkowski v4l2_ctrl_auto_cluster(2, &ctrls->gain_auto, 0, true); 2066e43ccb0aSPaul Kocialkowski 2067e43ccb0aSPaul Kocialkowski /* White Balance */ 2068e43ccb0aSPaul Kocialkowski 2069e43ccb0aSPaul Kocialkowski ctrls->white_balance_auto = 2070e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std(handler, ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 2071e43ccb0aSPaul Kocialkowski 1, 1, 1); 2072e43ccb0aSPaul Kocialkowski 2073e43ccb0aSPaul Kocialkowski ctrls->red_balance = v4l2_ctrl_new_std(handler, ops, 2074e43ccb0aSPaul Kocialkowski V4L2_CID_RED_BALANCE, 0, 4095, 2075e43ccb0aSPaul Kocialkowski 1, 1024); 2076e43ccb0aSPaul Kocialkowski 2077e43ccb0aSPaul Kocialkowski ctrls->blue_balance = v4l2_ctrl_new_std(handler, ops, 2078e43ccb0aSPaul Kocialkowski V4L2_CID_BLUE_BALANCE, 0, 4095, 2079e43ccb0aSPaul Kocialkowski 1, 1024); 2080e43ccb0aSPaul Kocialkowski 2081e43ccb0aSPaul Kocialkowski v4l2_ctrl_auto_cluster(3, &ctrls->white_balance_auto, 0, false); 2082e43ccb0aSPaul Kocialkowski 2083e43ccb0aSPaul Kocialkowski /* Flip */ 2084e43ccb0aSPaul Kocialkowski 2085e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std(handler, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); 2086e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std(handler, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); 2087e43ccb0aSPaul Kocialkowski 2088e43ccb0aSPaul Kocialkowski /* Test Pattern */ 2089e43ccb0aSPaul Kocialkowski 2090e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std_menu_items(handler, ops, V4L2_CID_TEST_PATTERN, 2091e43ccb0aSPaul Kocialkowski ARRAY_SIZE(ov5648_test_pattern_menu) - 1, 2092e43ccb0aSPaul Kocialkowski 0, 0, ov5648_test_pattern_menu); 2093e43ccb0aSPaul Kocialkowski 2094e43ccb0aSPaul Kocialkowski /* MIPI CSI-2 */ 2095e43ccb0aSPaul Kocialkowski 2096e43ccb0aSPaul Kocialkowski ctrls->link_freq = 2097e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, 2098e43ccb0aSPaul Kocialkowski ARRAY_SIZE(ov5648_link_freq_menu) - 1, 2099e43ccb0aSPaul Kocialkowski 0, ov5648_link_freq_menu); 2100e43ccb0aSPaul Kocialkowski 2101e43ccb0aSPaul Kocialkowski ctrls->pixel_rate = 2102e43ccb0aSPaul Kocialkowski v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1, 2103e43ccb0aSPaul Kocialkowski INT_MAX, 1, 1); 2104e43ccb0aSPaul Kocialkowski 2105e43ccb0aSPaul Kocialkowski if (handler->error) { 2106e43ccb0aSPaul Kocialkowski ret = handler->error; 2107e43ccb0aSPaul Kocialkowski goto error_ctrls; 2108e43ccb0aSPaul Kocialkowski } 2109e43ccb0aSPaul Kocialkowski 2110e43ccb0aSPaul Kocialkowski ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; 2111e43ccb0aSPaul Kocialkowski ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE; 2112e43ccb0aSPaul Kocialkowski 2113e43ccb0aSPaul Kocialkowski ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; 2114e43ccb0aSPaul Kocialkowski ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; 2115e43ccb0aSPaul Kocialkowski 2116e43ccb0aSPaul Kocialkowski sensor->subdev.ctrl_handler = handler; 2117e43ccb0aSPaul Kocialkowski 2118e43ccb0aSPaul Kocialkowski return 0; 2119e43ccb0aSPaul Kocialkowski 2120e43ccb0aSPaul Kocialkowski error_ctrls: 2121e43ccb0aSPaul Kocialkowski v4l2_ctrl_handler_free(handler); 2122e43ccb0aSPaul Kocialkowski 2123e43ccb0aSPaul Kocialkowski return ret; 2124e43ccb0aSPaul Kocialkowski } 2125e43ccb0aSPaul Kocialkowski 2126e43ccb0aSPaul Kocialkowski /* Subdev Video Operations */ 2127e43ccb0aSPaul Kocialkowski 2128e43ccb0aSPaul Kocialkowski static int ov5648_s_stream(struct v4l2_subdev *subdev, int enable) 2129e43ccb0aSPaul Kocialkowski { 2130e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2131e43ccb0aSPaul Kocialkowski struct ov5648_state *state = &sensor->state; 2132e43ccb0aSPaul Kocialkowski int ret; 2133e43ccb0aSPaul Kocialkowski 2134e43ccb0aSPaul Kocialkowski if (enable) { 2135e43ccb0aSPaul Kocialkowski ret = pm_runtime_get_sync(sensor->dev); 2136e43ccb0aSPaul Kocialkowski if (ret < 0) { 2137e43ccb0aSPaul Kocialkowski pm_runtime_put_noidle(sensor->dev); 2138e43ccb0aSPaul Kocialkowski return ret; 2139e43ccb0aSPaul Kocialkowski } 2140e43ccb0aSPaul Kocialkowski } 2141e43ccb0aSPaul Kocialkowski 2142e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2143e43ccb0aSPaul Kocialkowski ret = ov5648_sw_standby(sensor, !enable); 2144e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2145e43ccb0aSPaul Kocialkowski 2146e43ccb0aSPaul Kocialkowski if (ret) 2147e43ccb0aSPaul Kocialkowski return ret; 2148e43ccb0aSPaul Kocialkowski 2149e43ccb0aSPaul Kocialkowski state->streaming = !!enable; 2150e43ccb0aSPaul Kocialkowski 2151e43ccb0aSPaul Kocialkowski if (!enable) 2152e43ccb0aSPaul Kocialkowski pm_runtime_put(sensor->dev); 2153e43ccb0aSPaul Kocialkowski 2154e43ccb0aSPaul Kocialkowski return 0; 2155e43ccb0aSPaul Kocialkowski } 2156e43ccb0aSPaul Kocialkowski 2157e43ccb0aSPaul Kocialkowski static int ov5648_g_frame_interval(struct v4l2_subdev *subdev, 2158e43ccb0aSPaul Kocialkowski struct v4l2_subdev_frame_interval *interval) 2159e43ccb0aSPaul Kocialkowski { 2160e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2161e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode; 2162e43ccb0aSPaul Kocialkowski int ret = 0; 2163e43ccb0aSPaul Kocialkowski 2164e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2165e43ccb0aSPaul Kocialkowski 2166e43ccb0aSPaul Kocialkowski mode = sensor->state.mode; 2167e43ccb0aSPaul Kocialkowski 2168e43ccb0aSPaul Kocialkowski switch (sensor->state.mbus_code) { 2169e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR8_1X8: 2170e43ccb0aSPaul Kocialkowski interval->interval = mode->frame_interval[0]; 2171e43ccb0aSPaul Kocialkowski break; 2172e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR10_1X10: 2173e43ccb0aSPaul Kocialkowski interval->interval = mode->frame_interval[1]; 2174e43ccb0aSPaul Kocialkowski break; 2175e43ccb0aSPaul Kocialkowski default: 2176e43ccb0aSPaul Kocialkowski ret = -EINVAL; 2177e43ccb0aSPaul Kocialkowski } 2178e43ccb0aSPaul Kocialkowski 2179e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2180e43ccb0aSPaul Kocialkowski 2181e43ccb0aSPaul Kocialkowski return ret; 2182e43ccb0aSPaul Kocialkowski } 2183e43ccb0aSPaul Kocialkowski 2184e43ccb0aSPaul Kocialkowski static const struct v4l2_subdev_video_ops ov5648_subdev_video_ops = { 2185e43ccb0aSPaul Kocialkowski .s_stream = ov5648_s_stream, 2186e43ccb0aSPaul Kocialkowski .g_frame_interval = ov5648_g_frame_interval, 2187e43ccb0aSPaul Kocialkowski .s_frame_interval = ov5648_g_frame_interval, 2188e43ccb0aSPaul Kocialkowski }; 2189e43ccb0aSPaul Kocialkowski 2190e43ccb0aSPaul Kocialkowski /* Subdev Pad Operations */ 2191e43ccb0aSPaul Kocialkowski 2192e43ccb0aSPaul Kocialkowski static int ov5648_enum_mbus_code(struct v4l2_subdev *subdev, 2193e43ccb0aSPaul Kocialkowski struct v4l2_subdev_pad_config *config, 2194e43ccb0aSPaul Kocialkowski struct v4l2_subdev_mbus_code_enum *code_enum) 2195e43ccb0aSPaul Kocialkowski { 2196e43ccb0aSPaul Kocialkowski if (code_enum->index >= ARRAY_SIZE(ov5648_mbus_codes)) 2197e43ccb0aSPaul Kocialkowski return -EINVAL; 2198e43ccb0aSPaul Kocialkowski 2199e43ccb0aSPaul Kocialkowski code_enum->code = ov5648_mbus_codes[code_enum->index]; 2200e43ccb0aSPaul Kocialkowski 2201e43ccb0aSPaul Kocialkowski return 0; 2202e43ccb0aSPaul Kocialkowski } 2203e43ccb0aSPaul Kocialkowski 2204e43ccb0aSPaul Kocialkowski static void ov5648_mbus_format_fill(struct v4l2_mbus_framefmt *mbus_format, 2205e43ccb0aSPaul Kocialkowski u32 mbus_code, 2206e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode) 2207e43ccb0aSPaul Kocialkowski { 2208e43ccb0aSPaul Kocialkowski mbus_format->width = mode->output_size_x; 2209e43ccb0aSPaul Kocialkowski mbus_format->height = mode->output_size_y; 2210e43ccb0aSPaul Kocialkowski mbus_format->code = mbus_code; 2211e43ccb0aSPaul Kocialkowski 2212e43ccb0aSPaul Kocialkowski mbus_format->field = V4L2_FIELD_NONE; 2213e43ccb0aSPaul Kocialkowski mbus_format->colorspace = V4L2_COLORSPACE_RAW; 2214e43ccb0aSPaul Kocialkowski mbus_format->ycbcr_enc = 2215e43ccb0aSPaul Kocialkowski V4L2_MAP_YCBCR_ENC_DEFAULT(mbus_format->colorspace); 2216e43ccb0aSPaul Kocialkowski mbus_format->quantization = V4L2_QUANTIZATION_FULL_RANGE; 2217e43ccb0aSPaul Kocialkowski mbus_format->xfer_func = 2218e43ccb0aSPaul Kocialkowski V4L2_MAP_XFER_FUNC_DEFAULT(mbus_format->colorspace); 2219e43ccb0aSPaul Kocialkowski } 2220e43ccb0aSPaul Kocialkowski 2221e43ccb0aSPaul Kocialkowski static int ov5648_get_fmt(struct v4l2_subdev *subdev, 2222e43ccb0aSPaul Kocialkowski struct v4l2_subdev_pad_config *config, 2223e43ccb0aSPaul Kocialkowski struct v4l2_subdev_format *format) 2224e43ccb0aSPaul Kocialkowski { 2225e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2226e43ccb0aSPaul Kocialkowski struct v4l2_mbus_framefmt *mbus_format = &format->format; 2227e43ccb0aSPaul Kocialkowski 2228e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2229e43ccb0aSPaul Kocialkowski 2230e43ccb0aSPaul Kocialkowski if (format->which == V4L2_SUBDEV_FORMAT_TRY) 2231e43ccb0aSPaul Kocialkowski *mbus_format = *v4l2_subdev_get_try_format(subdev, config, 2232e43ccb0aSPaul Kocialkowski format->pad); 2233e43ccb0aSPaul Kocialkowski else 2234e43ccb0aSPaul Kocialkowski ov5648_mbus_format_fill(mbus_format, sensor->state.mbus_code, 2235e43ccb0aSPaul Kocialkowski sensor->state.mode); 2236e43ccb0aSPaul Kocialkowski 2237e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2238e43ccb0aSPaul Kocialkowski 2239e43ccb0aSPaul Kocialkowski return 0; 2240e43ccb0aSPaul Kocialkowski } 2241e43ccb0aSPaul Kocialkowski 2242e43ccb0aSPaul Kocialkowski static int ov5648_set_fmt(struct v4l2_subdev *subdev, 2243e43ccb0aSPaul Kocialkowski struct v4l2_subdev_pad_config *config, 2244e43ccb0aSPaul Kocialkowski struct v4l2_subdev_format *format) 2245e43ccb0aSPaul Kocialkowski { 2246e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2247e43ccb0aSPaul Kocialkowski struct v4l2_mbus_framefmt *mbus_format = &format->format; 2248e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode; 2249e43ccb0aSPaul Kocialkowski u32 mbus_code = 0; 2250e43ccb0aSPaul Kocialkowski unsigned int index; 2251e43ccb0aSPaul Kocialkowski int ret = 0; 2252e43ccb0aSPaul Kocialkowski 2253e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2254e43ccb0aSPaul Kocialkowski 2255e43ccb0aSPaul Kocialkowski if (sensor->state.streaming) { 2256e43ccb0aSPaul Kocialkowski ret = -EBUSY; 2257e43ccb0aSPaul Kocialkowski goto complete; 2258e43ccb0aSPaul Kocialkowski } 2259e43ccb0aSPaul Kocialkowski 2260e43ccb0aSPaul Kocialkowski /* Try to find requested mbus code. */ 2261e43ccb0aSPaul Kocialkowski for (index = 0; index < ARRAY_SIZE(ov5648_mbus_codes); index++) { 2262e43ccb0aSPaul Kocialkowski if (ov5648_mbus_codes[index] == mbus_format->code) { 2263e43ccb0aSPaul Kocialkowski mbus_code = mbus_format->code; 2264e43ccb0aSPaul Kocialkowski break; 2265e43ccb0aSPaul Kocialkowski } 2266e43ccb0aSPaul Kocialkowski } 2267e43ccb0aSPaul Kocialkowski 2268e43ccb0aSPaul Kocialkowski /* Fallback to default. */ 2269e43ccb0aSPaul Kocialkowski if (!mbus_code) 2270e43ccb0aSPaul Kocialkowski mbus_code = ov5648_mbus_codes[0]; 2271e43ccb0aSPaul Kocialkowski 2272e43ccb0aSPaul Kocialkowski /* Find the mode with nearest dimensions. */ 2273e43ccb0aSPaul Kocialkowski mode = v4l2_find_nearest_size(ov5648_modes, ARRAY_SIZE(ov5648_modes), 2274e43ccb0aSPaul Kocialkowski output_size_x, output_size_y, 2275e43ccb0aSPaul Kocialkowski mbus_format->width, mbus_format->height); 2276e43ccb0aSPaul Kocialkowski if (!mode) { 2277e43ccb0aSPaul Kocialkowski ret = -EINVAL; 2278e43ccb0aSPaul Kocialkowski goto complete; 2279e43ccb0aSPaul Kocialkowski } 2280e43ccb0aSPaul Kocialkowski 2281e43ccb0aSPaul Kocialkowski ov5648_mbus_format_fill(mbus_format, mbus_code, mode); 2282e43ccb0aSPaul Kocialkowski 2283e43ccb0aSPaul Kocialkowski if (format->which == V4L2_SUBDEV_FORMAT_TRY) 2284e43ccb0aSPaul Kocialkowski *v4l2_subdev_get_try_format(subdev, config, format->pad) = 2285e43ccb0aSPaul Kocialkowski *mbus_format; 2286e43ccb0aSPaul Kocialkowski else if (sensor->state.mode != mode || 2287e43ccb0aSPaul Kocialkowski sensor->state.mbus_code != mbus_code) 2288e43ccb0aSPaul Kocialkowski ret = ov5648_state_configure(sensor, mode, mbus_code); 2289e43ccb0aSPaul Kocialkowski 2290e43ccb0aSPaul Kocialkowski complete: 2291e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2292e43ccb0aSPaul Kocialkowski 2293e43ccb0aSPaul Kocialkowski return ret; 2294e43ccb0aSPaul Kocialkowski } 2295e43ccb0aSPaul Kocialkowski 2296e43ccb0aSPaul Kocialkowski static int ov5648_enum_frame_size(struct v4l2_subdev *subdev, 2297e43ccb0aSPaul Kocialkowski struct v4l2_subdev_pad_config *config, 2298e43ccb0aSPaul Kocialkowski struct v4l2_subdev_frame_size_enum *size_enum) 2299e43ccb0aSPaul Kocialkowski { 2300e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode; 2301e43ccb0aSPaul Kocialkowski 2302e43ccb0aSPaul Kocialkowski if (size_enum->index >= ARRAY_SIZE(ov5648_modes)) 2303e43ccb0aSPaul Kocialkowski return -EINVAL; 2304e43ccb0aSPaul Kocialkowski 2305e43ccb0aSPaul Kocialkowski mode = &ov5648_modes[size_enum->index]; 2306e43ccb0aSPaul Kocialkowski 2307e43ccb0aSPaul Kocialkowski size_enum->min_width = size_enum->max_width = mode->output_size_x; 2308e43ccb0aSPaul Kocialkowski size_enum->min_height = size_enum->max_height = mode->output_size_y; 2309e43ccb0aSPaul Kocialkowski 2310e43ccb0aSPaul Kocialkowski return 0; 2311e43ccb0aSPaul Kocialkowski } 2312e43ccb0aSPaul Kocialkowski 2313e43ccb0aSPaul Kocialkowski static int ov5648_enum_frame_interval(struct v4l2_subdev *subdev, 2314e43ccb0aSPaul Kocialkowski struct v4l2_subdev_pad_config *config, 2315e43ccb0aSPaul Kocialkowski struct v4l2_subdev_frame_interval_enum *interval_enum) 2316e43ccb0aSPaul Kocialkowski { 2317e43ccb0aSPaul Kocialkowski const struct ov5648_mode *mode = NULL; 2318e43ccb0aSPaul Kocialkowski unsigned int mode_index; 2319e43ccb0aSPaul Kocialkowski unsigned int interval_index; 2320e43ccb0aSPaul Kocialkowski 2321e43ccb0aSPaul Kocialkowski if (interval_enum->index > 0) 2322e43ccb0aSPaul Kocialkowski return -EINVAL; 2323e43ccb0aSPaul Kocialkowski 2324e43ccb0aSPaul Kocialkowski /* 2325e43ccb0aSPaul Kocialkowski * Multiple modes with the same dimensions may have different frame 2326e43ccb0aSPaul Kocialkowski * intervals, so look up each relevant mode. 2327e43ccb0aSPaul Kocialkowski */ 2328e43ccb0aSPaul Kocialkowski for (mode_index = 0, interval_index = 0; 2329e43ccb0aSPaul Kocialkowski mode_index < ARRAY_SIZE(ov5648_modes); mode_index++) { 2330e43ccb0aSPaul Kocialkowski mode = &ov5648_modes[mode_index]; 2331e43ccb0aSPaul Kocialkowski 2332e43ccb0aSPaul Kocialkowski if (mode->output_size_x == interval_enum->width && 2333e43ccb0aSPaul Kocialkowski mode->output_size_y == interval_enum->height) { 2334e43ccb0aSPaul Kocialkowski if (interval_index == interval_enum->index) 2335e43ccb0aSPaul Kocialkowski break; 2336e43ccb0aSPaul Kocialkowski 2337e43ccb0aSPaul Kocialkowski interval_index++; 2338e43ccb0aSPaul Kocialkowski } 2339e43ccb0aSPaul Kocialkowski } 2340e43ccb0aSPaul Kocialkowski 2341e43ccb0aSPaul Kocialkowski if (mode_index == ARRAY_SIZE(ov5648_modes) || !mode) 2342e43ccb0aSPaul Kocialkowski return -EINVAL; 2343e43ccb0aSPaul Kocialkowski 2344e43ccb0aSPaul Kocialkowski switch (interval_enum->code) { 2345e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR8_1X8: 2346e43ccb0aSPaul Kocialkowski interval_enum->interval = mode->frame_interval[0]; 2347e43ccb0aSPaul Kocialkowski break; 2348e43ccb0aSPaul Kocialkowski case MEDIA_BUS_FMT_SBGGR10_1X10: 2349e43ccb0aSPaul Kocialkowski interval_enum->interval = mode->frame_interval[1]; 2350e43ccb0aSPaul Kocialkowski break; 2351e43ccb0aSPaul Kocialkowski default: 2352e43ccb0aSPaul Kocialkowski return -EINVAL; 2353e43ccb0aSPaul Kocialkowski } 2354e43ccb0aSPaul Kocialkowski 2355e43ccb0aSPaul Kocialkowski return 0; 2356e43ccb0aSPaul Kocialkowski } 2357e43ccb0aSPaul Kocialkowski 2358e43ccb0aSPaul Kocialkowski static const struct v4l2_subdev_pad_ops ov5648_subdev_pad_ops = { 2359e43ccb0aSPaul Kocialkowski .enum_mbus_code = ov5648_enum_mbus_code, 2360e43ccb0aSPaul Kocialkowski .get_fmt = ov5648_get_fmt, 2361e43ccb0aSPaul Kocialkowski .set_fmt = ov5648_set_fmt, 2362e43ccb0aSPaul Kocialkowski .enum_frame_size = ov5648_enum_frame_size, 2363e43ccb0aSPaul Kocialkowski .enum_frame_interval = ov5648_enum_frame_interval, 2364e43ccb0aSPaul Kocialkowski }; 2365e43ccb0aSPaul Kocialkowski 2366e43ccb0aSPaul Kocialkowski static const struct v4l2_subdev_ops ov5648_subdev_ops = { 2367e43ccb0aSPaul Kocialkowski .video = &ov5648_subdev_video_ops, 2368e43ccb0aSPaul Kocialkowski .pad = &ov5648_subdev_pad_ops, 2369e43ccb0aSPaul Kocialkowski }; 2370e43ccb0aSPaul Kocialkowski 2371e43ccb0aSPaul Kocialkowski static int ov5648_suspend(struct device *dev) 2372e43ccb0aSPaul Kocialkowski { 2373e43ccb0aSPaul Kocialkowski struct i2c_client *client = to_i2c_client(dev); 2374e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev = i2c_get_clientdata(client); 2375e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2376e43ccb0aSPaul Kocialkowski struct ov5648_state *state = &sensor->state; 2377e43ccb0aSPaul Kocialkowski int ret = 0; 2378e43ccb0aSPaul Kocialkowski 2379e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2380e43ccb0aSPaul Kocialkowski 2381e43ccb0aSPaul Kocialkowski if (state->streaming) { 2382e43ccb0aSPaul Kocialkowski ret = ov5648_sw_standby(sensor, true); 2383e43ccb0aSPaul Kocialkowski if (ret) 2384e43ccb0aSPaul Kocialkowski goto complete; 2385e43ccb0aSPaul Kocialkowski } 2386e43ccb0aSPaul Kocialkowski 2387e43ccb0aSPaul Kocialkowski ret = ov5648_sensor_power(sensor, false); 2388e43ccb0aSPaul Kocialkowski if (ret) 2389e43ccb0aSPaul Kocialkowski ov5648_sw_standby(sensor, false); 2390e43ccb0aSPaul Kocialkowski 2391e43ccb0aSPaul Kocialkowski complete: 2392e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2393e43ccb0aSPaul Kocialkowski 2394e43ccb0aSPaul Kocialkowski return ret; 2395e43ccb0aSPaul Kocialkowski } 2396e43ccb0aSPaul Kocialkowski 2397e43ccb0aSPaul Kocialkowski static int ov5648_resume(struct device *dev) 2398e43ccb0aSPaul Kocialkowski { 2399e43ccb0aSPaul Kocialkowski struct i2c_client *client = to_i2c_client(dev); 2400e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev = i2c_get_clientdata(client); 2401e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2402e43ccb0aSPaul Kocialkowski struct ov5648_state *state = &sensor->state; 2403e43ccb0aSPaul Kocialkowski int ret = 0; 2404e43ccb0aSPaul Kocialkowski 2405e43ccb0aSPaul Kocialkowski mutex_lock(&sensor->mutex); 2406e43ccb0aSPaul Kocialkowski 2407e43ccb0aSPaul Kocialkowski ret = ov5648_sensor_power(sensor, true); 2408e43ccb0aSPaul Kocialkowski if (ret) 2409e43ccb0aSPaul Kocialkowski goto complete; 2410e43ccb0aSPaul Kocialkowski 2411e43ccb0aSPaul Kocialkowski ret = ov5648_sensor_init(sensor); 2412e43ccb0aSPaul Kocialkowski if (ret) 2413e43ccb0aSPaul Kocialkowski goto error_power; 2414e43ccb0aSPaul Kocialkowski 2415e43ccb0aSPaul Kocialkowski ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); 2416e43ccb0aSPaul Kocialkowski if (ret) 2417e43ccb0aSPaul Kocialkowski goto error_power; 2418e43ccb0aSPaul Kocialkowski 2419e43ccb0aSPaul Kocialkowski if (state->streaming) { 2420e43ccb0aSPaul Kocialkowski ret = ov5648_sw_standby(sensor, false); 2421e43ccb0aSPaul Kocialkowski if (ret) 2422e43ccb0aSPaul Kocialkowski goto error_power; 2423e43ccb0aSPaul Kocialkowski } 2424e43ccb0aSPaul Kocialkowski 2425e43ccb0aSPaul Kocialkowski goto complete; 2426e43ccb0aSPaul Kocialkowski 2427e43ccb0aSPaul Kocialkowski error_power: 2428e43ccb0aSPaul Kocialkowski ov5648_sensor_power(sensor, false); 2429e43ccb0aSPaul Kocialkowski 2430e43ccb0aSPaul Kocialkowski complete: 2431e43ccb0aSPaul Kocialkowski mutex_unlock(&sensor->mutex); 2432e43ccb0aSPaul Kocialkowski 2433e43ccb0aSPaul Kocialkowski return ret; 2434e43ccb0aSPaul Kocialkowski } 2435e43ccb0aSPaul Kocialkowski 2436e43ccb0aSPaul Kocialkowski static int ov5648_probe(struct i2c_client *client) 2437e43ccb0aSPaul Kocialkowski { 2438e43ccb0aSPaul Kocialkowski struct device *dev = &client->dev; 2439e43ccb0aSPaul Kocialkowski struct fwnode_handle *handle; 2440e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor; 2441e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev; 2442e43ccb0aSPaul Kocialkowski struct media_pad *pad; 2443e43ccb0aSPaul Kocialkowski unsigned long rate; 2444e43ccb0aSPaul Kocialkowski int ret; 2445e43ccb0aSPaul Kocialkowski 2446e43ccb0aSPaul Kocialkowski sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); 2447e43ccb0aSPaul Kocialkowski if (!sensor) 2448e43ccb0aSPaul Kocialkowski return -ENOMEM; 2449e43ccb0aSPaul Kocialkowski 2450e43ccb0aSPaul Kocialkowski sensor->dev = dev; 2451e43ccb0aSPaul Kocialkowski sensor->i2c_client = client; 2452e43ccb0aSPaul Kocialkowski 2453e43ccb0aSPaul Kocialkowski /* Graph Endpoint */ 2454e43ccb0aSPaul Kocialkowski 2455e43ccb0aSPaul Kocialkowski handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); 2456e43ccb0aSPaul Kocialkowski if (!handle) { 2457*ea12d248SColin Ian King dev_err(dev, "unable to find endpoint node\n"); 2458e43ccb0aSPaul Kocialkowski return -EINVAL; 2459e43ccb0aSPaul Kocialkowski } 2460e43ccb0aSPaul Kocialkowski 2461e43ccb0aSPaul Kocialkowski sensor->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY; 2462e43ccb0aSPaul Kocialkowski 2463e43ccb0aSPaul Kocialkowski ret = v4l2_fwnode_endpoint_alloc_parse(handle, &sensor->endpoint); 2464e43ccb0aSPaul Kocialkowski fwnode_handle_put(handle); 2465e43ccb0aSPaul Kocialkowski if (ret) { 2466e43ccb0aSPaul Kocialkowski dev_err(dev, "failed to parse endpoint node\n"); 2467e43ccb0aSPaul Kocialkowski return ret; 2468e43ccb0aSPaul Kocialkowski } 2469e43ccb0aSPaul Kocialkowski 2470e43ccb0aSPaul Kocialkowski /* GPIOs */ 2471e43ccb0aSPaul Kocialkowski 2472e43ccb0aSPaul Kocialkowski sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", 2473e43ccb0aSPaul Kocialkowski GPIOD_OUT_HIGH); 2474e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->powerdown)) { 2475e43ccb0aSPaul Kocialkowski ret = PTR_ERR(sensor->powerdown); 2476e43ccb0aSPaul Kocialkowski goto error_endpoint; 2477e43ccb0aSPaul Kocialkowski } 2478e43ccb0aSPaul Kocialkowski 2479e43ccb0aSPaul Kocialkowski sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 2480e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->reset)) { 2481e43ccb0aSPaul Kocialkowski ret = PTR_ERR(sensor->reset); 2482e43ccb0aSPaul Kocialkowski goto error_endpoint; 2483e43ccb0aSPaul Kocialkowski } 2484e43ccb0aSPaul Kocialkowski 2485e43ccb0aSPaul Kocialkowski /* Regulators */ 2486e43ccb0aSPaul Kocialkowski 2487e43ccb0aSPaul Kocialkowski /* DVDD: digital core */ 2488e43ccb0aSPaul Kocialkowski sensor->dvdd = devm_regulator_get(dev, "dvdd"); 2489e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->dvdd)) { 2490e43ccb0aSPaul Kocialkowski dev_err(dev, "cannot get DVDD (digital core) regulator\n"); 2491e43ccb0aSPaul Kocialkowski ret = PTR_ERR(sensor->dvdd); 2492e43ccb0aSPaul Kocialkowski goto error_endpoint; 2493e43ccb0aSPaul Kocialkowski } 2494e43ccb0aSPaul Kocialkowski 2495e43ccb0aSPaul Kocialkowski /* DOVDD: digital I/O */ 2496e43ccb0aSPaul Kocialkowski sensor->dovdd = devm_regulator_get(dev, "dovdd"); 2497e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->dvdd)) { 2498e43ccb0aSPaul Kocialkowski dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n"); 2499e43ccb0aSPaul Kocialkowski ret = PTR_ERR(sensor->dvdd); 2500e43ccb0aSPaul Kocialkowski goto error_endpoint; 2501e43ccb0aSPaul Kocialkowski } 2502e43ccb0aSPaul Kocialkowski 2503e43ccb0aSPaul Kocialkowski /* AVDD: analog */ 2504e43ccb0aSPaul Kocialkowski sensor->avdd = devm_regulator_get_optional(dev, "avdd"); 2505e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->avdd)) { 2506e43ccb0aSPaul Kocialkowski dev_info(dev, "no AVDD regulator provided, using internal\n"); 2507e43ccb0aSPaul Kocialkowski sensor->avdd = NULL; 2508e43ccb0aSPaul Kocialkowski } 2509e43ccb0aSPaul Kocialkowski 2510e43ccb0aSPaul Kocialkowski /* External Clock */ 2511e43ccb0aSPaul Kocialkowski 2512e43ccb0aSPaul Kocialkowski sensor->xvclk = devm_clk_get(dev, NULL); 2513e43ccb0aSPaul Kocialkowski if (IS_ERR(sensor->xvclk)) { 2514e43ccb0aSPaul Kocialkowski dev_err(dev, "failed to get external clock\n"); 2515e43ccb0aSPaul Kocialkowski ret = PTR_ERR(sensor->xvclk); 2516e43ccb0aSPaul Kocialkowski goto error_endpoint; 2517e43ccb0aSPaul Kocialkowski } 2518e43ccb0aSPaul Kocialkowski 2519e43ccb0aSPaul Kocialkowski rate = clk_get_rate(sensor->xvclk); 2520e43ccb0aSPaul Kocialkowski if (rate != OV5648_XVCLK_RATE) { 2521e43ccb0aSPaul Kocialkowski dev_err(dev, "clock rate %lu Hz is unsupported\n", rate); 2522e43ccb0aSPaul Kocialkowski ret = -EINVAL; 2523e43ccb0aSPaul Kocialkowski goto error_endpoint; 2524e43ccb0aSPaul Kocialkowski } 2525e43ccb0aSPaul Kocialkowski 2526e43ccb0aSPaul Kocialkowski /* Subdev, entity and pad */ 2527e43ccb0aSPaul Kocialkowski 2528e43ccb0aSPaul Kocialkowski subdev = &sensor->subdev; 2529e43ccb0aSPaul Kocialkowski v4l2_i2c_subdev_init(subdev, client, &ov5648_subdev_ops); 2530e43ccb0aSPaul Kocialkowski 2531e43ccb0aSPaul Kocialkowski subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 2532e43ccb0aSPaul Kocialkowski subdev->entity.function = MEDIA_ENT_F_CAM_SENSOR; 2533e43ccb0aSPaul Kocialkowski 2534e43ccb0aSPaul Kocialkowski pad = &sensor->pad; 2535e43ccb0aSPaul Kocialkowski pad->flags = MEDIA_PAD_FL_SOURCE; 2536e43ccb0aSPaul Kocialkowski 2537e43ccb0aSPaul Kocialkowski ret = media_entity_pads_init(&subdev->entity, 1, pad); 2538e43ccb0aSPaul Kocialkowski if (ret) 2539e43ccb0aSPaul Kocialkowski goto error_entity; 2540e43ccb0aSPaul Kocialkowski 2541e43ccb0aSPaul Kocialkowski /* Mutex */ 2542e43ccb0aSPaul Kocialkowski 2543e43ccb0aSPaul Kocialkowski mutex_init(&sensor->mutex); 2544e43ccb0aSPaul Kocialkowski 2545e43ccb0aSPaul Kocialkowski /* Sensor */ 2546e43ccb0aSPaul Kocialkowski 2547e43ccb0aSPaul Kocialkowski ret = ov5648_ctrls_init(sensor); 2548e43ccb0aSPaul Kocialkowski if (ret) 2549e43ccb0aSPaul Kocialkowski goto error_mutex; 2550e43ccb0aSPaul Kocialkowski 2551e43ccb0aSPaul Kocialkowski ret = ov5648_state_init(sensor); 2552e43ccb0aSPaul Kocialkowski if (ret) 2553e43ccb0aSPaul Kocialkowski goto error_ctrls; 2554e43ccb0aSPaul Kocialkowski 2555e43ccb0aSPaul Kocialkowski /* Runtime PM */ 2556e43ccb0aSPaul Kocialkowski 2557e43ccb0aSPaul Kocialkowski pm_runtime_enable(sensor->dev); 2558e43ccb0aSPaul Kocialkowski pm_runtime_set_suspended(sensor->dev); 2559e43ccb0aSPaul Kocialkowski 2560e43ccb0aSPaul Kocialkowski /* V4L2 subdev register */ 2561e43ccb0aSPaul Kocialkowski 2562e43ccb0aSPaul Kocialkowski ret = v4l2_async_register_subdev_sensor_common(subdev); 2563e43ccb0aSPaul Kocialkowski if (ret) 2564e43ccb0aSPaul Kocialkowski goto error_pm; 2565e43ccb0aSPaul Kocialkowski 2566e43ccb0aSPaul Kocialkowski return 0; 2567e43ccb0aSPaul Kocialkowski 2568e43ccb0aSPaul Kocialkowski error_pm: 2569e43ccb0aSPaul Kocialkowski pm_runtime_disable(sensor->dev); 2570e43ccb0aSPaul Kocialkowski 2571e43ccb0aSPaul Kocialkowski error_ctrls: 2572e43ccb0aSPaul Kocialkowski v4l2_ctrl_handler_free(&sensor->ctrls.handler); 2573e43ccb0aSPaul Kocialkowski 2574e43ccb0aSPaul Kocialkowski error_mutex: 2575e43ccb0aSPaul Kocialkowski mutex_destroy(&sensor->mutex); 2576e43ccb0aSPaul Kocialkowski 2577e43ccb0aSPaul Kocialkowski error_entity: 2578e43ccb0aSPaul Kocialkowski media_entity_cleanup(&sensor->subdev.entity); 2579e43ccb0aSPaul Kocialkowski 2580e43ccb0aSPaul Kocialkowski error_endpoint: 2581e43ccb0aSPaul Kocialkowski v4l2_fwnode_endpoint_free(&sensor->endpoint); 2582e43ccb0aSPaul Kocialkowski 2583e43ccb0aSPaul Kocialkowski return ret; 2584e43ccb0aSPaul Kocialkowski } 2585e43ccb0aSPaul Kocialkowski 2586e43ccb0aSPaul Kocialkowski static int ov5648_remove(struct i2c_client *client) 2587e43ccb0aSPaul Kocialkowski { 2588e43ccb0aSPaul Kocialkowski struct v4l2_subdev *subdev = i2c_get_clientdata(client); 2589e43ccb0aSPaul Kocialkowski struct ov5648_sensor *sensor = ov5648_subdev_sensor(subdev); 2590e43ccb0aSPaul Kocialkowski 2591e43ccb0aSPaul Kocialkowski v4l2_async_unregister_subdev(subdev); 2592e43ccb0aSPaul Kocialkowski pm_runtime_disable(sensor->dev); 2593e43ccb0aSPaul Kocialkowski v4l2_ctrl_handler_free(&sensor->ctrls.handler); 2594e43ccb0aSPaul Kocialkowski mutex_destroy(&sensor->mutex); 2595e43ccb0aSPaul Kocialkowski media_entity_cleanup(&subdev->entity); 2596e43ccb0aSPaul Kocialkowski 2597e43ccb0aSPaul Kocialkowski return 0; 2598e43ccb0aSPaul Kocialkowski } 2599e43ccb0aSPaul Kocialkowski 2600e43ccb0aSPaul Kocialkowski static const struct dev_pm_ops ov5648_pm_ops = { 2601e43ccb0aSPaul Kocialkowski SET_RUNTIME_PM_OPS(ov5648_suspend, ov5648_resume, NULL) 2602e43ccb0aSPaul Kocialkowski }; 2603e43ccb0aSPaul Kocialkowski 2604e43ccb0aSPaul Kocialkowski static const struct of_device_id ov5648_of_match[] = { 2605e43ccb0aSPaul Kocialkowski { .compatible = "ovti,ov5648" }, 2606e43ccb0aSPaul Kocialkowski { } 2607e43ccb0aSPaul Kocialkowski }; 2608e43ccb0aSPaul Kocialkowski MODULE_DEVICE_TABLE(of, ov5648_of_match); 2609e43ccb0aSPaul Kocialkowski 2610e43ccb0aSPaul Kocialkowski static struct i2c_driver ov5648_driver = { 2611e43ccb0aSPaul Kocialkowski .driver = { 2612e43ccb0aSPaul Kocialkowski .name = "ov5648", 2613e43ccb0aSPaul Kocialkowski .of_match_table = ov5648_of_match, 2614e43ccb0aSPaul Kocialkowski .pm = &ov5648_pm_ops, 2615e43ccb0aSPaul Kocialkowski }, 2616e43ccb0aSPaul Kocialkowski .probe_new = ov5648_probe, 2617e43ccb0aSPaul Kocialkowski .remove = ov5648_remove, 2618e43ccb0aSPaul Kocialkowski }; 2619e43ccb0aSPaul Kocialkowski 2620e43ccb0aSPaul Kocialkowski module_i2c_driver(ov5648_driver); 2621e43ccb0aSPaul Kocialkowski 2622e43ccb0aSPaul Kocialkowski MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>"); 2623e43ccb0aSPaul Kocialkowski MODULE_DESCRIPTION("V4L2 driver for the OmniVision OV5648 image sensor"); 2624e43ccb0aSPaul Kocialkowski MODULE_LICENSE("GPL v2"); 2625