xref: /openbmc/linux/drivers/media/i2c/ov5648.c (revision e43ccb0a)
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