xref: /OK3568_Linux_fs/kernel/drivers/misc/rk628/rk628_csi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Shunqing Chen <csq@rock-chisp.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "rk628.h"
9*4882a593Smuzhiyun #include "rk628_combtxphy.h"
10*4882a593Smuzhiyun #include "rk628_config.h"
11*4882a593Smuzhiyun #include "rk628_csi.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define CSITX_ERR_RETRY_TIMES		3
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define MIPI_DATARATE_MBPS_LOW		750
16*4882a593Smuzhiyun #define MIPI_DATARATE_MBPS_HIGH		1250
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define USE_4_LANES			4
19*4882a593Smuzhiyun #define YUV422_8BIT			0x1e
20*4882a593Smuzhiyun /* Test Code: 0x44 (HS RX Control of Lane 0) */
21*4882a593Smuzhiyun #define HSFREQRANGE(x)			UPDATE(x, 6, 1)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct rk628_csi {
24*4882a593Smuzhiyun 	struct rk628_display_mode mode;
25*4882a593Smuzhiyun 	bool txphy_pwron;
26*4882a593Smuzhiyun 	u64 lane_mbps;
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
testif_testclk_assert(struct rk628 * rk628)29*4882a593Smuzhiyun static inline void testif_testclk_assert(struct rk628 *rk628)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
32*4882a593Smuzhiyun 			   PHY_TESTCLK, PHY_TESTCLK);
33*4882a593Smuzhiyun 	udelay(1);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
testif_testclk_deassert(struct rk628 * rk628)36*4882a593Smuzhiyun static inline void testif_testclk_deassert(struct rk628 *rk628)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
39*4882a593Smuzhiyun 			   PHY_TESTCLK, 0);
40*4882a593Smuzhiyun 	udelay(1);
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
testif_testclr_assert(struct rk628 * rk628)43*4882a593Smuzhiyun static inline void testif_testclr_assert(struct rk628 *rk628)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
46*4882a593Smuzhiyun 			   PHY_TESTCLR, PHY_TESTCLR);
47*4882a593Smuzhiyun 	udelay(1);
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
testif_testclr_deassert(struct rk628 * rk628)50*4882a593Smuzhiyun static inline void testif_testclr_deassert(struct rk628 *rk628)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
53*4882a593Smuzhiyun 			   PHY_TESTCLR, 0);
54*4882a593Smuzhiyun 	udelay(1);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
testif_testen_assert(struct rk628 * rk628)57*4882a593Smuzhiyun static inline void testif_testen_assert(struct rk628 *rk628)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
60*4882a593Smuzhiyun 			   PHY_TESTEN, PHY_TESTEN);
61*4882a593Smuzhiyun 	udelay(1);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
testif_testen_deassert(struct rk628 * rk628)64*4882a593Smuzhiyun static inline void testif_testen_deassert(struct rk628 *rk628)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
67*4882a593Smuzhiyun 			   PHY_TESTEN, 0);
68*4882a593Smuzhiyun 	udelay(1);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
testif_set_data(struct rk628 * rk628,u8 data)71*4882a593Smuzhiyun static inline void testif_set_data(struct rk628 *rk628, u8 data)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
74*4882a593Smuzhiyun 			   PHY_TESTDIN_MASK, PHY_TESTDIN(data));
75*4882a593Smuzhiyun 	udelay(1);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
testif_get_data(struct rk628 * rk628)78*4882a593Smuzhiyun static inline u8 testif_get_data(struct rk628 *rk628)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	u32 data = 0;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_DPHY0_STATUS, &data);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return data >> PHY_TESTDOUT_SHIFT;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
testif_test_code_write(struct rk628 * rk628,u8 test_code)87*4882a593Smuzhiyun static void testif_test_code_write(struct rk628 *rk628, u8 test_code)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	testif_testclk_assert(rk628);
90*4882a593Smuzhiyun 	testif_set_data(rk628, test_code);
91*4882a593Smuzhiyun 	testif_testen_assert(rk628);
92*4882a593Smuzhiyun 	testif_testclk_deassert(rk628);
93*4882a593Smuzhiyun 	testif_testen_deassert(rk628);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
testif_test_data_write(struct rk628 * rk628,u8 test_data)96*4882a593Smuzhiyun static void testif_test_data_write(struct rk628 *rk628, u8 test_data)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	testif_testclk_deassert(rk628);
99*4882a593Smuzhiyun 	testif_set_data(rk628, test_data);
100*4882a593Smuzhiyun 	testif_testclk_assert(rk628);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
testif_write(struct rk628 * rk628,u8 test_code,u8 test_data)103*4882a593Smuzhiyun static u8 testif_write(struct rk628 *rk628, u8 test_code, u8 test_data)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	u8 monitor_data;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	testif_test_code_write(rk628, test_code);
108*4882a593Smuzhiyun 	testif_test_data_write(rk628, test_data);
109*4882a593Smuzhiyun 	monitor_data = testif_get_data(rk628);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	dev_info(rk628->dev, "test_code=0x%02x, ", test_code);
112*4882a593Smuzhiyun 	dev_info(rk628->dev, "test_data=0x%02x, ", test_data);
113*4882a593Smuzhiyun 	dev_info(rk628->dev, "monitor_data=0x%02x\n", monitor_data);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	return monitor_data;
116*4882a593Smuzhiyun }
rk628_csi_get_detected_timings(struct rk628 * rk628)117*4882a593Smuzhiyun static void rk628_csi_get_detected_timings(struct rk628 *rk628)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	struct rk628_display_mode *src, *dst;
120*4882a593Smuzhiyun 	struct rk628_csi *csi = rk628->csi;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	if (!csi)
123*4882a593Smuzhiyun 		return;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	src = rk628_display_get_src_mode(rk628);
126*4882a593Smuzhiyun 	dst = rk628_display_get_dst_mode(rk628);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	rk628_set_output_bus_format(rk628, BUS_FMT_YUV422);
129*4882a593Smuzhiyun 	rk628_mode_copy(dst, src);
130*4882a593Smuzhiyun 	rk628_mode_copy(&csi->mode, dst);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 
testif_read(struct rk628 * rk628,u8 test_code)134*4882a593Smuzhiyun static inline u8 testif_read(struct rk628 *rk628, u8 test_code)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	u8 test_data;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	testif_test_code_write(rk628, test_code);
139*4882a593Smuzhiyun 	test_data = testif_get_data(rk628);
140*4882a593Smuzhiyun 	testif_test_data_write(rk628, test_data);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	return test_data;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
mipi_dphy_enableclk_assert(struct rk628 * rk628)145*4882a593Smuzhiyun static inline void mipi_dphy_enableclk_assert(struct rk628 *rk628)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, CSITX_DPHY_CTRL, DPHY_ENABLECLK,
148*4882a593Smuzhiyun 			DPHY_ENABLECLK);
149*4882a593Smuzhiyun 	udelay(1);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
mipi_dphy_enableclk_deassert(struct rk628 * rk628)152*4882a593Smuzhiyun static inline void mipi_dphy_enableclk_deassert(struct rk628 *rk628)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628,  CSITX_DPHY_CTRL, DPHY_ENABLECLK, 0);
155*4882a593Smuzhiyun 	udelay(1);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
mipi_dphy_shutdownz_assert(struct rk628 * rk628)158*4882a593Smuzhiyun static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628,  GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
161*4882a593Smuzhiyun 	udelay(1);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
mipi_dphy_shutdownz_deassert(struct rk628 * rk628)164*4882a593Smuzhiyun static inline void mipi_dphy_shutdownz_deassert(struct rk628 *rk628)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628,  GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ,
167*4882a593Smuzhiyun 			CSI_PHYSHUTDOWNZ);
168*4882a593Smuzhiyun 	udelay(1);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
mipi_dphy_rstz_assert(struct rk628 * rk628)171*4882a593Smuzhiyun static inline void mipi_dphy_rstz_assert(struct rk628 *rk628)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628,  GRF_MIPI_TX0_CON, CSI_PHYRSTZ, 0);
174*4882a593Smuzhiyun 	udelay(1);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
mipi_dphy_rstz_deassert(struct rk628 * rk628)177*4882a593Smuzhiyun static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628,  GRF_MIPI_TX0_CON, CSI_PHYRSTZ,
180*4882a593Smuzhiyun 			CSI_PHYRSTZ);
181*4882a593Smuzhiyun 	udelay(1);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
mipi_dphy_init_hsfreqrange(struct rk628 * rk628)184*4882a593Smuzhiyun static void mipi_dphy_init_hsfreqrange(struct rk628 *rk628)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	const struct {
187*4882a593Smuzhiyun 		unsigned long max_lane_mbps;
188*4882a593Smuzhiyun 		u8 hsfreqrange;
189*4882a593Smuzhiyun 	} hsfreqrange_table[] = {
190*4882a593Smuzhiyun 		{  90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
191*4882a593Smuzhiyun 		{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
192*4882a593Smuzhiyun 		{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
193*4882a593Smuzhiyun 		{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
194*4882a593Smuzhiyun 		{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
195*4882a593Smuzhiyun 		{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
196*4882a593Smuzhiyun 		{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
197*4882a593Smuzhiyun 		{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
198*4882a593Smuzhiyun 		{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
199*4882a593Smuzhiyun 		{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
200*4882a593Smuzhiyun 	};
201*4882a593Smuzhiyun 	u8 hsfreqrange;
202*4882a593Smuzhiyun 	unsigned int index;
203*4882a593Smuzhiyun 	struct rk628_csi *csi = rk628->csi;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if (!csi)
206*4882a593Smuzhiyun 		return;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
209*4882a593Smuzhiyun 		if (csi->lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
210*4882a593Smuzhiyun 			break;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (index == ARRAY_SIZE(hsfreqrange_table))
213*4882a593Smuzhiyun 		--index;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	hsfreqrange = hsfreqrange_table[index].hsfreqrange;
216*4882a593Smuzhiyun 	testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange));
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
mipi_dphy_reset(struct rk628 * rk628)219*4882a593Smuzhiyun static int mipi_dphy_reset(struct rk628 *rk628)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	u32 val;
222*4882a593Smuzhiyun 	int ret;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	mipi_dphy_enableclk_deassert(rk628);
225*4882a593Smuzhiyun 	mipi_dphy_shutdownz_assert(rk628);
226*4882a593Smuzhiyun 	mipi_dphy_rstz_assert(rk628);
227*4882a593Smuzhiyun 	testif_testclr_assert(rk628);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	/* Set all REQUEST inputs to zero */
230*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
231*4882a593Smuzhiyun 		     FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
232*4882a593Smuzhiyun 		     FORCETXSTOPMODE(0) | FORCERXMODE(0));
233*4882a593Smuzhiyun 	udelay(1);
234*4882a593Smuzhiyun 	testif_testclr_deassert(rk628);
235*4882a593Smuzhiyun 	mipi_dphy_enableclk_assert(rk628);
236*4882a593Smuzhiyun 	mipi_dphy_shutdownz_deassert(rk628);
237*4882a593Smuzhiyun 	mipi_dphy_rstz_deassert(rk628);
238*4882a593Smuzhiyun 	usleep_range(1500, 2000);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	ret = rk628_i2c_read(rk628, CSITX_CSITX_STATUS1, &val);
241*4882a593Smuzhiyun 	if (ret < 0) {
242*4882a593Smuzhiyun 		dev_info(rk628->dev, "lane module is not in stop state\n");
243*4882a593Smuzhiyun 		return ret;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
mipi_dphy_power_on(struct rk628 * rk628)249*4882a593Smuzhiyun static int mipi_dphy_power_on(struct rk628 *rk628)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	unsigned int val;
252*4882a593Smuzhiyun 	u32 bus_width, mask;
253*4882a593Smuzhiyun 	struct rk628_csi *csi = rk628->csi;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (!csi)
256*4882a593Smuzhiyun 		return -1;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if ((csi->mode.hdisplay == 3840) &&
259*4882a593Smuzhiyun 	    (csi->mode.vdisplay == 2160)) {
260*4882a593Smuzhiyun 		csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH;
261*4882a593Smuzhiyun 	} else {
262*4882a593Smuzhiyun 		csi->lane_mbps = MIPI_DATARATE_MBPS_LOW;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	bus_width =  csi->lane_mbps << 8;
266*4882a593Smuzhiyun 	bus_width |= COMBTXPHY_MODULEA_EN;
267*4882a593Smuzhiyun 	dev_info(rk628->dev, "%s mipi bitrate:%llu mbps\n", __func__, csi->lane_mbps);
268*4882a593Smuzhiyun 	rk628_combtxphy_set_bus_width(rk628, bus_width);
269*4882a593Smuzhiyun 	rk628_combtxphy_set_mode(rk628, PHY_MODE_VIDEO_MIPI);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	mipi_dphy_init_hsfreqrange(rk628);
272*4882a593Smuzhiyun 	usleep_range(1500, 2000);
273*4882a593Smuzhiyun 	rk628_combtxphy_power_on(rk628);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	usleep_range(1500, 2000);
276*4882a593Smuzhiyun 	mask = DPHY_PLL_LOCK;
277*4882a593Smuzhiyun 	rk628_i2c_read(rk628, CSITX_CSITX_STATUS1, &val);
278*4882a593Smuzhiyun 	if ((val & mask) != mask) {
279*4882a593Smuzhiyun 		dev_info(rk628->dev, "PHY is not locked\n");
280*4882a593Smuzhiyun 		return -1;
281*4882a593Smuzhiyun 	}
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	udelay(10);
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
mipi_dphy_power_off(struct rk628 * rk628)288*4882a593Smuzhiyun static void mipi_dphy_power_off(struct rk628 *rk628)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	rk628_combtxphy_power_off(rk628);
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
rk62_csi_reset(struct rk628 * rk628)293*4882a593Smuzhiyun static void rk62_csi_reset(struct rk628 *rk628)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1);
296*4882a593Smuzhiyun 	usleep_range(1000, 1100);
297*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x0);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
rk628_csi_set_csi(struct rk628 * rk628)300*4882a593Smuzhiyun static void rk628_csi_set_csi(struct rk628 *rk628)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	u8 lanes = USE_4_LANES;
303*4882a593Smuzhiyun 	u8 lane_num;
304*4882a593Smuzhiyun 	u8 dphy_lane_en;
305*4882a593Smuzhiyun 	u32 wc_usrdef;
306*4882a593Smuzhiyun 	struct rk628_csi *csi;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	if (!rk628->csi) {
309*4882a593Smuzhiyun 		csi = devm_kzalloc(rk628->dev, sizeof(*csi), GFP_KERNEL);
310*4882a593Smuzhiyun 		if (!csi)
311*4882a593Smuzhiyun 			return;
312*4882a593Smuzhiyun 		rk628->csi = csi;
313*4882a593Smuzhiyun 	} else {
314*4882a593Smuzhiyun 		csi = rk628->csi;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 	lane_num = lanes - 1;
317*4882a593Smuzhiyun 	dphy_lane_en = (1 << (lanes + 1)) - 1;
318*4882a593Smuzhiyun 	wc_usrdef = csi->mode.hdisplay * 2;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	rk62_csi_reset(rk628);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (csi->txphy_pwron) {
323*4882a593Smuzhiyun 		dev_info(rk628->dev, "%s: txphy already power on, power off\n",
324*4882a593Smuzhiyun 			__func__);
325*4882a593Smuzhiyun 		mipi_dphy_power_off(rk628);
326*4882a593Smuzhiyun 		csi->txphy_pwron = false;
327*4882a593Smuzhiyun 	}
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	mipi_dphy_power_on(rk628);
330*4882a593Smuzhiyun 	csi->txphy_pwron = true;
331*4882a593Smuzhiyun 	dev_info(rk628->dev, "%s: txphy power on!\n", __func__);
332*4882a593Smuzhiyun 	usleep_range(1000, 1500);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, CSITX_CSITX_EN,
335*4882a593Smuzhiyun 			VOP_UV_SWAP_MASK |
336*4882a593Smuzhiyun 			VOP_YUV422_EN_MASK |
337*4882a593Smuzhiyun 			VOP_P2_EN_MASK |
338*4882a593Smuzhiyun 			LANE_NUM_MASK |
339*4882a593Smuzhiyun 			DPHY_EN_MASK |
340*4882a593Smuzhiyun 			CSITX_EN_MASK,
341*4882a593Smuzhiyun 			VOP_UV_SWAP(1) |
342*4882a593Smuzhiyun 			VOP_YUV422_EN(1) |
343*4882a593Smuzhiyun 			VOP_P2_EN(1) |
344*4882a593Smuzhiyun 			LANE_NUM(lane_num) |
345*4882a593Smuzhiyun 			DPHY_EN(0) |
346*4882a593Smuzhiyun 			CSITX_EN(0));
347*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, CSITX_SYS_CTRL1,
348*4882a593Smuzhiyun 			BYPASS_SELECT_MASK,
349*4882a593Smuzhiyun 			BYPASS_SELECT(1));
350*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
351*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_SYS_CTRL2, VOP_WHOLE_FRM_EN | VSYNC_ENABLE);
352*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, CSITX_SYS_CTRL3_IMD,
353*4882a593Smuzhiyun 			CONT_MODE_CLK_CLR_MASK |
354*4882a593Smuzhiyun 			CONT_MODE_CLK_SET_MASK |
355*4882a593Smuzhiyun 			NON_CONTINOUS_MODE_MASK,
356*4882a593Smuzhiyun 			CONT_MODE_CLK_CLR(0) |
357*4882a593Smuzhiyun 			CONT_MODE_CLK_SET(0) |
358*4882a593Smuzhiyun 			NON_CONTINOUS_MODE(1));
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_VOP_PATH_CTRL,
361*4882a593Smuzhiyun 			VOP_WC_USERDEFINE(wc_usrdef) |
362*4882a593Smuzhiyun 			VOP_DT_USERDEFINE(YUV422_8BIT) |
363*4882a593Smuzhiyun 			VOP_PIXEL_FORMAT(0) |
364*4882a593Smuzhiyun 			VOP_WC_USERDEFINE_EN(1) |
365*4882a593Smuzhiyun 			VOP_DT_USERDEFINE_EN(1) |
366*4882a593Smuzhiyun 			VOP_PATH_EN(1));
367*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, CSITX_DPHY_CTRL,
368*4882a593Smuzhiyun 				CSI_DPHY_EN_MASK,
369*4882a593Smuzhiyun 				CSI_DPHY_EN(dphy_lane_en));
370*4882a593Smuzhiyun 	rk628_i2c_write(rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
371*4882a593Smuzhiyun 	dev_info(rk628->dev, "%s csi cofig done\n", __func__);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun 
enable_csitx(struct rk628 * rk628)374*4882a593Smuzhiyun static void enable_csitx(struct rk628 *rk628)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	u32 i, ret, val;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	for (i = 0; i < CSITX_ERR_RETRY_TIMES; i++) {
379*4882a593Smuzhiyun 		rk628_csi_set_csi(rk628);
380*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, CSITX_CSITX_EN,
381*4882a593Smuzhiyun 					DPHY_EN_MASK |
382*4882a593Smuzhiyun 					CSITX_EN_MASK,
383*4882a593Smuzhiyun 					DPHY_EN(1) |
384*4882a593Smuzhiyun 					CSITX_EN(1));
385*4882a593Smuzhiyun 		rk628_i2c_write(rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
386*4882a593Smuzhiyun 		msleep(40);
387*4882a593Smuzhiyun 		rk628_i2c_write(rk628, CSITX_ERR_INTR_CLR_IMD, 0xffffffff);
388*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, CSITX_SYS_CTRL1,
389*4882a593Smuzhiyun 				BYPASS_SELECT_MASK, BYPASS_SELECT(0));
390*4882a593Smuzhiyun 		rk628_i2c_write(rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
391*4882a593Smuzhiyun 		msleep(40);
392*4882a593Smuzhiyun 		ret = rk628_i2c_read(rk628, CSITX_ERR_INTR_RAW_STATUS_IMD, &val);
393*4882a593Smuzhiyun 		if (!ret && !val)
394*4882a593Smuzhiyun 			break;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 		dev_info(rk628->dev, "%s csitx err, retry:%d, err status:%#x, ret:%d\n",
397*4882a593Smuzhiyun 			 __func__, i, val, ret);
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
enable_stream(struct rk628 * rk628,bool en)402*4882a593Smuzhiyun static void enable_stream(struct rk628 *rk628, bool en)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun 	dev_info(rk628->dev, "%s: %sable\n", __func__, en ? "en" : "dis");
405*4882a593Smuzhiyun 	if (en) {
406*4882a593Smuzhiyun 		enable_csitx(rk628);
407*4882a593Smuzhiyun 	} else {
408*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, CSITX_CSITX_EN,
409*4882a593Smuzhiyun 					DPHY_EN_MASK |
410*4882a593Smuzhiyun 					CSITX_EN_MASK,
411*4882a593Smuzhiyun 					DPHY_EN(0) |
412*4882a593Smuzhiyun 					CSITX_EN(0));
413*4882a593Smuzhiyun 		rk628_i2c_write(rk628, CSITX_CONFIG_DONE, CONFIG_DONE_IMD);
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun 
rk628_csi_init(struct rk628 * rk628)417*4882a593Smuzhiyun void rk628_csi_init(struct rk628 *rk628)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
420*4882a593Smuzhiyun 			      SW_OUTPUT_MODE_MASK, SW_OUTPUT_MODE(OUTPUT_MODE_CSI));
421*4882a593Smuzhiyun 	rk628_csi_get_detected_timings(rk628);
422*4882a593Smuzhiyun 	mipi_dphy_reset(rk628);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun 
rk628_csi_enable(struct rk628 * rk628)425*4882a593Smuzhiyun void rk628_csi_enable(struct rk628 *rk628)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun 	rk628_csi_get_detected_timings(rk628);
428*4882a593Smuzhiyun 	return enable_stream(rk628, true);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
rk628_csi_disable(struct rk628 * rk628)431*4882a593Smuzhiyun void rk628_csi_disable(struct rk628 *rk628)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun 	return enable_stream(rk628, false);
434*4882a593Smuzhiyun }
435