xref: /OK3568_Linux_fs/u-boot/drivers/video/rk_eink/rk_ebc_tcon.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: Wenping Zhang <wenping.zhang@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <clk.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <dm/pinctrl.h>
11*4882a593Smuzhiyun #include <pwm.h>
12*4882a593Smuzhiyun #include <regmap.h>
13*4882a593Smuzhiyun #include <syscon.h>
14*4882a593Smuzhiyun #include <asm/arch/clock.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <syscon.h>
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include "rk_ebc.h"
19*4882a593Smuzhiyun #ifdef CONFIG_IRQ
20*4882a593Smuzhiyun #include <irq-generic.h>
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct ebc_tcon_priv {
24*4882a593Smuzhiyun 	struct udevice *dev;
25*4882a593Smuzhiyun 	void __iomem *reg;
26*4882a593Smuzhiyun 	u32 *regcache;
27*4882a593Smuzhiyun 	u32 reg_len;
28*4882a593Smuzhiyun 	void *grf;
29*4882a593Smuzhiyun 	void *pmugrf;
30*4882a593Smuzhiyun 	struct clk dclk;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define msleep(a)		udelay((a) * 1000)
34*4882a593Smuzhiyun #define HIWORD_UPDATE(x, l, h)	(((x) << (l)) | (GENMASK(h, l) << 16))
35*4882a593Smuzhiyun #define UPDATE(x, h, l)		(((x) << (l)) & GENMASK((h), (l)))
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define REG_LOAD_GLOBAL_EN	0x1
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* ebc register define */
40*4882a593Smuzhiyun #define EBC_DSP_START		0x0000 //Frame statrt register
41*4882a593Smuzhiyun #define EBC_EPD_CTRL		0x0004 //EPD control register
42*4882a593Smuzhiyun #define EBC_DSP_CTRL		0x0008 //Display control register
43*4882a593Smuzhiyun #define EBC_DSP_HTIMING0	0x000c //H-Timing setting register0
44*4882a593Smuzhiyun #define EBC_DSP_HTIMING1	0x0010 //H-Timing setting register1
45*4882a593Smuzhiyun #define EBC_DSP_VTIMING0	0x0014 //V-Timing setting register0
46*4882a593Smuzhiyun #define EBC_DSP_VTIMING1	0x0018 //V-Timing setting register1
47*4882a593Smuzhiyun #define EBC_DSP_ACT_INFO	0x001c //ACTIVE width/height
48*4882a593Smuzhiyun #define EBC_WIN_CTRL		0x0020 //Window ctrl
49*4882a593Smuzhiyun #define EBC_WIN_MST0		0x0024 //Current win memory start
50*4882a593Smuzhiyun #define EBC_WIN_MST1		0x0028 //Next win memory start
51*4882a593Smuzhiyun #define EBC_WIN_VIR		0x002c //Window vir width/height
52*4882a593Smuzhiyun #define EBC_WIN_ACT		0x0030 //Window act width/height
53*4882a593Smuzhiyun #define EBC_WIN_DSP		0x0034 //Window dsp width/height
54*4882a593Smuzhiyun #define EBC_WIN_DSP_ST		0x0038 //Window display start point
55*4882a593Smuzhiyun #define EBC_INT_STATUS		0x003c //Interrupt register
56*4882a593Smuzhiyun #define EBC_VCOM0		0x0040 //VCOM setting register0
57*4882a593Smuzhiyun #define EBC_VCOM1		0x0044 //VCOM setting register1
58*4882a593Smuzhiyun #define EBC_VCOM2		0x0048 //VCOM setting register2
59*4882a593Smuzhiyun #define EBC_VCOM3		0x004c //VCOM setting register3
60*4882a593Smuzhiyun #define EBC_CONFIG_DONE		0x0050 //Config done register
61*4882a593Smuzhiyun #define EBC_VNUM		0x0054 //Line flag num
62*4882a593Smuzhiyun #define EBC_WIN_MST2		0x0058 //Framecount memory start
63*4882a593Smuzhiyun #define EBC_LUT_DATA_ADDR	0x1000 //lut data address
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define DSP_HTOTAL(x)		UPDATE(x, 27, 16)
66*4882a593Smuzhiyun #define DSP_HS_END(x)		UPDATE(x, 7, 0)
67*4882a593Smuzhiyun #define DSP_HACT_END(x)		UPDATE(x, 26, 16)
68*4882a593Smuzhiyun #define DSP_HACT_ST(x)		UPDATE(x, 7, 0)
69*4882a593Smuzhiyun #define DSP_VTOTAL(x)		UPDATE(x, 26, 16)
70*4882a593Smuzhiyun #define DSP_VS_END(x)		UPDATE(x, 7, 0)
71*4882a593Smuzhiyun #define DSP_VACT_END(x)		UPDATE(x, 26, 16)
72*4882a593Smuzhiyun #define DSP_VACT_ST(x)		UPDATE(x, 7, 0)
73*4882a593Smuzhiyun #define DSP_HEIGHT(x)		UPDATE(x, 26, 16)
74*4882a593Smuzhiyun #define DSP_WIDTH(x)		UPDATE(x, 11, 0)
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun #define WIN2_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 27, 19)
77*4882a593Smuzhiyun #define WIN_EN(x)			UPDATE(x, 18, 18)
78*4882a593Smuzhiyun #define BURST_REG(x)			UPDATE(x, 12, 10)
79*4882a593Smuzhiyun #define WIN_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 9, 2)
80*4882a593Smuzhiyun #define WIN_FMT(x)			UPDATE(x, 1, 0)
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #define WIN_VIR_HEIGHT(x)		UPDATE(x, 31, 16)
83*4882a593Smuzhiyun #define WIN_VIR_WIDTH(x)		UPDATE(x, 15, 0)
84*4882a593Smuzhiyun #define WIN_ACT_HEIGHT(x)		UPDATE(x, 26, 16)
85*4882a593Smuzhiyun #define WIN_ACT_WIDTH(x)		UPDATE(x, 11, 0)
86*4882a593Smuzhiyun #define WIN_DSP_HEIGHT(x)		UPDATE(x, 26, 16)
87*4882a593Smuzhiyun #define WIN_DSP_WIDTH(x)		UPDATE(x, 11, 0)
88*4882a593Smuzhiyun #define WIN_DSP_YST(x)			UPDATE(x, 26, 16)
89*4882a593Smuzhiyun #define WIN_DSP_XST(x)			UPDATE(x, 11, 0)
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun #define DSP_OUT_LOW			BIT(31)
92*4882a593Smuzhiyun #define DSP_EINK_MODE(x)		UPDATE(x, 13, 13)
93*4882a593Smuzhiyun #define DSP_EINK_MODE_MASK		BIT(13)
94*4882a593Smuzhiyun #define DSP_SDCE_WIDTH(x)		UPDATE(x, 25, 16)
95*4882a593Smuzhiyun #define DSP_FRM_TOTAL(x)		UPDATE(x, 9, 2)
96*4882a593Smuzhiyun #define DSP_FRM_TOTAL_MASK		GENMASK(9, 2)
97*4882a593Smuzhiyun #define DSP_FRM_START			BIT(0)
98*4882a593Smuzhiyun #define DSP_FRM_START_MASK		BIT(0)
99*4882a593Smuzhiyun #define SW_BURST_CTRL			BIT(12)
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #define EINK_MODE_SWAP(x)		UPDATE(x, 31, 31)
102*4882a593Smuzhiyun #define EINK_MODE_FRM_SEL(x)		UPDATE(x, 30, 30)
103*4882a593Smuzhiyun #define DSP_GD_END(x)			UPDATE(x, 26, 16)
104*4882a593Smuzhiyun #define DSP_GD_ST(x)			UPDATE(x, 15, 8)
105*4882a593Smuzhiyun #define DSP_THREE_WIN_MODE(x)		UPDATE(x, 7, 7)
106*4882a593Smuzhiyun #define THREE_WIN_MODE_MASK		BIT(7)
107*4882a593Smuzhiyun #define DSP_SDDW_MODE(x)		UPDATE(x, 6, 6)
108*4882a593Smuzhiyun #define EPD_AUO(x)			UPDATE(x, 5, 5)
109*4882a593Smuzhiyun #define EPD_PWR(x)			UPDATE(x, 4, 2)
110*4882a593Smuzhiyun #define EPD_GDRL(x)			UPDATE(x, 1, 1)
111*4882a593Smuzhiyun #define EPD_SDSHR(x)			UPDATE(x, 0, 0)
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define DSP_SWAP_MODE(x)		UPDATE(x, 31, 30)
114*4882a593Smuzhiyun #define DSP_SWAP_MODE_MASK		GENMASK(31, 30)
115*4882a593Smuzhiyun #define DSP_SDCLK_DIV(x)		UPDATE(x, 19, 16)
116*4882a593Smuzhiyun #define DSP_SDCLK_DIV_MASK		GENMASK(19, 16)
117*4882a593Smuzhiyun #define DSP_VCOM_MODE(x)		UPDATE(x, 27, 27)
118*4882a593Smuzhiyun #define DSP_VCOM_MODE_MASK		BIT(27)
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define DSP_UPDATE_MODE(x)	UPDATE(x, 29, 29)
121*4882a593Smuzhiyun #define DSP_DISPLAY_MODE(x)	UPDATE(x, 28, 28)
122*4882a593Smuzhiyun #define UPDATE_MODE_MASK	BIT(29)
123*4882a593Smuzhiyun #define DISPLAY_MODE_MASK	BIT(28)
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun #define DSP_FRM_INT_NUM(x)	UPDATE(x, 19, 12)
126*4882a593Smuzhiyun #define FRM_END_INT		BIT(0)
127*4882a593Smuzhiyun #define DSP_END_INT		BIT(1)
128*4882a593Smuzhiyun #define DSP_FRM_INT		BIT(2)
129*4882a593Smuzhiyun #define LINE_FLAG_INT		BIT(3)
130*4882a593Smuzhiyun #define FRM_END_INT_MASK	BIT(4)
131*4882a593Smuzhiyun #define DSP_END_INT_MASK	BIT(5)
132*4882a593Smuzhiyun #define DSP_FRM_INT_MASK	BIT(6)
133*4882a593Smuzhiyun #define LINE_FLAG_INT_MASK	BIT(7)
134*4882a593Smuzhiyun #define FRM_END_INT_CLR		BIT(8)
135*4882a593Smuzhiyun #define DSP_END_INT_CLR		BIT(9)
136*4882a593Smuzhiyun #define DSP_FRM_INT_CLR		BIT(10)
137*4882a593Smuzhiyun #define LINE_FLAG_INT_CLR	BIT(11)
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #define PMU_BASE_ADDR		0xfdd90000
140*4882a593Smuzhiyun #define PMU_PWR_GATE_SFTCON	0xA0
141*4882a593Smuzhiyun #define PMU_PWR_DWN_ST		0x98
142*4882a593Smuzhiyun #define RGA_PD_OFF		BIT(5)
143*4882a593Smuzhiyun #define RGA_PD_STAT		BIT(5)
144*4882a593Smuzhiyun enum ebc_win_data_fmt {
145*4882a593Smuzhiyun 	Y_DATA_4BPP = 0,
146*4882a593Smuzhiyun 	Y_DATA_8BPP = 1,
147*4882a593Smuzhiyun 	RGB888 = 2,
148*4882a593Smuzhiyun 	RGB565 = 3,
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun #ifdef CONFIG_IRQ
152*4882a593Smuzhiyun #define IRQ_EBC			49
153*4882a593Smuzhiyun #endif
154*4882a593Smuzhiyun static volatile int last_frame_done = -1;
regs_dump(struct ebc_tcon_priv * tcon)155*4882a593Smuzhiyun static inline void regs_dump(struct ebc_tcon_priv *tcon)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	int i;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	printf("dump registers:\n");
160*4882a593Smuzhiyun 	for (i = 0; i <= EBC_WIN_MST2; i = i + 4) {
161*4882a593Smuzhiyun 		if (!(i % 16))
162*4882a593Smuzhiyun 			printf("\n 0x%p:\t", tcon->reg + i);
163*4882a593Smuzhiyun 		printf("0x%x\t", readl(tcon->reg + i));
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun 	printf("\nlut data:\n");
166*4882a593Smuzhiyun 	for (i = 0x1000; i <= 0x1100; i = i + 4) {
167*4882a593Smuzhiyun 		if (!(i % 16))
168*4882a593Smuzhiyun 			printf("\n 0x%p:\t", tcon->reg + i);
169*4882a593Smuzhiyun 		printf("0x%x\t", readl(tcon->reg + i));
170*4882a593Smuzhiyun 	}
171*4882a593Smuzhiyun 	printf("\n");
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
ebc_power_domain(int on)174*4882a593Smuzhiyun static int ebc_power_domain(int on)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	u32 pd_reg;
177*4882a593Smuzhiyun 	u32 pd_stat;
178*4882a593Smuzhiyun 	int delay = 0;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (on) {
181*4882a593Smuzhiyun 		pd_reg = RGA_PD_OFF << 16;
182*4882a593Smuzhiyun 		pd_stat = RGA_PD_STAT;
183*4882a593Smuzhiyun 	} else {
184*4882a593Smuzhiyun 		pd_reg = RGA_PD_OFF | (RGA_PD_OFF << 16);
185*4882a593Smuzhiyun 		pd_stat = ~((u32)RGA_PD_STAT);
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* enable rga pd for ebc tcon*/
189*4882a593Smuzhiyun 	writel(pd_reg, PMU_BASE_ADDR + PMU_PWR_GATE_SFTCON);
190*4882a593Smuzhiyun 	delay = 1000;
191*4882a593Smuzhiyun 	do {
192*4882a593Smuzhiyun 		udelay(1);
193*4882a593Smuzhiyun 		delay--;
194*4882a593Smuzhiyun 		if (delay == 0) {
195*4882a593Smuzhiyun 			printf("Enable rga pd for ebc failed !\n");
196*4882a593Smuzhiyun 			return -1;
197*4882a593Smuzhiyun 		}
198*4882a593Smuzhiyun 	} while (readl(PMU_BASE_ADDR + PMU_PWR_DWN_ST) & pd_stat);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	return 0;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
tcon_write(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int value)203*4882a593Smuzhiyun static inline void tcon_write(struct ebc_tcon_priv *tcon, unsigned int reg,
204*4882a593Smuzhiyun 			      unsigned int value)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	unsigned int *cache = tcon->regcache + (reg >> 2);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	writel(value, tcon->reg + reg);
209*4882a593Smuzhiyun 	*cache = value;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
tcon_read(struct ebc_tcon_priv * tcon,unsigned int reg)212*4882a593Smuzhiyun static inline unsigned int tcon_read(struct ebc_tcon_priv *tcon,
213*4882a593Smuzhiyun 				     unsigned int reg)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	return readl(tcon->reg + reg);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
tcon_update_bits(struct ebc_tcon_priv * tcon,unsigned int reg,unsigned int mask,unsigned int val)218*4882a593Smuzhiyun static inline void tcon_update_bits(struct ebc_tcon_priv *tcon,
219*4882a593Smuzhiyun 				    unsigned int reg, unsigned int mask,
220*4882a593Smuzhiyun 				    unsigned int val)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	unsigned int tmp;
223*4882a593Smuzhiyun 	unsigned int *cache = tcon->regcache + (reg >> 2);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	tmp = *cache & ~mask;
226*4882a593Smuzhiyun 	tmp |= val & mask;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	writel(tmp, tcon->reg + reg);
229*4882a593Smuzhiyun 	*cache = tmp;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #ifdef CONFIG_IRQ
ebc_irq_handler(int irq,void * data)233*4882a593Smuzhiyun static void ebc_irq_handler(int irq, void *data)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	u32 intr_status;
236*4882a593Smuzhiyun 	struct udevice *dev = data;
237*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	intr_status = readl(tcon->reg + EBC_INT_STATUS);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	if (intr_status & DSP_END_INT) {
242*4882a593Smuzhiyun 		tcon_update_bits(tcon, EBC_INT_STATUS,
243*4882a593Smuzhiyun 				 DSP_END_INT_CLR, DSP_END_INT_CLR);
244*4882a593Smuzhiyun 		last_frame_done = 1;
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun #endif
248*4882a593Smuzhiyun 
tcon_cfg_done(struct ebc_tcon_priv * tcon)249*4882a593Smuzhiyun static inline void tcon_cfg_done(struct ebc_tcon_priv *tcon)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	writel(REG_LOAD_GLOBAL_EN, tcon->reg + EBC_CONFIG_DONE);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
ebc_tcon_enable(struct udevice * dev,struct ebc_panel * panel)254*4882a593Smuzhiyun static int ebc_tcon_enable(struct udevice *dev, struct ebc_panel *panel)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	int ret;
257*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
258*4882a593Smuzhiyun 	u32 width, height, vir_width, vir_height;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (panel->rearrange) {
261*4882a593Smuzhiyun 		width = panel->width * 2;
262*4882a593Smuzhiyun 		height = panel->height / 2;
263*4882a593Smuzhiyun 		vir_width = panel->vir_width * 2;
264*4882a593Smuzhiyun 		vir_height = panel->vir_height / 2;
265*4882a593Smuzhiyun 	} else {
266*4882a593Smuzhiyun 		width = panel->width;
267*4882a593Smuzhiyun 		height = panel->height;
268*4882a593Smuzhiyun 		vir_width = panel->vir_width;
269*4882a593Smuzhiyun 		vir_height = panel->vir_height;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	/* panel timing and win info config */
273*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_HTIMING0,
274*4882a593Smuzhiyun 		   DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl +
275*4882a593Smuzhiyun 			      panel->lel) | DSP_HS_END(panel->lsl));
276*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_HTIMING1,
277*4882a593Smuzhiyun 		   DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) |
278*4882a593Smuzhiyun 		   DSP_HACT_ST(panel->lsl + panel->lbl - 1));
279*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_VTIMING0,
280*4882a593Smuzhiyun 		   DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl +
281*4882a593Smuzhiyun 			      panel->fel) | DSP_VS_END(panel->fsl));
282*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_VTIMING1,
283*4882a593Smuzhiyun 		   DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) |
284*4882a593Smuzhiyun 		   DSP_VACT_ST(panel->fsl + panel->fbl));
285*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_ACT_INFO,
286*4882a593Smuzhiyun 		   DSP_HEIGHT(height) |
287*4882a593Smuzhiyun 		   DSP_WIDTH(width));
288*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_VIR,
289*4882a593Smuzhiyun 		   WIN_VIR_HEIGHT(vir_height) |
290*4882a593Smuzhiyun 		   WIN_VIR_WIDTH(vir_width));
291*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_ACT,
292*4882a593Smuzhiyun 		   WIN_ACT_HEIGHT(height) |
293*4882a593Smuzhiyun 		   WIN_ACT_WIDTH(width));
294*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_DSP,
295*4882a593Smuzhiyun 		   WIN_DSP_HEIGHT(height) |
296*4882a593Smuzhiyun 		   WIN_DSP_WIDTH(width));
297*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_DSP_ST,
298*4882a593Smuzhiyun 		   WIN_DSP_YST(panel->fsl + panel->fbl) |
299*4882a593Smuzhiyun 		   WIN_DSP_XST(panel->lsl + panel->lbl));
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	/* win2 fifo is 512x128, win fifo is 256x128,
302*4882a593Smuzhiyun 	 * we set fifo almost value (fifo_size - 16)
303*4882a593Smuzhiyun 	 * burst_reg = 7 mean ahb burst is incr16
304*4882a593Smuzhiyun 	 */
305*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_CTRL,
306*4882a593Smuzhiyun 		   WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1) |
307*4882a593Smuzhiyun 		   BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) |
308*4882a593Smuzhiyun 		   WIN_FMT(Y_DATA_4BPP));
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	/*
311*4882a593Smuzhiyun 	 * EBC_EPD_CTRL info:
312*4882a593Smuzhiyun 	 * DSP_GD_ST: GCLK rising edge point(SCLK), which count from
313*4882a593Smuzhiyun 	 *            the rasing edge of hsync(spec is wrong, count
314*4882a593Smuzhiyun 	 *            from rasing edge of hsync, not falling edge of hsync)
315*4882a593Smuzhiyun 	 * DSP_GD_END : GCLK falling edge point(SCLK), which count from
316*4882a593Smuzhiyun 	 *              the rasing edge of hsync
317*4882a593Smuzhiyun 	 * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
318*4882a593Smuzhiyun 	 * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
319*4882a593Smuzhiyun 	 * EPD_AUO: 0: EINK; 1:AUO
320*4882a593Smuzhiyun 	 * EPD_GDRL: gate scanning direction: 1:button to top 0:top to button
321*4882a593Smuzhiyun 	 * EPD_SDSHR: source scanning direction 1:right to left 0:left to right
322*4882a593Smuzhiyun 	 */
323*4882a593Smuzhiyun 	tcon_write(tcon, EBC_EPD_CTRL,
324*4882a593Smuzhiyun 		   EINK_MODE_SWAP(1) |
325*4882a593Smuzhiyun 		   DSP_GD_ST(panel->lsl + panel->gdck_sta) |
326*4882a593Smuzhiyun 		   DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl) |
327*4882a593Smuzhiyun 		   DSP_THREE_WIN_MODE(0) |
328*4882a593Smuzhiyun 		   DSP_SDDW_MODE(!!panel->panel_16bit) |
329*4882a593Smuzhiyun 		   EPD_AUO(0) |
330*4882a593Smuzhiyun 		   EPD_GDRL(1) |
331*4882a593Smuzhiyun 		   EPD_SDSHR(1));
332*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_START,
333*4882a593Smuzhiyun 		   DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	tcon_write(tcon, EBC_DSP_CTRL,
336*4882a593Smuzhiyun 		   DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) |
337*4882a593Smuzhiyun 		   DSP_VCOM_MODE(1) |
338*4882a593Smuzhiyun 		   DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3));
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	ret = clk_set_rate(&tcon->dclk, panel->sdck * ((panel->panel_16bit ? 7 : 3) + 1));
343*4882a593Smuzhiyun 	if (ret < 0) {
344*4882a593Smuzhiyun 		printf("%s: set clock rate failed, %d\n", __func__, ret);
345*4882a593Smuzhiyun 		return ret;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
ebc_tcon_disable(struct udevice * dev)351*4882a593Smuzhiyun static int ebc_tcon_disable(struct udevice *dev)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun 
ebc_tcon_dsp_mode_set(struct udevice * dev,int update_mode,int display_mode,int three_win_mode,int eink_mode)356*4882a593Smuzhiyun static int ebc_tcon_dsp_mode_set(struct udevice *dev, int update_mode,
357*4882a593Smuzhiyun 				 int display_mode, int three_win_mode,
358*4882a593Smuzhiyun 				 int eink_mode)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_DSP_CTRL,
363*4882a593Smuzhiyun 			 UPDATE_MODE_MASK | DISPLAY_MODE_MASK,
364*4882a593Smuzhiyun 			 DSP_UPDATE_MODE(!!update_mode) |
365*4882a593Smuzhiyun 			 DSP_DISPLAY_MODE(!!display_mode));
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK,
368*4882a593Smuzhiyun 			 DSP_THREE_WIN_MODE(!!three_win_mode));
369*4882a593Smuzhiyun 	/* always set frm start bit 0 before real frame start */
370*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_DSP_START,
371*4882a593Smuzhiyun 			 DSP_EINK_MODE_MASK | DSP_FRM_START_MASK,
372*4882a593Smuzhiyun 			 DSP_EINK_MODE(!!eink_mode));
373*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
ebc_tcon_image_addr_set(struct udevice * dev,u32 pre_image_addr,u32 cur_image_addr)378*4882a593Smuzhiyun static int ebc_tcon_image_addr_set(struct udevice *dev, u32 pre_image_addr,
379*4882a593Smuzhiyun 				   u32 cur_image_addr)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_MST0, pre_image_addr);
384*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_MST1, cur_image_addr);
385*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	return 0;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
ebc_tcon_frame_addr_set(struct udevice * dev,u32 frame_addr)390*4882a593Smuzhiyun static int ebc_tcon_frame_addr_set(struct udevice *dev, u32 frame_addr)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	tcon_write(tcon, EBC_WIN_MST2, frame_addr);
395*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	return 0;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
ebc_tcon_lut_data_set(struct udevice * dev,unsigned int * lut_data,int frame_count,int lut_32)400*4882a593Smuzhiyun static int ebc_tcon_lut_data_set(struct udevice *dev, unsigned int *lut_data,
401*4882a593Smuzhiyun 				 int frame_count, int lut_32)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	int i, lut_size;
404*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) {
407*4882a593Smuzhiyun 		dev_err(tcon->dev, "frame count over flow\n");
408*4882a593Smuzhiyun 		return -1;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	if (lut_32)
412*4882a593Smuzhiyun 		lut_size = frame_count * 64;
413*4882a593Smuzhiyun 	else
414*4882a593Smuzhiyun 		lut_size = frame_count * 16;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	for (i = 0; i < lut_size; i++)
417*4882a593Smuzhiyun 		tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	return 0;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
wait_for_last_frame_complete(struct udevice * dev)424*4882a593Smuzhiyun static int wait_for_last_frame_complete(struct udevice *dev)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun #ifndef CONFIG_IRQ
427*4882a593Smuzhiyun 	u32 intr_status;
428*4882a593Smuzhiyun #endif
429*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun #ifdef CONFIG_IRQ
432*4882a593Smuzhiyun 	while (1) {
433*4882a593Smuzhiyun 		if ((last_frame_done == -1) || (last_frame_done == 1))
434*4882a593Smuzhiyun 			break;
435*4882a593Smuzhiyun 		msleep(1);
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun #else
438*4882a593Smuzhiyun 	/* wait for frame display end*/
439*4882a593Smuzhiyun 	while (1) {
440*4882a593Smuzhiyun 		/* first frame don't need to wait*/
441*4882a593Smuzhiyun 		if (last_frame_done == -1)
442*4882a593Smuzhiyun 			break;
443*4882a593Smuzhiyun 		intr_status = readl(tcon->reg + EBC_INT_STATUS);
444*4882a593Smuzhiyun 		if (intr_status & DSP_END_INT)
445*4882a593Smuzhiyun 			break;
446*4882a593Smuzhiyun 		msleep(1);
447*4882a593Smuzhiyun 	}
448*4882a593Smuzhiyun #endif
449*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_INT_STATUS,
450*4882a593Smuzhiyun 			 DSP_END_INT_CLR, DSP_END_INT_CLR);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
ebc_tcon_frame_start(struct udevice * dev,int frame_total)455*4882a593Smuzhiyun static int ebc_tcon_frame_start(struct udevice *dev, int frame_total)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	struct ebc_tcon_priv *tcon = dev_get_priv(dev);
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	tcon_write(tcon, EBC_INT_STATUS,
460*4882a593Smuzhiyun 		   LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK);
461*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_DSP_START,
462*4882a593Smuzhiyun 			 DSP_FRM_TOTAL_MASK, DSP_FRM_TOTAL(frame_total - 1));
463*4882a593Smuzhiyun 	tcon_cfg_done(tcon);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	tcon_update_bits(tcon, EBC_DSP_START,
466*4882a593Smuzhiyun 			 DSP_FRM_START_MASK, DSP_FRM_START);
467*4882a593Smuzhiyun 	last_frame_done = 0;
468*4882a593Smuzhiyun 	return 0;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
rk_ebc_tcon_probe(struct udevice * dev)471*4882a593Smuzhiyun static int rk_ebc_tcon_probe(struct udevice *dev)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	int ret;
474*4882a593Smuzhiyun 	struct ebc_tcon_priv *priv = dev_get_priv(dev);
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	/*Enable PD first*/
477*4882a593Smuzhiyun 	ret = ebc_power_domain(1);
478*4882a593Smuzhiyun 	if (ret) {
479*4882a593Smuzhiyun 		printf("%s, enable pd failed\n", __func__);
480*4882a593Smuzhiyun 		return -1;
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	priv->dev = dev;
484*4882a593Smuzhiyun 	ret = clk_get_by_index(dev, 1, &priv->dclk);
485*4882a593Smuzhiyun 	if (ret < 0) {
486*4882a593Smuzhiyun 		printf("%s get clock fail! %d\n", __func__, ret);
487*4882a593Smuzhiyun 		return -EINVAL;
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun #ifdef CONFIG_IRQ
491*4882a593Smuzhiyun 	irq_install_handler(IRQ_EBC, ebc_irq_handler, dev);
492*4882a593Smuzhiyun 	irq_handler_enable(IRQ_EBC);
493*4882a593Smuzhiyun #endif
494*4882a593Smuzhiyun 	return 0;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun const struct rk_ebc_tcon_ops ebc_tcon_funcs = {
498*4882a593Smuzhiyun 	.enable = ebc_tcon_enable,
499*4882a593Smuzhiyun 	.disable = ebc_tcon_disable,
500*4882a593Smuzhiyun 	.dsp_mode_set = ebc_tcon_dsp_mode_set,
501*4882a593Smuzhiyun 	.image_addr_set = ebc_tcon_image_addr_set,
502*4882a593Smuzhiyun 	.frame_addr_set = ebc_tcon_frame_addr_set,
503*4882a593Smuzhiyun 	.lut_data_set = ebc_tcon_lut_data_set,
504*4882a593Smuzhiyun 	.frame_start = ebc_tcon_frame_start,
505*4882a593Smuzhiyun 	.wait_for_last_frame_complete = wait_for_last_frame_complete,
506*4882a593Smuzhiyun };
507*4882a593Smuzhiyun 
rk_ebc_tcon_ofdata_to_platdata(struct udevice * dev)508*4882a593Smuzhiyun static int rk_ebc_tcon_ofdata_to_platdata(struct udevice *dev)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	fdt_size_t size;
511*4882a593Smuzhiyun 	fdt_addr_t addr;
512*4882a593Smuzhiyun 	struct ebc_tcon_priv *priv = dev_get_priv(dev);
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
515*4882a593Smuzhiyun 	if (priv->grf <= 0) {
516*4882a593Smuzhiyun 		debug("%s: Get syscon grf failed (ret=%p)\n",
517*4882a593Smuzhiyun 		      __func__, priv->grf);
518*4882a593Smuzhiyun 		return  -ENXIO;
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
521*4882a593Smuzhiyun 	if (priv->pmugrf <= 0) {
522*4882a593Smuzhiyun 		debug("%s: Get syscon pmugrf failed (ret=%p)\n",
523*4882a593Smuzhiyun 		      __func__, priv->grf);
524*4882a593Smuzhiyun 		return  -ENXIO;
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 	addr = dev_read_addr_size(dev, "reg", &size);
527*4882a593Smuzhiyun 	if (addr == FDT_ADDR_T_NONE) {
528*4882a593Smuzhiyun 		debug("%s: Get ebc_tcon address failed\n", __func__);
529*4882a593Smuzhiyun 		return  -ENXIO;
530*4882a593Smuzhiyun 	}
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	priv->reg = ioremap(addr, size);
533*4882a593Smuzhiyun 	priv->reg_len = size;
534*4882a593Smuzhiyun 	priv->regcache = malloc(size);
535*4882a593Smuzhiyun 	memset(priv->regcache, 0, size);
536*4882a593Smuzhiyun 	return 0;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun static const struct udevice_id ebc_tcon_ids[] = {
540*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3568-ebc-tcon" },
541*4882a593Smuzhiyun 	{ }
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun U_BOOT_DRIVER(rk_ebc_tcon) = {
545*4882a593Smuzhiyun 	.name	= "rk_ebc_tcon",
546*4882a593Smuzhiyun 	.id	= UCLASS_EBC,
547*4882a593Smuzhiyun 	.of_match = ebc_tcon_ids,
548*4882a593Smuzhiyun 	.ofdata_to_platdata = rk_ebc_tcon_ofdata_to_platdata,
549*4882a593Smuzhiyun 	.probe	= rk_ebc_tcon_probe,
550*4882a593Smuzhiyun 	.ops	= &ebc_tcon_funcs,
551*4882a593Smuzhiyun 	.priv_auto_alloc_size   = sizeof(struct ebc_tcon_priv),
552*4882a593Smuzhiyun };
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun UCLASS_DRIVER(ebc_tcon) = {
555*4882a593Smuzhiyun 	.id	= UCLASS_EBC,
556*4882a593Smuzhiyun 	.name	= "ebc_tcon",
557*4882a593Smuzhiyun };
558*4882a593Smuzhiyun 
559