xref: /OK3568_Linux_fs/kernel/drivers/misc/rk628/rk628.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: Wyon Bi <bivvy.bi@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/irq.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
14*4882a593Smuzhiyun #include <linux/regmap.h>
15*4882a593Smuzhiyun #include <linux/backlight.h>
16*4882a593Smuzhiyun #include <linux/pm_runtime.h>
17*4882a593Smuzhiyun #include <video/videomode.h>
18*4882a593Smuzhiyun #include <linux/debugfs.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "rk628.h"
21*4882a593Smuzhiyun #include "rk628_cru.h"
22*4882a593Smuzhiyun #include "rk628_combrxphy.h"
23*4882a593Smuzhiyun #include "rk628_post_process.h"
24*4882a593Smuzhiyun #include "rk628_hdmirx.h"
25*4882a593Smuzhiyun #include "rk628_combtxphy.h"
26*4882a593Smuzhiyun #include "rk628_dsi.h"
27*4882a593Smuzhiyun #include "rk628_rgb.h"
28*4882a593Smuzhiyun #include "rk628_lvds.h"
29*4882a593Smuzhiyun #include "rk628_gvi.h"
30*4882a593Smuzhiyun #include "rk628_csi.h"
31*4882a593Smuzhiyun #include "rk628_hdmitx.h"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun static const struct regmap_range rk628_cru_readable_ranges[] = {
34*4882a593Smuzhiyun 	regmap_reg_range(CRU_CPLL_CON0, CRU_CPLL_CON4),
35*4882a593Smuzhiyun 	regmap_reg_range(CRU_GPLL_CON0, CRU_GPLL_CON4),
36*4882a593Smuzhiyun 	regmap_reg_range(CRU_MODE_CON00, CRU_MODE_CON00),
37*4882a593Smuzhiyun 	regmap_reg_range(CRU_CLKSEL_CON00, CRU_CLKSEL_CON21),
38*4882a593Smuzhiyun 	regmap_reg_range(CRU_GATE_CON00, CRU_GATE_CON05),
39*4882a593Smuzhiyun 	regmap_reg_range(CRU_SOFTRST_CON00, CRU_SOFTRST_CON04),
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun static const struct regmap_access_table rk628_cru_readable_table = {
43*4882a593Smuzhiyun 	.yes_ranges     = rk628_cru_readable_ranges,
44*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_cru_readable_ranges),
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun static const struct regmap_range rk628_combrxphy_readable_ranges[] = {
48*4882a593Smuzhiyun 	regmap_reg_range(COMBRX_REG(0x6600), COMBRX_REG(0x665b)),
49*4882a593Smuzhiyun 	regmap_reg_range(COMBRX_REG(0x66a0), COMBRX_REG(0x66db)),
50*4882a593Smuzhiyun 	regmap_reg_range(COMBRX_REG(0x66f0), COMBRX_REG(0x66ff)),
51*4882a593Smuzhiyun 	regmap_reg_range(COMBRX_REG(0x6700), COMBRX_REG(0x6790)),
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun static const struct regmap_access_table rk628_combrxphy_readable_table = {
55*4882a593Smuzhiyun 	.yes_ranges     = rk628_combrxphy_readable_ranges,
56*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_combrxphy_readable_ranges),
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
60*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_SETUP_CTRL, HDMI_RX_HDMI_SETUP_CTRL),
61*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_PCB_CTRL, HDMI_RX_HDMI_PCB_CTRL),
62*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_MODE_RECOVER, HDMI_RX_HDMI_ERROR_PROTECT),
63*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_SYNC_CTRL, HDMI_RX_HDMI_CKM_RESULT),
64*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_RESMPL_CTRL, HDMI_RX_HDMI_RESMPL_CTRL),
65*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_VM_CFG_CH2, HDMI_RX_HDMI_STS),
66*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDCP_CTRL, HDMI_RX_HDCP_SETTINGS),
67*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDCP_KIDX, HDMI_RX_HDCP_KIDX),
68*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDCP_DBG, HDMI_RX_HDCP_AN0),
69*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDCP_STS, HDMI_RX_HDCP_STS),
70*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_MD_HCTRL1, HDMI_RX_MD_HACT_PX),
71*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_MD_VCTRL, HDMI_RX_MD_VSC),
72*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_MD_VOL, HDMI_RX_MD_VTL),
73*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_MD_IL_POL, HDMI_RX_MD_STS),
74*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_CTRL, HDMI_RX_AUD_CTRL),
75*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_PLL_CTRL, HDMI_RX_AUD_PLL_CTRL),
76*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_CLK_CTRL, HDMI_RX_AUD_CLK_CTRL),
77*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_FIFO_CTRL, HDMI_RX_AUD_FIFO_TH),
78*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_CHEXTR_CTRL, HDMI_RX_AUD_PAO_CTRL),
79*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_FIFO_STS, HDMI_RX_AUD_FIFO_STS),
80*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUDPLL_GEN_CTS, HDMI_RX_AUDPLL_GEN_N),
81*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_CTRL, HDMI_RX_PDEC_CTRL),
82*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_AUDIODET_CTRL, HDMI_RX_PDEC_AUDIODET_CTRL),
83*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_ERR_FILTER, HDMI_RX_PDEC_ASP_CTRL),
84*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_STS, HDMI_RX_PDEC_STS),
85*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_GCP_AVMUTE, HDMI_RX_PDEC_GCP_AVMUTE),
86*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_ACR_CTS, HDMI_RX_PDEC_ACR_N),
87*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_AIF_CTRL, HDMI_RX_PDEC_AIF_PB0),
88*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_AVI_PB, HDMI_RX_PDEC_AVI_PB),
89*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI20_CONTROL, HDMI_RX_CHLOCK_CONFIG),
90*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_SCDC_REGS1, HDMI_RX_SCDC_REGS2),
91*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_SCDC_WRDATA0, HDMI_RX_SCDC_WRDATA0),
92*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_PDEC_ISTS, HDMI_RX_PDEC_IEN),
93*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_AUD_FIFO_ISTS, HDMI_RX_AUD_FIFO_IEN),
94*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_MD_ISTS, HDMI_RX_MD_IEN),
95*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_HDMI_ISTS, HDMI_RX_HDMI_IEN),
96*4882a593Smuzhiyun 	regmap_reg_range(HDMI_RX_DMI_DISABLE_IF, HDMI_RX_DMI_DISABLE_IF),
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun static const struct regmap_access_table rk628_hdmirx_readable_table = {
100*4882a593Smuzhiyun 	.yes_ranges     = rk628_hdmirx_readable_ranges,
101*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_hdmirx_readable_ranges),
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static const struct regmap_range rk628_key_readable_ranges[] = {
105*4882a593Smuzhiyun 	regmap_reg_range(EDID_BASE, EDID_BASE + 0x400),
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static const struct regmap_access_table rk628_key_readable_table = {
109*4882a593Smuzhiyun 	.yes_ranges     = rk628_key_readable_ranges,
110*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_key_readable_ranges),
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun static const struct regmap_range rk628_combtxphy_readable_ranges[] = {
114*4882a593Smuzhiyun 	regmap_reg_range(COMBTXPHY_BASE, COMBTXPHY_CON10),
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun static const struct regmap_access_table rk628_combtxphy_readable_table = {
118*4882a593Smuzhiyun 	.yes_ranges     = rk628_combtxphy_readable_ranges,
119*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_combtxphy_readable_ranges),
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun static const struct regmap_range rk628_dsi0_readable_ranges[] = {
123*4882a593Smuzhiyun 	regmap_reg_range(DSI0_BASE, DSI0_BASE + DSI_MAX_REGISTER),
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun static const struct regmap_access_table rk628_dsi0_readable_table = {
127*4882a593Smuzhiyun 	.yes_ranges     = rk628_dsi0_readable_ranges,
128*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_dsi0_readable_ranges),
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun static const struct regmap_range rk628_dsi1_readable_ranges[] = {
132*4882a593Smuzhiyun 	regmap_reg_range(DSI1_BASE, DSI1_BASE + DSI_MAX_REGISTER),
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun static const struct regmap_access_table rk628_dsi1_readable_table = {
136*4882a593Smuzhiyun 	.yes_ranges     = rk628_dsi1_readable_ranges,
137*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_dsi1_readable_ranges),
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static const struct regmap_range rk628_gvi_readable_ranges[] = {
141*4882a593Smuzhiyun 	regmap_reg_range(GVI_BASE, GVI_BASE + GVI_COLOR_BAR_VTIMING1),
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun static const struct regmap_access_table rk628_gvi_readable_table = {
145*4882a593Smuzhiyun 	.yes_ranges     = rk628_gvi_readable_ranges,
146*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_gvi_readable_ranges),
147*4882a593Smuzhiyun };
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun static const struct regmap_range rk628_csi_readable_ranges[] = {
150*4882a593Smuzhiyun 	regmap_reg_range(CSITX_CONFIG_DONE, CSITX_CSITX_VERSION),
151*4882a593Smuzhiyun 	regmap_reg_range(CSITX_SYS_CTRL0_IMD, CSITX_TIMING_HPW_PADDING_NUM),
152*4882a593Smuzhiyun 	regmap_reg_range(CSITX_VOP_PATH_CTRL, CSITX_VOP_PATH_CTRL),
153*4882a593Smuzhiyun 	regmap_reg_range(CSITX_VOP_PATH_PKT_CTRL, CSITX_VOP_PATH_PKT_CTRL),
154*4882a593Smuzhiyun 	regmap_reg_range(CSITX_CSITX_STATUS0, CSITX_LPDT_DATA_IMD),
155*4882a593Smuzhiyun 	regmap_reg_range(CSITX_DPHY_CTRL, CSITX_DPHY_CTRL),
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun static const struct regmap_access_table rk628_csi_readable_table = {
159*4882a593Smuzhiyun 	.yes_ranges     = rk628_csi_readable_ranges,
160*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_csi_readable_ranges),
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun static const struct regmap_range rk628_hdmi_volatile_reg_ranges[] = {
164*4882a593Smuzhiyun 	regmap_reg_range(HDMI_SYS_CTRL, HDMI_MAX_REG),
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun static const struct regmap_access_table rk628_hdmi_volatile_regs = {
168*4882a593Smuzhiyun 	.yes_ranges = rk628_hdmi_volatile_reg_ranges,
169*4882a593Smuzhiyun 	.n_yes_ranges = ARRAY_SIZE(rk628_hdmi_volatile_reg_ranges),
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static const struct regmap_range rk628_gpio0_readable_ranges[] = {
173*4882a593Smuzhiyun 	regmap_reg_range(RK628_GPIO0_BASE, RK628_GPIO0_BASE + GPIO_VER_ID),
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static const struct regmap_access_table rk628_gpio0_readable_table = {
177*4882a593Smuzhiyun 	.yes_ranges     = rk628_gpio0_readable_ranges,
178*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_gpio0_readable_ranges),
179*4882a593Smuzhiyun };
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun static const struct regmap_range rk628_gpio1_readable_ranges[] = {
182*4882a593Smuzhiyun 	regmap_reg_range(RK628_GPIO1_BASE, RK628_GPIO1_BASE + GPIO_VER_ID),
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun static const struct regmap_access_table rk628_gpio1_readable_table = {
186*4882a593Smuzhiyun 	.yes_ranges     = rk628_gpio1_readable_ranges,
187*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_gpio1_readable_ranges),
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun static const struct regmap_range rk628_gpio2_readable_ranges[] = {
191*4882a593Smuzhiyun 	regmap_reg_range(RK628_GPIO2_BASE, RK628_GPIO2_BASE + GPIO_VER_ID),
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun static const struct regmap_access_table rk628_gpio2_readable_table = {
195*4882a593Smuzhiyun 	.yes_ranges     = rk628_gpio2_readable_ranges,
196*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_gpio2_readable_ranges),
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun static const struct regmap_range rk628_gpio3_readable_ranges[] = {
200*4882a593Smuzhiyun 	regmap_reg_range(RK628_GPIO3_BASE, RK628_GPIO3_BASE + GPIO_VER_ID),
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun static const struct regmap_access_table rk628_gpio3_readable_table = {
204*4882a593Smuzhiyun 	.yes_ranges     = rk628_gpio3_readable_ranges,
205*4882a593Smuzhiyun 	.n_yes_ranges   = ARRAY_SIZE(rk628_gpio3_readable_ranges),
206*4882a593Smuzhiyun };
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static const struct regmap_config rk628_regmap_config[RK628_DEV_MAX] = {
209*4882a593Smuzhiyun 	[RK628_DEV_GRF] = {
210*4882a593Smuzhiyun 		.name = "grf",
211*4882a593Smuzhiyun 		.reg_bits = 32,
212*4882a593Smuzhiyun 		.val_bits = 32,
213*4882a593Smuzhiyun 		.reg_stride = 4,
214*4882a593Smuzhiyun 		.max_register = GRF_MAX_REGISTER,
215*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
216*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
217*4882a593Smuzhiyun 	},
218*4882a593Smuzhiyun 	[RK628_DEV_CRU] = {
219*4882a593Smuzhiyun 		.name = "cru",
220*4882a593Smuzhiyun 		.reg_bits = 32,
221*4882a593Smuzhiyun 		.val_bits = 32,
222*4882a593Smuzhiyun 		.reg_stride = 4,
223*4882a593Smuzhiyun 		.max_register = CRU_MAX_REGISTER,
224*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
225*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
226*4882a593Smuzhiyun 		.rd_table = &rk628_cru_readable_table,
227*4882a593Smuzhiyun 	},
228*4882a593Smuzhiyun 	[RK628_DEV_COMBRXPHY] = {
229*4882a593Smuzhiyun 		.name = "combrxphy",
230*4882a593Smuzhiyun 		.reg_bits = 32,
231*4882a593Smuzhiyun 		.val_bits = 32,
232*4882a593Smuzhiyun 		.reg_stride = 4,
233*4882a593Smuzhiyun 		.max_register = COMBRX_REG(0x6790),
234*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
235*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
236*4882a593Smuzhiyun 		.rd_table = &rk628_combrxphy_readable_table,
237*4882a593Smuzhiyun 	},
238*4882a593Smuzhiyun 	[RK628_DEV_HDMIRX] = {
239*4882a593Smuzhiyun 		.name = "hdmirx",
240*4882a593Smuzhiyun 		.reg_bits = 32,
241*4882a593Smuzhiyun 		.val_bits = 32,
242*4882a593Smuzhiyun 		.reg_stride = 4,
243*4882a593Smuzhiyun 		.max_register = HDMI_RX_MAX_REGISTER,
244*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
245*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
246*4882a593Smuzhiyun 		.rd_table = &rk628_hdmirx_readable_table,
247*4882a593Smuzhiyun 	},
248*4882a593Smuzhiyun 	[RK628_DEV_ADAPTER] = {
249*4882a593Smuzhiyun 		.name = "adapter",
250*4882a593Smuzhiyun 		.reg_bits = 32,
251*4882a593Smuzhiyun 		.val_bits = 32,
252*4882a593Smuzhiyun 		.reg_stride = 4,
253*4882a593Smuzhiyun 		.max_register = KEY_MAX_REGISTER,
254*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
255*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
256*4882a593Smuzhiyun 		.rd_table = &rk628_key_readable_table,
257*4882a593Smuzhiyun 	},
258*4882a593Smuzhiyun 	[RK628_DEV_COMBTXPHY] = {
259*4882a593Smuzhiyun 		.name = "combtxphy",
260*4882a593Smuzhiyun 		.reg_bits = 32,
261*4882a593Smuzhiyun 		.val_bits = 32,
262*4882a593Smuzhiyun 		.reg_stride = 4,
263*4882a593Smuzhiyun 		.max_register = COMBTXPHY_CON10,
264*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
265*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
266*4882a593Smuzhiyun 		.rd_table = &rk628_combtxphy_readable_table,
267*4882a593Smuzhiyun 	},
268*4882a593Smuzhiyun 	[RK628_DEV_DSI0] = {
269*4882a593Smuzhiyun 		.name = "dsi0",
270*4882a593Smuzhiyun 		.reg_bits = 32,
271*4882a593Smuzhiyun 		.val_bits = 32,
272*4882a593Smuzhiyun 		.reg_stride = 4,
273*4882a593Smuzhiyun 		.max_register = DSI0_BASE + DSI_MAX_REGISTER,
274*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
275*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
276*4882a593Smuzhiyun 		.rd_table = &rk628_dsi0_readable_table,
277*4882a593Smuzhiyun 	},
278*4882a593Smuzhiyun 	[RK628_DEV_DSI1] = {
279*4882a593Smuzhiyun 		.name = "dsi1",
280*4882a593Smuzhiyun 		.reg_bits = 32,
281*4882a593Smuzhiyun 		.val_bits = 32,
282*4882a593Smuzhiyun 		.reg_stride = 4,
283*4882a593Smuzhiyun 		.max_register = DSI1_BASE + DSI_MAX_REGISTER,
284*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
285*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
286*4882a593Smuzhiyun 		.rd_table = &rk628_dsi1_readable_table,
287*4882a593Smuzhiyun 	},
288*4882a593Smuzhiyun 	[RK628_DEV_GVI] = {
289*4882a593Smuzhiyun 		.name = "gvi",
290*4882a593Smuzhiyun 		.reg_bits = 32,
291*4882a593Smuzhiyun 		.val_bits = 32,
292*4882a593Smuzhiyun 		.reg_stride = 4,
293*4882a593Smuzhiyun 		.max_register = GVI_COLOR_BAR_VTIMING1,
294*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
295*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
296*4882a593Smuzhiyun 		.rd_table = &rk628_gvi_readable_table,
297*4882a593Smuzhiyun 	},
298*4882a593Smuzhiyun 	[RK628_DEV_CSI] = {
299*4882a593Smuzhiyun 		.name = "csi",
300*4882a593Smuzhiyun 		.reg_bits = 32,
301*4882a593Smuzhiyun 		.val_bits = 32,
302*4882a593Smuzhiyun 		.reg_stride = 4,
303*4882a593Smuzhiyun 		.max_register = CSI_MAX_REGISTER,
304*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
305*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
306*4882a593Smuzhiyun 		.rd_table = &rk628_csi_readable_table,
307*4882a593Smuzhiyun 	},
308*4882a593Smuzhiyun 	[RK628_DEV_HDMITX] = {
309*4882a593Smuzhiyun 		.name = "hdmi",
310*4882a593Smuzhiyun 		.reg_bits = 32,
311*4882a593Smuzhiyun 		.val_bits = 32,
312*4882a593Smuzhiyun 		.reg_stride = 4,
313*4882a593Smuzhiyun 		.max_register = HDMI_MAX_REG,
314*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
315*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
316*4882a593Smuzhiyun 		.rd_table = &rk628_hdmi_volatile_regs,
317*4882a593Smuzhiyun 	},
318*4882a593Smuzhiyun 	[RK628_DEV_GPIO0] = {
319*4882a593Smuzhiyun 		.name = "gpio0",
320*4882a593Smuzhiyun 		.reg_bits = 32,
321*4882a593Smuzhiyun 		.val_bits = 32,
322*4882a593Smuzhiyun 		.reg_stride = 4,
323*4882a593Smuzhiyun 		.max_register = RK628_GPIO0_BASE + GPIO_VER_ID,
324*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
325*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
326*4882a593Smuzhiyun 		.rd_table = &rk628_gpio0_readable_table,
327*4882a593Smuzhiyun 	},
328*4882a593Smuzhiyun 	[RK628_DEV_GPIO1] = {
329*4882a593Smuzhiyun 		.name = "gpio1",
330*4882a593Smuzhiyun 		.reg_bits = 32,
331*4882a593Smuzhiyun 		.val_bits = 32,
332*4882a593Smuzhiyun 		.reg_stride = 4,
333*4882a593Smuzhiyun 		.max_register = RK628_GPIO1_BASE + GPIO_VER_ID,
334*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
335*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
336*4882a593Smuzhiyun 		.rd_table = &rk628_gpio1_readable_table,
337*4882a593Smuzhiyun 	},
338*4882a593Smuzhiyun 	[RK628_DEV_GPIO2] = {
339*4882a593Smuzhiyun 		.name = "gpio2",
340*4882a593Smuzhiyun 		.reg_bits = 32,
341*4882a593Smuzhiyun 		.val_bits = 32,
342*4882a593Smuzhiyun 		.reg_stride = 4,
343*4882a593Smuzhiyun 		.max_register = RK628_GPIO2_BASE + GPIO_VER_ID,
344*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
345*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
346*4882a593Smuzhiyun 		.rd_table = &rk628_gpio2_readable_table,
347*4882a593Smuzhiyun 	},
348*4882a593Smuzhiyun 	[RK628_DEV_GPIO3] = {
349*4882a593Smuzhiyun 		.name = "gpio3",
350*4882a593Smuzhiyun 		.reg_bits = 32,
351*4882a593Smuzhiyun 		.val_bits = 32,
352*4882a593Smuzhiyun 		.reg_stride = 4,
353*4882a593Smuzhiyun 		.max_register = RK628_GPIO3_BASE + GPIO_VER_ID,
354*4882a593Smuzhiyun 		.reg_format_endian = REGMAP_ENDIAN_NATIVE,
355*4882a593Smuzhiyun 		.val_format_endian = REGMAP_ENDIAN_NATIVE,
356*4882a593Smuzhiyun 		.rd_table = &rk628_gpio3_readable_table,
357*4882a593Smuzhiyun 	},
358*4882a593Smuzhiyun };
359*4882a593Smuzhiyun 
rk628_display_disable(struct rk628 * rk628)360*4882a593Smuzhiyun static void rk628_display_disable(struct rk628 *rk628)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	if (!rk628->display_enabled)
363*4882a593Smuzhiyun 		return;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_CSI)
366*4882a593Smuzhiyun 		rk628_csi_disable(rk628);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_GVI)
369*4882a593Smuzhiyun 		rk628_gvi_disable(rk628);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_LVDS)
372*4882a593Smuzhiyun 		rk628_lvds_disable(rk628);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_DSI)
375*4882a593Smuzhiyun 		rk628_dsi_disable(rk628);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	rk628_post_process_disable(rk628);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI)
380*4882a593Smuzhiyun 		rk628_hdmirx_disable(rk628);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	rk628->display_enabled = false;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
rk628_display_resume(struct rk628 * rk628)385*4882a593Smuzhiyun static void rk628_display_resume(struct rk628 *rk628)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	u8 ret = 0;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	if (rk628->display_enabled)
390*4882a593Smuzhiyun 		return;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI) {
393*4882a593Smuzhiyun 		ret = rk628_hdmirx_enable(rk628);
394*4882a593Smuzhiyun 		if ((ret == HDMIRX_PLUGOUT) || (ret & HDMIRX_NOSIGNAL)) {
395*4882a593Smuzhiyun 			rk628_display_disable(rk628);
396*4882a593Smuzhiyun 			return;
397*4882a593Smuzhiyun 		}
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_RGB)
401*4882a593Smuzhiyun 		rk628_rgb_rx_enable(rk628);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_BT1120)
404*4882a593Smuzhiyun 		rk628_bt1120_rx_enable(rk628);
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	rk628_post_process_init(rk628);
407*4882a593Smuzhiyun 	rk628_post_process_enable(rk628);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_DSI) {
410*4882a593Smuzhiyun 		rk628_mipi_dsi_pre_enable(rk628);
411*4882a593Smuzhiyun 		rk628_mipi_dsi_enable(rk628);
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_LVDS)
415*4882a593Smuzhiyun 		rk628_lvds_enable(rk628);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_GVI)
418*4882a593Smuzhiyun 		rk628_gvi_enable(rk628);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_CSI)
421*4882a593Smuzhiyun 		rk628_csi_enable(rk628);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun #ifdef CONFIG_RK628_MISC_HDMITX
424*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_HDMI)
425*4882a593Smuzhiyun 		rk628_hdmitx_enable(rk628);
426*4882a593Smuzhiyun #endif
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	rk628->display_enabled = true;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
rk628_display_enable(struct rk628 * rk628)431*4882a593Smuzhiyun static void rk628_display_enable(struct rk628 *rk628)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun 	u8 ret = 0;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	if (rk628->display_enabled)
436*4882a593Smuzhiyun 		return;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_RGB)
439*4882a593Smuzhiyun 		rk628_rgb_rx_enable(rk628);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_BT1120)
442*4882a593Smuzhiyun 		rk628_bt1120_rx_enable(rk628);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_BT1120)
445*4882a593Smuzhiyun 		rk628_bt1120_tx_enable(rk628);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_DSI)
448*4882a593Smuzhiyun 		queue_delayed_work(rk628->dsi_wq, &rk628->dsi_delay_work, msecs_to_jiffies(10));
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI) {
451*4882a593Smuzhiyun 		ret = rk628_hdmirx_enable(rk628);
452*4882a593Smuzhiyun 		if ((ret == HDMIRX_PLUGOUT) || (ret & HDMIRX_NOSIGNAL)) {
453*4882a593Smuzhiyun 			rk628_display_disable(rk628);
454*4882a593Smuzhiyun 			return;
455*4882a593Smuzhiyun 		}
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	if (rk628->output_mode != OUTPUT_MODE_HDMI) {
459*4882a593Smuzhiyun 		rk628_post_process_init(rk628);
460*4882a593Smuzhiyun 		rk628_post_process_enable(rk628);
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_LVDS)
464*4882a593Smuzhiyun 		rk628_lvds_enable(rk628);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_GVI)
467*4882a593Smuzhiyun 		rk628_gvi_enable(rk628);
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_CSI)
470*4882a593Smuzhiyun 		rk628_csi_enable(rk628);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun #ifdef CONFIG_RK628_MISC_HDMITX
473*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_HDMI)
474*4882a593Smuzhiyun 		rk628_hdmitx_enable(rk628);
475*4882a593Smuzhiyun #endif
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	rk628->display_enabled = true;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
rk628_display_work(struct work_struct * work)480*4882a593Smuzhiyun static void rk628_display_work(struct work_struct *work)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	u8 ret = 0;
483*4882a593Smuzhiyun 	struct rk628 *rk628 =
484*4882a593Smuzhiyun 		container_of(work, struct rk628, delay_work.work);
485*4882a593Smuzhiyun 	int delay = msecs_to_jiffies(2000);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI) {
488*4882a593Smuzhiyun 		ret = rk628_hdmirx_detect(rk628);
489*4882a593Smuzhiyun 		if (!(ret & (HDMIRX_CHANGED | HDMIRX_NOLOCK))) {
490*4882a593Smuzhiyun 			if (!rk628->plugin_det_gpio)
491*4882a593Smuzhiyun 				queue_delayed_work(rk628->monitor_wq,
492*4882a593Smuzhiyun 						   &rk628->delay_work, delay);
493*4882a593Smuzhiyun 			else
494*4882a593Smuzhiyun 				rk628_hdmirx_enable_interrupts(rk628, true);
495*4882a593Smuzhiyun 			return;
496*4882a593Smuzhiyun 		}
497*4882a593Smuzhiyun 	}
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	if (ret & HDMIRX_PLUGIN) {
500*4882a593Smuzhiyun 		/* if resolution or input format change, disable first */
501*4882a593Smuzhiyun 		rk628_display_disable(rk628);
502*4882a593Smuzhiyun 		rk628_display_enable(rk628);
503*4882a593Smuzhiyun 	} else if (ret & HDMIRX_PLUGOUT) {
504*4882a593Smuzhiyun 		rk628_display_disable(rk628);
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI) {
508*4882a593Smuzhiyun 		if (!rk628->plugin_det_gpio) {
509*4882a593Smuzhiyun 			if (ret & HDMIRX_NOLOCK)
510*4882a593Smuzhiyun 				delay = msecs_to_jiffies(200);
511*4882a593Smuzhiyun 			queue_delayed_work(rk628->monitor_wq, &rk628->delay_work,
512*4882a593Smuzhiyun 					   delay);
513*4882a593Smuzhiyun 		} else {
514*4882a593Smuzhiyun 			rk628_hdmirx_enable_interrupts(rk628, true);
515*4882a593Smuzhiyun 		}
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
rk628_dsi_work(struct work_struct * work)519*4882a593Smuzhiyun static void rk628_dsi_work(struct work_struct *work)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun 	struct rk628 *rk628 = container_of(work, struct rk628, dsi_delay_work.work);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	rk628_mipi_dsi_pre_enable(rk628);
524*4882a593Smuzhiyun 	rk628_mipi_dsi_enable(rk628);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
rk628_hdmirx_plugin_irq(int irq,void * dev_id)527*4882a593Smuzhiyun static irqreturn_t rk628_hdmirx_plugin_irq(int irq, void *dev_id)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct rk628 *rk628 = dev_id;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	rk628_hdmirx_enable_interrupts(rk628, false);
532*4882a593Smuzhiyun 	/* clear interrupts */
533*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_ICLR, 0xffffffff);
534*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
535*4882a593Smuzhiyun 	rk628_i2c_write(rk628, GRF_INTR0_CLR_EN, 0x01000100);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	/* control hpd after 50ms */
538*4882a593Smuzhiyun 	schedule_delayed_work(&rk628->delay_work, HZ / 20);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	return IRQ_HANDLED;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun 
rk628_input_is_rgb(struct rk628 * rk628)543*4882a593Smuzhiyun static bool rk628_input_is_rgb(struct rk628 *rk628)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_RGB || rk628->input_mode == INPUT_MODE_BT1120)
546*4882a593Smuzhiyun 		return true;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	return false;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
rk628_display_route_info_parse(struct rk628 * rk628)551*4882a593Smuzhiyun static int rk628_display_route_info_parse(struct rk628 *rk628)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	struct device_node *np;
554*4882a593Smuzhiyun 	int ret = 0;
555*4882a593Smuzhiyun 	u32 val;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	if (of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-in"))
558*4882a593Smuzhiyun 		rk628->input_mode = INPUT_MODE_HDMI;
559*4882a593Smuzhiyun 	else if (of_property_read_bool(rk628->dev->of_node, "rk628,rgb-in"))
560*4882a593Smuzhiyun 		rk628->input_mode = INPUT_MODE_RGB;
561*4882a593Smuzhiyun 	else if (of_property_read_bool(rk628->dev->of_node, "rk628,bt1120-in"))
562*4882a593Smuzhiyun 		rk628->input_mode = INPUT_MODE_BT1120;
563*4882a593Smuzhiyun 	else
564*4882a593Smuzhiyun 		rk628->input_mode = INPUT_MODE_RGB;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	if (of_find_node_by_name(rk628->dev->of_node, "rk628-dsi")) {
567*4882a593Smuzhiyun 		np = of_find_node_by_name(rk628->dev->of_node, "rk628-dsi");
568*4882a593Smuzhiyun 		ret = rk628_dsi_parse(rk628, np);
569*4882a593Smuzhiyun 	} else if (of_find_node_by_name(rk628->dev->of_node, "rk628-lvds")) {
570*4882a593Smuzhiyun 		np = of_find_node_by_name(rk628->dev->of_node, "rk628-lvds");
571*4882a593Smuzhiyun 		ret = rk628_lvds_parse(rk628, np);
572*4882a593Smuzhiyun 	} else if (of_find_node_by_name(rk628->dev->of_node, "rk628-gvi")) {
573*4882a593Smuzhiyun 		np = of_find_node_by_name(rk628->dev->of_node, "rk628-gvi");
574*4882a593Smuzhiyun 		ret = rk628_gvi_parse(rk628, np);
575*4882a593Smuzhiyun 	} else if (of_find_node_by_name(rk628->dev->of_node, "rk628-bt1120")) {
576*4882a593Smuzhiyun 		rk628->output_mode = OUTPUT_MODE_BT1120;
577*4882a593Smuzhiyun 	} else {
578*4882a593Smuzhiyun 		if (of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-out"))
579*4882a593Smuzhiyun 			rk628->output_mode = OUTPUT_MODE_HDMI;
580*4882a593Smuzhiyun 		else if (of_property_read_bool(rk628->dev->of_node, "rk628,csi-out"))
581*4882a593Smuzhiyun 			rk628->output_mode = OUTPUT_MODE_CSI;
582*4882a593Smuzhiyun 	}
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	if (of_property_read_u32(rk628->dev->of_node, "mode-sync-pol", &val) < 0)
585*4882a593Smuzhiyun 		rk628->sync_pol = MODE_FLAG_PSYNC;
586*4882a593Smuzhiyun 	else
587*4882a593Smuzhiyun 		rk628->sync_pol = (!val ? MODE_FLAG_NSYNC : MODE_FLAG_PSYNC);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	if (rk628_input_is_rgb(rk628) && rk628->output_mode == OUTPUT_MODE_RGB)
590*4882a593Smuzhiyun 		return -EINVAL;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	return ret;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun static void
rk628_display_mode_from_videomode(const struct rk628_videomode * vm,struct rk628_display_mode * dmode)596*4882a593Smuzhiyun rk628_display_mode_from_videomode(const struct rk628_videomode *vm,
597*4882a593Smuzhiyun 				  struct rk628_display_mode *dmode)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	dmode->hdisplay = vm->hactive;
600*4882a593Smuzhiyun 	dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
601*4882a593Smuzhiyun 	dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
602*4882a593Smuzhiyun 	dmode->htotal = dmode->hsync_end + vm->hback_porch;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	dmode->vdisplay = vm->vactive;
605*4882a593Smuzhiyun 	dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
606*4882a593Smuzhiyun 	dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
607*4882a593Smuzhiyun 	dmode->vtotal = dmode->vsync_end + vm->vback_porch;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	dmode->clock = vm->pixelclock / 1000;
610*4882a593Smuzhiyun 	dmode->flags = vm->flags;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun static void
of_parse_rk628_display_timing(struct device_node * np,struct rk628_videomode * vm)614*4882a593Smuzhiyun of_parse_rk628_display_timing(struct device_node *np, struct rk628_videomode *vm)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	u8 val;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	of_property_read_u32(np, "clock-frequency", &vm->pixelclock);
619*4882a593Smuzhiyun 	of_property_read_u32(np, "hactive", &vm->hactive);
620*4882a593Smuzhiyun 	of_property_read_u32(np, "hfront-porch", &vm->hfront_porch);
621*4882a593Smuzhiyun 	of_property_read_u32(np, "hback-porch", &vm->hback_porch);
622*4882a593Smuzhiyun 	of_property_read_u32(np, "hsync-len", &vm->hsync_len);
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	of_property_read_u32(np, "vactive", &vm->vactive);
625*4882a593Smuzhiyun 	of_property_read_u32(np, "vfront-porch", &vm->vfront_porch);
626*4882a593Smuzhiyun 	of_property_read_u32(np, "vback-porch", &vm->vback_porch);
627*4882a593Smuzhiyun 	of_property_read_u32(np, "vsync-len", &vm->vsync_len);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	vm->flags = 0;
630*4882a593Smuzhiyun 	of_property_read_u8(np, "hsync-active", &val);
631*4882a593Smuzhiyun 	vm->flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	of_property_read_u8(np, "vsync-active", &val);
634*4882a593Smuzhiyun 	vm->flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
rk628_get_video_mode(struct rk628 * rk628)637*4882a593Smuzhiyun static int rk628_get_video_mode(struct rk628 *rk628)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	struct device_node *timings_np, *src_np, *dst_np;
641*4882a593Smuzhiyun 	struct rk628_videomode vm;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	timings_np = of_get_child_by_name(rk628->dev->of_node, "display-timings");
644*4882a593Smuzhiyun 	if (!timings_np) {
645*4882a593Smuzhiyun 		dev_info(rk628->dev, "failed to found display timings\n");
646*4882a593Smuzhiyun 		return -EINVAL;
647*4882a593Smuzhiyun 	}
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	src_np = of_get_child_by_name(timings_np, "src-timing");
650*4882a593Smuzhiyun 	if (!src_np) {
651*4882a593Smuzhiyun 		dev_info(rk628->dev, "failed to found src timing\n");
652*4882a593Smuzhiyun 		of_node_put(timings_np);
653*4882a593Smuzhiyun 		return -EINVAL;
654*4882a593Smuzhiyun 	}
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	of_parse_rk628_display_timing(src_np, &vm);
657*4882a593Smuzhiyun 	rk628_display_mode_from_videomode(&vm, &rk628->src_mode);
658*4882a593Smuzhiyun 	dev_info(rk628->dev, "src mode: %d %d %d %d %d %d %d %d %d 0x%x\n",
659*4882a593Smuzhiyun 		 rk628->src_mode.clock, rk628->src_mode.hdisplay, rk628->src_mode.hsync_start,
660*4882a593Smuzhiyun 		 rk628->src_mode.hsync_end, rk628->src_mode.htotal, rk628->src_mode.vdisplay,
661*4882a593Smuzhiyun 		 rk628->src_mode.vsync_start, rk628->src_mode.vsync_end, rk628->src_mode.vtotal,
662*4882a593Smuzhiyun 		 rk628->src_mode.flags);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	dst_np = of_get_child_by_name(timings_np, "dst-timing");
665*4882a593Smuzhiyun 	if (!dst_np) {
666*4882a593Smuzhiyun 		dev_info(rk628->dev, "failed to found dst timing\n");
667*4882a593Smuzhiyun 		of_node_put(timings_np);
668*4882a593Smuzhiyun 		of_node_put(src_np);
669*4882a593Smuzhiyun 		return -EINVAL;
670*4882a593Smuzhiyun 	}
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	of_parse_rk628_display_timing(dst_np, &vm);
673*4882a593Smuzhiyun 	rk628_display_mode_from_videomode(&vm, &rk628->dst_mode);
674*4882a593Smuzhiyun 	dev_info(rk628->dev, "dst mode: %d %d %d %d %d %d %d %d %d 0x%x\n",
675*4882a593Smuzhiyun 		 rk628->dst_mode.clock, rk628->dst_mode.hdisplay, rk628->dst_mode.hsync_start,
676*4882a593Smuzhiyun 		 rk628->dst_mode.hsync_end, rk628->dst_mode.htotal, rk628->dst_mode.vdisplay,
677*4882a593Smuzhiyun 		 rk628->dst_mode.vsync_start, rk628->dst_mode.vsync_end, rk628->dst_mode.vtotal,
678*4882a593Smuzhiyun 		 rk628->dst_mode.flags);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	of_node_put(timings_np);
681*4882a593Smuzhiyun 	of_node_put(src_np);
682*4882a593Smuzhiyun 	of_node_put(dst_np);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	return 0;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun 
rk628_display_timings_get(struct rk628 * rk628)687*4882a593Smuzhiyun static int rk628_display_timings_get(struct rk628 *rk628)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	int ret;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	ret = rk628_get_video_mode(rk628);
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	return ret;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun #define DEBUG_PRINT(args...) \
698*4882a593Smuzhiyun 		do { \
699*4882a593Smuzhiyun 			if (s) \
700*4882a593Smuzhiyun 				seq_printf(s, args); \
701*4882a593Smuzhiyun 			else \
702*4882a593Smuzhiyun 				pr_info(args); \
703*4882a593Smuzhiyun 		} while (0)
704*4882a593Smuzhiyun 
rk628_debugfs_dump(struct seq_file * s,void * data)705*4882a593Smuzhiyun static int rk628_debugfs_dump(struct seq_file *s, void *data)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	struct rk628 *rk628 = s->private;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	u32 val;
710*4882a593Smuzhiyun 	u32 dsp_htotal, dsp_hs_end, dsp_hact_st, dsp_hact_end;
711*4882a593Smuzhiyun 	u32 dsp_vtotal, dsp_vs_end, dsp_vact_st, dsp_vact_end;
712*4882a593Smuzhiyun 	u32 src_hactive, src_hoffset, src_htotal, src_hs_end;
713*4882a593Smuzhiyun 	u32 src_vactive, src_voffset, src_vtotal, src_vs_end;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	u32 input_mode, output_mode;
716*4882a593Smuzhiyun 	char input_s[10];
717*4882a593Smuzhiyun 	char output_s[13];
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	bool r2y, y2r;
720*4882a593Smuzhiyun 	char csc_mode_r2y_s[10];
721*4882a593Smuzhiyun 	char csc_mode_y2r_s[10];
722*4882a593Smuzhiyun 	u32 csc;
723*4882a593Smuzhiyun 	enum csc_mode {
724*4882a593Smuzhiyun 		BT601_L,
725*4882a593Smuzhiyun 		BT709_L,
726*4882a593Smuzhiyun 		BT601_F,
727*4882a593Smuzhiyun 		BT2020
728*4882a593Smuzhiyun 	};
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	int sw_hsync_pol, sw_vsync_pol;
731*4882a593Smuzhiyun 	u32 dsp_frame_v_start, dsp_frame_h_start;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	int sclk_vop_sel = 0;
734*4882a593Smuzhiyun 	u32 sclk_vop_div;
735*4882a593Smuzhiyun 	u64 sclk_vop;
736*4882a593Smuzhiyun 	u32 reg_v;
737*4882a593Smuzhiyun 	u32 fps;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	u32 imodet_clk;
740*4882a593Smuzhiyun 	u32 imodet_clk_sel;
741*4882a593Smuzhiyun 	u32 imodet_clk_div;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	int clk_rx_read_sel = 0;
744*4882a593Smuzhiyun 	u32 clk_rx_read_div;
745*4882a593Smuzhiyun 	u64 clk_rx_read;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	u32 tdms_clk_div;
748*4882a593Smuzhiyun 	u32 tdms_clk;
749*4882a593Smuzhiyun 	u32 common_tdms_clk[19] = {
750*4882a593Smuzhiyun 		25170, 27000, 33750, 40000, 59400,
751*4882a593Smuzhiyun 		65000, 68250, 74250, 83500, 85500,
752*4882a593Smuzhiyun 		88750, 92812, 101000, 108000, 119000,
753*4882a593Smuzhiyun 		135000, 148500, 162000, 297000,
754*4882a593Smuzhiyun 	};
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	//get sclk vop
757*4882a593Smuzhiyun 	rk628_i2c_read(rk628, 0xc0088, &reg_v);
758*4882a593Smuzhiyun 	sclk_vop_sel = (reg_v & 0x20) ? 1 : 0;
759*4882a593Smuzhiyun 	rk628_i2c_read(rk628, 0xc00b4, &reg_v);
760*4882a593Smuzhiyun 	if (reg_v)
761*4882a593Smuzhiyun 		sclk_vop_div = reg_v;
762*4882a593Smuzhiyun 	else
763*4882a593Smuzhiyun 		sclk_vop_div = 0x10002;
764*4882a593Smuzhiyun 	/* gpll 983.04MHz */
765*4882a593Smuzhiyun 	/* cpll 1188MHz */
766*4882a593Smuzhiyun 	if (sclk_vop_sel)
767*4882a593Smuzhiyun 		sclk_vop = (u64)983040 * ((sclk_vop_div & 0xffff0000) >> 16);
768*4882a593Smuzhiyun 	else
769*4882a593Smuzhiyun 		sclk_vop = (u64)1188000 * ((sclk_vop_div & 0xffff0000) >> 16);
770*4882a593Smuzhiyun 	do_div(sclk_vop, sclk_vop_div & 0xffff);
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	//get rx read clk
773*4882a593Smuzhiyun 	rk628_i2c_read(rk628, 0xc0088, &reg_v);
774*4882a593Smuzhiyun 	clk_rx_read_sel = (reg_v & 0x10) ? 1 : 0;
775*4882a593Smuzhiyun 	rk628_i2c_read(rk628, 0xc00b8, &reg_v);
776*4882a593Smuzhiyun 	if (reg_v)
777*4882a593Smuzhiyun 		clk_rx_read_div = reg_v;
778*4882a593Smuzhiyun 	else
779*4882a593Smuzhiyun 		clk_rx_read_div = 0x10002;
780*4882a593Smuzhiyun 	/* gpll 983.04MHz */
781*4882a593Smuzhiyun 	/* cpll 1188MHz */
782*4882a593Smuzhiyun 	if (clk_rx_read_sel)
783*4882a593Smuzhiyun 		clk_rx_read = (u64)983040 * ((clk_rx_read_div & 0xffff0000) >> 16);
784*4882a593Smuzhiyun 	else
785*4882a593Smuzhiyun 		clk_rx_read = (u64)1188000 * ((clk_rx_read_div & 0xffff0000) >> 16);
786*4882a593Smuzhiyun 	do_div(clk_rx_read, clk_rx_read_div & 0xffff);
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	//get imodet clk
789*4882a593Smuzhiyun 	rk628_i2c_read(rk628, 0xc0094, &reg_v);
790*4882a593Smuzhiyun 	imodet_clk_sel = (reg_v & 0x20) ? 1 : 0;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	if (reg_v)
793*4882a593Smuzhiyun 		imodet_clk_div = (reg_v & 0x1f) + 1;
794*4882a593Smuzhiyun 	else
795*4882a593Smuzhiyun 		imodet_clk_div = 0x18;
796*4882a593Smuzhiyun 	/* gpll 983.04MHz */
797*4882a593Smuzhiyun 	/* cpll 1188MHz */
798*4882a593Smuzhiyun 	if (imodet_clk_sel)
799*4882a593Smuzhiyun 		imodet_clk = 983040 / imodet_clk_div;
800*4882a593Smuzhiyun 	else
801*4882a593Smuzhiyun 		imodet_clk = 1188000 / imodet_clk_div;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	//get input interface type
804*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SYSTEM_CON0, &val);
805*4882a593Smuzhiyun 	input_mode = val & 0x7;
806*4882a593Smuzhiyun 	output_mode = (val & 0xf8) >> 3;
807*4882a593Smuzhiyun 	sw_hsync_pol = (val & 0x4000000) ? 1 : 0;
808*4882a593Smuzhiyun 	sw_vsync_pol = (val & 0x2000000) ? 1 : 0;
809*4882a593Smuzhiyun 	switch (input_mode) {
810*4882a593Smuzhiyun 	case 0:
811*4882a593Smuzhiyun 		strcpy(input_s, "HDMI");
812*4882a593Smuzhiyun 		break;
813*4882a593Smuzhiyun 	case 1:
814*4882a593Smuzhiyun 		strcpy(input_s, "reserved");
815*4882a593Smuzhiyun 		break;
816*4882a593Smuzhiyun 	case 2:
817*4882a593Smuzhiyun 		strcpy(input_s, "BT1120");
818*4882a593Smuzhiyun 		break;
819*4882a593Smuzhiyun 	case 3:
820*4882a593Smuzhiyun 		strcpy(input_s, "RGB");
821*4882a593Smuzhiyun 		break;
822*4882a593Smuzhiyun 	case 4:
823*4882a593Smuzhiyun 		strcpy(input_s, "YUV");
824*4882a593Smuzhiyun 		break;
825*4882a593Smuzhiyun 	default:
826*4882a593Smuzhiyun 		strcpy(input_s, "unknown");
827*4882a593Smuzhiyun 	}
828*4882a593Smuzhiyun 	DEBUG_PRINT("input:%s\n", input_s);
829*4882a593Smuzhiyun 	if (input_mode == 0) {
830*4882a593Smuzhiyun 		//get tdms clk
831*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x16654, &reg_v);
832*4882a593Smuzhiyun 		reg_v = (reg_v & 0x3f0000) >> 16;
833*4882a593Smuzhiyun 		if (reg_v >= 0 && reg_v <= 19)
834*4882a593Smuzhiyun 			tdms_clk = common_tdms_clk[reg_v];
835*4882a593Smuzhiyun 		else
836*4882a593Smuzhiyun 			tdms_clk = 148500;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x166a8, &reg_v);
839*4882a593Smuzhiyun 		reg_v = (reg_v & 0xf00) >> 8;
840*4882a593Smuzhiyun 		if (reg_v == 0x6)
841*4882a593Smuzhiyun 			tdms_clk_div = 1;
842*4882a593Smuzhiyun 		else if (reg_v == 0x0)
843*4882a593Smuzhiyun 			tdms_clk_div = 2;
844*4882a593Smuzhiyun 		else
845*4882a593Smuzhiyun 			tdms_clk_div = 1;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		//get input hdmi timing
848*4882a593Smuzhiyun 		//get horizon timing
849*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x30150, &reg_v);
850*4882a593Smuzhiyun 		src_hactive = reg_v & 0xffff;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x3014c, &reg_v);
853*4882a593Smuzhiyun 		src_hoffset = (reg_v & 0xffff);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 		src_hactive *= tdms_clk_div;
856*4882a593Smuzhiyun 		src_hoffset *=  tdms_clk_div;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 		src_htotal = (reg_v & 0xffff0000)>>16;
859*4882a593Smuzhiyun 		src_htotal *= tdms_clk_div;
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x30148, &reg_v);
862*4882a593Smuzhiyun 		reg_v = reg_v & 0xffff;
863*4882a593Smuzhiyun 		src_hs_end = reg_v * tdms_clk * tdms_clk_div / imodet_clk;
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 		//get vertical timing
866*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x30168, &reg_v);
867*4882a593Smuzhiyun 		src_vactive = reg_v & 0xffff;
868*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x30170, &reg_v);
869*4882a593Smuzhiyun 		src_vtotal = reg_v & 0xffff;
870*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x30164, &reg_v);
871*4882a593Smuzhiyun 		src_voffset = (reg_v & 0xffff);
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x3015c, &reg_v);
874*4882a593Smuzhiyun 		reg_v = reg_v & 0xffff;
875*4882a593Smuzhiyun 		src_vs_end = reg_v * clk_rx_read;
876*4882a593Smuzhiyun 		do_div(src_vs_end, imodet_clk * src_htotal);
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 		//get fps and print
879*4882a593Smuzhiyun 		fps = clk_rx_read * 1000;
880*4882a593Smuzhiyun 		do_div(fps, src_htotal * src_vtotal);
881*4882a593Smuzhiyun 		DEBUG_PRINT("    Display mode: %dx%dp%d,dclk[%llu],tdms_clk[%d]\n",
882*4882a593Smuzhiyun 			    src_hactive, src_vactive, fps, clk_rx_read, tdms_clk);
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 		DEBUG_PRINT("\tH: %d %d %d %d\n", src_hactive, src_htotal - src_hoffset,
885*4882a593Smuzhiyun 			    src_htotal - src_hoffset + src_hs_end, src_htotal);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 		DEBUG_PRINT("\tV: %d %d %d %d\n", src_vactive,
888*4882a593Smuzhiyun 			    src_vtotal - src_voffset - src_vs_end,
889*4882a593Smuzhiyun 			    src_vtotal - src_voffset, src_vtotal);
890*4882a593Smuzhiyun 	} else if (input_mode == 2 || input_mode == 3 || input_mode == 4) {
891*4882a593Smuzhiyun 		//get timing
892*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x130, &reg_v);
893*4882a593Smuzhiyun 		src_hactive = reg_v & 0xffff;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x12c, &reg_v);
896*4882a593Smuzhiyun 		src_vactive = (reg_v & 0xffff);
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 		rk628_i2c_read(rk628, 0x134, &reg_v);
899*4882a593Smuzhiyun 		src_htotal = (reg_v & 0xffff0000) >> 16;
900*4882a593Smuzhiyun 		src_vtotal = reg_v & 0xffff;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 		//get fps and print
903*4882a593Smuzhiyun 		fps = clk_rx_read * 1000;
904*4882a593Smuzhiyun 		do_div(fps, src_htotal * src_vtotal);
905*4882a593Smuzhiyun 		DEBUG_PRINT("    Display mode: %dx%dp%d,dclk[%llu]\n",
906*4882a593Smuzhiyun 			    src_hactive, src_vactive, fps, clk_rx_read);
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 		DEBUG_PRINT("\tH-total: %d\n", src_htotal);
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 		DEBUG_PRINT("\tV-total: %d\n", src_vtotal);
911*4882a593Smuzhiyun 	}
912*4882a593Smuzhiyun 	//get output interface type
913*4882a593Smuzhiyun 	switch (output_mode & 0x7) {
914*4882a593Smuzhiyun 	case 1:
915*4882a593Smuzhiyun 		strcpy(output_s, "GVI");
916*4882a593Smuzhiyun 		break;
917*4882a593Smuzhiyun 	case 2:
918*4882a593Smuzhiyun 		strcpy(output_s, "LVDS");
919*4882a593Smuzhiyun 		break;
920*4882a593Smuzhiyun 	case 3:
921*4882a593Smuzhiyun 		strcpy(output_s, "HDMI");
922*4882a593Smuzhiyun 		break;
923*4882a593Smuzhiyun 	case 4:
924*4882a593Smuzhiyun 		strcpy(output_s, "CSI");
925*4882a593Smuzhiyun 		break;
926*4882a593Smuzhiyun 	case 5:
927*4882a593Smuzhiyun 		strcpy(output_s, "DSI");
928*4882a593Smuzhiyun 		break;
929*4882a593Smuzhiyun 	default:
930*4882a593Smuzhiyun 		strcpy(output_s, "");
931*4882a593Smuzhiyun 	}
932*4882a593Smuzhiyun 	strcpy(output_s + 4, " ");
933*4882a593Smuzhiyun 	switch (output_mode >> 2) {
934*4882a593Smuzhiyun 	case 0:
935*4882a593Smuzhiyun 		strcpy(output_s + 5, "");
936*4882a593Smuzhiyun 		break;
937*4882a593Smuzhiyun 	case 1:
938*4882a593Smuzhiyun 		strcpy(output_s + 5, "BT1120");
939*4882a593Smuzhiyun 		break;
940*4882a593Smuzhiyun 	case 2:
941*4882a593Smuzhiyun 		strcpy(output_s + 5, "RGB");
942*4882a593Smuzhiyun 		break;
943*4882a593Smuzhiyun 	case 3:
944*4882a593Smuzhiyun 		strcpy(output_s + 5, "YUV");
945*4882a593Smuzhiyun 		break;
946*4882a593Smuzhiyun 	default:
947*4882a593Smuzhiyun 		strcpy(output_s + 5, "unknown");
948*4882a593Smuzhiyun 	}
949*4882a593Smuzhiyun 	DEBUG_PRINT("output:%s\n", output_s);
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	//get output timing
952*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SCALER_CON3, &val);
953*4882a593Smuzhiyun 	dsp_htotal = val & 0xffff;
954*4882a593Smuzhiyun 	dsp_hs_end = (val & 0xff0000) >> 16;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SCALER_CON4, &val);
957*4882a593Smuzhiyun 	dsp_hact_end = val & 0xffff;
958*4882a593Smuzhiyun 	dsp_hact_st = (val & 0xfff0000) >> 16;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SCALER_CON5, &val);
961*4882a593Smuzhiyun 	dsp_vtotal = val & 0xfff;
962*4882a593Smuzhiyun 	dsp_vs_end = (val & 0xff0000) >> 16;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SCALER_CON6, &val);
965*4882a593Smuzhiyun 	dsp_vact_st = (val & 0xfff0000) >> 16;
966*4882a593Smuzhiyun 	dsp_vact_end = val & 0xfff;
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	fps = sclk_vop * 1000;
969*4882a593Smuzhiyun 	do_div(fps, dsp_vtotal * dsp_htotal);
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	DEBUG_PRINT("    Display mode: %dx%dp%d,dclk[%llu]\n",
972*4882a593Smuzhiyun 		    dsp_hact_end - dsp_hact_st, dsp_vact_end - dsp_vact_st, fps, sclk_vop);
973*4882a593Smuzhiyun 	DEBUG_PRINT("\tH: %d %d %d %d\n", dsp_hact_end - dsp_hact_st,
974*4882a593Smuzhiyun 		    dsp_htotal - dsp_hact_st, dsp_htotal - dsp_hact_st + dsp_hs_end, dsp_htotal);
975*4882a593Smuzhiyun 	DEBUG_PRINT("\tV: %d %d %d %d\n", dsp_vact_end - dsp_vact_st,
976*4882a593Smuzhiyun 		    dsp_vtotal - dsp_vact_st, dsp_vtotal - dsp_vact_st + dsp_vs_end, dsp_vtotal);
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	//get csc and system information
979*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_CSC_CTRL_CON, &val);
980*4882a593Smuzhiyun 	r2y = ((val & 0x10) == 0x10);
981*4882a593Smuzhiyun 	y2r = ((val & 0x1) == 0x1);
982*4882a593Smuzhiyun 	csc = (val & 0xc0) >> 6;
983*4882a593Smuzhiyun 	switch (csc) {
984*4882a593Smuzhiyun 	case BT601_L:
985*4882a593Smuzhiyun 		strcpy(csc_mode_r2y_s, "BT601_L");
986*4882a593Smuzhiyun 		break;
987*4882a593Smuzhiyun 	case BT601_F:
988*4882a593Smuzhiyun 		strcpy(csc_mode_r2y_s, "BT601_F");
989*4882a593Smuzhiyun 		break;
990*4882a593Smuzhiyun 	case BT709_L:
991*4882a593Smuzhiyun 		strcpy(csc_mode_r2y_s, "BT709_L");
992*4882a593Smuzhiyun 		break;
993*4882a593Smuzhiyun 	case BT2020:
994*4882a593Smuzhiyun 		strcpy(csc_mode_r2y_s, "BT2020");
995*4882a593Smuzhiyun 		break;
996*4882a593Smuzhiyun 	}
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	csc = (val & 0xc) >> 2;
999*4882a593Smuzhiyun 	switch (csc) {
1000*4882a593Smuzhiyun 	case BT601_L:
1001*4882a593Smuzhiyun 		strcpy(csc_mode_y2r_s, "BT601_L");
1002*4882a593Smuzhiyun 		break;
1003*4882a593Smuzhiyun 	case BT601_F:
1004*4882a593Smuzhiyun 		strcpy(csc_mode_y2r_s, "BT601_F");
1005*4882a593Smuzhiyun 		break;
1006*4882a593Smuzhiyun 	case BT709_L:
1007*4882a593Smuzhiyun 		strcpy(csc_mode_y2r_s, "BT709_L");
1008*4882a593Smuzhiyun 		break;
1009*4882a593Smuzhiyun 	case BT2020:
1010*4882a593Smuzhiyun 		strcpy(csc_mode_y2r_s, "BT2020");
1011*4882a593Smuzhiyun 		break;
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	}
1014*4882a593Smuzhiyun 	DEBUG_PRINT("csc:\n");
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	if (r2y)
1017*4882a593Smuzhiyun 		DEBUG_PRINT("\tr2y[1],csc mode:%s\n", csc_mode_r2y_s);
1018*4882a593Smuzhiyun 	else if (y2r)
1019*4882a593Smuzhiyun 		DEBUG_PRINT("\ty2r[1],csc mode:%s\n", csc_mode_y2r_s);
1020*4882a593Smuzhiyun 	else
1021*4882a593Smuzhiyun 		DEBUG_PRINT("\tnot open\n");
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	rk628_i2c_read(rk628, GRF_SCALER_CON2, &val);
1024*4882a593Smuzhiyun 	dsp_frame_h_start = val & 0xffff;
1025*4882a593Smuzhiyun 	dsp_frame_v_start = (val & 0xffff0000) >> 16;
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun 	DEBUG_PRINT("system:\n");
1028*4882a593Smuzhiyun 	DEBUG_PRINT("\tsw_hsync_pol:%d, sw_vsync_pol:%d\n", sw_hsync_pol, sw_vsync_pol);
1029*4882a593Smuzhiyun 	DEBUG_PRINT("\tdsp_frame_h_start:%d, dsp_frame_v_start:%d\n",
1030*4882a593Smuzhiyun 		    dsp_frame_h_start, dsp_frame_v_start);
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	return 0;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun 
rk628_debugfs_open(struct inode * inode,struct file * file)1035*4882a593Smuzhiyun static int rk628_debugfs_open(struct inode *inode, struct file *file)
1036*4882a593Smuzhiyun {
1037*4882a593Smuzhiyun 	struct rk628 *rk628 = inode->i_private;
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	return single_open(file, rk628_debugfs_dump, rk628);
1040*4882a593Smuzhiyun }
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun static const struct file_operations rk628_debugfs_summary_fops = {
1044*4882a593Smuzhiyun 	.owner = THIS_MODULE,
1045*4882a593Smuzhiyun 	.open = rk628_debugfs_open,
1046*4882a593Smuzhiyun 	.read = seq_read,
1047*4882a593Smuzhiyun 	.llseek = seq_lseek,
1048*4882a593Smuzhiyun 	.release = single_release,
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun };
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun static int
rk628_i2c_probe(struct i2c_client * client,const struct i2c_device_id * id)1053*4882a593Smuzhiyun rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
1054*4882a593Smuzhiyun {
1055*4882a593Smuzhiyun 	struct device *dev = &client->dev;
1056*4882a593Smuzhiyun 	struct rk628 *rk628;
1057*4882a593Smuzhiyun 	int i, ret;
1058*4882a593Smuzhiyun 	int err;
1059*4882a593Smuzhiyun 	unsigned long irq_flags;
1060*4882a593Smuzhiyun 	struct dentry *debug_dir;
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	dev_info(dev, "RK628 misc driver version: %s\n", DRIVER_VERSION);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	rk628 = devm_kzalloc(dev, sizeof(*rk628), GFP_KERNEL);
1065*4882a593Smuzhiyun 	if (!rk628)
1066*4882a593Smuzhiyun 		return -ENOMEM;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	rk628->dev = dev;
1069*4882a593Smuzhiyun 	rk628->client = client;
1070*4882a593Smuzhiyun 	i2c_set_clientdata(client, rk628);
1071*4882a593Smuzhiyun 	rk628->hdmirx_irq = client->irq;
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun 	ret = rk628_display_route_info_parse(rk628);
1074*4882a593Smuzhiyun 	if (ret) {
1075*4882a593Smuzhiyun 		dev_err(dev, "display route err\n");
1076*4882a593Smuzhiyun 		return ret;
1077*4882a593Smuzhiyun 	}
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	if (rk628->output_mode != OUTPUT_MODE_HDMI &&
1080*4882a593Smuzhiyun 	    rk628->output_mode != OUTPUT_MODE_CSI) {
1081*4882a593Smuzhiyun 		ret = rk628_display_timings_get(rk628);
1082*4882a593Smuzhiyun 		if (ret) {
1083*4882a593Smuzhiyun 			dev_info(dev, "display timings err\n");
1084*4882a593Smuzhiyun 			return ret;
1085*4882a593Smuzhiyun 		}
1086*4882a593Smuzhiyun 	}
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	rk628->soc_24M = devm_clk_get(dev, "soc_24M");
1089*4882a593Smuzhiyun 	if (rk628->soc_24M == ERR_PTR(-ENOENT))
1090*4882a593Smuzhiyun 		rk628->soc_24M = NULL;
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	if (IS_ERR(rk628->soc_24M)) {
1093*4882a593Smuzhiyun 		ret = PTR_ERR(rk628->soc_24M);
1094*4882a593Smuzhiyun 		dev_err(dev, "Unable to get soc_24M: %d\n", ret);
1095*4882a593Smuzhiyun 		return ret;
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	clk_prepare_enable(rk628->soc_24M);
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	rk628->enable_gpio = devm_gpiod_get_optional(dev, "enable",
1101*4882a593Smuzhiyun 						     GPIOD_OUT_LOW);
1102*4882a593Smuzhiyun 	if (IS_ERR(rk628->enable_gpio)) {
1103*4882a593Smuzhiyun 		ret = PTR_ERR(rk628->enable_gpio);
1104*4882a593Smuzhiyun 		dev_err(dev, "failed to request enable GPIO: %d\n", ret);
1105*4882a593Smuzhiyun 		return ret;
1106*4882a593Smuzhiyun 	}
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 	rk628->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1109*4882a593Smuzhiyun 	if (IS_ERR(rk628->reset_gpio)) {
1110*4882a593Smuzhiyun 		ret = PTR_ERR(rk628->reset_gpio);
1111*4882a593Smuzhiyun 		dev_err(dev, "failed to request reset GPIO: %d\n", ret);
1112*4882a593Smuzhiyun 		return ret;
1113*4882a593Smuzhiyun 	}
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	rk628->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det",
1116*4882a593Smuzhiyun 						    GPIOD_IN);
1117*4882a593Smuzhiyun 	if (IS_ERR(rk628->plugin_det_gpio)) {
1118*4882a593Smuzhiyun 		dev_err(rk628->dev, "failed to get hdmirx det gpio\n");
1119*4882a593Smuzhiyun 		ret = PTR_ERR(rk628->plugin_det_gpio);
1120*4882a593Smuzhiyun 		return ret;
1121*4882a593Smuzhiyun 	}
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 	gpiod_set_value(rk628->enable_gpio, 1);
1124*4882a593Smuzhiyun 	usleep_range(10000, 11000);
1125*4882a593Smuzhiyun 	gpiod_set_value(rk628->reset_gpio, 0);
1126*4882a593Smuzhiyun 	usleep_range(10000, 11000);
1127*4882a593Smuzhiyun 	gpiod_set_value(rk628->reset_gpio, 1);
1128*4882a593Smuzhiyun 	usleep_range(10000, 11000);
1129*4882a593Smuzhiyun 	gpiod_set_value(rk628->reset_gpio, 0);
1130*4882a593Smuzhiyun 	usleep_range(10000, 11000);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	for (i = 0; i < RK628_DEV_MAX; i++) {
1133*4882a593Smuzhiyun 		const struct regmap_config *config = &rk628_regmap_config[i];
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 		if (!config->name)
1136*4882a593Smuzhiyun 			continue;
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 		rk628->regmap[i] = devm_regmap_init_i2c(client, config);
1139*4882a593Smuzhiyun 		if (IS_ERR(rk628->regmap[i])) {
1140*4882a593Smuzhiyun 			ret = PTR_ERR(rk628->regmap[i]);
1141*4882a593Smuzhiyun 			dev_err(dev, "failed to allocate register map %d: %d\n",
1142*4882a593Smuzhiyun 				i, ret);
1143*4882a593Smuzhiyun 			return ret;
1144*4882a593Smuzhiyun 		}
1145*4882a593Smuzhiyun 	}
1146*4882a593Smuzhiyun 
1147*4882a593Smuzhiyun 	/* selete int io function */
1148*4882a593Smuzhiyun 	ret = rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x30002000);
1149*4882a593Smuzhiyun 	if (ret) {
1150*4882a593Smuzhiyun 		dev_err(dev, "failed to access register: %d\n", ret);
1151*4882a593Smuzhiyun 		return ret;
1152*4882a593Smuzhiyun 	}
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	rk628->monitor_wq = alloc_ordered_workqueue("%s",
1155*4882a593Smuzhiyun 		WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk628-monitor-wq");
1156*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&rk628->delay_work, rk628_display_work);
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_DSI) {
1159*4882a593Smuzhiyun 		rk628->dsi_wq = alloc_ordered_workqueue("%s",
1160*4882a593Smuzhiyun 			WQ_MEM_RECLAIM | WQ_FREEZABLE, "rk628-dsi-wq");
1161*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&rk628->dsi_delay_work, rk628_dsi_work);
1162*4882a593Smuzhiyun 	}
1163*4882a593Smuzhiyun 
1164*4882a593Smuzhiyun 	rk628_cru_init(rk628);
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_CSI)
1167*4882a593Smuzhiyun 		rk628_csi_init(rk628);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 	if (rk628->input_mode == INPUT_MODE_HDMI) {
1170*4882a593Smuzhiyun 		if (rk628->plugin_det_gpio) {
1171*4882a593Smuzhiyun 			rk628->plugin_irq = gpiod_to_irq(rk628->plugin_det_gpio);
1172*4882a593Smuzhiyun 			if (rk628->plugin_irq < 0) {
1173*4882a593Smuzhiyun 				dev_err(rk628->dev, "failed to get plugin det irq\n");
1174*4882a593Smuzhiyun 				err = rk628->plugin_irq;
1175*4882a593Smuzhiyun 				return err;
1176*4882a593Smuzhiyun 			}
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 			err = devm_request_threaded_irq(dev, rk628->plugin_irq, NULL,
1179*4882a593Smuzhiyun 					rk628_hdmirx_plugin_irq, IRQF_TRIGGER_FALLING |
1180*4882a593Smuzhiyun 					IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rk628_hdmirx", rk628);
1181*4882a593Smuzhiyun 			if (err) {
1182*4882a593Smuzhiyun 				dev_err(rk628->dev, "failed to register plugin det irq (%d)\n",
1183*4882a593Smuzhiyun 					err);
1184*4882a593Smuzhiyun 				return err;
1185*4882a593Smuzhiyun 			}
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun 			if (rk628->hdmirx_irq) {
1188*4882a593Smuzhiyun 				irq_flags =
1189*4882a593Smuzhiyun 					irqd_get_trigger_type(irq_get_irq_data(rk628->hdmirx_irq));
1190*4882a593Smuzhiyun 				dev_dbg(rk628->dev, "cfg hdmirx irq, flags: %lu!\n", irq_flags);
1191*4882a593Smuzhiyun 				err = devm_request_threaded_irq(dev, rk628->hdmirx_irq, NULL,
1192*4882a593Smuzhiyun 						rk628_hdmirx_plugin_irq, irq_flags |
1193*4882a593Smuzhiyun 						IRQF_ONESHOT, "rk628", rk628);
1194*4882a593Smuzhiyun 				if (err) {
1195*4882a593Smuzhiyun 					dev_err(rk628->dev, "request rk628 irq failed! err:%d\n",
1196*4882a593Smuzhiyun 							err);
1197*4882a593Smuzhiyun 					return err;
1198*4882a593Smuzhiyun 				}
1199*4882a593Smuzhiyun 				/* hdmirx int en */
1200*4882a593Smuzhiyun 				rk628_i2c_write(rk628, GRF_INTR0_EN, 0x01000100);
1201*4882a593Smuzhiyun 				rk628_display_enable(rk628);
1202*4882a593Smuzhiyun 				queue_delayed_work(rk628->monitor_wq, &rk628->delay_work,
1203*4882a593Smuzhiyun 						   msecs_to_jiffies(20));
1204*4882a593Smuzhiyun 			}
1205*4882a593Smuzhiyun 		} else {
1206*4882a593Smuzhiyun 			rk628_display_enable(rk628);
1207*4882a593Smuzhiyun 			queue_delayed_work(rk628->monitor_wq, &rk628->delay_work,
1208*4882a593Smuzhiyun 					    msecs_to_jiffies(50));
1209*4882a593Smuzhiyun 		}
1210*4882a593Smuzhiyun 	} else {
1211*4882a593Smuzhiyun 		rk628_display_enable(rk628);
1212*4882a593Smuzhiyun 	}
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun 	pm_runtime_enable(dev);
1215*4882a593Smuzhiyun 	debug_dir = debugfs_create_dir(rk628->dev->driver->name, NULL);
1216*4882a593Smuzhiyun 	if (!debug_dir)
1217*4882a593Smuzhiyun 		return 0;
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun 	debugfs_create_file("summary", 0400, debug_dir, rk628, &rk628_debugfs_summary_fops);
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun 	return 0;
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun 
rk628_i2c_remove(struct i2c_client * client)1224*4882a593Smuzhiyun static int rk628_i2c_remove(struct i2c_client *client)
1225*4882a593Smuzhiyun {
1226*4882a593Smuzhiyun 	struct rk628 *rk628 = i2c_get_clientdata(client);
1227*4882a593Smuzhiyun 	struct device *dev = &client->dev;
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	if (rk628->output_mode == OUTPUT_MODE_DSI) {
1230*4882a593Smuzhiyun 		cancel_delayed_work_sync(&rk628->dsi_delay_work);
1231*4882a593Smuzhiyun 		destroy_workqueue(rk628->dsi_wq);
1232*4882a593Smuzhiyun 	}
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	cancel_delayed_work_sync(&rk628->delay_work);
1235*4882a593Smuzhiyun 	destroy_workqueue(rk628->monitor_wq);
1236*4882a593Smuzhiyun 	pm_runtime_disable(dev);
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun 	return 0;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun 
1241*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
rk628_suspend(struct device * dev)1242*4882a593Smuzhiyun static int rk628_suspend(struct device *dev)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	struct rk628 *rk628 = dev_get_drvdata(dev);
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 	rk628_display_disable(rk628);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun 	return 0;
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun 
rk628_resume(struct device * dev)1251*4882a593Smuzhiyun static int rk628_resume(struct device *dev)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun 	struct rk628 *rk628 = dev_get_drvdata(dev);
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	rk628_display_resume(rk628);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	return 0;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun #endif
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun static const struct dev_pm_ops rk628_pm_ops = {
1262*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
1263*4882a593Smuzhiyun 	.suspend = rk628_suspend,
1264*4882a593Smuzhiyun 	.resume = rk628_resume,
1265*4882a593Smuzhiyun #endif
1266*4882a593Smuzhiyun };
1267*4882a593Smuzhiyun static const struct of_device_id rk628_of_match[] = {
1268*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk628", },
1269*4882a593Smuzhiyun 	{}
1270*4882a593Smuzhiyun };
1271*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rk628_of_match);
1272*4882a593Smuzhiyun 
1273*4882a593Smuzhiyun static const struct i2c_device_id rk628_i2c_id[] = {
1274*4882a593Smuzhiyun 	{ "rk628", 0 },
1275*4882a593Smuzhiyun 	{}
1276*4882a593Smuzhiyun };
1277*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, rk628_i2c_id);
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun static struct i2c_driver rk628_i2c_driver = {
1280*4882a593Smuzhiyun 	.driver = {
1281*4882a593Smuzhiyun 		.name = "rk628",
1282*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rk628_of_match),
1283*4882a593Smuzhiyun 		.pm = &rk628_pm_ops,
1284*4882a593Smuzhiyun 	},
1285*4882a593Smuzhiyun 	.probe = rk628_i2c_probe,
1286*4882a593Smuzhiyun 	.remove = rk628_i2c_remove,
1287*4882a593Smuzhiyun 	.id_table = rk628_i2c_id,
1288*4882a593Smuzhiyun };
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_RK628
rk628_i2c_driver_init(void)1291*4882a593Smuzhiyun static int __init rk628_i2c_driver_init(void)
1292*4882a593Smuzhiyun {
1293*4882a593Smuzhiyun 	i2c_add_driver(&rk628_i2c_driver);
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	return 0;
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun subsys_initcall_sync(rk628_i2c_driver_init);
1298*4882a593Smuzhiyun 
rk628_i2c_driver_exit(void)1299*4882a593Smuzhiyun static void __exit rk628_i2c_driver_exit(void)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun 	i2c_del_driver(&rk628_i2c_driver);
1302*4882a593Smuzhiyun }
1303*4882a593Smuzhiyun module_exit(rk628_i2c_driver_exit);
1304*4882a593Smuzhiyun #else
1305*4882a593Smuzhiyun module_i2c_driver(rk628_i2c_driver);
1306*4882a593Smuzhiyun #endif
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
1309*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip RK628 MFD driver");
1310*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1311