xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/rk628/rk628_gvi.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: Sandy Huang <hjc@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/regmap.h>
13*4882a593Smuzhiyun #include <linux/reset.h>
14*4882a593Smuzhiyun #include <linux/mfd/rk628.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <drm/drm_of.h>
17*4882a593Smuzhiyun #include <drm/drm_atomic.h>
18*4882a593Smuzhiyun #include <drm/drm_probe_helper.h>
19*4882a593Smuzhiyun #include <drm/drm_atomic_helper.h>
20*4882a593Smuzhiyun #include <drm/drm_panel.h>
21*4882a593Smuzhiyun #include <video/of_display_timing.h>
22*4882a593Smuzhiyun #include <video/videomode.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "rk628_combtxphy.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define HOSTREG(x)					((x) + 0x80000)
27*4882a593Smuzhiyun #define GVI_SYS_CTRL0					HOSTREG(0x0000)
28*4882a593Smuzhiyun #define GVI_SYS_CTRL1					HOSTREG(0x0004)
29*4882a593Smuzhiyun #define GVI_SYS_CTRL2					HOSTREG(0x0008)
30*4882a593Smuzhiyun #define GVI_SYS_CTRL3					HOSTREG(0x000c)
31*4882a593Smuzhiyun #define GVI_VERSION					HOSTREG(0x0010)
32*4882a593Smuzhiyun #define GVI_SYS_RST					HOSTREG(0x0014)
33*4882a593Smuzhiyun #define GVI_LINE_FLAG					HOSTREG(0x0018)
34*4882a593Smuzhiyun #define GVI_STATUS					HOSTREG(0x001c)
35*4882a593Smuzhiyun #define GVI_PLL_LOCK_TIMEOUT				HOSTREG(0x0030)
36*4882a593Smuzhiyun #define GVI_HTPDN_TIMEOUT				HOSTREG(0x0034)
37*4882a593Smuzhiyun #define GVI_LOCKN_TIMEOUT				HOSTREG(0x0038)
38*4882a593Smuzhiyun #define GVI_WAIT_LOCKN					HOSTREG(0x003C)
39*4882a593Smuzhiyun #define GVI_WAIT_HTPDN					HOSTREG(0x0040)
40*4882a593Smuzhiyun #define GVI_INTR_EN					HOSTREG(0x0050)
41*4882a593Smuzhiyun #define GVI_INTR_CLR					HOSTREG(0x0054)
42*4882a593Smuzhiyun #define GVI_INTR_RAW_STATUS				HOSTREG(0x0058)
43*4882a593Smuzhiyun #define GVI_INTR_STATUS					HOSTREG(0x005c)
44*4882a593Smuzhiyun #define GVI_COLOR_BAR_CTRL				HOSTREG(0x0060)
45*4882a593Smuzhiyun #define GVI_COLOR_BAR_HTIMING0				HOSTREG(0x0070)
46*4882a593Smuzhiyun #define GVI_COLOR_BAR_HTIMING1				HOSTREG(0x0074)
47*4882a593Smuzhiyun #define GVI_COLOR_BAR_VTIMING0				HOSTREG(0x0078)
48*4882a593Smuzhiyun #define GVI_COLOR_BAR_VTIMING1				HOSTREG(0x007c)
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* SYS_CTRL0 */
51*4882a593Smuzhiyun #define SYS_CTRL0_GVI_EN				BIT(0)
52*4882a593Smuzhiyun #define SYS_CTRL0_AUTO_GATING				BIT(1)
53*4882a593Smuzhiyun #define SYS_CTRL0_FRM_RST_EN				BIT(2)
54*4882a593Smuzhiyun #define SYS_CTRL0_FRM_RST_MODE				BIT(3)
55*4882a593Smuzhiyun #define SYS_CTRL0_LANE_NUM_MASK				GENMASK(7, 4)
56*4882a593Smuzhiyun #define SYS_CTRL0_LANE_NUM(x)				UPDATE(x, 7, 4)
57*4882a593Smuzhiyun #define SYS_CTRL0_BYTE_MODE_MASK			GENMASK(9, 8)
58*4882a593Smuzhiyun #define SYS_CTRL0_BYTE_MODE(x)				UPDATE(x, 9, 8)
59*4882a593Smuzhiyun #define SYS_CTRL0_SECTION_NUM_MASK			GENMASK(11, 10)
60*4882a593Smuzhiyun #define SYS_CTRL0_SECTION_NUM(x)			UPDATE(x, 11, 10)
61*4882a593Smuzhiyun #define SYS_CTRL0_CDR_ENDIAN_SWAP			BIT(12)
62*4882a593Smuzhiyun #define SYS_CTRL0_PACK_BYTE_SWAP			BIT(13)
63*4882a593Smuzhiyun #define SYS_CTRL0_PACK_ENDIAN_SWAP			BIT(14)
64*4882a593Smuzhiyun #define SYS_CTRL0_ENC8B10B_ENDIAN_SWAP			BIT(15)
65*4882a593Smuzhiyun #define SYS_CTRL0_CDR_EN				BIT(16)
66*4882a593Smuzhiyun #define SYS_CTRL0_ALN_EN				BIT(17)
67*4882a593Smuzhiyun #define SYS_CTRL0_NOR_EN				BIT(18)
68*4882a593Smuzhiyun #define SYS_CTRL0_ALN_NOR_MODE				BIT(19)
69*4882a593Smuzhiyun #define SYS_CTRL0_GVI_MASK				GENMASK(19, 16)
70*4882a593Smuzhiyun #define SYS_CTRL0_GVI_GN_EN(x)				UPDATE(x, 19, 16)
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #define SYS_CTRL0_SCRAMBLER_EN				BIT(20)
73*4882a593Smuzhiyun #define SYS_CTRL0_ENCODE8B10B_EN			BIT(21)
74*4882a593Smuzhiyun #define SYS_CTRL0_INIT_RD_EN				BIT(22)
75*4882a593Smuzhiyun #define SYS_CTRL0_INIT_RD_VALUE				BIT(23)
76*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_HTPDN_EN			BIT(24)
77*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_HTPDN_VALUE			BIT(25)
78*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_PLL_EN				BIT(26)
79*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_PLL_VALUE			BIT(27)
80*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_LOCKN_EN			BIT(28)
81*4882a593Smuzhiyun #define SYS_CTRL0_FORCE_LOCKN_VALUE			BIT(29)
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /* SYS_CTRL1 */
84*4882a593Smuzhiyun #define SYS_CTRL1_COLOR_DEPTH_MASK			GENMASK(3, 0)
85*4882a593Smuzhiyun #define SYS_CTRL1_COLOR_DEPTH(x)			UPDATE(x, 3, 0)
86*4882a593Smuzhiyun #define SYS_CTRL1_DUAL_PIXEL_EN				BIT(4)
87*4882a593Smuzhiyun #define SYS_CTRL1_TIMING_ALIGN_EN			BIT(8)
88*4882a593Smuzhiyun #define SYS_CTRL1_LANE_ALIGN_EN				BIT(9)
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun #define SYS_CTRL1_DUAL_PIXEL_SWAP			BIT(12)
91*4882a593Smuzhiyun #define SYS_CTRL1_RB_SWAP				BIT(13)
92*4882a593Smuzhiyun #define SYS_CTRL1_YC_SWAP				BIT(14)
93*4882a593Smuzhiyun #define SYS_CTRL1_WHOLE_FRM_EN				BIT(16)
94*4882a593Smuzhiyun #define SYS_CTRL1_NOR_PROTECT				BIT(17)
95*4882a593Smuzhiyun #define SYS_CTRL1_RD_WCNT_UPDATE			BIT(31)
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun /* SYS_CTRL2 */
98*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_READ_THOLD_MASK			GENMASK(7, 0)
99*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_READ_THOLD(x)			UPDATE(x, 7, 0)
100*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_ALMOST_FULL_THOLD_MASK		GENMASK(23, 16)
101*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_ALMOST_FULL_THOLD(x)		UPDATE(x, 23, 16)
102*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_ALMOST_EMPTY_THOLD_MASK		GENMASK(31, 24)
103*4882a593Smuzhiyun #define SYS_CTRL2_AFIFO_ALMOST_EMPTY_THOLD(x)		UPDATE(x, 31, 24)
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun /* SYS_CTRL3 */
106*4882a593Smuzhiyun #define SYS_CTRL3_LANE0_SEL_MASK			GENMASK(2, 0)
107*4882a593Smuzhiyun #define SYS_CTRL3_LANE0_SEL(x)				UPDATE(x, 2, 0)
108*4882a593Smuzhiyun #define SYS_CTRL3_LANE1_SEL_MASK			GENMASK(6, 4)
109*4882a593Smuzhiyun #define SYS_CTRL3_LANE1_SEL(x)				UPDATE(x, 6, 4)
110*4882a593Smuzhiyun #define SYS_CTRL3_LANE2_SEL_MASK			GENMASK(10, 8)
111*4882a593Smuzhiyun #define SYS_CTRL3_LANE2_SEL(x)				UPDATE(x, 10, 8)
112*4882a593Smuzhiyun #define SYS_CTRL3_LANE3_SEL_MASK			GENMASK(14, 12)
113*4882a593Smuzhiyun #define SYS_CTRL3_LANE3_SEL(x)				UPDATE(x, 14, 12)
114*4882a593Smuzhiyun #define SYS_CTRL3_LANE4_SEL_MASK			GENMASK(18, 16)
115*4882a593Smuzhiyun #define SYS_CTRL3_LANE4_SEL(x)				UPDATE(x, 18, 16)
116*4882a593Smuzhiyun #define SYS_CTRL3_LANE5_SEL_MASK			GENMASK(22, 20)
117*4882a593Smuzhiyun #define SYS_CTRL3_LANE5_SEL(x)				UPDATE(x, 22, 20)
118*4882a593Smuzhiyun #define SYS_CTRL3_LANE6_SEL_MASK			GENMASK(26, 24)
119*4882a593Smuzhiyun #define SYS_CTRL3_LANE6_SEL(x)				UPDATE(x, 26, 24)
120*4882a593Smuzhiyun #define SYS_CTRL3_LANE7_SEL_MASK			GENMASK(30, 28)
121*4882a593Smuzhiyun #define SYS_CTRL3_LANE7_SEL(x)				UPDATE(x, 30, 28)
122*4882a593Smuzhiyun /* VERSIION */
123*4882a593Smuzhiyun #define VERSION_VERSION(x)				UPDATE(x, 31, 0)
124*4882a593Smuzhiyun /* SYS_RESET*/
125*4882a593Smuzhiyun #define SYS_RST_SOFT_RST				BIT(0)
126*4882a593Smuzhiyun /* LINE_FLAG */
127*4882a593Smuzhiyun #define LINE_FLAG_LANE_FLAG0_MASK			GENMASK(15, 0)
128*4882a593Smuzhiyun #define LINE_FLAG_LANE_FLAG0(x)				UPDATE(x, 15, 0)
129*4882a593Smuzhiyun #define LINE_FLAG_LANE_FLAG1_MASK			GENMASK(31, 16)
130*4882a593Smuzhiyun #define LINE_FLAG_LANE_FLAG1(x)				UPDATE(x, 31, 16)
131*4882a593Smuzhiyun /* STATUS */
132*4882a593Smuzhiyun #define STATUS_HTDPN					BIT(4)
133*4882a593Smuzhiyun #define STATUS_LOCKN					BIT(5)
134*4882a593Smuzhiyun #define STATUS_PLL_LOCKN				BIT(6)
135*4882a593Smuzhiyun #define STATUS_AFIFO0_WCNT_MASK				GENMASK(23, 16)
136*4882a593Smuzhiyun #define STATUS_AFIFO0_WCNT(x)				UPDATE(x, 23, 16)
137*4882a593Smuzhiyun #define STATUS_AFIFO1_WCNT_MASK				GENMASK(31, 24)
138*4882a593Smuzhiyun #define STATUS_AFIFO1_WCNT(x)				UPDATE(x, 31, 24)
139*4882a593Smuzhiyun /* PLL_LTIMEOUT */
140*4882a593Smuzhiyun #define PLL_LOCK_TIMEOUT_PLL_LOCK_TIME_OUT_MASK		GENMASK(31, 0)
141*4882a593Smuzhiyun #define PLL_LOCK_TIMEOUT_PLL_LOCK_TIME_OUT(x)		UPDATE(x, 31, 0)
142*4882a593Smuzhiyun /* HTPDNEOUT */
143*4882a593Smuzhiyun #define HTPDN_TIMEOUT_HTPDN_TIME_OUT_MASK		GENMASK(31, 0)
144*4882a593Smuzhiyun #define HTPDN_TIMEOUT_HTPDN_TIME_OUT(x)			UPDATE(x, 31, 0)
145*4882a593Smuzhiyun /* LOCKNEOUT */
146*4882a593Smuzhiyun #define LOCKN_TIMEOUT_LOCKN_TIME_OUT_MASK		GENMASK(31, 0)
147*4882a593Smuzhiyun #define LOCKN_TIMEOUT_LOCKN_TIME_OUT(x)			UPDATE(x, 31, 0)
148*4882a593Smuzhiyun /* WAIT_LOCKN */
149*4882a593Smuzhiyun #define WAIT_LOCKN_WAIT_LOCKN_TIME_MASK			GENMASK(30, 0)
150*4882a593Smuzhiyun #define WAIT_LOCKN_WAIT_LOCKN_TIME(x)			UPDATE(x, 30, 0)
151*4882a593Smuzhiyun #define WAIT_LOCKN_WAIT_LOCKN_TIME_EN			BIT(31)
152*4882a593Smuzhiyun /* WAIT_HTPDN */
153*4882a593Smuzhiyun #define WAIT_HTPDN_WAIT_HTPDN_TIME_MASK			GENMASK(30, 0)
154*4882a593Smuzhiyun #define WAIT_HTPDN_WAIT_HTPDN_TIME(x)			UPDATE(x, 30, 0)
155*4882a593Smuzhiyun #define WAIT_HTPDN_WAIT_HTPDN_EN			BIT(31)
156*4882a593Smuzhiyun /* INTR_EN */
157*4882a593Smuzhiyun #define INTR_EN_INTR_FRM_ST_EN				BIT(0)
158*4882a593Smuzhiyun #define INTR_EN_INTR_PLL_LOCK_EN			BIT(1)
159*4882a593Smuzhiyun #define INTR_EN_INTR_HTPDN_EN				BIT(2)
160*4882a593Smuzhiyun #define INTR_EN_INTR_LOCKN_EN				BIT(3)
161*4882a593Smuzhiyun #define INTR_EN_INTR_PLL_TIMEOUT_EN			BIT(4)
162*4882a593Smuzhiyun #define INTR_EN_INTR_HTPDN_TIMEOUT_EN			BIT(5)
163*4882a593Smuzhiyun #define INTR_EN_INTR_LOCKN_TIMEOUT_EN			BIT(6)
164*4882a593Smuzhiyun #define INTR_EN_INTR_LINE_FLAG0_EN			BIT(8)
165*4882a593Smuzhiyun #define INTR_EN_INTR_LINE_FLAG1_EN			BIT(9)
166*4882a593Smuzhiyun #define INTR_EN_INTR_AFIFO_OVERFLOW_EN			BIT(10)
167*4882a593Smuzhiyun #define INTR_EN_INTR_AFIFO_UNDERFLOW_EN			BIT(11)
168*4882a593Smuzhiyun #define INTR_EN_INTR_PLL_ERR_EN				BIT(12)
169*4882a593Smuzhiyun #define INTR_EN_INTR_HTPDN_ERR_EN			BIT(13)
170*4882a593Smuzhiyun #define INTR_EN_INTR_LOCKN_ERR_EN			BIT(14)
171*4882a593Smuzhiyun /* INTR_CLR*/
172*4882a593Smuzhiyun #define INTR_CLR_INTR_FRM_ST_CLR			BIT(0)
173*4882a593Smuzhiyun #define INTR_CLR_INTR_PLL_LOCK_CLR			BIT(1)
174*4882a593Smuzhiyun #define INTR_CLR_INTR_HTPDN_CLR				BIT(2)
175*4882a593Smuzhiyun #define INTR_CLR_INTR_LOCKN_CLR				BIT(3)
176*4882a593Smuzhiyun #define INTR_CLR_INTR_PLL_TIMEOUT_CLR			BIT(4)
177*4882a593Smuzhiyun #define INTR_CLR_INTR_HTPDN_TIMEOUT_CLR			BIT(5)
178*4882a593Smuzhiyun #define INTR_CLR_INTR_LOCKN_TIMEOUT_CLR			BIT(6)
179*4882a593Smuzhiyun #define INTR_CLR_INTR_LINE_FLAG0_CLR			BIT(8)
180*4882a593Smuzhiyun #define INTR_CLR_INTR_LINE_FLAG1_CLR			BIT(9)
181*4882a593Smuzhiyun #define INTR_CLR_INTR_AFIFO_OVERFLOW_CLR		BIT(10)
182*4882a593Smuzhiyun #define INTR_CLR_INTR_AFIFO_UNDERFLOW_CLR		BIT(11)
183*4882a593Smuzhiyun #define INTR_CLR_INTR_PLL_ERR_CLR			BIT(12)
184*4882a593Smuzhiyun #define INTR_CLR_INTR_HTPDN_ERR_CLR			BIT(13)
185*4882a593Smuzhiyun #define INTR_CLR_INTR_LOCKN_ERR_CLR			BIT(14)
186*4882a593Smuzhiyun /* INTR_RAW_STATUS */
187*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_FRM_ST			BIT(0)
188*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_PLL_LOCK		BIT(1)
189*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_HTPDN			BIT(2)
190*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_LOCKN			BIT(3)
191*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_PLL_TIMEOUT		BIT(4)
192*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_HTPDN_TIMEOUT		BIT(5)
193*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_LOCKN_TIMEOUT		BIT(6)
194*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_LINE_FLAG0		BIT(8)
195*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_LINE_FLAG1		BIT(9)
196*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_AFIFO_OVERFLOW		BIT(10)
197*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_AFIFO_UNDERFLOW	BIT(11)
198*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_PLL_ERR		BIT(12)
199*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_HTPDN_ERR		BIT(13)
200*4882a593Smuzhiyun #define INTR_RAW_STATUS_RAW_INTR_LOCKN_ERR		BIT(14)
201*4882a593Smuzhiyun /* INTR_STATUS */
202*4882a593Smuzhiyun #define INTR_STATUS_INTR_FRM_ST				BIT(0)
203*4882a593Smuzhiyun #define INTR_STATUS_INTR_PLL_LOCK			BIT(1)
204*4882a593Smuzhiyun #define INTR_STATUS_INTR_HTPDN				BIT(2)
205*4882a593Smuzhiyun #define INTR_STATUS_INTR_LOCKN				BIT(3)
206*4882a593Smuzhiyun #define INTR_STATUS_INTR_PLL_TIMEOUT			BIT(4)
207*4882a593Smuzhiyun #define INTR_STATUS_INTR_HTPDN_TIMEOUT			BIT(5)
208*4882a593Smuzhiyun #define INTR_STATUS_INTR_LOCKN_TIMEOUT			BIT(6)
209*4882a593Smuzhiyun #define INTR_STATUS_INTR_LINE_FLAG0			BIT(8)
210*4882a593Smuzhiyun #define INTR_STATUS_INTR_LINE_FLAG1			BIT(9)
211*4882a593Smuzhiyun #define INTR_STATUS_INTR_AFIFO_OVERFLOW			BIT(10)
212*4882a593Smuzhiyun #define INTR_STATUS_INTR_AFIFO_UNDERFLOW		BIT(11)
213*4882a593Smuzhiyun #define INTR_STATUS_INTR_PLL_ERR			BIT(12)
214*4882a593Smuzhiyun #define INTR_STATUS_INTR_HTPDN_ERR			BIT(13)
215*4882a593Smuzhiyun #define INTR_STATUS_INTR_LOCKN_ERR			BIT(14)
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun /* COLOR_BAR_CTRL */
218*4882a593Smuzhiyun #define COLOR_BAR_EN					BIT(0)
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun #define COLOR_DEPTH_RGB_YUV444_18BIT			0
221*4882a593Smuzhiyun #define COLOR_DEPTH_RGB_YUV444_24BIT			1
222*4882a593Smuzhiyun #define COLOR_DEPTH_RGB_YUV444_30BIT			2
223*4882a593Smuzhiyun #define COLOR_DEPTH_YUV422_16BIT			8
224*4882a593Smuzhiyun #define COLOR_DEPTH_YUV422_20BIT			9
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun enum gvi_byte_mode {
227*4882a593Smuzhiyun 	GVI_3BYTE_MODE = 0,
228*4882a593Smuzhiyun 	GVI_4BYTE_MODE,
229*4882a593Smuzhiyun 	GVI_5BYTE_MODE,
230*4882a593Smuzhiyun };
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun struct rk628_gvi {
233*4882a593Smuzhiyun 	struct drm_bridge base;
234*4882a593Smuzhiyun 	struct drm_connector connector;
235*4882a593Smuzhiyun 	struct drm_panel *panel;
236*4882a593Smuzhiyun 	struct drm_display_mode mode;
237*4882a593Smuzhiyun 	struct device *dev;
238*4882a593Smuzhiyun 	struct regmap *grf;
239*4882a593Smuzhiyun 	struct regmap *regmap;
240*4882a593Smuzhiyun 	struct clk *pclk;
241*4882a593Smuzhiyun 	struct reset_control *rst;
242*4882a593Smuzhiyun 	struct phy *phy;
243*4882a593Smuzhiyun 	struct rk628 *parent;
244*4882a593Smuzhiyun 	u32 lane_mbps;
245*4882a593Smuzhiyun 	u32 bus_format;
246*4882a593Smuzhiyun 	u32 lane_num;
247*4882a593Smuzhiyun 	u8 color_depth;
248*4882a593Smuzhiyun 	u8 byte_mode;
249*4882a593Smuzhiyun 	bool division_mode;
250*4882a593Smuzhiyun };
251*4882a593Smuzhiyun 
bridge_to_gvi(struct drm_bridge * b)252*4882a593Smuzhiyun static inline struct rk628_gvi *bridge_to_gvi(struct drm_bridge *b)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	return container_of(b, struct rk628_gvi, base);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
connector_to_gvi(struct drm_connector * c)257*4882a593Smuzhiyun static inline struct rk628_gvi *connector_to_gvi(struct drm_connector *c)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	return container_of(c, struct rk628_gvi, connector);
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun 
rk628_gvi_connector_best_encoder(struct drm_connector * connector)262*4882a593Smuzhiyun static struct drm_encoder *rk628_gvi_connector_best_encoder(struct drm_connector
263*4882a593Smuzhiyun 							    *connector)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	struct rk628_gvi *gvi = connector_to_gvi(connector);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return gvi->base.encoder;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
rk628_gvi_connector_get_modes(struct drm_connector * connector)270*4882a593Smuzhiyun static int rk628_gvi_connector_get_modes(struct drm_connector *connector)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct rk628_gvi *gvi = connector_to_gvi(connector);
273*4882a593Smuzhiyun 	struct drm_display_info *info = &connector->display_info;
274*4882a593Smuzhiyun 	int num_modes;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	num_modes = drm_panel_get_modes(gvi->panel, connector);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (info->num_bus_formats)
279*4882a593Smuzhiyun 		gvi->bus_format = info->bus_formats[0];
280*4882a593Smuzhiyun 	else
281*4882a593Smuzhiyun 		gvi->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	switch (gvi->bus_format) {
284*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X18:
285*4882a593Smuzhiyun 		gvi->byte_mode = 3;
286*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_RGB_YUV444_18BIT;
287*4882a593Smuzhiyun 		break;
288*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X24:
289*4882a593Smuzhiyun 		gvi->byte_mode = 4;
290*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_RGB_YUV444_24BIT;
291*4882a593Smuzhiyun 		break;
292*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X30:
293*4882a593Smuzhiyun 		gvi->byte_mode = 4;
294*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_RGB_YUV444_30BIT;
295*4882a593Smuzhiyun 		break;
296*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV8_1X16:
297*4882a593Smuzhiyun 		gvi->byte_mode = 3;
298*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_YUV422_16BIT;
299*4882a593Smuzhiyun 		break;
300*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_YUYV10_1X20:
301*4882a593Smuzhiyun 		gvi->byte_mode = 3;
302*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_YUV422_20BIT;
303*4882a593Smuzhiyun 		break;
304*4882a593Smuzhiyun 	default:
305*4882a593Smuzhiyun 		gvi->byte_mode = 3;
306*4882a593Smuzhiyun 		gvi->color_depth = COLOR_DEPTH_RGB_YUV444_24BIT;
307*4882a593Smuzhiyun 		dev_info(gvi->dev, "unsupported bus_format: 0x%x\n",
308*4882a593Smuzhiyun 			 gvi->bus_format);
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	info->edid_hdmi_dc_modes = 0;
313*4882a593Smuzhiyun 	info->hdmi.y420_dc_modes = 0;
314*4882a593Smuzhiyun 	info->color_formats = 0;
315*4882a593Smuzhiyun 	info->max_tmds_clock = 300000;
316*4882a593Smuzhiyun 	connector->ycbcr_420_allowed = true;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	num_modes += rk628_scaler_add_src_mode(gvi->parent, connector);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	return num_modes;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun static const
324*4882a593Smuzhiyun struct drm_connector_helper_funcs rk628_gvi_connector_helper_funcs = {
325*4882a593Smuzhiyun 	.get_modes = rk628_gvi_connector_get_modes,
326*4882a593Smuzhiyun 	.best_encoder = rk628_gvi_connector_best_encoder,
327*4882a593Smuzhiyun };
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun static enum drm_connector_status
rk628_gvi_connector_detect(struct drm_connector * connector,bool force)330*4882a593Smuzhiyun rk628_gvi_connector_detect(struct drm_connector *connector, bool force)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	return connector_status_connected;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
rk628_gvi_connector_destroy(struct drm_connector * connector)335*4882a593Smuzhiyun static void rk628_gvi_connector_destroy(struct drm_connector *connector)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	drm_connector_cleanup(connector);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static const struct drm_connector_funcs rk628_gvi_connector_funcs = {
341*4882a593Smuzhiyun 	.detect = rk628_gvi_connector_detect,
342*4882a593Smuzhiyun 	.fill_modes = drm_helper_probe_single_connector_modes,
343*4882a593Smuzhiyun 	.destroy = rk628_gvi_connector_destroy,
344*4882a593Smuzhiyun 	.reset = drm_atomic_helper_connector_reset,
345*4882a593Smuzhiyun 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
346*4882a593Smuzhiyun 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun 
rk628_gvi_get_lane_rate(struct rk628_gvi * gvi)349*4882a593Smuzhiyun static unsigned int rk628_gvi_get_lane_rate(struct rk628_gvi *gvi)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	struct device *dev = gvi->dev;
352*4882a593Smuzhiyun 	const struct drm_display_mode *mode = &gvi->mode;
353*4882a593Smuzhiyun 	u32 lane_bit_rate, min_lane_rate = 500000, max_lane_rate = 4000000;
354*4882a593Smuzhiyun 	u64 total_bw;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	/* optional override of the desired bandwidth */
357*4882a593Smuzhiyun 	if (!of_property_read_u32
358*4882a593Smuzhiyun 	    (dev->of_node, "rockchip,lane-rate", &lane_bit_rate))
359*4882a593Smuzhiyun 		return lane_bit_rate;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/**
362*4882a593Smuzhiyun 	 * [ENCODER TOTAL BIT-RATE](bps) = [byte mode](byte) x 10 / [pixel clock](HZ)
363*4882a593Smuzhiyun 	 *
364*4882a593Smuzhiyun 	 * lane_bit_rate = [total bit-rate](bps) / [lane number]
365*4882a593Smuzhiyun 	 *
366*4882a593Smuzhiyun 	 * 500Mbps <= lane_bit_rate <= 4Gbps
367*4882a593Smuzhiyun 	 */
368*4882a593Smuzhiyun 	total_bw = (unsigned long long)gvi->byte_mode * 10 * mode->clock;	/* Kbps */
369*4882a593Smuzhiyun 	do_div(total_bw, gvi->lane_num);
370*4882a593Smuzhiyun 	lane_bit_rate = total_bw;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	if (lane_bit_rate < min_lane_rate)
373*4882a593Smuzhiyun 		lane_bit_rate = min_lane_rate;
374*4882a593Smuzhiyun 	if (lane_bit_rate > max_lane_rate)
375*4882a593Smuzhiyun 		lane_bit_rate = max_lane_rate;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	return lane_bit_rate;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
rk628_gvi_enable_color_bar(struct rk628_gvi * gvi)380*4882a593Smuzhiyun static void rk628_gvi_enable_color_bar(struct rk628_gvi *gvi)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	const struct drm_display_mode *mode = &gvi->mode;
383*4882a593Smuzhiyun 	struct videomode vm;
384*4882a593Smuzhiyun 	u16 hsync_len, hact_st, hact_end, htotal;
385*4882a593Smuzhiyun 	u16 vsync_len, vact_st, vact_end, vtotal;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	drm_display_mode_to_videomode(mode, &vm);
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	if (gvi->division_mode) {
390*4882a593Smuzhiyun 		hsync_len = vm.hsync_len / 2;
391*4882a593Smuzhiyun 		hact_st = (vm.hsync_len + vm.hback_porch) / 2;
392*4882a593Smuzhiyun 		hact_end = (vm.hsync_len + vm.hback_porch + vm.hactive) / 2;
393*4882a593Smuzhiyun 		htotal = mode->htotal / 2;
394*4882a593Smuzhiyun 	} else {
395*4882a593Smuzhiyun 		hsync_len = vm.hsync_len;
396*4882a593Smuzhiyun 		hact_st = vm.hsync_len + vm.hback_porch;
397*4882a593Smuzhiyun 		hact_end = vm.hsync_len + vm.hback_porch + vm.hactive;
398*4882a593Smuzhiyun 		htotal = mode->htotal;
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 	vsync_len = vm.vsync_len;
401*4882a593Smuzhiyun 	vact_st = vsync_len + vm.vback_porch;
402*4882a593Smuzhiyun 	vact_end = vact_st + vm.vactive;
403*4882a593Smuzhiyun 	vtotal = mode->vtotal;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	regmap_write(gvi->regmap, GVI_COLOR_BAR_HTIMING0,
406*4882a593Smuzhiyun 		     hact_st << 16 | hsync_len);
407*4882a593Smuzhiyun 	regmap_write(gvi->regmap, GVI_COLOR_BAR_HTIMING1,
408*4882a593Smuzhiyun 		     (htotal - 1) << 16 | hact_end);
409*4882a593Smuzhiyun 	regmap_write(gvi->regmap, GVI_COLOR_BAR_VTIMING0,
410*4882a593Smuzhiyun 		     vact_st << 16 | vsync_len);
411*4882a593Smuzhiyun 	regmap_write(gvi->regmap, GVI_COLOR_BAR_VTIMING1,
412*4882a593Smuzhiyun 		     (vtotal - 1) << 16 | vact_end);
413*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_COLOR_BAR_CTRL, COLOR_BAR_EN, 0);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
rk628_gvi_pre_enable(struct rk628_gvi * gvi)416*4882a593Smuzhiyun static void rk628_gvi_pre_enable(struct rk628_gvi *gvi)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	clk_prepare_enable(gvi->pclk);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	/* gvi reset */
421*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_RST, SYS_RST_SOFT_RST,
422*4882a593Smuzhiyun 			  SYS_RST_SOFT_RST);
423*4882a593Smuzhiyun 	udelay(10);
424*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_RST, SYS_RST_SOFT_RST, 0);
425*4882a593Smuzhiyun 	udelay(10);
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_LANE_NUM_MASK,
428*4882a593Smuzhiyun 			  SYS_CTRL0_LANE_NUM(gvi->lane_num - 1));
429*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_BYTE_MODE_MASK,
430*4882a593Smuzhiyun 			  SYS_CTRL0_BYTE_MODE(gvi->byte_mode ==
431*4882a593Smuzhiyun 					      3 ? 0 : (gvi->byte_mode ==
432*4882a593Smuzhiyun 						       4 ? 1 : 2)));
433*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0,
434*4882a593Smuzhiyun 			  SYS_CTRL0_SECTION_NUM_MASK,
435*4882a593Smuzhiyun 			  SYS_CTRL0_SECTION_NUM(gvi->division_mode));
436*4882a593Smuzhiyun 	regmap_update_bits(gvi->grf, GRF_POST_PROC_CON, SW_SPLIT_EN,
437*4882a593Smuzhiyun 			   gvi->division_mode ? SW_SPLIT_EN : 0);
438*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL1, SYS_CTRL1_DUAL_PIXEL_EN,
439*4882a593Smuzhiyun 			  gvi->division_mode ? SYS_CTRL1_DUAL_PIXEL_EN : 0);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_FRM_RST_EN, 0);
442*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL1, SYS_CTRL1_LANE_ALIGN_EN, 0);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun 
rk628_gvi_post_enable(struct rk628_gvi * gvi)445*4882a593Smuzhiyun static void rk628_gvi_post_enable(struct rk628_gvi *gvi)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	u32 val;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	val = SYS_CTRL0_GVI_EN | SYS_CTRL0_AUTO_GATING;
450*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, val, 3);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
rk628_gvi_bridge_enable(struct drm_bridge * bridge)453*4882a593Smuzhiyun static void rk628_gvi_bridge_enable(struct drm_bridge *bridge)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	struct rk628_gvi *gvi = bridge_to_gvi(bridge);
456*4882a593Smuzhiyun 	unsigned int rate = rk628_gvi_get_lane_rate(gvi);
457*4882a593Smuzhiyun 	int ret;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	regmap_update_bits(gvi->grf, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
460*4882a593Smuzhiyun 			   SW_OUTPUT_MODE(OUTPUT_MODE_GVI));
461*4882a593Smuzhiyun 	phy_set_bus_width(gvi->phy, rate);
462*4882a593Smuzhiyun 	rk628_combtxphy_set_gvi_division_mode(gvi->phy, gvi->division_mode);
463*4882a593Smuzhiyun 	ret = phy_set_mode(gvi->phy, 0);
464*4882a593Smuzhiyun 	if (ret) {
465*4882a593Smuzhiyun 		dev_err(gvi->dev, "failed to set phy mode: %d\n", ret);
466*4882a593Smuzhiyun 		return;
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 	phy_power_on(gvi->phy);
469*4882a593Smuzhiyun 	gvi->lane_mbps = phy_get_bus_width(gvi->phy);
470*4882a593Smuzhiyun 	rk628_gvi_pre_enable(gvi);
471*4882a593Smuzhiyun 	drm_panel_prepare(gvi->panel);
472*4882a593Smuzhiyun 	rk628_gvi_enable_color_bar(gvi);
473*4882a593Smuzhiyun 	rk628_gvi_post_enable(gvi);
474*4882a593Smuzhiyun 	drm_panel_enable(gvi->panel);
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	dev_info(gvi->dev,
477*4882a593Smuzhiyun 		 "GVI-Link bandwidth: %d x %d Mbps, Byte mode: %d, Color Depty: %d, %s division mode\n",
478*4882a593Smuzhiyun 		 gvi->lane_mbps, gvi->lane_num, gvi->byte_mode,
479*4882a593Smuzhiyun 		 gvi->color_depth, gvi->division_mode ? "two" : "one");
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
rk628_gvi_post_disable(struct drm_bridge * bridge)482*4882a593Smuzhiyun static void rk628_gvi_post_disable(struct drm_bridge *bridge)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	struct rk628_gvi *gvi = bridge_to_gvi(bridge);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_GVI_EN, 0);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
rk628_gvi_bridge_disable(struct drm_bridge * bridge)489*4882a593Smuzhiyun static void rk628_gvi_bridge_disable(struct drm_bridge *bridge)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun 	struct rk628_gvi *gvi = bridge_to_gvi(bridge);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	drm_panel_disable(gvi->panel);
494*4882a593Smuzhiyun 	drm_panel_unprepare(gvi->panel);
495*4882a593Smuzhiyun 	rk628_gvi_post_disable(bridge);
496*4882a593Smuzhiyun 	clk_disable_unprepare(gvi->pclk);
497*4882a593Smuzhiyun 	phy_power_off(gvi->phy);
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
rk628_gvi_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)500*4882a593Smuzhiyun static int rk628_gvi_bridge_attach(struct drm_bridge *bridge,
501*4882a593Smuzhiyun 				   enum drm_bridge_attach_flags flags)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	struct rk628_gvi *gvi = bridge_to_gvi(bridge);
504*4882a593Smuzhiyun 	struct drm_connector *connector = &gvi->connector;
505*4882a593Smuzhiyun 	struct drm_device *drm = bridge->dev;
506*4882a593Smuzhiyun 	int ret;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
509*4882a593Smuzhiyun 		return 0;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	ret = drm_connector_init(drm, connector, &rk628_gvi_connector_funcs,
512*4882a593Smuzhiyun 				 DRM_MODE_CONNECTOR_LVDS);
513*4882a593Smuzhiyun 	if (ret) {
514*4882a593Smuzhiyun 		dev_err(gvi->dev, "Failed to initialize connector with drm\n");
515*4882a593Smuzhiyun 		return ret;
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	drm_connector_helper_add(connector, &rk628_gvi_connector_helper_funcs);
519*4882a593Smuzhiyun 	drm_connector_attach_encoder(connector, bridge->encoder);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	return 0;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
rk628_gvi_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adj)524*4882a593Smuzhiyun static void rk628_gvi_bridge_mode_set(struct drm_bridge *bridge,
525*4882a593Smuzhiyun 				      const struct drm_display_mode *mode,
526*4882a593Smuzhiyun 				      const struct drm_display_mode *adj)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun 	struct rk628_gvi *gvi = bridge_to_gvi(bridge);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	rk628_mode_copy(gvi->parent, &gvi->mode, mode);
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	dev_info(gvi->dev, "src mode: %dx%d, clk: %d, dst mode: %dx%d, clk: %d\n",
533*4882a593Smuzhiyun 		 mode->hdisplay, mode->vdisplay, mode->clock,
534*4882a593Smuzhiyun 		 gvi->mode.hdisplay, gvi->mode.vdisplay, gvi->mode.clock);
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun static const struct drm_bridge_funcs rk628_gvi_bridge_funcs = {
538*4882a593Smuzhiyun 	.attach = rk628_gvi_bridge_attach,
539*4882a593Smuzhiyun 	.enable = rk628_gvi_bridge_enable,
540*4882a593Smuzhiyun 	.disable = rk628_gvi_bridge_disable,
541*4882a593Smuzhiyun 	.mode_set = rk628_gvi_bridge_mode_set,
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun static const struct regmap_range rk628_gvi_readable_ranges[] = {
545*4882a593Smuzhiyun 	regmap_reg_range(GVI_SYS_CTRL0, GVI_COLOR_BAR_VTIMING1),
546*4882a593Smuzhiyun };
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun static const struct regmap_access_table rk628_gvi_readable_table = {
549*4882a593Smuzhiyun 	.yes_ranges = rk628_gvi_readable_ranges,
550*4882a593Smuzhiyun 	.n_yes_ranges = ARRAY_SIZE(rk628_gvi_readable_ranges),
551*4882a593Smuzhiyun };
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun static const struct regmap_config rk628_gvi_regmap_cfg = {
554*4882a593Smuzhiyun 	.name = "gvi",
555*4882a593Smuzhiyun 	.reg_bits = 32,
556*4882a593Smuzhiyun 	.val_bits = 32,
557*4882a593Smuzhiyun 	.reg_stride = 4,
558*4882a593Smuzhiyun 	.max_register = GVI_COLOR_BAR_VTIMING1,
559*4882a593Smuzhiyun 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
560*4882a593Smuzhiyun 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
561*4882a593Smuzhiyun 	.rd_table = &rk628_gvi_readable_table,
562*4882a593Smuzhiyun };
563*4882a593Smuzhiyun 
rk628_gvi_probe(struct platform_device * pdev)564*4882a593Smuzhiyun static int rk628_gvi_probe(struct platform_device *pdev)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun 	struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
567*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
568*4882a593Smuzhiyun 	struct rk628_gvi *gvi;
569*4882a593Smuzhiyun 	int ret = 0;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	if (!of_device_is_available(dev->of_node))
572*4882a593Smuzhiyun 		return -ENODEV;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	gvi = devm_kzalloc(dev, sizeof(*gvi), GFP_KERNEL);
575*4882a593Smuzhiyun 	if (!gvi)
576*4882a593Smuzhiyun 		return -ENOMEM;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
579*4882a593Smuzhiyun 					  &gvi->panel, NULL);
580*4882a593Smuzhiyun 	if (ret)
581*4882a593Smuzhiyun 		return ret;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	gvi->dev = dev;
584*4882a593Smuzhiyun 	gvi->parent = rk628;
585*4882a593Smuzhiyun 	gvi->division_mode = of_property_read_bool(dev->of_node,
586*4882a593Smuzhiyun 						   "rockchip,division-mode");
587*4882a593Smuzhiyun 	ret = of_property_read_u32(dev->of_node, "rockchip,lane-num",
588*4882a593Smuzhiyun 				   &gvi->lane_num);
589*4882a593Smuzhiyun 	if (ret) {
590*4882a593Smuzhiyun 		dev_err(gvi->dev, "Failed to get lane num\n");
591*4882a593Smuzhiyun 		gvi->lane_num = 4;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	platform_set_drvdata(pdev, gvi);
595*4882a593Smuzhiyun 	gvi->grf = rk628->grf;
596*4882a593Smuzhiyun 	if (!gvi->grf)
597*4882a593Smuzhiyun 		return -ENODEV;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	gvi->regmap = devm_regmap_init_i2c(rk628->client,
600*4882a593Smuzhiyun 					   &rk628_gvi_regmap_cfg);
601*4882a593Smuzhiyun 	if (IS_ERR(gvi->regmap)) {
602*4882a593Smuzhiyun 		ret = PTR_ERR(gvi->regmap);
603*4882a593Smuzhiyun 		dev_err(dev, "failed to allocate register map: %d\n", ret);
604*4882a593Smuzhiyun 		return ret;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	gvi->pclk = devm_clk_get(dev, "pclk");
608*4882a593Smuzhiyun 	if (IS_ERR(gvi->pclk)) {
609*4882a593Smuzhiyun 		ret = PTR_ERR(gvi->pclk);
610*4882a593Smuzhiyun 		dev_err(dev, "failed to get pclk: %d\n", ret);
611*4882a593Smuzhiyun 		return ret;
612*4882a593Smuzhiyun 	}
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	gvi->rst = of_reset_control_get(dev->of_node, NULL);
615*4882a593Smuzhiyun 	if (IS_ERR(gvi->rst)) {
616*4882a593Smuzhiyun 		ret = PTR_ERR(gvi->rst);
617*4882a593Smuzhiyun 		dev_err(dev, "failed to get reset control: %d\n", ret);
618*4882a593Smuzhiyun 		return ret;
619*4882a593Smuzhiyun 	}
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	gvi->phy = devm_of_phy_get(dev, dev->of_node, NULL);
622*4882a593Smuzhiyun 	if (IS_ERR(gvi->phy)) {
623*4882a593Smuzhiyun 		ret = PTR_ERR(gvi->phy);
624*4882a593Smuzhiyun 		dev_err(dev, "failed to get phy: %d\n", ret);
625*4882a593Smuzhiyun 		return ret;
626*4882a593Smuzhiyun 	}
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	gvi->base.funcs = &rk628_gvi_bridge_funcs;
629*4882a593Smuzhiyun 	gvi->base.of_node = dev->of_node;
630*4882a593Smuzhiyun 	drm_bridge_add(&gvi->base);
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	return 0;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun 
rk628_gvi_remove(struct platform_device * pdev)635*4882a593Smuzhiyun static int rk628_gvi_remove(struct platform_device *pdev)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun 	struct rk628_gvi *gvi = platform_get_drvdata(pdev);
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	drm_bridge_remove(&gvi->base);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	return 0;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun static const struct of_device_id rk628_gvi_of_match[] = {
645*4882a593Smuzhiyun 	{.compatible = "rockchip,rk628-gvi",},
646*4882a593Smuzhiyun 	{},
647*4882a593Smuzhiyun };
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk628_gvi_of_match);
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun static struct platform_driver rk628_gvi_driver = {
652*4882a593Smuzhiyun 	.driver = {
653*4882a593Smuzhiyun 		.name = "rk628-gvi",
654*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rk628_gvi_of_match),
655*4882a593Smuzhiyun 	},
656*4882a593Smuzhiyun 	.probe = rk628_gvi_probe,
657*4882a593Smuzhiyun 	.remove = rk628_gvi_remove,
658*4882a593Smuzhiyun };
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun module_platform_driver(rk628_gvi_driver);
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun MODULE_AUTHOR("Sandy Huang <hjc@rock-chips.com>");
663*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip RK628 GVI driver");
664*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
665