xref: /OK3568_Linux_fs/kernel/drivers/misc/rk628/rk628_combtxphy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Guochun Huang <hero.huang@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "rk628.h"
9*4882a593Smuzhiyun #include "rk628_combtxphy.h"
10*4882a593Smuzhiyun #include "rk628_cru.h"
11*4882a593Smuzhiyun 
rk628_combtxphy_dsi_power_on(struct rk628 * rk628)12*4882a593Smuzhiyun static void rk628_combtxphy_dsi_power_on(struct rk628 *rk628)
13*4882a593Smuzhiyun {
14*4882a593Smuzhiyun 	struct rk628_combtxphy *combtxphy = &rk628->combtxphy;
15*4882a593Smuzhiyun 	u32 val;
16*4882a593Smuzhiyun 	int ret;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_BUS_WIDTH_MASK |
19*4882a593Smuzhiyun 			      SW_GVI_LVDS_EN_MASK | SW_MIPI_DSI_EN_MASK,
20*4882a593Smuzhiyun 			       SW_BUS_WIDTH_8BIT | SW_MIPI_DSI_EN);
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 	if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
23*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
24*4882a593Smuzhiyun 				      SW_MODULEA_EN_MASK, SW_MODULEA_EN);
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 	if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
27*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
28*4882a593Smuzhiyun 				      SW_MODULEB_EN_MASK, SW_MODULEB_EN);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	rk628_i2c_write(rk628, COMBTXPHY_CON5,
31*4882a593Smuzhiyun 			SW_REF_DIV(combtxphy->ref_div - 1) |
32*4882a593Smuzhiyun 			SW_PLL_FB_DIV(combtxphy->fb_div) |
33*4882a593Smuzhiyun 			SW_PLL_FRAC_DIV(combtxphy->frac_div) |
34*4882a593Smuzhiyun 			SW_RATE(combtxphy->rate_div / 2));
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_PD_PLL, 0);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_GRF],
39*4882a593Smuzhiyun 				       GRF_DPHY0_STATUS, val,
40*4882a593Smuzhiyun 				       val & DPHY_PHYLOCK, 0, 1000);
41*4882a593Smuzhiyun 	if (ret < 0)
42*4882a593Smuzhiyun 		dev_err(rk628->dev, "phy is not lock\n");
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON9,
46*4882a593Smuzhiyun 			      SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK,
47*4882a593Smuzhiyun 			      SW_DSI_FSET_EN | SW_DSI_RCAL_EN);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	usleep_range(200, 400);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
rk628_combtxphy_lvds_power_on(struct rk628 * rk628)52*4882a593Smuzhiyun static void rk628_combtxphy_lvds_power_on(struct rk628 *rk628)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	struct rk628_combtxphy *combtxphy = &rk628->combtxphy;
56*4882a593Smuzhiyun 	u32 val;
57*4882a593Smuzhiyun 	int ret;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* Adjust terminal resistance 133 ohm, bypass 0.95v ldo for driver. */
60*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON7,
61*4882a593Smuzhiyun 			      SW_TX_RTERM_MASK | SW_TX_MODE_MASK |
62*4882a593Smuzhiyun 			      BYPASS_095V_LDO_MASK | TX_COM_VOLT_ADJ_MASK,
63*4882a593Smuzhiyun 			      SW_TX_RTERM(6) | SW_TX_MODE(3) |
64*4882a593Smuzhiyun 			      BYPASS_095V_LDO(1) | TX_COM_VOLT_ADJ(0));
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	rk628_i2c_write(rk628, COMBTXPHY_CON10, TX7_CKDRV_EN | TX2_CKDRV_EN);
67*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
68*4882a593Smuzhiyun 			      SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
69*4882a593Smuzhiyun 			      SW_MIPI_DSI_EN_MASK,
70*4882a593Smuzhiyun 			      SW_BUS_WIDTH_7BIT | SW_GVI_LVDS_EN);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
73*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
74*4882a593Smuzhiyun 				      SW_MODULEA_EN_MASK, SW_MODULEA_EN);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
77*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
78*4882a593Smuzhiyun 				      SW_MODULEB_EN_MASK, SW_MODULEB_EN);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	rk628_i2c_write(rk628, COMBTXPHY_CON5,
81*4882a593Smuzhiyun 			SW_REF_DIV(combtxphy->ref_div - 1) |
82*4882a593Smuzhiyun 			SW_PLL_FB_DIV(combtxphy->fb_div) |
83*4882a593Smuzhiyun 			SW_PLL_FRAC_DIV(combtxphy->frac_div) |
84*4882a593Smuzhiyun 			SW_RATE(combtxphy->rate_div / 2));
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
87*4882a593Smuzhiyun 			      SW_PD_PLL, 0);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_GRF],
90*4882a593Smuzhiyun 				       GRF_DPHY0_STATUS, val,
91*4882a593Smuzhiyun 				       val & DPHY_PHYLOCK, 0, 1000);
92*4882a593Smuzhiyun 	if (ret < 0)
93*4882a593Smuzhiyun 		dev_err(rk628->dev, "phy is not lock\n");
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	usleep_range(100, 200);
96*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_TX_IDLE_MASK | SW_TX_PD_MASK, 0);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
rk628_combtxphy_gvi_power_on(struct rk628 * rk628)99*4882a593Smuzhiyun static void rk628_combtxphy_gvi_power_on(struct rk628 *rk628)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	struct rk628_combtxphy *combtxphy = &rk628->combtxphy;
102*4882a593Smuzhiyun 	int ref_div = 0;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (combtxphy->ref_div % 2) {
105*4882a593Smuzhiyun 		ref_div = combtxphy->ref_div - 1;
106*4882a593Smuzhiyun 	} else {
107*4882a593Smuzhiyun 		ref_div = BIT(4);
108*4882a593Smuzhiyun 		ref_div |= combtxphy->ref_div / 2 - 1;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	rk628_i2c_write(rk628, COMBTXPHY_CON5,
112*4882a593Smuzhiyun 			SW_REF_DIV(ref_div) |
113*4882a593Smuzhiyun 			SW_PLL_FB_DIV(combtxphy->fb_div) |
114*4882a593Smuzhiyun 			SW_PLL_FRAC_DIV(combtxphy->frac_div) |
115*4882a593Smuzhiyun 			SW_RATE(combtxphy->rate_div / 2));
116*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
117*4882a593Smuzhiyun 			      SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
118*4882a593Smuzhiyun 			      SW_MIPI_DSI_EN_MASK |
119*4882a593Smuzhiyun 			      SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
120*4882a593Smuzhiyun 			      SW_BUS_WIDTH_10BIT | SW_GVI_LVDS_EN |
121*4882a593Smuzhiyun 			      SW_MODULEB_EN | SW_MODULEA_EN);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
124*4882a593Smuzhiyun 			      SW_PD_PLL | SW_TX_PD_MASK, 0);
125*4882a593Smuzhiyun 	usleep_range(100, 200);
126*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
127*4882a593Smuzhiyun 			      SW_TX_IDLE_MASK, 0);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
rk628_combtxphy_power_on(struct rk628 * rk628)130*4882a593Smuzhiyun void rk628_combtxphy_power_on(struct rk628 *rk628)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	struct rk628_combtxphy *combtxphy = &rk628->combtxphy;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
135*4882a593Smuzhiyun 			      SW_TX_IDLE_MASK | SW_TX_PD_MASK |
136*4882a593Smuzhiyun 			      SW_PD_PLL_MASK, SW_TX_IDLE(0x3ff) |
137*4882a593Smuzhiyun 			      SW_TX_PD(0x3ff) | SW_PD_PLL);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	switch (combtxphy->mode) {
140*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_MIPI:
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
143*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL_MASK,
144*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL(0));
145*4882a593Smuzhiyun 		rk628_combtxphy_dsi_power_on(rk628);
146*4882a593Smuzhiyun 		break;
147*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_LVDS:
148*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
149*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL_MASK,
150*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL(1));
151*4882a593Smuzhiyun 		rk628_combtxphy_lvds_power_on(rk628);
152*4882a593Smuzhiyun 		break;
153*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_GVI:
154*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
155*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL_MASK,
156*4882a593Smuzhiyun 				      SW_TXPHY_REFCLK_SEL(2));
157*4882a593Smuzhiyun 		rk628_combtxphy_gvi_power_on(rk628);
158*4882a593Smuzhiyun 		break;
159*4882a593Smuzhiyun 	default:
160*4882a593Smuzhiyun 		break;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
rk628_combtxphy_power_off(struct rk628 * rk628)164*4882a593Smuzhiyun void rk628_combtxphy_power_off(struct rk628 *rk628)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_TX_IDLE_MASK |
167*4882a593Smuzhiyun 			      SW_TX_PD_MASK | SW_PD_PLL_MASK |
168*4882a593Smuzhiyun 			      SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
169*4882a593Smuzhiyun 			      SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
rk628_combtxphy_set_bus_width(struct rk628 * rk628,u32 bus_width)172*4882a593Smuzhiyun void rk628_combtxphy_set_bus_width(struct rk628 *rk628, u32 bus_width)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	rk628->combtxphy.bus_width = bus_width;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
rk628_combtxphy_get_bus_width(struct rk628 * rk628)177*4882a593Smuzhiyun u32 rk628_combtxphy_get_bus_width(struct rk628 *rk628)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	return rk628->combtxphy.bus_width;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
rk628_combtxphy_set_gvi_division_mode(struct rk628 * rk628,bool division)182*4882a593Smuzhiyun void rk628_combtxphy_set_gvi_division_mode(struct rk628 *rk628, bool division)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	rk628->combtxphy.division_mode = division;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
rk628_combtxphy_set_mode(struct rk628 * rk628,enum phy_mode mode)187*4882a593Smuzhiyun void rk628_combtxphy_set_mode(struct rk628 *rk628, enum phy_mode mode)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	struct rk628_combtxphy *combtxphy = &rk628->combtxphy;
190*4882a593Smuzhiyun 	unsigned int fvco, fpfd, frac_rate, fin = 24;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	switch (mode) {
193*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_MIPI:
194*4882a593Smuzhiyun 	{
195*4882a593Smuzhiyun 		int bus_width = rk628_combtxphy_get_bus_width(rk628);
196*4882a593Smuzhiyun 		unsigned int fhsc = bus_width >> 8;
197*4882a593Smuzhiyun 		unsigned int flags = bus_width & 0xff;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 		fhsc = fin * (fhsc / fin);
200*4882a593Smuzhiyun 		if (fhsc < 80 || fhsc > 1500)
201*4882a593Smuzhiyun 			return;
202*4882a593Smuzhiyun 		else if (fhsc < 375)
203*4882a593Smuzhiyun 			combtxphy->rate_div = 4;
204*4882a593Smuzhiyun 		else if (fhsc < 750)
205*4882a593Smuzhiyun 			combtxphy->rate_div = 2;
206*4882a593Smuzhiyun 		else
207*4882a593Smuzhiyun 			combtxphy->rate_div = 1;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 		combtxphy->flags = flags;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 		fvco = fhsc * 2 * combtxphy->rate_div;
212*4882a593Smuzhiyun 		combtxphy->ref_div = 1;
213*4882a593Smuzhiyun 		combtxphy->fb_div = fvco / 8 / fin;
214*4882a593Smuzhiyun 		frac_rate = fvco - (fin * 8 * combtxphy->fb_div);
215*4882a593Smuzhiyun 		if (frac_rate) {
216*4882a593Smuzhiyun 			frac_rate <<= 10;
217*4882a593Smuzhiyun 			frac_rate /= fin * 8;
218*4882a593Smuzhiyun 			combtxphy->frac_div = frac_rate;
219*4882a593Smuzhiyun 		} else {
220*4882a593Smuzhiyun 			combtxphy->frac_div = 0;
221*4882a593Smuzhiyun 		}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 		fvco = fin * (1024 * combtxphy->fb_div + combtxphy->frac_div);
224*4882a593Smuzhiyun 		fvco *= 8;
225*4882a593Smuzhiyun 		fvco = DIV_ROUND_UP(fvco, 1024 * combtxphy->ref_div);
226*4882a593Smuzhiyun 		fhsc = fvco / 2 / combtxphy->rate_div;
227*4882a593Smuzhiyun 		combtxphy->bus_width = fhsc;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 		break;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_LVDS:
232*4882a593Smuzhiyun 	{
233*4882a593Smuzhiyun 		int bus_width = rk628_combtxphy_get_bus_width(rk628);
234*4882a593Smuzhiyun 		unsigned int flags = bus_width & 0xff;
235*4882a593Smuzhiyun 		unsigned int rate = (bus_width >> 8) * 7;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		combtxphy->flags = flags;
238*4882a593Smuzhiyun 		combtxphy->ref_div = 1;
239*4882a593Smuzhiyun 		combtxphy->fb_div = 14;
240*4882a593Smuzhiyun 		combtxphy->frac_div = 0;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		if (rate < 500)
243*4882a593Smuzhiyun 			combtxphy->rate_div = 4;
244*4882a593Smuzhiyun 		else if (rate < 1000)
245*4882a593Smuzhiyun 			combtxphy->rate_div = 2;
246*4882a593Smuzhiyun 		else
247*4882a593Smuzhiyun 			combtxphy->rate_div = 1;
248*4882a593Smuzhiyun 		break;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 	case PHY_MODE_VIDEO_GVI:
251*4882a593Smuzhiyun 	{
252*4882a593Smuzhiyun 		unsigned int i, delta_freq, best_delta_freq, fb_div;
253*4882a593Smuzhiyun 		unsigned int bus_width = rk628_combtxphy_get_bus_width(rk628);
254*4882a593Smuzhiyun 		unsigned long ref_clk;
255*4882a593Smuzhiyun 		unsigned long long pre_clk;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 		if (bus_width < 500000 || bus_width > 4000000)
258*4882a593Smuzhiyun 			return;
259*4882a593Smuzhiyun 		else if (bus_width < 1000000)
260*4882a593Smuzhiyun 			combtxphy->rate_div = 4;
261*4882a593Smuzhiyun 		else if (bus_width < 2000000)
262*4882a593Smuzhiyun 			combtxphy->rate_div = 2;
263*4882a593Smuzhiyun 		else
264*4882a593Smuzhiyun 			combtxphy->rate_div = 1;
265*4882a593Smuzhiyun 		fvco = bus_width * combtxphy->rate_div;
266*4882a593Smuzhiyun 		ref_clk = rk628_cru_clk_get_rate(rk628, CGU_SCLK_VOP) / 1000; /* khz */
267*4882a593Smuzhiyun 		if (combtxphy->division_mode)
268*4882a593Smuzhiyun 			ref_clk /= 2;
269*4882a593Smuzhiyun 		/*
270*4882a593Smuzhiyun 		 * the reference clock at PFD(FPFD = ref_clk / ref_div) about
271*4882a593Smuzhiyun 		 * 25MHz is recommende, FPFD must range from 16MHz to 35MHz,
272*4882a593Smuzhiyun 		 * here to find the best rev_div.
273*4882a593Smuzhiyun 		 */
274*4882a593Smuzhiyun 		best_delta_freq = ref_clk;
275*4882a593Smuzhiyun 		for (i = 1; i <= 32; i++) {
276*4882a593Smuzhiyun 			fpfd = ref_clk / i;
277*4882a593Smuzhiyun 			delta_freq = abs(fpfd - 25000);
278*4882a593Smuzhiyun 			if (delta_freq < best_delta_freq) {
279*4882a593Smuzhiyun 				best_delta_freq = delta_freq;
280*4882a593Smuzhiyun 				combtxphy->ref_div = i;
281*4882a593Smuzhiyun 			}
282*4882a593Smuzhiyun 		}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 		/*
285*4882a593Smuzhiyun 		 * ref_clk / ref_div * 8 * fb_div = FVCO
286*4882a593Smuzhiyun 		 */
287*4882a593Smuzhiyun 		pre_clk = (unsigned long long)fvco / 8 * combtxphy->ref_div * 1024;
288*4882a593Smuzhiyun 		do_div(pre_clk, ref_clk);
289*4882a593Smuzhiyun 		fb_div = pre_clk / 1024;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 		/*
292*4882a593Smuzhiyun 		 * get the actually frequency
293*4882a593Smuzhiyun 		 */
294*4882a593Smuzhiyun 		bus_width = ref_clk / combtxphy->ref_div * 8;
295*4882a593Smuzhiyun 		bus_width *= fb_div;
296*4882a593Smuzhiyun 		bus_width /= combtxphy->rate_div;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 		combtxphy->frac_div = 0;
299*4882a593Smuzhiyun 		combtxphy->fb_div = fb_div;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 		combtxphy->bus_width = bus_width;
302*4882a593Smuzhiyun 		break;
303*4882a593Smuzhiyun 	}
304*4882a593Smuzhiyun 	default:
305*4882a593Smuzhiyun 		break;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	combtxphy->mode = mode;
309*4882a593Smuzhiyun }
310