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