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