xref: /OK3568_Linux_fs/kernel/drivers/phy/rockchip/phy-rockchip-mipi-rx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Rockchip MIPI RX Synopsys/Innosilicon DPHY driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This software is available to you under a choice of one of two
7*4882a593Smuzhiyun  * licenses.  You may choose to be licensed under the terms of the GNU
8*4882a593Smuzhiyun  * General Public License (GPL) Version 2, available from the file
9*4882a593Smuzhiyun  * COPYING in the main directory of this source tree, or the
10*4882a593Smuzhiyun  * OpenIB.org BSD license below:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *     Redistribution and use in source and binary forms, with or
13*4882a593Smuzhiyun  *     without modification, are permitted provided that the following
14*4882a593Smuzhiyun  *     conditions are met:
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  *      - Redistributions of source code must retain the above
17*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
18*4882a593Smuzhiyun  *        disclaimer.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  *      - Redistributions in binary form must reproduce the above
21*4882a593Smuzhiyun  *        copyright notice, this list of conditions and the following
22*4882a593Smuzhiyun  *        disclaimer in the documentation and/or other materials
23*4882a593Smuzhiyun  *        provided with the distribution.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*4882a593Smuzhiyun  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*4882a593Smuzhiyun  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*4882a593Smuzhiyun  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*4882a593Smuzhiyun  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*4882a593Smuzhiyun  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*4882a593Smuzhiyun  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*4882a593Smuzhiyun  * SOFTWARE.
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/clk.h>
36*4882a593Smuzhiyun #include <linux/delay.h>
37*4882a593Smuzhiyun #include <linux/io.h>
38*4882a593Smuzhiyun #include <linux/module.h>
39*4882a593Smuzhiyun #include <linux/of.h>
40*4882a593Smuzhiyun #include <linux/of_graph.h>
41*4882a593Smuzhiyun #include <linux/of_platform.h>
42*4882a593Smuzhiyun #include <linux/platform_device.h>
43*4882a593Smuzhiyun #include <linux/pm_runtime.h>
44*4882a593Smuzhiyun #include <linux/regmap.h>
45*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
46*4882a593Smuzhiyun #include <media/media-entity.h>
47*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
48*4882a593Smuzhiyun #include <media/v4l2-fwnode.h>
49*4882a593Smuzhiyun #include <media/v4l2-subdev.h>
50*4882a593Smuzhiyun #include <media/v4l2-device.h>
51*4882a593Smuzhiyun #include <linux/rockchip/cpu.h>
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /* GRF */
54*4882a593Smuzhiyun #define RK1808_GRF_PD_VI_CON_OFFSET	0x0430
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON6	0x025c
57*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON8	0x0264
58*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON9	0x0268
59*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON10	0x026c
60*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON14	0x027c
61*4882a593Smuzhiyun #define RK3288_GRF_SOC_STATUS21	0x02d4
62*4882a593Smuzhiyun #define RK3288_GRF_IO_VSEL	0x0380
63*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON15	0x03a4
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define RK3326_GRF_IO_VSEL_OFFSET	0x0180
66*4882a593Smuzhiyun #define RK3326_GRF_PD_VI_CON_OFFSET	0x0430
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #define RK3368_GRF_SOC_CON6_OFFSET	0x0418
69*4882a593Smuzhiyun #define RK3368_GRF_IO_VSEL_OFFSET	0x0900
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON9	0x6224
72*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON21	0x6254
73*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON22	0x6258
74*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON23	0x625c
75*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON24	0x6260
76*4882a593Smuzhiyun #define RK3399_GRF_SOC_CON25	0x6264
77*4882a593Smuzhiyun #define RK3399_GRF_SOC_STATUS1	0xe2a4
78*4882a593Smuzhiyun #define RK3399_GRF_IO_VSEL	0x0900
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define RV1126_GRF_CSIPHY0_CON		0x10200
81*4882a593Smuzhiyun #define RV1126_GRF_CSIPHY1_CON		0x10210
82*4882a593Smuzhiyun #define RV1126_GRF_IOFUNC_CON3		0x1026c
83*4882a593Smuzhiyun #define RV1126_GRF_PHY1_SEL_CIFLITE	BIT(2)
84*4882a593Smuzhiyun #define RV1126_GRF_PHY1_SEL_ISP		BIT(1)
85*4882a593Smuzhiyun #define RV1126_GRF_PHY1_SEL_CIF		BIT(0)
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /* PHY */
88*4882a593Smuzhiyun #define RK3288_PHY_TEST_CTRL0	0x30
89*4882a593Smuzhiyun #define RK3288_PHY_TEST_CTRL1	0x34
90*4882a593Smuzhiyun #define RK3288_PHY_SHUTDOWNZ	0x08
91*4882a593Smuzhiyun #define RK3288_PHY_RSTZ		0x0c
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun #define RK3399_PHY_TEST_CTRL0	0xb4
94*4882a593Smuzhiyun #define RK3399_PHY_TEST_CTRL1	0xb8
95*4882a593Smuzhiyun #define RK3399_PHY_SHUTDOWNZ	0xa0
96*4882a593Smuzhiyun #define RK3399_PHY_RSTZ		0xa0
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun #define CLOCK_LANE_HS_RX_CONTROL		0x34
99*4882a593Smuzhiyun #define LANE0_HS_RX_CONTROL			0x44
100*4882a593Smuzhiyun #define LANE1_HS_RX_CONTROL			0x54
101*4882a593Smuzhiyun #define LANE2_HS_RX_CONTROL			0x84
102*4882a593Smuzhiyun #define LANE3_HS_RX_CONTROL			0x94
103*4882a593Smuzhiyun #define HS_RX_DATA_LANES_THS_SETTLE_CONTROL	0x75
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun /* LOW POWER MODE SET */
106*4882a593Smuzhiyun #define MIPI_CSI_DPHY_CTRL_INVALID_OFFSET	0xFFFF
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun #define RK1808_CSI_DPHY_CTRL_LANE_ENABLE	0x00
109*4882a593Smuzhiyun #define RK1808_CSI_DPHY_CTRL_PWRCTL	\
110*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
111*4882a593Smuzhiyun #define RK1808_CSI_DPHY_CTRL_DIG_RST		0x80
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define RK3326_CSI_DPHY_CTRL_LANE_ENABLE	0x00
114*4882a593Smuzhiyun #define RK3326_CSI_DPHY_CTRL_PWRCTL		0x04
115*4882a593Smuzhiyun #define RK3326_CSI_DPHY_CTRL_DIG_RST		0x80
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun #define RK3368_CSI_DPHY_CTRL_LANE_ENABLE	0x00
118*4882a593Smuzhiyun #define RK3368_CSI_DPHY_CTRL_PWRCTL		0x04
119*4882a593Smuzhiyun #define RK3368_CSI_DPHY_CTRL_DIG_RST		0x80
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun #define RV1126_CSI_DPHY_CTRL_LANE_ENABLE	0x00
122*4882a593Smuzhiyun #define RV1126_CSI_DPHY_CTRL_PWRCTL	\
123*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
124*4882a593Smuzhiyun #define RV1126_CSI_DPHY_CTRL_DIG_RST		0x80
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun #define MIPI_CSI_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT	2
127*4882a593Smuzhiyun #define MIPI_CSI_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT	6
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun /* Configure the count time of the THS-SETTLE by protocol. */
130*4882a593Smuzhiyun #define RK1808_CSI_DPHY_CLK_WR_THS_SETTLE	0x160
131*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE0_WR_THS_SETTLE	\
132*4882a593Smuzhiyun 		(RK1808_CSI_DPHY_CLK_WR_THS_SETTLE + 0x80)
133*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE1_WR_THS_SETTLE	\
134*4882a593Smuzhiyun 		(RK1808_CSI_DPHY_LANE0_WR_THS_SETTLE + 0x80)
135*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE2_WR_THS_SETTLE	\
136*4882a593Smuzhiyun 		(RK1808_CSI_DPHY_LANE1_WR_THS_SETTLE + 0x80)
137*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE3_WR_THS_SETTLE	\
138*4882a593Smuzhiyun 		(RK1808_CSI_DPHY_LANE2_WR_THS_SETTLE + 0x80)
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun #define RK3326_CSI_DPHY_CLK_WR_THS_SETTLE	0x100
141*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE0_WR_THS_SETTLE	\
142*4882a593Smuzhiyun 		(RK3326_CSI_DPHY_CLK_WR_THS_SETTLE + 0x80)
143*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE1_WR_THS_SETTLE	\
144*4882a593Smuzhiyun 		(RK3326_CSI_DPHY_LANE0_WR_THS_SETTLE + 0x80)
145*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE2_WR_THS_SETTLE	\
146*4882a593Smuzhiyun 		(RK3326_CSI_DPHY_LANE1_WR_THS_SETTLE + 0x80)
147*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE3_WR_THS_SETTLE	\
148*4882a593Smuzhiyun 		(RK3326_CSI_DPHY_LANE2_WR_THS_SETTLE + 0x80)
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_CLK_WR_THS_SETTLE	0x160
151*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_LANE0_WR_THS_SETTLE	\
152*4882a593Smuzhiyun 		(RK3326S_CSI_DPHY_CLK_WR_THS_SETTLE + 0x80)
153*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_LANE1_WR_THS_SETTLE	\
154*4882a593Smuzhiyun 		(RK3326S_CSI_DPHY_LANE0_WR_THS_SETTLE + 0x80)
155*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_LANE2_WR_THS_SETTLE	\
156*4882a593Smuzhiyun 		(RK3326S_CSI_DPHY_LANE1_WR_THS_SETTLE + 0x80)
157*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_LANE3_WR_THS_SETTLE	\
158*4882a593Smuzhiyun 		(RK3326S_CSI_DPHY_LANE2_WR_THS_SETTLE + 0x80)
159*4882a593Smuzhiyun #define RK3326S_CSI_DPHY_CLK_MODE		0x128
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun #define RK3368_CSI_DPHY_CLK_WR_THS_SETTLE	0x100
162*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE0_WR_THS_SETTLE	\
163*4882a593Smuzhiyun 		(RK3368_CSI_DPHY_CLK_WR_THS_SETTLE + 0x80)
164*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE1_WR_THS_SETTLE	\
165*4882a593Smuzhiyun 		(RK3368_CSI_DPHY_LANE0_WR_THS_SETTLE + 0x80)
166*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE2_WR_THS_SETTLE	\
167*4882a593Smuzhiyun 		(RK3368_CSI_DPHY_LANE1_WR_THS_SETTLE + 0x80)
168*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE3_WR_THS_SETTLE	\
169*4882a593Smuzhiyun 		(RK3368_CSI_DPHY_LANE2_WR_THS_SETTLE + 0x80)
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun #define RV1126_CSI_DPHY_CLK_WR_THS_SETTLE	0x160
172*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE0_WR_THS_SETTLE	0x1e0
173*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE1_WR_THS_SETTLE	0x260
174*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE2_WR_THS_SETTLE	0x2e0
175*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE3_WR_THS_SETTLE	0x360
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun /* Calibration reception enable */
178*4882a593Smuzhiyun #define RK1808_CSI_DPHY_CLK_CALIB_EN		0x168
179*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE0_CALIB_EN		0x1e8
180*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE1_CALIB_EN		0x268
181*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE2_CALIB_EN		0x2e8
182*4882a593Smuzhiyun #define RK1808_CSI_DPHY_LANE3_CALIB_EN		0x368
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun #define RK3326_CSI_DPHY_CLK_CALIB_EN		\
185*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
186*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE0_CALIB_EN		\
187*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
188*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE1_CALIB_EN		\
189*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
190*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE2_CALIB_EN		\
191*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
192*4882a593Smuzhiyun #define RK3326_CSI_DPHY_LANE3_CALIB_EN		\
193*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun #define RK3368_CSI_DPHY_CLK_CALIB_EN		\
196*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
197*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE0_CALIB_EN		\
198*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
199*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE1_CALIB_EN		\
200*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
201*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE2_CALIB_EN		\
202*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
203*4882a593Smuzhiyun #define RK3368_CSI_DPHY_LANE3_CALIB_EN		\
204*4882a593Smuzhiyun 		MIPI_CSI_DPHY_CTRL_INVALID_OFFSET
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun #define RV1126_CSI_DPHY_CLK_CALIB_EN		0x168
207*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE0_CALIB_EN		0x1e8
208*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE1_CALIB_EN		0x268
209*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE2_CALIB_EN		0x2e8
210*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LANE3_CALIB_EN		0x368
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun #define RV1126_CSI_DPHY_MIPI_LVDS_MODEL		0x2cc
213*4882a593Smuzhiyun #define RV1126_CSI_DPHY_LVDS_MODE		0x300
214*4882a593Smuzhiyun /*
215*4882a593Smuzhiyun  * CSI HOST
216*4882a593Smuzhiyun  */
217*4882a593Smuzhiyun #define PHY_TESTEN_ADDR			(0x1 << 16)
218*4882a593Smuzhiyun #define PHY_TESTEN_DATA			(0x0 << 16)
219*4882a593Smuzhiyun #define PHY_TESTCLK			(0x1 << 1)
220*4882a593Smuzhiyun #define PHY_TESTCLR			(0x1 << 0)
221*4882a593Smuzhiyun #define THS_SETTLE_COUNTER_THRESHOLD	0x04
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun #define HIWORD_UPDATE(val, mask, shift) \
224*4882a593Smuzhiyun 	((val) << (shift) | (mask) << ((shift) + 16))
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun enum mipi_dphy_chip_id {
227*4882a593Smuzhiyun 	CHIP_ID_RK1808 = 0,
228*4882a593Smuzhiyun 	CHIP_ID_RK3288,
229*4882a593Smuzhiyun 	CHIP_ID_RK3326,
230*4882a593Smuzhiyun 	CHIP_ID_RK3368,
231*4882a593Smuzhiyun 	CHIP_ID_RK3399,
232*4882a593Smuzhiyun 	CHIP_ID_RK1126,
233*4882a593Smuzhiyun 	CHIP_ID_RK3326S,
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun enum mipi_dphy_rx_pads {
237*4882a593Smuzhiyun 	MIPI_DPHY_RX_PAD_SINK = 0,
238*4882a593Smuzhiyun 	MIPI_DPHY_RX_PAD_SOURCE,
239*4882a593Smuzhiyun 	MIPI_DPHY_RX_PADS_NUM,
240*4882a593Smuzhiyun };
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun enum dphy_reg_id {
243*4882a593Smuzhiyun 	GRF_DPHY_RX0_TURNDISABLE = 0,
244*4882a593Smuzhiyun 	GRF_DPHY_RX0_FORCERXMODE,
245*4882a593Smuzhiyun 	GRF_DPHY_RX0_FORCETXSTOPMODE,
246*4882a593Smuzhiyun 	GRF_DPHY_RX0_ENABLE,
247*4882a593Smuzhiyun 	GRF_DPHY_RX0_TESTCLR,
248*4882a593Smuzhiyun 	GRF_DPHY_RX0_TESTCLK,
249*4882a593Smuzhiyun 	GRF_DPHY_RX0_TESTEN,
250*4882a593Smuzhiyun 	GRF_DPHY_RX0_TESTDIN,
251*4882a593Smuzhiyun 	GRF_DPHY_RX0_TURNREQUEST,
252*4882a593Smuzhiyun 	GRF_DPHY_RX0_TESTDOUT,
253*4882a593Smuzhiyun 	GRF_DPHY_TX0_TURNDISABLE,
254*4882a593Smuzhiyun 	GRF_DPHY_TX0_FORCERXMODE,
255*4882a593Smuzhiyun 	GRF_DPHY_TX0_FORCETXSTOPMODE,
256*4882a593Smuzhiyun 	GRF_DPHY_TX0_TURNREQUEST,
257*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_TURNDISABLE,
258*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_FORCERXMODE,
259*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_FORCETXSTOPMODE,
260*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_ENABLE,
261*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_MASTERSLAVEZ,
262*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_BASEDIR,
263*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_ENABLECLK,
264*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_TURNREQUEST,
265*4882a593Smuzhiyun 	GRF_DPHY_RX1_SRC_SEL,
266*4882a593Smuzhiyun 	/* rk3288 only */
267*4882a593Smuzhiyun 	GRF_CON_DISABLE_ISP,
268*4882a593Smuzhiyun 	GRF_CON_ISP_DPHY_SEL,
269*4882a593Smuzhiyun 	GRF_DSI_CSI_TESTBUS_SEL,
270*4882a593Smuzhiyun 	GRF_DVP_V18SEL,
271*4882a593Smuzhiyun 	/* rk1808 & rk3326 & rv1126 */
272*4882a593Smuzhiyun 	GRF_DPHY_CSIPHY_FORCERXMODE,
273*4882a593Smuzhiyun 	GRF_DPHY_CSIPHY_CLKLANE_EN,
274*4882a593Smuzhiyun 	GRF_DPHY_CSIPHY_DATALANE_EN,
275*4882a593Smuzhiyun 	/* rv1126 only */
276*4882a593Smuzhiyun 	GRF_DPHY_CLK_INV_SEL,
277*4882a593Smuzhiyun 	GRF_DPHY_SEL,
278*4882a593Smuzhiyun 	/* rk3368 only */
279*4882a593Smuzhiyun 	GRF_ISP_MIPI_CSI_HOST_SEL,
280*4882a593Smuzhiyun 	/* below is for rk3399 only */
281*4882a593Smuzhiyun 	GRF_DPHY_RX0_CLK_INV_SEL,
282*4882a593Smuzhiyun 	GRF_DPHY_RX1_CLK_INV_SEL,
283*4882a593Smuzhiyun 	GRF_DPHY_TX1RX1_SRC_SEL,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun enum csiphy_reg_id {
287*4882a593Smuzhiyun 	CSIPHY_CTRL_LANE_ENABLE = 0,
288*4882a593Smuzhiyun 	CSIPHY_CTRL_PWRCTL,
289*4882a593Smuzhiyun 	CSIPHY_CTRL_DIG_RST,
290*4882a593Smuzhiyun 	CSIPHY_CLK_THS_SETTLE,
291*4882a593Smuzhiyun 	CSIPHY_LANE0_THS_SETTLE,
292*4882a593Smuzhiyun 	CSIPHY_LANE1_THS_SETTLE,
293*4882a593Smuzhiyun 	CSIPHY_LANE2_THS_SETTLE,
294*4882a593Smuzhiyun 	CSIPHY_LANE3_THS_SETTLE,
295*4882a593Smuzhiyun 	CSIPHY_CLK_CALIB_ENABLE,
296*4882a593Smuzhiyun 	CSIPHY_LANE0_CALIB_ENABLE,
297*4882a593Smuzhiyun 	CSIPHY_LANE1_CALIB_ENABLE,
298*4882a593Smuzhiyun 	CSIPHY_LANE2_CALIB_ENABLE,
299*4882a593Smuzhiyun 	CSIPHY_LANE3_CALIB_ENABLE,
300*4882a593Smuzhiyun 	//rv1126 only
301*4882a593Smuzhiyun 	CSIPHY_MIPI_LVDS_MODEL,
302*4882a593Smuzhiyun 	CSIPHY_LVDS_MODE,
303*4882a593Smuzhiyun 	CSIPHY_CLK_MODE,
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun enum mipi_dphy_ctl_type {
307*4882a593Smuzhiyun 	MIPI_DPHY_CTL_GRF_ONLY = 0,
308*4882a593Smuzhiyun 	MIPI_DPHY_CTL_CSI_HOST
309*4882a593Smuzhiyun };
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun enum mipi_dphy_lane {
312*4882a593Smuzhiyun 	MIPI_DPHY_LANE_CLOCK = 0,
313*4882a593Smuzhiyun 	MIPI_DPHY_LANE_DATA0,
314*4882a593Smuzhiyun 	MIPI_DPHY_LANE_DATA1,
315*4882a593Smuzhiyun 	MIPI_DPHY_LANE_DATA2,
316*4882a593Smuzhiyun 	MIPI_DPHY_LANE_DATA3
317*4882a593Smuzhiyun };
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun enum txrx_reg_id {
320*4882a593Smuzhiyun 	TXRX_PHY_TEST_CTRL0 = 0,
321*4882a593Smuzhiyun 	TXRX_PHY_TEST_CTRL1,
322*4882a593Smuzhiyun 	TXRX_PHY_SHUTDOWNZ,
323*4882a593Smuzhiyun 	TXRX_PHY_RSTZ,
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun struct dphy_reg {
327*4882a593Smuzhiyun 	u32 offset;
328*4882a593Smuzhiyun 	u32 mask;
329*4882a593Smuzhiyun 	u32 shift;
330*4882a593Smuzhiyun };
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun struct txrx_reg {
333*4882a593Smuzhiyun 	u32 offset;
334*4882a593Smuzhiyun };
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun struct csiphy_reg {
337*4882a593Smuzhiyun 	u32 offset;
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun #define PHY_REG(_offset, _width, _shift) \
341*4882a593Smuzhiyun 	{ .offset = _offset, .mask = BIT(_width) - 1, .shift = _shift, }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun #define TXRX_REG(_offset) \
344*4882a593Smuzhiyun 	{ .offset = _offset, }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun #define CSIPHY_REG(_offset) \
347*4882a593Smuzhiyun 	{ .offset = _offset, }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun static const struct dphy_reg rk1808_grf_dphy_regs[] = {
350*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 0),
351*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 1, 8),
352*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK1808_GRF_PD_VI_CON_OFFSET, 4, 4),
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static const struct dphy_reg rk3288_grf_dphy_regs[] = {
356*4882a593Smuzhiyun 	[GRF_CON_DISABLE_ISP] = PHY_REG(RK3288_GRF_SOC_CON6, 1, 0),
357*4882a593Smuzhiyun 	[GRF_CON_ISP_DPHY_SEL] = PHY_REG(RK3288_GRF_SOC_CON6, 1, 1),
358*4882a593Smuzhiyun 	[GRF_DSI_CSI_TESTBUS_SEL] = PHY_REG(RK3288_GRF_SOC_CON6, 1, 14),
359*4882a593Smuzhiyun 	[GRF_DPHY_TX0_TURNDISABLE] = PHY_REG(RK3288_GRF_SOC_CON8, 4, 0),
360*4882a593Smuzhiyun 	[GRF_DPHY_TX0_FORCERXMODE] = PHY_REG(RK3288_GRF_SOC_CON8, 4, 4),
361*4882a593Smuzhiyun 	[GRF_DPHY_TX0_FORCETXSTOPMODE] = PHY_REG(RK3288_GRF_SOC_CON8, 4, 8),
362*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_TURNDISABLE] = PHY_REG(RK3288_GRF_SOC_CON9, 4, 0),
363*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_FORCERXMODE] = PHY_REG(RK3288_GRF_SOC_CON9, 4, 4),
364*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_FORCETXSTOPMODE] = PHY_REG(RK3288_GRF_SOC_CON9, 4, 8),
365*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_ENABLE] = PHY_REG(RK3288_GRF_SOC_CON9, 4, 12),
366*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TURNDISABLE] = PHY_REG(RK3288_GRF_SOC_CON10, 4, 0),
367*4882a593Smuzhiyun 	[GRF_DPHY_RX0_FORCERXMODE] = PHY_REG(RK3288_GRF_SOC_CON10, 4, 4),
368*4882a593Smuzhiyun 	[GRF_DPHY_RX0_FORCETXSTOPMODE] = PHY_REG(RK3288_GRF_SOC_CON10, 4, 8),
369*4882a593Smuzhiyun 	[GRF_DPHY_RX0_ENABLE] = PHY_REG(RK3288_GRF_SOC_CON10, 4, 12),
370*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTCLR] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 0),
371*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTCLK] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 1),
372*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTEN] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 2),
373*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTDIN] = PHY_REG(RK3288_GRF_SOC_CON14, 8, 3),
374*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_ENABLECLK] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 12),
375*4882a593Smuzhiyun 	[GRF_DPHY_RX1_SRC_SEL] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 13),
376*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_MASTERSLAVEZ] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 14),
377*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_BASEDIR] = PHY_REG(RK3288_GRF_SOC_CON14, 1, 15),
378*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TURNREQUEST] = PHY_REG(RK3288_GRF_SOC_CON15, 4, 0),
379*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_TURNREQUEST] = PHY_REG(RK3288_GRF_SOC_CON15, 4, 4),
380*4882a593Smuzhiyun 	[GRF_DPHY_TX0_TURNREQUEST] = PHY_REG(RK3288_GRF_SOC_CON15, 3, 8),
381*4882a593Smuzhiyun 	[GRF_DVP_V18SEL] = PHY_REG(RK3288_GRF_IO_VSEL, 1, 1),
382*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTDOUT] = PHY_REG(RK3288_GRF_SOC_STATUS21, 8, 0),
383*4882a593Smuzhiyun };
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun static const struct dphy_reg rk3326_grf_dphy_regs[] = {
386*4882a593Smuzhiyun 	[GRF_DVP_V18SEL] = PHY_REG(RK3326_GRF_IO_VSEL_OFFSET, 1, 4),
387*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 0),
388*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 1, 8),
389*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RK3326_GRF_PD_VI_CON_OFFSET, 4, 4),
390*4882a593Smuzhiyun };
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun static const struct dphy_reg rk3368_grf_dphy_regs[] = {
393*4882a593Smuzhiyun 	[GRF_DVP_V18SEL] = PHY_REG(RK3368_GRF_IO_VSEL_OFFSET, 1, 1),
394*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 4, 8),
395*4882a593Smuzhiyun 	[GRF_ISP_MIPI_CSI_HOST_SEL] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 1, 1),
396*4882a593Smuzhiyun 	[GRF_CON_DISABLE_ISP] = PHY_REG(RK3368_GRF_SOC_CON6_OFFSET, 1, 0),
397*4882a593Smuzhiyun };
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun static const struct dphy_reg rk3399_grf_dphy_regs[] = {
400*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON9, 4, 0),
401*4882a593Smuzhiyun 	[GRF_DPHY_RX0_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 10),
402*4882a593Smuzhiyun 	[GRF_DPHY_RX1_CLK_INV_SEL] = PHY_REG(RK3399_GRF_SOC_CON9, 1, 11),
403*4882a593Smuzhiyun 	[GRF_DPHY_RX0_ENABLE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 0),
404*4882a593Smuzhiyun 	[GRF_DPHY_RX0_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 4),
405*4882a593Smuzhiyun 	[GRF_DPHY_RX0_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 8),
406*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON21, 4, 12),
407*4882a593Smuzhiyun 	[GRF_DPHY_TX0_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 0),
408*4882a593Smuzhiyun 	[GRF_DPHY_TX0_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 4),
409*4882a593Smuzhiyun 	[GRF_DPHY_TX0_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 8),
410*4882a593Smuzhiyun 	[GRF_DPHY_TX0_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON22, 4, 12),
411*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_ENABLE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 0),
412*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_FORCERXMODE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 4),
413*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_FORCETXSTOPMODE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 8),
414*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_TURNDISABLE] = PHY_REG(RK3399_GRF_SOC_CON23, 4, 12),
415*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_TURNREQUEST] = PHY_REG(RK3399_GRF_SOC_CON24, 4, 0),
416*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_SRC_SEL] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 4),
417*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_BASEDIR] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 5),
418*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_ENABLECLK] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 6),
419*4882a593Smuzhiyun 	[GRF_DPHY_TX1RX1_MASTERSLAVEZ] = PHY_REG(RK3399_GRF_SOC_CON24, 1, 7),
420*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTDIN] = PHY_REG(RK3399_GRF_SOC_CON25, 8, 0),
421*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTEN] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 8),
422*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTCLK] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 9),
423*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTCLR] = PHY_REG(RK3399_GRF_SOC_CON25, 1, 10),
424*4882a593Smuzhiyun 	[GRF_DPHY_RX0_TESTDOUT] = PHY_REG(RK3399_GRF_SOC_STATUS1, 8, 0),
425*4882a593Smuzhiyun 	[GRF_DVP_V18SEL] = PHY_REG(RK3399_GRF_IO_VSEL, 1, 1),
426*4882a593Smuzhiyun };
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun static const struct dphy_reg rv1126_grf_dphy0_regs[] = {
429*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RV1126_GRF_CSIPHY0_CON, 4, 0),
430*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RV1126_GRF_CSIPHY0_CON, 4, 4),
431*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RV1126_GRF_CSIPHY0_CON, 1, 8),
432*4882a593Smuzhiyun 	[GRF_DPHY_CLK_INV_SEL] = PHY_REG(RV1126_GRF_CSIPHY0_CON, 1, 9),
433*4882a593Smuzhiyun 	[GRF_DPHY_SEL] = PHY_REG(RV1126_GRF_IOFUNC_CON3, 3, 9),
434*4882a593Smuzhiyun };
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun static const struct dphy_reg rv1126_grf_dphy1_regs[] = {
437*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_FORCERXMODE] = PHY_REG(RV1126_GRF_CSIPHY1_CON, 4, 0),
438*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_DATALANE_EN] = PHY_REG(RV1126_GRF_CSIPHY1_CON, 4, 4),
439*4882a593Smuzhiyun 	[GRF_DPHY_CSIPHY_CLKLANE_EN] = PHY_REG(RV1126_GRF_CSIPHY1_CON, 1, 8),
440*4882a593Smuzhiyun 	[GRF_DPHY_CLK_INV_SEL] = PHY_REG(RV1126_GRF_CSIPHY1_CON, 1, 9),
441*4882a593Smuzhiyun 	[GRF_DPHY_SEL] = PHY_REG(RV1126_GRF_IOFUNC_CON3, 3, 9),
442*4882a593Smuzhiyun };
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun static const struct txrx_reg rk3288_txrx_regs[] = {
445*4882a593Smuzhiyun 	[TXRX_PHY_TEST_CTRL0] = TXRX_REG(RK3288_PHY_TEST_CTRL0),
446*4882a593Smuzhiyun 	[TXRX_PHY_TEST_CTRL1] = TXRX_REG(RK3288_PHY_TEST_CTRL1),
447*4882a593Smuzhiyun 	[TXRX_PHY_SHUTDOWNZ] = TXRX_REG(RK3288_PHY_SHUTDOWNZ),
448*4882a593Smuzhiyun 	[TXRX_PHY_RSTZ] = TXRX_REG(RK3288_PHY_RSTZ),
449*4882a593Smuzhiyun };
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun static const struct txrx_reg rk3399_txrx_regs[] = {
452*4882a593Smuzhiyun 	[TXRX_PHY_TEST_CTRL0] = TXRX_REG(RK3399_PHY_TEST_CTRL0),
453*4882a593Smuzhiyun 	[TXRX_PHY_TEST_CTRL1] = TXRX_REG(RK3399_PHY_TEST_CTRL1),
454*4882a593Smuzhiyun 	[TXRX_PHY_SHUTDOWNZ] = TXRX_REG(RK3399_PHY_SHUTDOWNZ),
455*4882a593Smuzhiyun 	[TXRX_PHY_RSTZ] = TXRX_REG(RK3399_PHY_RSTZ),
456*4882a593Smuzhiyun };
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun static const struct csiphy_reg rk1808_csiphy_regs[] = {
459*4882a593Smuzhiyun 	[CSIPHY_CTRL_LANE_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_CTRL_LANE_ENABLE),
460*4882a593Smuzhiyun 	[CSIPHY_CTRL_PWRCTL] = CSIPHY_REG(RK1808_CSI_DPHY_CTRL_PWRCTL),
461*4882a593Smuzhiyun 	[CSIPHY_CTRL_DIG_RST] = CSIPHY_REG(RK1808_CSI_DPHY_CTRL_DIG_RST),
462*4882a593Smuzhiyun 	[CSIPHY_CLK_THS_SETTLE] = CSIPHY_REG(RK1808_CSI_DPHY_CLK_WR_THS_SETTLE),
463*4882a593Smuzhiyun 	[CSIPHY_LANE0_THS_SETTLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE0_WR_THS_SETTLE),
464*4882a593Smuzhiyun 	[CSIPHY_LANE1_THS_SETTLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE1_WR_THS_SETTLE),
465*4882a593Smuzhiyun 	[CSIPHY_LANE2_THS_SETTLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE2_WR_THS_SETTLE),
466*4882a593Smuzhiyun 	[CSIPHY_LANE3_THS_SETTLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE3_WR_THS_SETTLE),
467*4882a593Smuzhiyun 	[CSIPHY_CLK_CALIB_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_CLK_CALIB_EN),
468*4882a593Smuzhiyun 	[CSIPHY_LANE0_CALIB_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE0_CALIB_EN),
469*4882a593Smuzhiyun 	[CSIPHY_LANE1_CALIB_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE1_CALIB_EN),
470*4882a593Smuzhiyun 	[CSIPHY_LANE2_CALIB_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE2_CALIB_EN),
471*4882a593Smuzhiyun 	[CSIPHY_LANE3_CALIB_ENABLE] = CSIPHY_REG(RK1808_CSI_DPHY_LANE3_CALIB_EN),
472*4882a593Smuzhiyun };
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun static const struct csiphy_reg rk3326_csiphy_regs[] = {
475*4882a593Smuzhiyun 	[CSIPHY_CTRL_LANE_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_LANE_ENABLE),
476*4882a593Smuzhiyun 	[CSIPHY_CTRL_PWRCTL] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_PWRCTL),
477*4882a593Smuzhiyun 	[CSIPHY_CTRL_DIG_RST] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_DIG_RST),
478*4882a593Smuzhiyun 	[CSIPHY_CLK_THS_SETTLE] = CSIPHY_REG(RK3326_CSI_DPHY_CLK_WR_THS_SETTLE),
479*4882a593Smuzhiyun 	[CSIPHY_LANE0_THS_SETTLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE0_WR_THS_SETTLE),
480*4882a593Smuzhiyun 	[CSIPHY_LANE1_THS_SETTLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE1_WR_THS_SETTLE),
481*4882a593Smuzhiyun 	[CSIPHY_LANE2_THS_SETTLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE2_WR_THS_SETTLE),
482*4882a593Smuzhiyun 	[CSIPHY_LANE3_THS_SETTLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE3_WR_THS_SETTLE),
483*4882a593Smuzhiyun 	[CSIPHY_CLK_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_CLK_CALIB_EN),
484*4882a593Smuzhiyun 	[CSIPHY_LANE0_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE0_CALIB_EN),
485*4882a593Smuzhiyun 	[CSIPHY_LANE1_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE1_CALIB_EN),
486*4882a593Smuzhiyun 	[CSIPHY_LANE2_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE2_CALIB_EN),
487*4882a593Smuzhiyun 	[CSIPHY_LANE3_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE3_CALIB_EN),
488*4882a593Smuzhiyun };
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun static const struct csiphy_reg rk3326s_csiphy_regs[] = {
491*4882a593Smuzhiyun 	[CSIPHY_CTRL_LANE_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_LANE_ENABLE),
492*4882a593Smuzhiyun 	[CSIPHY_CTRL_PWRCTL] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_PWRCTL),
493*4882a593Smuzhiyun 	[CSIPHY_CTRL_DIG_RST] = CSIPHY_REG(RK3326_CSI_DPHY_CTRL_DIG_RST),
494*4882a593Smuzhiyun 	[CSIPHY_CLK_THS_SETTLE] = CSIPHY_REG(RK3326S_CSI_DPHY_CLK_WR_THS_SETTLE),
495*4882a593Smuzhiyun 	[CSIPHY_LANE0_THS_SETTLE] = CSIPHY_REG(RK3326S_CSI_DPHY_LANE0_WR_THS_SETTLE),
496*4882a593Smuzhiyun 	[CSIPHY_LANE1_THS_SETTLE] = CSIPHY_REG(RK3326S_CSI_DPHY_LANE1_WR_THS_SETTLE),
497*4882a593Smuzhiyun 	[CSIPHY_LANE2_THS_SETTLE] = CSIPHY_REG(RK3326S_CSI_DPHY_LANE2_WR_THS_SETTLE),
498*4882a593Smuzhiyun 	[CSIPHY_LANE3_THS_SETTLE] = CSIPHY_REG(RK3326S_CSI_DPHY_LANE3_WR_THS_SETTLE),
499*4882a593Smuzhiyun 	[CSIPHY_CLK_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_CLK_CALIB_EN),
500*4882a593Smuzhiyun 	[CSIPHY_LANE0_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE0_CALIB_EN),
501*4882a593Smuzhiyun 	[CSIPHY_LANE1_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE1_CALIB_EN),
502*4882a593Smuzhiyun 	[CSIPHY_LANE2_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE2_CALIB_EN),
503*4882a593Smuzhiyun 	[CSIPHY_LANE3_CALIB_ENABLE] = CSIPHY_REG(RK3326_CSI_DPHY_LANE3_CALIB_EN),
504*4882a593Smuzhiyun 	[CSIPHY_CLK_MODE] = CSIPHY_REG(RK3326S_CSI_DPHY_CLK_MODE),
505*4882a593Smuzhiyun };
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun static const struct csiphy_reg rk3368_csiphy_regs[] = {
508*4882a593Smuzhiyun 	[CSIPHY_CTRL_LANE_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_CTRL_LANE_ENABLE),
509*4882a593Smuzhiyun 	[CSIPHY_CTRL_PWRCTL] = CSIPHY_REG(RK3368_CSI_DPHY_CTRL_PWRCTL),
510*4882a593Smuzhiyun 	[CSIPHY_CTRL_DIG_RST] = CSIPHY_REG(RK3368_CSI_DPHY_CTRL_DIG_RST),
511*4882a593Smuzhiyun 	[CSIPHY_CLK_THS_SETTLE] = CSIPHY_REG(RK3368_CSI_DPHY_CLK_WR_THS_SETTLE),
512*4882a593Smuzhiyun 	[CSIPHY_LANE0_THS_SETTLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE0_WR_THS_SETTLE),
513*4882a593Smuzhiyun 	[CSIPHY_LANE1_THS_SETTLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE1_WR_THS_SETTLE),
514*4882a593Smuzhiyun 	[CSIPHY_LANE2_THS_SETTLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE2_WR_THS_SETTLE),
515*4882a593Smuzhiyun 	[CSIPHY_LANE3_THS_SETTLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE3_WR_THS_SETTLE),
516*4882a593Smuzhiyun 	[CSIPHY_CLK_CALIB_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_CLK_CALIB_EN),
517*4882a593Smuzhiyun 	[CSIPHY_LANE0_CALIB_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE0_CALIB_EN),
518*4882a593Smuzhiyun 	[CSIPHY_LANE1_CALIB_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE1_CALIB_EN),
519*4882a593Smuzhiyun 	[CSIPHY_LANE2_CALIB_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE2_CALIB_EN),
520*4882a593Smuzhiyun 	[CSIPHY_LANE3_CALIB_ENABLE] = CSIPHY_REG(RK3368_CSI_DPHY_LANE3_CALIB_EN),
521*4882a593Smuzhiyun };
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun static const struct csiphy_reg rv1126_csiphy_regs[] = {
524*4882a593Smuzhiyun 	[CSIPHY_CTRL_LANE_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_CTRL_LANE_ENABLE),
525*4882a593Smuzhiyun 	[CSIPHY_CTRL_PWRCTL] = CSIPHY_REG(RV1126_CSI_DPHY_CTRL_PWRCTL),
526*4882a593Smuzhiyun 	[CSIPHY_CTRL_DIG_RST] = CSIPHY_REG(RV1126_CSI_DPHY_CTRL_DIG_RST),
527*4882a593Smuzhiyun 	[CSIPHY_CLK_THS_SETTLE] = CSIPHY_REG(RV1126_CSI_DPHY_CLK_WR_THS_SETTLE),
528*4882a593Smuzhiyun 	[CSIPHY_LANE0_THS_SETTLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE0_WR_THS_SETTLE),
529*4882a593Smuzhiyun 	[CSIPHY_LANE1_THS_SETTLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE1_WR_THS_SETTLE),
530*4882a593Smuzhiyun 	[CSIPHY_LANE2_THS_SETTLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE2_WR_THS_SETTLE),
531*4882a593Smuzhiyun 	[CSIPHY_LANE3_THS_SETTLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE3_WR_THS_SETTLE),
532*4882a593Smuzhiyun 	[CSIPHY_CLK_CALIB_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_CLK_CALIB_EN),
533*4882a593Smuzhiyun 	[CSIPHY_LANE0_CALIB_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE0_CALIB_EN),
534*4882a593Smuzhiyun 	[CSIPHY_LANE1_CALIB_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE1_CALIB_EN),
535*4882a593Smuzhiyun 	[CSIPHY_LANE2_CALIB_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE2_CALIB_EN),
536*4882a593Smuzhiyun 	[CSIPHY_LANE3_CALIB_ENABLE] = CSIPHY_REG(RV1126_CSI_DPHY_LANE3_CALIB_EN),
537*4882a593Smuzhiyun 	[CSIPHY_MIPI_LVDS_MODEL] = CSIPHY_REG(RV1126_CSI_DPHY_MIPI_LVDS_MODEL),
538*4882a593Smuzhiyun 	[CSIPHY_LVDS_MODE] = CSIPHY_REG(RV1126_CSI_DPHY_LVDS_MODE),
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun struct hsfreq_range {
542*4882a593Smuzhiyun 	u32 range_h;
543*4882a593Smuzhiyun 	u8 cfg_bit;
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun struct mipidphy_priv;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun struct dphy_drv_data {
549*4882a593Smuzhiyun 	const char * const *clks;
550*4882a593Smuzhiyun 	int num_clks;
551*4882a593Smuzhiyun 	const struct hsfreq_range *hsfreq_ranges;
552*4882a593Smuzhiyun 	int num_hsfreq_ranges;
553*4882a593Smuzhiyun 	const struct dphy_reg *grf_regs;
554*4882a593Smuzhiyun 	const struct txrx_reg *txrx_regs;
555*4882a593Smuzhiyun 	const struct csiphy_reg *csiphy_regs;
556*4882a593Smuzhiyun 	enum mipi_dphy_ctl_type ctl_type;
557*4882a593Smuzhiyun 	void (*individual_init)(struct mipidphy_priv *priv);
558*4882a593Smuzhiyun 	enum mipi_dphy_chip_id chip_id;
559*4882a593Smuzhiyun };
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun struct sensor_async_subdev {
562*4882a593Smuzhiyun 	struct v4l2_async_subdev asd;
563*4882a593Smuzhiyun 	struct v4l2_mbus_config mbus;
564*4882a593Smuzhiyun 	int lanes;
565*4882a593Smuzhiyun };
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun #define MAX_DPHY_CLK		8
568*4882a593Smuzhiyun #define MAX_DPHY_SENSORS	2
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun struct mipidphy_sensor {
571*4882a593Smuzhiyun 	struct v4l2_subdev *sd;
572*4882a593Smuzhiyun 	struct v4l2_mbus_config mbus;
573*4882a593Smuzhiyun 	struct v4l2_mbus_framefmt format;
574*4882a593Smuzhiyun 	int lanes;
575*4882a593Smuzhiyun };
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun struct mipidphy_priv {
578*4882a593Smuzhiyun 	struct device *dev;
579*4882a593Smuzhiyun 	struct regmap *regmap_grf;
580*4882a593Smuzhiyun 	const struct dphy_reg *grf_regs;
581*4882a593Smuzhiyun 	const struct txrx_reg *txrx_regs;
582*4882a593Smuzhiyun 	const struct csiphy_reg *csiphy_regs;
583*4882a593Smuzhiyun 	void __iomem *csihost_base_addr;
584*4882a593Smuzhiyun 	struct clk *clks[MAX_DPHY_CLK];
585*4882a593Smuzhiyun 	const struct dphy_drv_data *drv_data;
586*4882a593Smuzhiyun 	u64 data_rate_mbps;
587*4882a593Smuzhiyun 	struct v4l2_async_notifier notifier;
588*4882a593Smuzhiyun 	struct v4l2_subdev sd;
589*4882a593Smuzhiyun 	struct mutex mutex; /* lock for updating protection */
590*4882a593Smuzhiyun 	struct media_pad pads[MIPI_DPHY_RX_PADS_NUM];
591*4882a593Smuzhiyun 	struct mipidphy_sensor sensors[MAX_DPHY_SENSORS];
592*4882a593Smuzhiyun 	int num_sensors;
593*4882a593Smuzhiyun 	int phy_index;
594*4882a593Smuzhiyun 	bool is_streaming;
595*4882a593Smuzhiyun 	void __iomem *txrx_base_addr;
596*4882a593Smuzhiyun 	int (*stream_on)(struct mipidphy_priv *priv, struct v4l2_subdev *sd);
597*4882a593Smuzhiyun 	int (*stream_off)(struct mipidphy_priv *priv, struct v4l2_subdev *sd);
598*4882a593Smuzhiyun };
599*4882a593Smuzhiyun 
to_dphy_priv(struct v4l2_subdev * subdev)600*4882a593Smuzhiyun static inline struct mipidphy_priv *to_dphy_priv(struct v4l2_subdev *subdev)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun 	return container_of(subdev, struct mipidphy_priv, sd);
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun 
write_grf_reg(struct mipidphy_priv * priv,int index,u8 value)605*4882a593Smuzhiyun static inline void write_grf_reg(struct mipidphy_priv *priv,
606*4882a593Smuzhiyun 				 int index, u8 value)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun 	const struct dphy_reg *reg = &priv->grf_regs[index];
609*4882a593Smuzhiyun 	unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	if (reg->offset)
612*4882a593Smuzhiyun 		regmap_write(priv->regmap_grf, reg->offset, val);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
read_grf_reg(struct mipidphy_priv * priv,int index)615*4882a593Smuzhiyun static inline u32 read_grf_reg(struct mipidphy_priv *priv, int index)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun 	const struct dphy_reg *reg = &priv->grf_regs[index];
618*4882a593Smuzhiyun 	unsigned int val = 0;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	if (reg->offset) {
621*4882a593Smuzhiyun 		regmap_read(priv->regmap_grf, reg->offset, &val);
622*4882a593Smuzhiyun 		val = (val >> reg->shift) & reg->mask;
623*4882a593Smuzhiyun 	}
624*4882a593Smuzhiyun 	return val;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
write_txrx_reg(struct mipidphy_priv * priv,int index,u32 value)627*4882a593Smuzhiyun static inline void write_txrx_reg(struct mipidphy_priv *priv,
628*4882a593Smuzhiyun 				  int index, u32 value)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun 	const struct txrx_reg *reg = &priv->txrx_regs[index];
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	if (reg->offset)
633*4882a593Smuzhiyun 		writel(value, priv->txrx_base_addr + reg->offset);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun 
mipidphy0_wr_reg(struct mipidphy_priv * priv,u8 test_code,u8 test_data)636*4882a593Smuzhiyun static void mipidphy0_wr_reg(struct mipidphy_priv *priv,
637*4882a593Smuzhiyun 			     u8 test_code, u8 test_data)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	/*
640*4882a593Smuzhiyun 	 * With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
641*4882a593Smuzhiyun 	 * is latched internally as the current test code. Test data is
642*4882a593Smuzhiyun 	 * programmed internally by rising edge on TESTCLK.
643*4882a593Smuzhiyun 	 */
644*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
645*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_code);
646*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 1);
647*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 0);
648*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTEN, 0);
649*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTDIN, test_data);
650*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun 
mipidphy1_wr_reg(struct mipidphy_priv * priv,unsigned char addr,unsigned char data)653*4882a593Smuzhiyun static void mipidphy1_wr_reg(struct mipidphy_priv *priv, unsigned char addr,
654*4882a593Smuzhiyun 			     unsigned char data)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	/*
657*4882a593Smuzhiyun 	 * TESTEN =1,TESTDIN=addr
658*4882a593Smuzhiyun 	 * TESTCLK=0
659*4882a593Smuzhiyun 	 * TESTEN =0,TESTDIN=data
660*4882a593Smuzhiyun 	 * TESTCLK=1
661*4882a593Smuzhiyun 	 */
662*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL1, PHY_TESTEN_ADDR | addr);
663*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL0, 0x00);
664*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL1, PHY_TESTEN_DATA | data);
665*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL0, 0x02);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
write_csiphy_reg(struct mipidphy_priv * priv,int index,u32 value)668*4882a593Smuzhiyun static inline void write_csiphy_reg(struct mipidphy_priv *priv,
669*4882a593Smuzhiyun 				    int index, u32 value)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun 	const struct csiphy_reg *reg = &priv->csiphy_regs[index];
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	if (reg->offset != MIPI_CSI_DPHY_CTRL_INVALID_OFFSET)
674*4882a593Smuzhiyun 		writel(value, priv->csihost_base_addr + reg->offset);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun 
read_csiphy_reg(struct mipidphy_priv * priv,int index,u32 * value)677*4882a593Smuzhiyun static inline void read_csiphy_reg(struct mipidphy_priv *priv,
678*4882a593Smuzhiyun 				    int index, u32 *value)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun 	const struct csiphy_reg *reg = &priv->csiphy_regs[index];
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	if (reg->offset != MIPI_CSI_DPHY_CTRL_INVALID_OFFSET)
683*4882a593Smuzhiyun 		*value = readl(priv->csihost_base_addr + reg->offset);
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun 
csi_mipidphy_wr_ths_settle(struct mipidphy_priv * priv,int hsfreq,enum mipi_dphy_lane lane)686*4882a593Smuzhiyun static void csi_mipidphy_wr_ths_settle(struct mipidphy_priv *priv, int hsfreq,
687*4882a593Smuzhiyun 				       enum mipi_dphy_lane lane)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	unsigned int val = 0;
690*4882a593Smuzhiyun 	unsigned int offset;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	switch (lane) {
693*4882a593Smuzhiyun 	case MIPI_DPHY_LANE_CLOCK:
694*4882a593Smuzhiyun 		offset = CSIPHY_CLK_THS_SETTLE;
695*4882a593Smuzhiyun 		break;
696*4882a593Smuzhiyun 	case MIPI_DPHY_LANE_DATA0:
697*4882a593Smuzhiyun 		offset = CSIPHY_LANE0_THS_SETTLE;
698*4882a593Smuzhiyun 		break;
699*4882a593Smuzhiyun 	case MIPI_DPHY_LANE_DATA1:
700*4882a593Smuzhiyun 		offset = CSIPHY_LANE1_THS_SETTLE;
701*4882a593Smuzhiyun 		break;
702*4882a593Smuzhiyun 	case MIPI_DPHY_LANE_DATA2:
703*4882a593Smuzhiyun 		offset = CSIPHY_LANE2_THS_SETTLE;
704*4882a593Smuzhiyun 		break;
705*4882a593Smuzhiyun 	case MIPI_DPHY_LANE_DATA3:
706*4882a593Smuzhiyun 		offset = CSIPHY_LANE3_THS_SETTLE;
707*4882a593Smuzhiyun 		break;
708*4882a593Smuzhiyun 	default:
709*4882a593Smuzhiyun 		return;
710*4882a593Smuzhiyun 	}
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	read_csiphy_reg(priv, offset, &val);
713*4882a593Smuzhiyun 	val = (val & ~0x7f) | hsfreq;
714*4882a593Smuzhiyun 	write_csiphy_reg(priv, offset, val);
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun 
get_remote_sensor(struct v4l2_subdev * sd)717*4882a593Smuzhiyun static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	struct media_pad *local, *remote;
720*4882a593Smuzhiyun 	struct media_entity *sensor_me;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	local = &sd->entity.pads[MIPI_DPHY_RX_PAD_SINK];
723*4882a593Smuzhiyun 	remote = media_entity_remote_pad(local);
724*4882a593Smuzhiyun 	if (!remote) {
725*4882a593Smuzhiyun 		v4l2_warn(sd, "No link between dphy and sensor\n");
726*4882a593Smuzhiyun 		return NULL;
727*4882a593Smuzhiyun 	}
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	sensor_me = media_entity_remote_pad(local)->entity;
730*4882a593Smuzhiyun 	return media_entity_to_v4l2_subdev(sensor_me);
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun 
sd_to_sensor(struct mipidphy_priv * priv,struct v4l2_subdev * sd)733*4882a593Smuzhiyun static struct mipidphy_sensor *sd_to_sensor(struct mipidphy_priv *priv,
734*4882a593Smuzhiyun 					    struct v4l2_subdev *sd)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	int i;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	for (i = 0; i < priv->num_sensors; ++i)
739*4882a593Smuzhiyun 		if (priv->sensors[i].sd == sd)
740*4882a593Smuzhiyun 			return &priv->sensors[i];
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	return NULL;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun 
mipidphy_get_sensor_data_rate(struct v4l2_subdev * sd)745*4882a593Smuzhiyun static int mipidphy_get_sensor_data_rate(struct v4l2_subdev *sd)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
748*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
749*4882a593Smuzhiyun 	struct v4l2_ctrl *link_freq;
750*4882a593Smuzhiyun 	struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ, };
751*4882a593Smuzhiyun 	int ret;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	if (!sensor_sd)
754*4882a593Smuzhiyun 		return -ENODEV;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	link_freq = v4l2_ctrl_find(sensor_sd->ctrl_handler, V4L2_CID_LINK_FREQ);
757*4882a593Smuzhiyun 	if (!link_freq) {
758*4882a593Smuzhiyun 		v4l2_warn(sd, "No pixel rate control in subdev\n");
759*4882a593Smuzhiyun 		return -EPIPE;
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	qm.index = v4l2_ctrl_g_ctrl(link_freq);
763*4882a593Smuzhiyun 	ret = v4l2_querymenu(sensor_sd->ctrl_handler, &qm);
764*4882a593Smuzhiyun 	if (ret < 0) {
765*4882a593Smuzhiyun 		v4l2_err(sd, "Failed to get menu item\n");
766*4882a593Smuzhiyun 		return ret;
767*4882a593Smuzhiyun 	}
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	if (!qm.value) {
770*4882a593Smuzhiyun 		v4l2_err(sd, "Invalid link_freq\n");
771*4882a593Smuzhiyun 		return -EINVAL;
772*4882a593Smuzhiyun 	}
773*4882a593Smuzhiyun 	priv->data_rate_mbps = qm.value * 2;
774*4882a593Smuzhiyun 	do_div(priv->data_rate_mbps, 1000 * 1000);
775*4882a593Smuzhiyun 	v4l2_info(sd, "data_rate_mbps %lld\n", priv->data_rate_mbps);
776*4882a593Smuzhiyun 	return 0;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun 
mipidphy_update_sensor_mbus(struct v4l2_subdev * sd)779*4882a593Smuzhiyun static int mipidphy_update_sensor_mbus(struct v4l2_subdev *sd)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
782*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
783*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
784*4882a593Smuzhiyun 	struct v4l2_mbus_config mbus;
785*4882a593Smuzhiyun 	int ret;
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	if (!sensor_sd)
788*4882a593Smuzhiyun 		return -ENODEV;
789*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
790*4882a593Smuzhiyun 	if (!sensor)
791*4882a593Smuzhiyun 		return -ENODEV;
792*4882a593Smuzhiyun 	ret = v4l2_subdev_call(sensor_sd, pad, get_mbus_config, 0, &mbus);
793*4882a593Smuzhiyun 	if (ret)
794*4882a593Smuzhiyun 		return ret;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 	sensor->mbus = mbus;
797*4882a593Smuzhiyun 	switch (mbus.flags & V4L2_MBUS_CSI2_LANES) {
798*4882a593Smuzhiyun 	case V4L2_MBUS_CSI2_1_LANE:
799*4882a593Smuzhiyun 		sensor->lanes = 1;
800*4882a593Smuzhiyun 		break;
801*4882a593Smuzhiyun 	case V4L2_MBUS_CSI2_2_LANE:
802*4882a593Smuzhiyun 		sensor->lanes = 2;
803*4882a593Smuzhiyun 		break;
804*4882a593Smuzhiyun 	case V4L2_MBUS_CSI2_3_LANE:
805*4882a593Smuzhiyun 		sensor->lanes = 3;
806*4882a593Smuzhiyun 		break;
807*4882a593Smuzhiyun 	case V4L2_MBUS_CSI2_4_LANE:
808*4882a593Smuzhiyun 		sensor->lanes = 4;
809*4882a593Smuzhiyun 		break;
810*4882a593Smuzhiyun 	default:
811*4882a593Smuzhiyun 		return -EINVAL;
812*4882a593Smuzhiyun 	}
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	return 0;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun 
rk1126_mipidphy_dphy_sel(struct v4l2_subdev * sd)817*4882a593Smuzhiyun static void rk1126_mipidphy_dphy_sel(struct v4l2_subdev *sd)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
820*4882a593Smuzhiyun 	char *model;
821*4882a593Smuzhiyun 	u8 oldval, newval;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	model = sd->v4l2_dev->mdev->model;
824*4882a593Smuzhiyun 	oldval = read_grf_reg(priv, GRF_DPHY_SEL);
825*4882a593Smuzhiyun 	newval = oldval;
826*4882a593Smuzhiyun 	if (!strncmp(model, "rkcif_lite_mipi_lvds", sizeof("rkcif_lite_mipi_lvds") - 1)) {
827*4882a593Smuzhiyun 		if (priv->phy_index == 0)
828*4882a593Smuzhiyun 			newval &= ~RV1126_GRF_PHY1_SEL_CIFLITE;
829*4882a593Smuzhiyun 		else
830*4882a593Smuzhiyun 			newval |= RV1126_GRF_PHY1_SEL_CIFLITE;
831*4882a593Smuzhiyun 	} else if (!strncmp(model, "rkcif_mipi_lvds", sizeof("rkcif_mipi_lvds") - 1)) {
832*4882a593Smuzhiyun 		if (priv->phy_index == 0)
833*4882a593Smuzhiyun 			newval &= ~RV1126_GRF_PHY1_SEL_CIF;
834*4882a593Smuzhiyun 		else
835*4882a593Smuzhiyun 			newval |= RV1126_GRF_PHY1_SEL_CIF;
836*4882a593Smuzhiyun 	} else {
837*4882a593Smuzhiyun 		if (priv->phy_index == 0)
838*4882a593Smuzhiyun 			newval &= ~RV1126_GRF_PHY1_SEL_ISP;
839*4882a593Smuzhiyun 		else
840*4882a593Smuzhiyun 			newval |= RV1126_GRF_PHY1_SEL_ISP;
841*4882a593Smuzhiyun 	}
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun 	if (newval != oldval)
844*4882a593Smuzhiyun 		write_grf_reg(priv, GRF_DPHY_SEL, newval);
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun 
mipidphy_s_stream_start(struct v4l2_subdev * sd)847*4882a593Smuzhiyun static int mipidphy_s_stream_start(struct v4l2_subdev *sd)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
850*4882a593Smuzhiyun 	int  ret = 0;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	if (priv->is_streaming)
853*4882a593Smuzhiyun 		return 0;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	ret = mipidphy_get_sensor_data_rate(sd);
856*4882a593Smuzhiyun 	if (ret < 0)
857*4882a593Smuzhiyun 		return ret;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	if (priv->drv_data->chip_id == CHIP_ID_RK1126)
860*4882a593Smuzhiyun 		rk1126_mipidphy_dphy_sel(sd);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	mipidphy_update_sensor_mbus(sd);
863*4882a593Smuzhiyun 	priv->stream_on(priv, sd);
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	priv->is_streaming = true;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	return 0;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun 
mipidphy_s_stream_stop(struct v4l2_subdev * sd)870*4882a593Smuzhiyun static int mipidphy_s_stream_stop(struct v4l2_subdev *sd)
871*4882a593Smuzhiyun {
872*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	if (!priv->is_streaming)
875*4882a593Smuzhiyun 		return 0;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	if (priv->stream_off)
878*4882a593Smuzhiyun 		priv->stream_off(priv, sd);
879*4882a593Smuzhiyun 	priv->is_streaming = false;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	return 0;
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun 
mipidphy_s_stream(struct v4l2_subdev * sd,int on)884*4882a593Smuzhiyun static int mipidphy_s_stream(struct v4l2_subdev *sd, int on)
885*4882a593Smuzhiyun {
886*4882a593Smuzhiyun 	int ret = 0;
887*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	dev_info(priv->dev, "stream on:%d\n", on);
890*4882a593Smuzhiyun 	mutex_lock(&priv->mutex);
891*4882a593Smuzhiyun 	if (on)
892*4882a593Smuzhiyun 		ret = mipidphy_s_stream_start(sd);
893*4882a593Smuzhiyun 	else
894*4882a593Smuzhiyun 		ret = mipidphy_s_stream_stop(sd);
895*4882a593Smuzhiyun 	mutex_unlock(&priv->mutex);
896*4882a593Smuzhiyun 	return ret;
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun 
mipidphy_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)899*4882a593Smuzhiyun static int mipidphy_g_frame_interval(struct v4l2_subdev *sd,
900*4882a593Smuzhiyun 				     struct v4l2_subdev_frame_interval *fi)
901*4882a593Smuzhiyun {
902*4882a593Smuzhiyun 	struct v4l2_subdev *sensor = get_remote_sensor(sd);
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	if (sensor)
905*4882a593Smuzhiyun 		return v4l2_subdev_call(sensor, video, g_frame_interval, fi);
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	return -EINVAL;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun 
mipidphy_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)910*4882a593Smuzhiyun static int mipidphy_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
911*4882a593Smuzhiyun 				  struct v4l2_mbus_config *config)
912*4882a593Smuzhiyun {
913*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
914*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
915*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun 	if (!sensor_sd)
918*4882a593Smuzhiyun 		return -ENODEV;
919*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
920*4882a593Smuzhiyun 	if (!sensor)
921*4882a593Smuzhiyun 		return -ENODEV;
922*4882a593Smuzhiyun 	mipidphy_update_sensor_mbus(sd);
923*4882a593Smuzhiyun 	*config = sensor->mbus;
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	return 0;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun 
mipidphy_s_power(struct v4l2_subdev * sd,int on)928*4882a593Smuzhiyun static int mipidphy_s_power(struct v4l2_subdev *sd, int on)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	if (on)
933*4882a593Smuzhiyun 		return pm_runtime_get_sync(priv->dev);
934*4882a593Smuzhiyun 	else
935*4882a593Smuzhiyun 		return pm_runtime_put(priv->dev);
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun 
mipidphy_runtime_suspend(struct device * dev)938*4882a593Smuzhiyun static int __maybe_unused mipidphy_runtime_suspend(struct device *dev)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun 	struct media_entity *me = dev_get_drvdata(dev);
941*4882a593Smuzhiyun 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
942*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
943*4882a593Smuzhiyun 	int i, num_clks;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	num_clks = priv->drv_data->num_clks;
946*4882a593Smuzhiyun 	for (i = num_clks - 1; i >= 0; i--)
947*4882a593Smuzhiyun 		if (!IS_ERR(priv->clks[i]))
948*4882a593Smuzhiyun 			clk_disable_unprepare(priv->clks[i]);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	return 0;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun 
mipidphy_runtime_resume(struct device * dev)953*4882a593Smuzhiyun static int __maybe_unused mipidphy_runtime_resume(struct device *dev)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun 	struct media_entity *me = dev_get_drvdata(dev);
956*4882a593Smuzhiyun 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
957*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
958*4882a593Smuzhiyun 	int i, num_clks, ret;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	num_clks = priv->drv_data->num_clks;
961*4882a593Smuzhiyun 	for (i = 0; i < num_clks; i++) {
962*4882a593Smuzhiyun 		if (!IS_ERR(priv->clks[i])) {
963*4882a593Smuzhiyun 			ret = clk_prepare_enable(priv->clks[i]);
964*4882a593Smuzhiyun 			if (ret < 0)
965*4882a593Smuzhiyun 				goto err;
966*4882a593Smuzhiyun 		}
967*4882a593Smuzhiyun 	}
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	return 0;
970*4882a593Smuzhiyun err:
971*4882a593Smuzhiyun 	while (--i >= 0)
972*4882a593Smuzhiyun 		clk_disable_unprepare(priv->clks[i]);
973*4882a593Smuzhiyun 	return ret;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun /* dphy accepts all fmt/size from sensor */
mipidphy_get_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)977*4882a593Smuzhiyun static int mipidphy_get_set_fmt(struct v4l2_subdev *sd,
978*4882a593Smuzhiyun 				struct v4l2_subdev_pad_config *cfg,
979*4882a593Smuzhiyun 				struct v4l2_subdev_format *fmt)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun 	struct mipidphy_priv *priv = to_dphy_priv(sd);
982*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
983*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
984*4882a593Smuzhiyun 	int ret;
985*4882a593Smuzhiyun 	/*
986*4882a593Smuzhiyun 	 * Do not allow format changes and just relay whatever
987*4882a593Smuzhiyun 	 * set currently in the sensor.
988*4882a593Smuzhiyun 	 */
989*4882a593Smuzhiyun 	if (!sensor_sd)
990*4882a593Smuzhiyun 		return -ENODEV;
991*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
992*4882a593Smuzhiyun 	if (!sensor)
993*4882a593Smuzhiyun 		return -ENODEV;
994*4882a593Smuzhiyun 	ret = v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, fmt);
995*4882a593Smuzhiyun 	if (!ret && fmt->pad == 0)
996*4882a593Smuzhiyun 		sensor->format = fmt->format;
997*4882a593Smuzhiyun 	return ret;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun 
mipidphy_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)1000*4882a593Smuzhiyun static int mipidphy_get_selection(struct v4l2_subdev *sd,
1001*4882a593Smuzhiyun 				  struct v4l2_subdev_pad_config *cfg,
1002*4882a593Smuzhiyun 				  struct v4l2_subdev_selection *sel)
1003*4882a593Smuzhiyun {
1004*4882a593Smuzhiyun 	struct v4l2_subdev *sensor = get_remote_sensor(sd);
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	return v4l2_subdev_call(sensor, pad, get_selection, NULL, sel);
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun static const struct v4l2_subdev_pad_ops mipidphy_subdev_pad_ops = {
1010*4882a593Smuzhiyun 	.set_fmt = mipidphy_get_set_fmt,
1011*4882a593Smuzhiyun 	.get_fmt = mipidphy_get_set_fmt,
1012*4882a593Smuzhiyun 	.get_selection = mipidphy_get_selection,
1013*4882a593Smuzhiyun 	.get_mbus_config = mipidphy_g_mbus_config,
1014*4882a593Smuzhiyun };
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops mipidphy_core_ops = {
1017*4882a593Smuzhiyun 	.s_power = mipidphy_s_power,
1018*4882a593Smuzhiyun };
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun static const struct v4l2_subdev_video_ops mipidphy_video_ops = {
1021*4882a593Smuzhiyun 	.g_frame_interval = mipidphy_g_frame_interval,
1022*4882a593Smuzhiyun 	.s_stream = mipidphy_s_stream,
1023*4882a593Smuzhiyun };
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun static const struct v4l2_subdev_ops mipidphy_subdev_ops = {
1026*4882a593Smuzhiyun 	.core = &mipidphy_core_ops,
1027*4882a593Smuzhiyun 	.video = &mipidphy_video_ops,
1028*4882a593Smuzhiyun 	.pad = &mipidphy_subdev_pad_ops,
1029*4882a593Smuzhiyun };
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun /* These tables must be sorted by .range_h ascending. */
1032*4882a593Smuzhiyun static const struct hsfreq_range rk1808_rv1126_mipidphy_hsfreq_ranges[] = {
1033*4882a593Smuzhiyun 	{ 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
1034*4882a593Smuzhiyun 	{ 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e},
1035*4882a593Smuzhiyun 	{ 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e},
1036*4882a593Smuzhiyun 	{1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37},
1037*4882a593Smuzhiyun 	{2199, 0x3c}, {2399, 0x41}, {2499, 0x46}
1038*4882a593Smuzhiyun };
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun static const struct hsfreq_range rk3288_mipidphy_hsfreq_ranges[] = {
1041*4882a593Smuzhiyun 	{  89, 0x00}, {  99, 0x10}, { 109, 0x20}, { 129, 0x01},
1042*4882a593Smuzhiyun 	{ 139, 0x11}, { 149, 0x21}, { 169, 0x02}, { 179, 0x12},
1043*4882a593Smuzhiyun 	{ 199, 0x22}, { 219, 0x03}, { 239, 0x13}, { 249, 0x23},
1044*4882a593Smuzhiyun 	{ 269, 0x04}, { 299, 0x14}, { 329, 0x05}, { 359, 0x15},
1045*4882a593Smuzhiyun 	{ 399, 0x25}, { 449, 0x06}, { 499, 0x16}, { 549, 0x07},
1046*4882a593Smuzhiyun 	{ 599, 0x17}, { 649, 0x08}, { 699, 0x18}, { 749, 0x09},
1047*4882a593Smuzhiyun 	{ 799, 0x19}, { 849, 0x29}, { 899, 0x39}, { 949, 0x0a},
1048*4882a593Smuzhiyun 	{ 999, 0x1a}
1049*4882a593Smuzhiyun };
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun static const struct hsfreq_range rk3326_mipidphy_hsfreq_ranges[] = {
1052*4882a593Smuzhiyun 	{ 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
1053*4882a593Smuzhiyun 	{ 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
1054*4882a593Smuzhiyun 	{ 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
1055*4882a593Smuzhiyun 	{1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
1056*4882a593Smuzhiyun };
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun static const struct hsfreq_range rk3326s_mipidphy_hsfreq_ranges[] = {
1059*4882a593Smuzhiyun 	{ 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
1060*4882a593Smuzhiyun 	{ 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e},
1061*4882a593Smuzhiyun 	{ 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e},
1062*4882a593Smuzhiyun };
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun static const struct hsfreq_range rk3368_mipidphy_hsfreq_ranges[] = {
1065*4882a593Smuzhiyun 	{ 109, 0x00}, { 149, 0x01}, { 199, 0x02}, { 249, 0x03},
1066*4882a593Smuzhiyun 	{ 299, 0x04}, { 399, 0x05}, { 499, 0x06}, { 599, 0x07},
1067*4882a593Smuzhiyun 	{ 699, 0x08}, { 799, 0x09}, { 899, 0x0a}, {1099, 0x0b},
1068*4882a593Smuzhiyun 	{1249, 0x0c}, {1349, 0x0d}, {1500, 0x0e}
1069*4882a593Smuzhiyun };
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun static const struct hsfreq_range rk3399_mipidphy_hsfreq_ranges[] = {
1072*4882a593Smuzhiyun 	{  89, 0x00}, {  99, 0x10}, { 109, 0x20}, { 129, 0x01},
1073*4882a593Smuzhiyun 	{ 139, 0x11}, { 149, 0x21}, { 169, 0x02}, { 179, 0x12},
1074*4882a593Smuzhiyun 	{ 199, 0x22}, { 219, 0x03}, { 239, 0x13}, { 249, 0x23},
1075*4882a593Smuzhiyun 	{ 269, 0x04}, { 299, 0x14}, { 329, 0x05}, { 359, 0x15},
1076*4882a593Smuzhiyun 	{ 399, 0x25}, { 449, 0x06}, { 499, 0x16}, { 549, 0x07},
1077*4882a593Smuzhiyun 	{ 599, 0x17}, { 649, 0x08}, { 699, 0x18}, { 749, 0x09},
1078*4882a593Smuzhiyun 	{ 799, 0x19}, { 849, 0x29}, { 899, 0x39}, { 949, 0x0a},
1079*4882a593Smuzhiyun 	{ 999, 0x1a}, {1049, 0x2a}, {1099, 0x3a}, {1149, 0x0b},
1080*4882a593Smuzhiyun 	{1199, 0x1b}, {1249, 0x2b}, {1299, 0x3b}, {1349, 0x0c},
1081*4882a593Smuzhiyun 	{1399, 0x1c}, {1449, 0x2c}, {1500, 0x3c}
1082*4882a593Smuzhiyun };
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun static const char * const rk1808_mipidphy_clks[] = {
1085*4882a593Smuzhiyun 	"pclk",
1086*4882a593Smuzhiyun };
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun static const char * const rk3288_mipidphy_clks[] = {
1089*4882a593Smuzhiyun 	"dphy-ref",
1090*4882a593Smuzhiyun 	"pclk",
1091*4882a593Smuzhiyun };
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun static const char * const rk3326_mipidphy_clks[] = {
1094*4882a593Smuzhiyun 	"dphy-ref",
1095*4882a593Smuzhiyun };
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun static const char * const rk3368_mipidphy_clks[] = {
1098*4882a593Smuzhiyun 	"pclk_dphyrx",
1099*4882a593Smuzhiyun };
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun static const char * const rk3399_mipidphy_clks[] = {
1102*4882a593Smuzhiyun 	"dphy-ref",
1103*4882a593Smuzhiyun 	"dphy-cfg",
1104*4882a593Smuzhiyun 	"grf",
1105*4882a593Smuzhiyun 	"pclk_mipi_dsi",
1106*4882a593Smuzhiyun };
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun static const char * const rv1126_mipidphy_clks[] = {
1109*4882a593Smuzhiyun 	"pclk",
1110*4882a593Smuzhiyun };
1111*4882a593Smuzhiyun 
default_mipidphy_individual_init(struct mipidphy_priv * priv)1112*4882a593Smuzhiyun static void default_mipidphy_individual_init(struct mipidphy_priv *priv)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
rk3368_mipidphy_individual_init(struct mipidphy_priv * priv)1116*4882a593Smuzhiyun static void rk3368_mipidphy_individual_init(struct mipidphy_priv *priv)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	/* isp select */
1119*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_ISP_MIPI_CSI_HOST_SEL, 1);
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun 
rk3399_mipidphy_individual_init(struct mipidphy_priv * priv)1122*4882a593Smuzhiyun static void rk3399_mipidphy_individual_init(struct mipidphy_priv *priv)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun 	/*
1125*4882a593Smuzhiyun 	 * According to the sequence of RK3399_TXRX_DPHY, the setting of isp0 mipi
1126*4882a593Smuzhiyun 	 * will affect txrx dphy in default state of grf_soc_con24.
1127*4882a593Smuzhiyun 	 */
1128*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_SRC_SEL, 0);
1129*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_MASTERSLAVEZ, 0);
1130*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_BASEDIR, 0);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DVP_V18SEL, 0x1);
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
rv1126_mipidphy_individual_init(struct mipidphy_priv * priv)1135*4882a593Smuzhiyun static void rv1126_mipidphy_individual_init(struct mipidphy_priv *priv)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun 	struct device *dev = priv->dev;
1138*4882a593Smuzhiyun 	struct device_node *parent = dev->of_node;
1139*4882a593Smuzhiyun 	struct device_node *remote = NULL;
1140*4882a593Smuzhiyun 	u8 val, sel;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	priv->grf_regs = priv->phy_index ?
1143*4882a593Smuzhiyun 		rv1126_grf_dphy1_regs : rv1126_grf_dphy0_regs;
1144*4882a593Smuzhiyun 	val = read_grf_reg(priv, GRF_DPHY_SEL);
1145*4882a593Smuzhiyun 	/* get port1 remote endpoint info */
1146*4882a593Smuzhiyun 	remote = of_graph_get_remote_node(parent, 1, 0);
1147*4882a593Smuzhiyun 	if (remote) {
1148*4882a593Smuzhiyun 		if (strstr(remote->name, "isp"))
1149*4882a593Smuzhiyun 			sel = !priv->phy_index ? 0 : RV1126_GRF_PHY1_SEL_ISP;
1150*4882a593Smuzhiyun 		else
1151*4882a593Smuzhiyun 			sel = !priv->phy_index ? 0 :
1152*4882a593Smuzhiyun 				RV1126_GRF_PHY1_SEL_CIF | RV1126_GRF_PHY1_SEL_CIFLITE;
1153*4882a593Smuzhiyun 		of_node_put(remote);
1154*4882a593Smuzhiyun 		write_grf_reg(priv, GRF_DPHY_SEL, val | sel);
1155*4882a593Smuzhiyun 	}
1156*4882a593Smuzhiyun }
1157*4882a593Smuzhiyun 
mipidphy_rx_stream_on(struct mipidphy_priv * priv,struct v4l2_subdev * sd)1158*4882a593Smuzhiyun static int mipidphy_rx_stream_on(struct mipidphy_priv *priv,
1159*4882a593Smuzhiyun 				 struct v4l2_subdev *sd)
1160*4882a593Smuzhiyun {
1161*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
1162*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
1163*4882a593Smuzhiyun 	const struct dphy_drv_data *drv_data = priv->drv_data;
1164*4882a593Smuzhiyun 	const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges;
1165*4882a593Smuzhiyun 	int num_hsfreq_ranges = drv_data->num_hsfreq_ranges;
1166*4882a593Smuzhiyun 	int i, hsfreq = 0;
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun 	if (!sensor_sd)
1169*4882a593Smuzhiyun 		return -ENODEV;
1170*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
1171*4882a593Smuzhiyun 	if (!sensor)
1172*4882a593Smuzhiyun 		return -ENODEV;
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	for (i = 0; i < num_hsfreq_ranges; i++) {
1175*4882a593Smuzhiyun 		if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) {
1176*4882a593Smuzhiyun 			hsfreq = hsfreq_ranges[i].cfg_bit;
1177*4882a593Smuzhiyun 			break;
1178*4882a593Smuzhiyun 		}
1179*4882a593Smuzhiyun 	}
1180*4882a593Smuzhiyun 
1181*4882a593Smuzhiyun 	if (i == num_hsfreq_ranges) {
1182*4882a593Smuzhiyun 		i = num_hsfreq_ranges - 1;
1183*4882a593Smuzhiyun 		dev_warn(priv->dev, "data rate: %lld mbps, max support %d mbps",
1184*4882a593Smuzhiyun 			 priv->data_rate_mbps, hsfreq_ranges[i].range_h + 1);
1185*4882a593Smuzhiyun 		hsfreq = hsfreq_ranges[i].cfg_bit;
1186*4882a593Smuzhiyun 	}
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun 	/* RK3288 isp connected to phy0-rx */
1189*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_CON_ISP_DPHY_SEL, 0);
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 	/* Belowed is the sequence of mipi configuration */
1192*4882a593Smuzhiyun 	/* Step1: set RSTZ = 1'b0, phy0 controlled by isp0 */
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	/* Step2: set SHUTDOWNZ = 1'b0, controlled by isp0 */
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun 	/* Step3: set TESTCLEAR = 1'b1 */
1197*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLK, 1);
1198*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 1);
1199*4882a593Smuzhiyun 	usleep_range(100, 150);
1200*4882a593Smuzhiyun 
1201*4882a593Smuzhiyun 	/* Step4: apply REFCLK signal with the appropriate frequency */
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	/* Step5: apply CFG_CLK signal with the appropriate frequency */
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	/* Step6: set MASTERSLAVEZ = 1'b0 (for SLAVE), phy0 default is slave */
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	/* Step7: set BASEDIR_N = 1’b1 (for SLAVE), phy0 default is slave */
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 	/*
1210*4882a593Smuzhiyun 	 * Step8: set all REQUEST inputs to zero, need to wait 15ns:
1211*4882a593Smuzhiyun 	 * step8.1:set lan turndisab as 1
1212*4882a593Smuzhiyun 	 * step8.2:set lan turnrequest as 0
1213*4882a593Smuzhiyun 	 */
1214*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TURNDISABLE, 0xf);
1215*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_FORCERXMODE, 0);
1216*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TURNREQUEST, 0);
1217*4882a593Smuzhiyun 	usleep_range(100, 150);
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun 	/* Step9: set TESTCLR to low, need to wait 15ns */
1220*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_TESTCLR, 0);
1221*4882a593Smuzhiyun 	usleep_range(100, 150);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	/*
1224*4882a593Smuzhiyun 	 * Step10: configure Test Code 0x44 hsfreqrange according to values
1225*4882a593Smuzhiyun 	 * step10.1:set clock lane
1226*4882a593Smuzhiyun 	 * step10.2:set hsfreqrange by lane0(test code 0x44)
1227*4882a593Smuzhiyun 	 */
1228*4882a593Smuzhiyun 	hsfreq <<= 1;
1229*4882a593Smuzhiyun 	mipidphy0_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0);
1230*4882a593Smuzhiyun 	mipidphy0_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq);
1231*4882a593Smuzhiyun 	mipidphy0_wr_reg(priv, LANE1_HS_RX_CONTROL, hsfreq);
1232*4882a593Smuzhiyun 	mipidphy0_wr_reg(priv, LANE2_HS_RX_CONTROL, hsfreq);
1233*4882a593Smuzhiyun 	mipidphy0_wr_reg(priv, LANE3_HS_RX_CONTROL, hsfreq);
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	/* Step11: Configure analog references: of Test Code 0x22 */
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	/* Step12: Set ENABLE_N=1'b1, need to wait 5ns */
1238*4882a593Smuzhiyun 	/* set lane num */
1239*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX0_ENABLE, GENMASK(sensor->lanes - 1, 0));
1240*4882a593Smuzhiyun 
1241*4882a593Smuzhiyun 	/* Step13: Set SHUTDOWNZ=1'b1, controlled by isp need to wait 5ns */
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	/* Step14: Set RSTZ=1'b1, controlled by isp */
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	/*
1246*4882a593Smuzhiyun 	 * Step15: Wait until STOPSTATEDATA_N & STOPSTATECLK
1247*4882a593Smuzhiyun 	 *         outputs are asserted
1248*4882a593Smuzhiyun 	 */
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	usleep_range(100, 150);
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun 	return 0;
1253*4882a593Smuzhiyun }
1254*4882a593Smuzhiyun 
mipidphy_txrx_stream_on(struct mipidphy_priv * priv,struct v4l2_subdev * sd)1255*4882a593Smuzhiyun static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
1256*4882a593Smuzhiyun 				   struct v4l2_subdev *sd)
1257*4882a593Smuzhiyun {
1258*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
1259*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
1260*4882a593Smuzhiyun 	const struct dphy_drv_data *drv_data = priv->drv_data;
1261*4882a593Smuzhiyun 	const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges;
1262*4882a593Smuzhiyun 	int num_hsfreq_ranges = drv_data->num_hsfreq_ranges;
1263*4882a593Smuzhiyun 	int i, hsfreq = 0;
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun 	if (!sensor_sd)
1266*4882a593Smuzhiyun 		return -ENODEV;
1267*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
1268*4882a593Smuzhiyun 	if (!sensor)
1269*4882a593Smuzhiyun 		return -ENODEV;
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 	for (i = 0; i < num_hsfreq_ranges; i++) {
1272*4882a593Smuzhiyun 		if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) {
1273*4882a593Smuzhiyun 			hsfreq = hsfreq_ranges[i].cfg_bit;
1274*4882a593Smuzhiyun 			break;
1275*4882a593Smuzhiyun 		}
1276*4882a593Smuzhiyun 	}
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	if (i == num_hsfreq_ranges) {
1279*4882a593Smuzhiyun 		i = num_hsfreq_ranges - 1;
1280*4882a593Smuzhiyun 		dev_warn(priv->dev, "data rate: %lld mbps, max support %d mbps",
1281*4882a593Smuzhiyun 			 priv->data_rate_mbps, hsfreq_ranges[i].range_h + 1);
1282*4882a593Smuzhiyun 		hsfreq = hsfreq_ranges[i].cfg_bit;
1283*4882a593Smuzhiyun 	}
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun 	/*
1286*4882a593Smuzhiyun 	 *Config rk3288:
1287*4882a593Smuzhiyun 	 *step1:rk3288 isp connected to phy1-rx
1288*4882a593Smuzhiyun 	 *step2:rk3288 phy1-rx test bus connected to csi host
1289*4882a593Smuzhiyun 	 *step3:rk3288 phy1-rx source selected as: isp = 1'b1,csi-host = 1'b0
1290*4882a593Smuzhiyun 	 */
1291*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_CON_ISP_DPHY_SEL, 1);
1292*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DSI_CSI_TESTBUS_SEL, 1);
1293*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_RX1_SRC_SEL, 1);
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	/*
1296*4882a593Smuzhiyun 	 * Config rk3399:
1297*4882a593Smuzhiyun 	 * step1:rk3399 phy1-rx source selected as:1'b0=isp1,1'b1=isp0
1298*4882a593Smuzhiyun 	 */
1299*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_SRC_SEL, 0);
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	/* Belowed is the sequence of mipi configuration */
1302*4882a593Smuzhiyun 	/* Step1: set RSTZ = 1'b0, phy1-rx controlled by isp */
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	/* Step2: set SHUTDOWNZ = 1'b0, phy1-rx controlled by isp */
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	/* Step3: set TESTCLR= 1'b1,TESTCLK=1'b1 */
1307*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL0, PHY_TESTCLR | PHY_TESTCLK);
1308*4882a593Smuzhiyun 	usleep_range(100, 150);
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun 	/* Step4: apply REFCLK signal with the appropriate frequency */
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	/* Step5: apply CFG_CLK signal with the appropriate frequency */
1313*4882a593Smuzhiyun 
1314*4882a593Smuzhiyun 	/*
1315*4882a593Smuzhiyun 	 * Step6: set MASTERSLAVEZ = 1'b0 (for SLAVE),
1316*4882a593Smuzhiyun 	 *        phy1 is set as slave,controlled by isp
1317*4882a593Smuzhiyun 	 */
1318*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_MASTERSLAVEZ, 0);
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	/*
1321*4882a593Smuzhiyun 	 * Step7: set BASEDIR_N = 1’b1 (for SLAVE),
1322*4882a593Smuzhiyun 	 *        phy1 is set as slave,controlled by isp
1323*4882a593Smuzhiyun 	 */
1324*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_BASEDIR, 1);
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	/* Step8: set all REQUEST inputs to zero, need to wait 15ns */
1327*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_FORCERXMODE, 0);
1328*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_FORCETXSTOPMODE, 0);
1329*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_TURNREQUEST, 0);
1330*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_TURNDISABLE, 0xf);
1331*4882a593Smuzhiyun 	usleep_range(100, 150);
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	/* Step9: set TESTCLR=1'b0,TESTCLK=1'b1 need to wait 15ns */
1334*4882a593Smuzhiyun 	write_txrx_reg(priv, TXRX_PHY_TEST_CTRL0, PHY_TESTCLK);
1335*4882a593Smuzhiyun 	usleep_range(100, 150);
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 	/*
1338*4882a593Smuzhiyun 	 * Step10: configure Test Code 0x44 hsfreqrange according to values
1339*4882a593Smuzhiyun 	 * step10.1:set clock lane
1340*4882a593Smuzhiyun 	 * step10.2:set hsfreqrange by lane0(test code 0x44)
1341*4882a593Smuzhiyun 	 */
1342*4882a593Smuzhiyun 	hsfreq <<= 1;
1343*4882a593Smuzhiyun 	mipidphy1_wr_reg(priv, CLOCK_LANE_HS_RX_CONTROL, 0);
1344*4882a593Smuzhiyun 	mipidphy1_wr_reg(priv, LANE0_HS_RX_CONTROL, hsfreq);
1345*4882a593Smuzhiyun 	mipidphy1_wr_reg(priv, LANE1_HS_RX_CONTROL, 0);
1346*4882a593Smuzhiyun 	mipidphy1_wr_reg(priv, LANE2_HS_RX_CONTROL, 0);
1347*4882a593Smuzhiyun 	mipidphy1_wr_reg(priv, LANE3_HS_RX_CONTROL, 0);
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	/* Step11: Configure analog references: of Test Code 0x22 */
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 	/*
1352*4882a593Smuzhiyun 	 * Step12: Set ENABLE_N=1'b1, need to wait 5ns
1353*4882a593Smuzhiyun 	 * Set lane num:
1354*4882a593Smuzhiyun 	 * for 3288,controlled by isp,enable lanes actually
1355*4882a593Smuzhiyun 	 * is set by grf_soc_con9[12:15];
1356*4882a593Smuzhiyun 	 * for 3399,controlled by isp1,enable lanes actually
1357*4882a593Smuzhiyun 	 * is set by isp1,
1358*4882a593Smuzhiyun 	 * if run 3399 here operates grf_soc_con23[0:3]
1359*4882a593Smuzhiyun 	 */
1360*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_TX1RX1_ENABLE,
1361*4882a593Smuzhiyun 		      GENMASK(sensor->lanes - 1, 0));
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun 	/*
1364*4882a593Smuzhiyun 	 * Step13:Set SHUTDOWNZ=1'b1, phy1-rx controlled by isp,
1365*4882a593Smuzhiyun 	 *        need to wait 5ns
1366*4882a593Smuzhiyun 	 */
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 	/* Step14:Set RSTZ=1'b1, phy1-rx controlled by isp*/
1369*4882a593Smuzhiyun 
1370*4882a593Smuzhiyun 	/*
1371*4882a593Smuzhiyun 	 * Step15:Wait until STOPSTATEDATA_N & STOPSTATECLK
1372*4882a593Smuzhiyun 	 *        outputs are asserted
1373*4882a593Smuzhiyun 	 */
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	usleep_range(100, 150);
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun 	return 0;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun 
csi_mipidphy_stream_on(struct mipidphy_priv * priv,struct v4l2_subdev * sd)1380*4882a593Smuzhiyun static int csi_mipidphy_stream_on(struct mipidphy_priv *priv,
1381*4882a593Smuzhiyun 				  struct v4l2_subdev *sd)
1382*4882a593Smuzhiyun {
1383*4882a593Smuzhiyun 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
1384*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
1385*4882a593Smuzhiyun 	const struct dphy_drv_data *drv_data = priv->drv_data;
1386*4882a593Smuzhiyun 	const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges;
1387*4882a593Smuzhiyun 	int num_hsfreq_ranges = drv_data->num_hsfreq_ranges;
1388*4882a593Smuzhiyun 	int i, hsfreq = 0;
1389*4882a593Smuzhiyun 	u32 val = 0;
1390*4882a593Smuzhiyun 	u32 clk_mode = 0x03;
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun 	if (!sensor_sd)
1393*4882a593Smuzhiyun 		return -ENODEV;
1394*4882a593Smuzhiyun 	sensor = sd_to_sensor(priv, sensor_sd);
1395*4882a593Smuzhiyun 	if (!sensor)
1396*4882a593Smuzhiyun 		return -ENODEV;
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DVP_V18SEL, 0x1);
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 	/* phy start */
1401*4882a593Smuzhiyun 	write_csiphy_reg(priv, CSIPHY_CTRL_PWRCTL, 0xe4);
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun 	/* set data lane num and enable clock lane */
1404*4882a593Smuzhiyun 	write_csiphy_reg(priv, CSIPHY_CTRL_LANE_ENABLE,
1405*4882a593Smuzhiyun 		((GENMASK(sensor->lanes - 1, 0) << MIPI_CSI_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
1406*4882a593Smuzhiyun 		(0x1 << MIPI_CSI_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT) | 0x1));
1407*4882a593Smuzhiyun 
1408*4882a593Smuzhiyun 	/* Reset dphy analog part */
1409*4882a593Smuzhiyun 	write_csiphy_reg(priv, CSIPHY_CTRL_PWRCTL, 0xe0);
1410*4882a593Smuzhiyun 	usleep_range(500, 1000);
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
1413*4882a593Smuzhiyun 		/* Reset dphy digital part */
1414*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_CTRL_DIG_RST, 0x1e);
1415*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_CTRL_DIG_RST, 0x1f);
1416*4882a593Smuzhiyun 		if (drv_data->chip_id == CHIP_ID_RK3326S) {
1417*4882a593Smuzhiyun 			if (sensor->mbus.flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK)
1418*4882a593Smuzhiyun 				clk_mode = 0x03;
1419*4882a593Smuzhiyun 			else if (sensor->mbus.flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK)
1420*4882a593Smuzhiyun 				clk_mode = 0;
1421*4882a593Smuzhiyun 			write_csiphy_reg(priv, CSIPHY_CLK_MODE, clk_mode);
1422*4882a593Smuzhiyun 		}
1423*4882a593Smuzhiyun 	} else {
1424*4882a593Smuzhiyun 		/* Disable MIPI internal logical and switch to LVDS bank */
1425*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_CTRL_DIG_RST, 0x3e);
1426*4882a593Smuzhiyun 		/* Enable LVDS mode */
1427*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_MIPI_LVDS_MODEL, 0x4);
1428*4882a593Smuzhiyun 		switch (sensor->format.code) {
1429*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_Y12_1X12:
1430*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SRGGB12_1X12:
1431*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SBGGR12_1X12:
1432*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SGBRG12_1X12:
1433*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SGRBG12_1X12:
1434*4882a593Smuzhiyun 			val = 0x1f; //12bit
1435*4882a593Smuzhiyun 			break;
1436*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_Y10_1X10:
1437*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SBGGR10_1X10:
1438*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SRGGB10_1X10:
1439*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SGBRG10_1X10:
1440*4882a593Smuzhiyun 		case MEDIA_BUS_FMT_SGRBG10_1X10:
1441*4882a593Smuzhiyun 			val = 0xf; //10bit
1442*4882a593Smuzhiyun 			break;
1443*4882a593Smuzhiyun 		default:
1444*4882a593Smuzhiyun 			val = 0x2f; //8bit
1445*4882a593Smuzhiyun 		}
1446*4882a593Smuzhiyun 		/* Enable LVDS internal logical and select bit mode */
1447*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_LVDS_MODE, val);
1448*4882a593Smuzhiyun 	}
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun 	/* not into receive mode/wait stopstate */
1451*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_CSIPHY_FORCERXMODE, 0x0);
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun 	/* enable calibration */
1454*4882a593Smuzhiyun 	if (priv->data_rate_mbps > 1500) {
1455*4882a593Smuzhiyun 		write_csiphy_reg(priv, CSIPHY_CLK_CALIB_ENABLE, 0x80);
1456*4882a593Smuzhiyun 		if (sensor->lanes > 0x00)
1457*4882a593Smuzhiyun 			write_csiphy_reg(priv, CSIPHY_LANE0_CALIB_ENABLE, 0x80);
1458*4882a593Smuzhiyun 		if (sensor->lanes > 0x01)
1459*4882a593Smuzhiyun 			write_csiphy_reg(priv, CSIPHY_LANE1_CALIB_ENABLE, 0x80);
1460*4882a593Smuzhiyun 		if (sensor->lanes > 0x02)
1461*4882a593Smuzhiyun 			write_csiphy_reg(priv, CSIPHY_LANE2_CALIB_ENABLE, 0x80);
1462*4882a593Smuzhiyun 		if (sensor->lanes > 0x03)
1463*4882a593Smuzhiyun 			write_csiphy_reg(priv, CSIPHY_LANE3_CALIB_ENABLE, 0x80);
1464*4882a593Smuzhiyun 	}
1465*4882a593Smuzhiyun 
1466*4882a593Smuzhiyun 	/* set clock lane and data lane */
1467*4882a593Smuzhiyun 	for (i = 0; i < num_hsfreq_ranges; i++) {
1468*4882a593Smuzhiyun 		if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) {
1469*4882a593Smuzhiyun 			hsfreq = hsfreq_ranges[i].cfg_bit;
1470*4882a593Smuzhiyun 			break;
1471*4882a593Smuzhiyun 		}
1472*4882a593Smuzhiyun 	}
1473*4882a593Smuzhiyun 
1474*4882a593Smuzhiyun 	if (i == num_hsfreq_ranges) {
1475*4882a593Smuzhiyun 		i = num_hsfreq_ranges - 1;
1476*4882a593Smuzhiyun 		dev_warn(priv->dev, "data rate: %lld mbps, max support %d mbps",
1477*4882a593Smuzhiyun 			 priv->data_rate_mbps, hsfreq_ranges[i].range_h + 1);
1478*4882a593Smuzhiyun 		hsfreq = hsfreq_ranges[i].cfg_bit;
1479*4882a593Smuzhiyun 	}
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun 	csi_mipidphy_wr_ths_settle(priv, hsfreq, MIPI_DPHY_LANE_CLOCK);
1482*4882a593Smuzhiyun 	if (sensor->lanes > 0x00)
1483*4882a593Smuzhiyun 		csi_mipidphy_wr_ths_settle(priv, hsfreq, MIPI_DPHY_LANE_DATA0);
1484*4882a593Smuzhiyun 	if (sensor->lanes > 0x01)
1485*4882a593Smuzhiyun 		csi_mipidphy_wr_ths_settle(priv, hsfreq, MIPI_DPHY_LANE_DATA1);
1486*4882a593Smuzhiyun 	if (sensor->lanes > 0x02)
1487*4882a593Smuzhiyun 		csi_mipidphy_wr_ths_settle(priv, hsfreq, MIPI_DPHY_LANE_DATA2);
1488*4882a593Smuzhiyun 	if (sensor->lanes > 0x03)
1489*4882a593Smuzhiyun 		csi_mipidphy_wr_ths_settle(priv, hsfreq, MIPI_DPHY_LANE_DATA3);
1490*4882a593Smuzhiyun 
1491*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_CLK_INV_SEL, 0x1);
1492*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_CSIPHY_CLKLANE_EN, 0x1);
1493*4882a593Smuzhiyun 	write_grf_reg(priv, GRF_DPHY_CSIPHY_DATALANE_EN,
1494*4882a593Smuzhiyun 		      GENMASK(sensor->lanes - 1, 0));
1495*4882a593Smuzhiyun 	return 0;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun 
csi_mipidphy_stream_off(struct mipidphy_priv * priv,struct v4l2_subdev * sd)1498*4882a593Smuzhiyun static int csi_mipidphy_stream_off(struct mipidphy_priv *priv,
1499*4882a593Smuzhiyun 				   struct v4l2_subdev *sd)
1500*4882a593Smuzhiyun {
1501*4882a593Smuzhiyun 	/* disable all lanes */
1502*4882a593Smuzhiyun 	write_csiphy_reg(priv, CSIPHY_CTRL_LANE_ENABLE, 0x01);
1503*4882a593Smuzhiyun 	/* disable pll and ldo */
1504*4882a593Smuzhiyun 	write_csiphy_reg(priv, CSIPHY_CTRL_PWRCTL, 0xe3);
1505*4882a593Smuzhiyun 	usleep_range(500, 1000);
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun 	return 0;
1508*4882a593Smuzhiyun }
1509*4882a593Smuzhiyun 
1510*4882a593Smuzhiyun static const struct dphy_drv_data rk1808_mipidphy_drv_data = {
1511*4882a593Smuzhiyun 	.clks = rk1808_mipidphy_clks,
1512*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk1808_mipidphy_clks),
1513*4882a593Smuzhiyun 	.hsfreq_ranges = rk1808_rv1126_mipidphy_hsfreq_ranges,
1514*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk1808_rv1126_mipidphy_hsfreq_ranges),
1515*4882a593Smuzhiyun 	.grf_regs = rk1808_grf_dphy_regs,
1516*4882a593Smuzhiyun 	.csiphy_regs = rk1808_csiphy_regs,
1517*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_CSI_HOST,
1518*4882a593Smuzhiyun 	.individual_init = default_mipidphy_individual_init,
1519*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK1808,
1520*4882a593Smuzhiyun };
1521*4882a593Smuzhiyun 
1522*4882a593Smuzhiyun static const struct dphy_drv_data rk3288_mipidphy_drv_data = {
1523*4882a593Smuzhiyun 	.clks = rk3288_mipidphy_clks,
1524*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk3288_mipidphy_clks),
1525*4882a593Smuzhiyun 	.hsfreq_ranges = rk3288_mipidphy_hsfreq_ranges,
1526*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk3288_mipidphy_hsfreq_ranges),
1527*4882a593Smuzhiyun 	.grf_regs = rk3288_grf_dphy_regs,
1528*4882a593Smuzhiyun 	.txrx_regs = rk3288_txrx_regs,
1529*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_GRF_ONLY,
1530*4882a593Smuzhiyun 	.individual_init = default_mipidphy_individual_init,
1531*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK3288,
1532*4882a593Smuzhiyun };
1533*4882a593Smuzhiyun 
1534*4882a593Smuzhiyun static const struct dphy_drv_data rk3326_mipidphy_drv_data = {
1535*4882a593Smuzhiyun 	.clks = rk3326_mipidphy_clks,
1536*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk3326_mipidphy_clks),
1537*4882a593Smuzhiyun 	.hsfreq_ranges = rk3326_mipidphy_hsfreq_ranges,
1538*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk3326_mipidphy_hsfreq_ranges),
1539*4882a593Smuzhiyun 	.grf_regs = rk3326_grf_dphy_regs,
1540*4882a593Smuzhiyun 	.csiphy_regs = rk3326_csiphy_regs,
1541*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_CSI_HOST,
1542*4882a593Smuzhiyun 	.individual_init = default_mipidphy_individual_init,
1543*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK3326,
1544*4882a593Smuzhiyun };
1545*4882a593Smuzhiyun 
1546*4882a593Smuzhiyun static const struct dphy_drv_data rk3326s_mipidphy_drv_data = {
1547*4882a593Smuzhiyun 	.clks = rk3326_mipidphy_clks,
1548*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk3326_mipidphy_clks),
1549*4882a593Smuzhiyun 	.hsfreq_ranges = rk3326s_mipidphy_hsfreq_ranges,
1550*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk3326s_mipidphy_hsfreq_ranges),
1551*4882a593Smuzhiyun 	.grf_regs = rk3326_grf_dphy_regs,
1552*4882a593Smuzhiyun 	.csiphy_regs = rk3326s_csiphy_regs,
1553*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_CSI_HOST,
1554*4882a593Smuzhiyun 	.individual_init = default_mipidphy_individual_init,
1555*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK3326S,
1556*4882a593Smuzhiyun };
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun static const struct dphy_drv_data rk3368_mipidphy_drv_data = {
1559*4882a593Smuzhiyun 	.clks = rk3368_mipidphy_clks,
1560*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk3368_mipidphy_clks),
1561*4882a593Smuzhiyun 	.hsfreq_ranges = rk3368_mipidphy_hsfreq_ranges,
1562*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk3368_mipidphy_hsfreq_ranges),
1563*4882a593Smuzhiyun 	.grf_regs = rk3368_grf_dphy_regs,
1564*4882a593Smuzhiyun 	.csiphy_regs = rk3368_csiphy_regs,
1565*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_CSI_HOST,
1566*4882a593Smuzhiyun 	.individual_init = rk3368_mipidphy_individual_init,
1567*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK3368,
1568*4882a593Smuzhiyun };
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun static const struct dphy_drv_data rk3399_mipidphy_drv_data = {
1571*4882a593Smuzhiyun 	.clks = rk3399_mipidphy_clks,
1572*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rk3399_mipidphy_clks),
1573*4882a593Smuzhiyun 	.hsfreq_ranges = rk3399_mipidphy_hsfreq_ranges,
1574*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk3399_mipidphy_hsfreq_ranges),
1575*4882a593Smuzhiyun 	.grf_regs = rk3399_grf_dphy_regs,
1576*4882a593Smuzhiyun 	.txrx_regs = rk3399_txrx_regs,
1577*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_GRF_ONLY,
1578*4882a593Smuzhiyun 	.individual_init = rk3399_mipidphy_individual_init,
1579*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK3399,
1580*4882a593Smuzhiyun };
1581*4882a593Smuzhiyun 
1582*4882a593Smuzhiyun static const struct dphy_drv_data rv1126_mipidphy_drv_data = {
1583*4882a593Smuzhiyun 	.clks = rv1126_mipidphy_clks,
1584*4882a593Smuzhiyun 	.num_clks = ARRAY_SIZE(rv1126_mipidphy_clks),
1585*4882a593Smuzhiyun 	.hsfreq_ranges = rk1808_rv1126_mipidphy_hsfreq_ranges,
1586*4882a593Smuzhiyun 	.num_hsfreq_ranges = ARRAY_SIZE(rk1808_rv1126_mipidphy_hsfreq_ranges),
1587*4882a593Smuzhiyun 	.csiphy_regs = rv1126_csiphy_regs,
1588*4882a593Smuzhiyun 	.ctl_type = MIPI_DPHY_CTL_CSI_HOST,
1589*4882a593Smuzhiyun 	.individual_init = rv1126_mipidphy_individual_init,
1590*4882a593Smuzhiyun 	.chip_id = CHIP_ID_RK1126,
1591*4882a593Smuzhiyun };
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun static const struct of_device_id rockchip_mipidphy_match_id[] = {
1594*4882a593Smuzhiyun 	{
1595*4882a593Smuzhiyun 		.compatible = "rockchip,rk1808-mipi-dphy-rx",
1596*4882a593Smuzhiyun 		.data = &rk1808_mipidphy_drv_data,
1597*4882a593Smuzhiyun 	},
1598*4882a593Smuzhiyun 	{
1599*4882a593Smuzhiyun 		.compatible = "rockchip,rk3288-mipi-dphy",
1600*4882a593Smuzhiyun 		.data = &rk3288_mipidphy_drv_data,
1601*4882a593Smuzhiyun 	},
1602*4882a593Smuzhiyun 	{
1603*4882a593Smuzhiyun 		.compatible = "rockchip,rk3326-mipi-dphy",
1604*4882a593Smuzhiyun 		.data = &rk3326_mipidphy_drv_data,
1605*4882a593Smuzhiyun 	},
1606*4882a593Smuzhiyun 	{
1607*4882a593Smuzhiyun 		.compatible = "rockchip,rk3326s-mipi-dphy",
1608*4882a593Smuzhiyun 		.data = &rk3326s_mipidphy_drv_data,
1609*4882a593Smuzhiyun 	},
1610*4882a593Smuzhiyun 	{
1611*4882a593Smuzhiyun 		.compatible = "rockchip,rk3368-mipi-dphy",
1612*4882a593Smuzhiyun 		.data = &rk3368_mipidphy_drv_data,
1613*4882a593Smuzhiyun 	},
1614*4882a593Smuzhiyun 	{
1615*4882a593Smuzhiyun 		.compatible = "rockchip,rk3399-mipi-dphy",
1616*4882a593Smuzhiyun 		.data = &rk3399_mipidphy_drv_data,
1617*4882a593Smuzhiyun 	},
1618*4882a593Smuzhiyun 	{
1619*4882a593Smuzhiyun 		.compatible = "rockchip,rv1126-csi-dphy",
1620*4882a593Smuzhiyun 		.data = &rv1126_mipidphy_drv_data,
1621*4882a593Smuzhiyun 	},
1622*4882a593Smuzhiyun 	{}
1623*4882a593Smuzhiyun };
1624*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_mipidphy_match_id);
1625*4882a593Smuzhiyun 
1626*4882a593Smuzhiyun /* The .bound() notifier callback when a match is found */
1627*4882a593Smuzhiyun static int
rockchip_mipidphy_notifier_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_subdev * asd)1628*4882a593Smuzhiyun rockchip_mipidphy_notifier_bound(struct v4l2_async_notifier *notifier,
1629*4882a593Smuzhiyun 				 struct v4l2_subdev *sd,
1630*4882a593Smuzhiyun 				 struct v4l2_async_subdev *asd)
1631*4882a593Smuzhiyun {
1632*4882a593Smuzhiyun 	struct mipidphy_priv *priv = container_of(notifier,
1633*4882a593Smuzhiyun 						  struct mipidphy_priv,
1634*4882a593Smuzhiyun 						  notifier);
1635*4882a593Smuzhiyun 	struct sensor_async_subdev *s_asd = container_of(asd,
1636*4882a593Smuzhiyun 					struct sensor_async_subdev, asd);
1637*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor;
1638*4882a593Smuzhiyun 	unsigned int pad, ret;
1639*4882a593Smuzhiyun 
1640*4882a593Smuzhiyun 	if (priv->num_sensors == ARRAY_SIZE(priv->sensors))
1641*4882a593Smuzhiyun 		return -EBUSY;
1642*4882a593Smuzhiyun 
1643*4882a593Smuzhiyun 	sensor = &priv->sensors[priv->num_sensors++];
1644*4882a593Smuzhiyun 	sensor->lanes = s_asd->lanes;
1645*4882a593Smuzhiyun 	sensor->mbus = s_asd->mbus;
1646*4882a593Smuzhiyun 	sensor->sd = sd;
1647*4882a593Smuzhiyun 	dev_info(priv->dev, "match %s:bus type %d\n", sd->name, s_asd->mbus.type);
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 	for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
1650*4882a593Smuzhiyun 		if (sensor->sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)
1651*4882a593Smuzhiyun 			break;
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun 	if (pad == sensor->sd->entity.num_pads) {
1654*4882a593Smuzhiyun 		dev_err(priv->dev,
1655*4882a593Smuzhiyun 			"failed to find src pad for %s\n",
1656*4882a593Smuzhiyun 			sensor->sd->name);
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 		return -ENXIO;
1659*4882a593Smuzhiyun 	}
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun 	ret = media_create_pad_link(
1662*4882a593Smuzhiyun 			&sensor->sd->entity, pad,
1663*4882a593Smuzhiyun 			&priv->sd.entity, MIPI_DPHY_RX_PAD_SINK,
1664*4882a593Smuzhiyun 			priv->num_sensors != 1 ? 0 : MEDIA_LNK_FL_ENABLED);
1665*4882a593Smuzhiyun 	if (ret) {
1666*4882a593Smuzhiyun 		dev_err(priv->dev,
1667*4882a593Smuzhiyun 			"failed to create link for %s\n",
1668*4882a593Smuzhiyun 			sensor->sd->name);
1669*4882a593Smuzhiyun 		return ret;
1670*4882a593Smuzhiyun 	}
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun 	return 0;
1673*4882a593Smuzhiyun }
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun /* The .unbind callback */
1676*4882a593Smuzhiyun static void
rockchip_mipidphy_notifier_unbind(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_subdev * asd)1677*4882a593Smuzhiyun rockchip_mipidphy_notifier_unbind(struct v4l2_async_notifier *notifier,
1678*4882a593Smuzhiyun 				  struct v4l2_subdev *sd,
1679*4882a593Smuzhiyun 				  struct v4l2_async_subdev *asd)
1680*4882a593Smuzhiyun {
1681*4882a593Smuzhiyun 	struct mipidphy_priv *priv = container_of(notifier,
1682*4882a593Smuzhiyun 						  struct mipidphy_priv,
1683*4882a593Smuzhiyun 						  notifier);
1684*4882a593Smuzhiyun 	struct mipidphy_sensor *sensor = sd_to_sensor(priv, sd);
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun 	if (sensor)
1687*4882a593Smuzhiyun 		sensor->sd = NULL;
1688*4882a593Smuzhiyun }
1689*4882a593Smuzhiyun 
1690*4882a593Smuzhiyun static const struct
1691*4882a593Smuzhiyun v4l2_async_notifier_operations rockchip_mipidphy_async_ops = {
1692*4882a593Smuzhiyun 	.bound = rockchip_mipidphy_notifier_bound,
1693*4882a593Smuzhiyun 	.unbind = rockchip_mipidphy_notifier_unbind,
1694*4882a593Smuzhiyun };
1695*4882a593Smuzhiyun 
rockchip_mipidphy_fwnode_parse(struct device * dev,struct v4l2_fwnode_endpoint * vep,struct v4l2_async_subdev * asd)1696*4882a593Smuzhiyun static int rockchip_mipidphy_fwnode_parse(struct device *dev,
1697*4882a593Smuzhiyun 					  struct v4l2_fwnode_endpoint *vep,
1698*4882a593Smuzhiyun 					  struct v4l2_async_subdev *asd)
1699*4882a593Smuzhiyun {
1700*4882a593Smuzhiyun 	struct sensor_async_subdev *s_asd =
1701*4882a593Smuzhiyun 			container_of(asd, struct sensor_async_subdev, asd);
1702*4882a593Smuzhiyun 	struct v4l2_mbus_config *config = &s_asd->mbus;
1703*4882a593Smuzhiyun 
1704*4882a593Smuzhiyun 	if (vep->base.port != 0) {
1705*4882a593Smuzhiyun 		dev_err(dev, "The PHY has only port 0\n");
1706*4882a593Smuzhiyun 		return -EINVAL;
1707*4882a593Smuzhiyun 	}
1708*4882a593Smuzhiyun 
1709*4882a593Smuzhiyun 	if (vep->bus_type == V4L2_MBUS_CSI2_DPHY) {
1710*4882a593Smuzhiyun 		config->type = V4L2_MBUS_CSI2_DPHY;
1711*4882a593Smuzhiyun 		config->flags = vep->bus.mipi_csi2.flags;
1712*4882a593Smuzhiyun 		s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
1713*4882a593Smuzhiyun 	} else if (vep->bus_type == V4L2_MBUS_CCP2) {
1714*4882a593Smuzhiyun 		/* V4L2_MBUS_CCP2 for lvds */
1715*4882a593Smuzhiyun 		config->type = V4L2_MBUS_CCP2;
1716*4882a593Smuzhiyun 		s_asd->lanes = vep->bus.mipi_csi1.data_lane;
1717*4882a593Smuzhiyun 	} else {
1718*4882a593Smuzhiyun 		dev_err(dev, "Only CSI2 and CCP2 bus type is currently supported\n");
1719*4882a593Smuzhiyun 		return -EINVAL;
1720*4882a593Smuzhiyun 	}
1721*4882a593Smuzhiyun 
1722*4882a593Smuzhiyun 	switch (s_asd->lanes) {
1723*4882a593Smuzhiyun 	case 1:
1724*4882a593Smuzhiyun 		config->flags |= V4L2_MBUS_CSI2_1_LANE;
1725*4882a593Smuzhiyun 		break;
1726*4882a593Smuzhiyun 	case 2:
1727*4882a593Smuzhiyun 		config->flags |= V4L2_MBUS_CSI2_2_LANE;
1728*4882a593Smuzhiyun 		break;
1729*4882a593Smuzhiyun 	case 3:
1730*4882a593Smuzhiyun 		config->flags |= V4L2_MBUS_CSI2_3_LANE;
1731*4882a593Smuzhiyun 		break;
1732*4882a593Smuzhiyun 	case 4:
1733*4882a593Smuzhiyun 		config->flags |= V4L2_MBUS_CSI2_4_LANE;
1734*4882a593Smuzhiyun 		break;
1735*4882a593Smuzhiyun 	default:
1736*4882a593Smuzhiyun 		return -EINVAL;
1737*4882a593Smuzhiyun 	}
1738*4882a593Smuzhiyun 
1739*4882a593Smuzhiyun 	return 0;
1740*4882a593Smuzhiyun }
1741*4882a593Smuzhiyun 
rockchip_mipidphy_media_init(struct mipidphy_priv * priv)1742*4882a593Smuzhiyun static int rockchip_mipidphy_media_init(struct mipidphy_priv *priv)
1743*4882a593Smuzhiyun {
1744*4882a593Smuzhiyun 	int ret;
1745*4882a593Smuzhiyun 
1746*4882a593Smuzhiyun 	priv->pads[MIPI_DPHY_RX_PAD_SOURCE].flags =
1747*4882a593Smuzhiyun 		MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
1748*4882a593Smuzhiyun 	priv->pads[MIPI_DPHY_RX_PAD_SINK].flags =
1749*4882a593Smuzhiyun 		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
1750*4882a593Smuzhiyun 	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
1751*4882a593Smuzhiyun 	ret = media_entity_pads_init(&priv->sd.entity,
1752*4882a593Smuzhiyun 				MIPI_DPHY_RX_PADS_NUM, priv->pads);
1753*4882a593Smuzhiyun 	if (ret < 0)
1754*4882a593Smuzhiyun 		return ret;
1755*4882a593Smuzhiyun 
1756*4882a593Smuzhiyun 	v4l2_async_notifier_init(&priv->notifier);
1757*4882a593Smuzhiyun 
1758*4882a593Smuzhiyun 	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
1759*4882a593Smuzhiyun 		priv->dev, &priv->notifier,
1760*4882a593Smuzhiyun 		sizeof(struct sensor_async_subdev), 0,
1761*4882a593Smuzhiyun 		rockchip_mipidphy_fwnode_parse);
1762*4882a593Smuzhiyun 	if (ret < 0)
1763*4882a593Smuzhiyun 		return ret;
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun 	priv->sd.subdev_notifier = &priv->notifier;
1766*4882a593Smuzhiyun 	priv->notifier.ops = &rockchip_mipidphy_async_ops;
1767*4882a593Smuzhiyun 	ret = v4l2_async_subdev_notifier_register(&priv->sd, &priv->notifier);
1768*4882a593Smuzhiyun 	if (ret) {
1769*4882a593Smuzhiyun 		dev_err(priv->dev,
1770*4882a593Smuzhiyun 			"failed to register async notifier : %d\n", ret);
1771*4882a593Smuzhiyun 		v4l2_async_notifier_cleanup(&priv->notifier);
1772*4882a593Smuzhiyun 		return ret;
1773*4882a593Smuzhiyun 	}
1774*4882a593Smuzhiyun 
1775*4882a593Smuzhiyun 	return v4l2_async_register_subdev(&priv->sd);
1776*4882a593Smuzhiyun }
1777*4882a593Smuzhiyun 
rockchip_mipidphy_probe(struct platform_device * pdev)1778*4882a593Smuzhiyun static int rockchip_mipidphy_probe(struct platform_device *pdev)
1779*4882a593Smuzhiyun {
1780*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
1781*4882a593Smuzhiyun 	struct v4l2_subdev *sd;
1782*4882a593Smuzhiyun 	struct mipidphy_priv *priv;
1783*4882a593Smuzhiyun 	struct regmap *grf;
1784*4882a593Smuzhiyun 	struct resource *res;
1785*4882a593Smuzhiyun 	const struct of_device_id *of_id;
1786*4882a593Smuzhiyun 	const struct dphy_drv_data *drv_data;
1787*4882a593Smuzhiyun 	int i, ret;
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1790*4882a593Smuzhiyun 	if (!priv)
1791*4882a593Smuzhiyun 		return -ENOMEM;
1792*4882a593Smuzhiyun 	priv->dev = dev;
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun 	of_id = of_match_device(rockchip_mipidphy_match_id, dev);
1795*4882a593Smuzhiyun 	if (!of_id)
1796*4882a593Smuzhiyun 		return -EINVAL;
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	grf = syscon_node_to_regmap(dev->parent->of_node);
1799*4882a593Smuzhiyun 	if (IS_ERR(grf)) {
1800*4882a593Smuzhiyun 		grf = syscon_regmap_lookup_by_phandle(dev->of_node,
1801*4882a593Smuzhiyun 						      "rockchip,grf");
1802*4882a593Smuzhiyun 		if (IS_ERR(grf)) {
1803*4882a593Smuzhiyun 			dev_err(dev, "Can't find GRF syscon\n");
1804*4882a593Smuzhiyun 			return -ENODEV;
1805*4882a593Smuzhiyun 		}
1806*4882a593Smuzhiyun 	}
1807*4882a593Smuzhiyun 	priv->regmap_grf = grf;
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 	priv->phy_index = of_alias_get_id(dev->of_node, "dphy");
1810*4882a593Smuzhiyun 	if (priv->phy_index < 0)
1811*4882a593Smuzhiyun 		priv->phy_index = 0;
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun 	drv_data = of_id->data;
1814*4882a593Smuzhiyun 	if (soc_is_px30s())
1815*4882a593Smuzhiyun 		drv_data = &rk3326s_mipidphy_drv_data;
1816*4882a593Smuzhiyun 
1817*4882a593Smuzhiyun 	for (i = 0; i < drv_data->num_clks; i++) {
1818*4882a593Smuzhiyun 		priv->clks[i] = devm_clk_get(dev, drv_data->clks[i]);
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun 		if (IS_ERR(priv->clks[i]))
1821*4882a593Smuzhiyun 			dev_dbg(dev, "Failed to get %s\n", drv_data->clks[i]);
1822*4882a593Smuzhiyun 	}
1823*4882a593Smuzhiyun 
1824*4882a593Smuzhiyun 	priv->grf_regs = drv_data->grf_regs;
1825*4882a593Smuzhiyun 	priv->txrx_regs = drv_data->txrx_regs;
1826*4882a593Smuzhiyun 	priv->csiphy_regs = drv_data->csiphy_regs;
1827*4882a593Smuzhiyun 	priv->drv_data = drv_data;
1828*4882a593Smuzhiyun 	if (drv_data->ctl_type == MIPI_DPHY_CTL_CSI_HOST) {
1829*4882a593Smuzhiyun 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1830*4882a593Smuzhiyun 		priv->csihost_base_addr = devm_ioremap_resource(dev, res);
1831*4882a593Smuzhiyun 		priv->stream_on = csi_mipidphy_stream_on;
1832*4882a593Smuzhiyun 		priv->stream_off = csi_mipidphy_stream_off;
1833*4882a593Smuzhiyun 	} else {
1834*4882a593Smuzhiyun 		priv->stream_on = mipidphy_txrx_stream_on;
1835*4882a593Smuzhiyun 		priv->txrx_base_addr = NULL;
1836*4882a593Smuzhiyun 		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1837*4882a593Smuzhiyun 		priv->txrx_base_addr = devm_ioremap_resource(dev, res);
1838*4882a593Smuzhiyun 		if (IS_ERR(priv->txrx_base_addr))
1839*4882a593Smuzhiyun 			priv->stream_on = mipidphy_rx_stream_on;
1840*4882a593Smuzhiyun 		priv->stream_off = NULL;
1841*4882a593Smuzhiyun 	}
1842*4882a593Smuzhiyun 
1843*4882a593Smuzhiyun 	sd = &priv->sd;
1844*4882a593Smuzhiyun 	mutex_init(&priv->mutex);
1845*4882a593Smuzhiyun 	v4l2_subdev_init(sd, &mipidphy_subdev_ops);
1846*4882a593Smuzhiyun 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1847*4882a593Smuzhiyun 	snprintf(sd->name, sizeof(sd->name), "rockchip-mipi-dphy-rx");
1848*4882a593Smuzhiyun 	sd->dev = dev;
1849*4882a593Smuzhiyun 
1850*4882a593Smuzhiyun 	platform_set_drvdata(pdev, &sd->entity);
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun 	ret = rockchip_mipidphy_media_init(priv);
1853*4882a593Smuzhiyun 	if (ret < 0)
1854*4882a593Smuzhiyun 		goto destroy_mutex;
1855*4882a593Smuzhiyun 
1856*4882a593Smuzhiyun 	pm_runtime_enable(&pdev->dev);
1857*4882a593Smuzhiyun 	drv_data->individual_init(priv);
1858*4882a593Smuzhiyun 	return 0;
1859*4882a593Smuzhiyun 
1860*4882a593Smuzhiyun destroy_mutex:
1861*4882a593Smuzhiyun 	mutex_destroy(&priv->mutex);
1862*4882a593Smuzhiyun 	return 0;
1863*4882a593Smuzhiyun }
1864*4882a593Smuzhiyun 
rockchip_mipidphy_remove(struct platform_device * pdev)1865*4882a593Smuzhiyun static int rockchip_mipidphy_remove(struct platform_device *pdev)
1866*4882a593Smuzhiyun {
1867*4882a593Smuzhiyun 	struct media_entity *me = platform_get_drvdata(pdev);
1868*4882a593Smuzhiyun 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
1869*4882a593Smuzhiyun 	struct mipidphy_priv *priv = platform_get_drvdata(pdev);
1870*4882a593Smuzhiyun 
1871*4882a593Smuzhiyun 	media_entity_cleanup(&sd->entity);
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	pm_runtime_disable(&pdev->dev);
1874*4882a593Smuzhiyun 	mutex_destroy(&priv->mutex);
1875*4882a593Smuzhiyun 	return 0;
1876*4882a593Smuzhiyun }
1877*4882a593Smuzhiyun 
1878*4882a593Smuzhiyun static const struct dev_pm_ops rockchip_mipidphy_pm_ops = {
1879*4882a593Smuzhiyun 	SET_RUNTIME_PM_OPS(mipidphy_runtime_suspend,
1880*4882a593Smuzhiyun 			   mipidphy_runtime_resume, NULL)
1881*4882a593Smuzhiyun };
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun static struct platform_driver rockchip_isp_mipidphy_driver = {
1884*4882a593Smuzhiyun 	.probe = rockchip_mipidphy_probe,
1885*4882a593Smuzhiyun 	.remove = rockchip_mipidphy_remove,
1886*4882a593Smuzhiyun 	.driver = {
1887*4882a593Smuzhiyun 			.name = "rockchip-mipi-dphy-rx",
1888*4882a593Smuzhiyun 			.pm = &rockchip_mipidphy_pm_ops,
1889*4882a593Smuzhiyun 			.of_match_table = rockchip_mipidphy_match_id,
1890*4882a593Smuzhiyun 	},
1891*4882a593Smuzhiyun };
1892*4882a593Smuzhiyun 
1893*4882a593Smuzhiyun module_platform_driver(rockchip_isp_mipidphy_driver);
1894*4882a593Smuzhiyun MODULE_AUTHOR("Rockchip Camera/ISP team");
1895*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip MIPI RX DPHY driver");
1896*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
1897