xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/ebc-dev/tcon/ebc_tcon.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Zorro Liu <zorro.liu@rock-chips.com>
6  */
7 
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/of.h>
14 #include <linux/slab.h>
15 #include <linux/device.h>
16 #include <linux/delay.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/platform_device.h>
20 #include <linux/clk.h>
21 #include <linux/irq.h>
22 #include <linux/pm_runtime.h>
23 #include <linux/mfd/syscon.h>
24 #include <linux/regmap.h>
25 
26 #include "ebc_tcon.h"
27 
28 #define HIWORD_UPDATE(x, l, h)	(((x) << (l)) | (GENMASK(h, l) << 16))
29 #define UPDATE(x, h, l)		(((x) << (l)) & GENMASK((h), (l)))
30 
31 #define REG_LOAD_GLOBAL_EN	0x1
32 
33 /* ebc register define */
34 #define EBC_DSP_START		0x0000 //Frame statrt register
35 #define EBC_EPD_CTRL			0x0004 //EPD control register
36 #define EBC_DSP_CTRL			0x0008 //Display control register
37 #define EBC_DSP_HTIMING0		0x000c //H-Timing setting register0
38 #define EBC_DSP_HTIMING1		0x0010 //H-Timing setting register1
39 #define EBC_DSP_VTIMING0		0x0014 //V-Timing setting register0
40 #define EBC_DSP_VTIMING1		0x0018 //V-Timing setting register1
41 #define EBC_DSP_ACT_INFO		0x001c //ACTIVE width/height
42 #define EBC_WIN_CTRL			0x0020 //Window ctrl
43 #define EBC_WIN_MST0			0x0024 //Current win memory start
44 #define EBC_WIN_MST1			0x0028 //Next win memory start
45 #define EBC_WIN_VIR			0x002c //Window vir width/height
46 #define EBC_WIN_ACT			0x0030 //Window act width/height
47 #define EBC_WIN_DSP			0x0034 //Window dsp width/height
48 #define EBC_WIN_DSP_ST		0x0038 //Window display start piont
49 #define EBC_INT_STATUS		0x003c //Interrupt register
50 #define EBC_VCOM0			0x0040 //VCOM setting register0
51 #define EBC_VCOM1			0x0044 //VCOM setting register1
52 #define EBC_VCOM2			0x0048 //VCOM setting register2
53 #define EBC_VCOM3			0x004c //VCOM setting register3
54 #define EBC_CONFIG_DONE		0x0050 //Config done register
55 #define EBC_VNUM				0x0054 //Line flag num
56 #define EBC_WIN_MST2			0x0058 //Framecount memory start
57 #define EBC_LUT_DATA_ADDR	0x1000 //lut data address
58 
59 #define DSP_HTOTAL(x)			UPDATE(x, 27, 16)
60 #define DSP_HS_END(x)			UPDATE(x, 7, 0)
61 #define DSP_HACT_END(x)		UPDATE(x, 26, 16)
62 #define DSP_HACT_ST(x)		UPDATE(x, 7, 0)
63 #define DSP_VTOTAL(x)			UPDATE(x, 26, 16)
64 #define DSP_VS_END(x)			UPDATE(x, 7, 0)
65 #define DSP_VACT_END(x)		UPDATE(x, 26, 16)
66 #define DSP_VACT_ST(x)		UPDATE(x, 7, 0)
67 #define DSP_HEIGHT(x)			UPDATE(x, 26, 16)
68 #define DSP_WIDTH(x)			UPDATE(x, 11, 0)
69 
70 #define WIN2_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 27, 19)
71 #define WIN_EN(x)				UPDATE(x, 18, 18)
72 #define BURST_REG(x)			UPDATE(x, 12, 10)
73 #define WIN_FIFO_ALMOST_FULL_LEVEL(x)	UPDATE(x, 9, 2)
74 #define WIN_FMT(x)			UPDATE(x, 1, 0)
75 
76 #define WIN_VIR_HEIGHT(x)		UPDATE(x, 31, 16)
77 #define WIN_VIR_WIDTH(x)		UPDATE(x, 15, 0)
78 #define WIN_ACT_HEIGHT(x)	UPDATE(x, 26, 16)
79 #define WIN_ACT_WIDTH(x)		UPDATE(x, 11, 0)
80 #define WIN_DSP_HEIGHT(x)	UPDATE(x, 26, 16)
81 #define WIN_DSP_WIDTH(x)		UPDATE(x, 11, 0)
82 #define WIN_DSP_YST(x)		UPDATE(x, 26, 16)
83 #define WIN_DSP_XST(x)		UPDATE(x, 11, 0)
84 
85 #define DSP_OUT_LOW			BIT(31)
86 #define DSP_EINK_MODE(x)		UPDATE(x, 13, 13)
87 #define DSP_EINK_MODE_MASK	BIT(13)
88 #define DSP_SDCE_WIDTH(x)	UPDATE(x, 25, 16)
89 #define DSP_FRM_TOTAL(x)		UPDATE(x, 9, 2)
90 #define DSP_FRM_TOTAL_MASK	GENMASK(9, 2)
91 #define DSP_FRM_START		BIT(0)
92 #define DSP_FRM_START_MASK	BIT(0)
93 #define SW_BURST_CTRL		BIT(12)
94 
95 #define EINK_MODE_SWAP(x)	UPDATE(x, 31, 31)
96 #define EINK_MODE_FRM_SEL(x)	UPDATE(x, 30, 30)
97 #define DSP_GD_END(x)			UPDATE(x, 26, 16)
98 #define DSP_GD_ST(x)			UPDATE(x, 15, 8)
99 #define DSP_THREE_WIN_MODE(x)		UPDATE(x, 7, 7)
100 #define THREE_WIN_MODE_MASK		BIT(7)
101 #define DSP_SDDW_MODE(x)	UPDATE(x, 6, 6)
102 #define EPD_AUO(x)			UPDATE(x, 5, 5)
103 #define EPD_PWR(x)			UPDATE(x, 4, 2)
104 #define EPD_GDRL(x)			UPDATE(x, 1, 1)
105 #define EPD_SDSHR(x)			UPDATE(x, 0, 0)
106 
107 #define DSP_SWAP_MODE(x)	UPDATE(x, 31, 30)
108 #define DSP_SDCLK_DIV(x)		UPDATE(x, 19, 16)
109 #define DSP_SDCLK_DIV_MASK	GENMASK(19, 16)
110 #define DSP_VCOM_MODE(x)		UPDATE(x, 27, 27)
111 
112 #define DSP_UPDATE_MODE(x)	UPDATE(x, 29, 29)
113 #define DSP_DISPLAY_MODE(x)	UPDATE(x, 28, 28)
114 #define UPDATE_MODE_MASK	BIT(29)
115 #define DISPLAY_MODE_MASK	BIT(28)
116 
117 #define DSP_FRM_INT_NUM(x)	UPDATE(x, 19, 12)
118 #define FRM_END_INT			BIT(0)
119 #define DSP_END_INT			BIT(1)
120 #define DSP_FRM_INT			BIT(2)
121 #define LINE_FLAG_INT			BIT(3)
122 #define FRM_END_INT_MASK	BIT(4)
123 #define DSP_END_INT_MASK	BIT(5)
124 #define DSP_FRM_INT_MASK	BIT(6)
125 #define LINE_FLAG_INT_MASK	BIT(7)
126 #define FRM_END_INT_CLR		BIT(8)
127 #define DSP_END_INT_CLR		BIT(9)
128 #define DSP_FRM_INT_CLR		BIT(10)
129 #define LINE_FLAG_INT_CLR	BIT(11)
130 
131 enum ebc_win_data_fmt {
132 	Y_DATA_4BPP = 0,
133 	Y_DATA_8BPP = 1,
134 	RGB888 = 2,
135 	RGB565 = 3,
136 };
137 
tcon_write(struct ebc_tcon * tcon,unsigned int reg,unsigned int value)138 static inline void tcon_write(struct ebc_tcon *tcon, unsigned int reg,
139 			      unsigned int value)
140 {
141 	regmap_write(tcon->regmap_base, reg, value);
142 }
143 
tcon_read(struct ebc_tcon * tcon,unsigned int reg)144 static inline unsigned int tcon_read(struct ebc_tcon *tcon, unsigned int reg)
145 {
146 	unsigned int value;
147 
148 	regmap_read(tcon->regmap_base, reg, &value);
149 
150 	return value;
151 }
152 
tcon_update_bits(struct ebc_tcon * tcon,unsigned int reg,unsigned int mask,unsigned int val)153 static inline void tcon_update_bits(struct ebc_tcon *tcon, unsigned int reg,
154 				    unsigned int mask, unsigned int val)
155 {
156 	regmap_update_bits(tcon->regmap_base, reg, mask, val);
157 }
158 
tcon_cfg_done(struct ebc_tcon * tcon)159 static inline void tcon_cfg_done(struct ebc_tcon *tcon)
160 {
161 	regmap_write(tcon->regmap_base, EBC_CONFIG_DONE, REG_LOAD_GLOBAL_EN);
162 }
163 
tcon_enable(struct ebc_tcon * tcon,struct ebc_panel * panel)164 static int tcon_enable(struct ebc_tcon *tcon, struct ebc_panel *panel)
165 {
166 	clk_prepare_enable(tcon->hclk);
167 	clk_prepare_enable(tcon->dclk);
168 	pm_runtime_get_sync(tcon->dev);
169 
170 	/* panel timing and win info config */
171 	tcon_write(tcon, EBC_DSP_HTIMING0,
172 				DSP_HTOTAL(panel->lsl + panel->lbl + panel->ldl + panel->lel) | DSP_HS_END(panel->lsl + 2));
173 	tcon_write(tcon, EBC_DSP_HTIMING1,
174 				DSP_HACT_END(panel->lsl + panel->lbl + panel->ldl) | DSP_HACT_ST(panel->lsl + panel->lbl - 1));
175 	tcon_write(tcon, EBC_DSP_VTIMING0,
176 				DSP_VTOTAL(panel->fsl + panel->fbl + panel->fdl + panel->fel) | DSP_VS_END(panel->fsl));
177 	tcon_write(tcon, EBC_DSP_VTIMING1,
178 				DSP_VACT_END(panel->fsl + panel->fbl + panel->fdl) | DSP_VACT_ST(panel->fsl + panel->fbl));
179 	tcon_write(tcon, EBC_DSP_ACT_INFO, DSP_HEIGHT(panel->height) | DSP_WIDTH(panel->width));
180 	tcon_write(tcon, EBC_WIN_VIR, WIN_VIR_HEIGHT(panel->vir_height) | WIN_VIR_WIDTH(panel->vir_width));
181 	tcon_write(tcon, EBC_WIN_ACT, WIN_ACT_HEIGHT(panel->height) | WIN_ACT_WIDTH(panel->width));
182 	tcon_write(tcon, EBC_WIN_DSP, WIN_DSP_HEIGHT(panel->height) | WIN_DSP_WIDTH(panel->width));
183 	tcon_write(tcon, EBC_WIN_DSP_ST, WIN_DSP_YST(panel->fsl + panel->fbl) | WIN_DSP_XST(panel->lsl + panel->lbl));
184 
185 	/* win2 fifo is 512x128, win fifo is 256x128, we set fifo almost value (fifo_size - 16)
186 	*  burst_reg = 7 mean ahb burst is incr16
187 	*/
188 	tcon_write(tcon, EBC_WIN_CTRL, WIN2_FIFO_ALMOST_FULL_LEVEL(496) | WIN_EN(1)
189 							| BURST_REG(7) | WIN_FIFO_ALMOST_FULL_LEVEL(240) | WIN_FMT(Y_DATA_4BPP));
190 
191 	/*
192 	 * EBC_EPD_CTRL info:
193 	 * DSP_GD_ST: GCLK rising edge point(SCLK), which count from the rasing edge of hsync(spec is wrong, count
194 	 * from rasing edge of hsync, not falling edge of hsync)
195 	 * DSP_GD_END : GCLK falling edge point(SCLK), which count from the rasing edge of hsync
196 	 * DSP_THREE_WIN_MODE: 0: lut mode or direct mode; 1: three win mode
197 	 * DSP_SDDW_MODE: 0: 8 bit data output; 1: 16 bit data output
198 	 * EPD_AUO: 0: EINK; 1:AUO
199 	 * EPD_GDRL: gate scanning direction: 1: button to top 0: top to button
200 	 * EPD_SDSHR: source scanning direction 1: right to left 0: left to right
201 	 */
202 	tcon_write(tcon, EBC_EPD_CTRL, EINK_MODE_SWAP(1)
203 				| DSP_GD_ST(panel->lsl + panel->gdck_sta)
204 				| DSP_GD_END(panel->lsl + panel->gdck_sta + panel->lgonl)
205 				| DSP_THREE_WIN_MODE(0)
206 				| DSP_SDDW_MODE(!!panel->panel_16bit)
207 				| EPD_AUO(0)
208 				| EPD_GDRL(1)
209 				| EPD_SDSHR(1));
210 	tcon_write(tcon, EBC_DSP_START, DSP_SDCE_WIDTH(panel->ldl) | SW_BURST_CTRL);
211 	tcon_write(tcon, EBC_DSP_CTRL,
212 				DSP_SWAP_MODE(panel->panel_16bit ? 2 : 3) | DSP_VCOM_MODE(1) | DSP_SDCLK_DIV(panel->panel_16bit ? 7 : 3));
213 	tcon_cfg_done(tcon);
214 
215 	enable_irq(tcon->irq);
216 
217 	return 0;
218 }
219 
tcon_disable(struct ebc_tcon * tcon)220 static void tcon_disable(struct ebc_tcon *tcon)
221 {
222 	disable_irq(tcon->irq);
223 	/* output low */
224 	tcon_update_bits(tcon, EBC_DSP_START, DSP_OUT_LOW | DSP_FRM_START_MASK, DSP_OUT_LOW);
225 
226 	pm_runtime_put_sync(tcon->dev);
227 	clk_disable_unprepare(tcon->dclk);
228 	clk_disable_unprepare(tcon->hclk);
229 }
230 
tcon_dsp_mode_set(struct ebc_tcon * tcon,int update_mode,int display_mode,int three_win_mode,int eink_mode)231 static void tcon_dsp_mode_set(struct ebc_tcon *tcon, int update_mode, int display_mode, int three_win_mode, int eink_mode)
232 {
233 	tcon_update_bits(tcon, EBC_DSP_CTRL, UPDATE_MODE_MASK | DISPLAY_MODE_MASK,
234 						DSP_UPDATE_MODE(!!update_mode) | DSP_DISPLAY_MODE(!!display_mode));
235 	tcon_update_bits(tcon, EBC_EPD_CTRL, THREE_WIN_MODE_MASK,
236 						DSP_THREE_WIN_MODE(!!three_win_mode));
237 	/* always set frm start bit 0 before real frame start */
238 	tcon_update_bits(tcon, EBC_DSP_START, DSP_EINK_MODE_MASK | DSP_FRM_START_MASK, DSP_EINK_MODE(!!eink_mode));
239 	tcon_cfg_done(tcon);
240 }
241 
tcon_image_addr_set(struct ebc_tcon * tcon,u32 pre_image_addr,u32 cur_image_addr)242 static void tcon_image_addr_set(struct ebc_tcon *tcon, u32 pre_image_addr, u32 cur_image_addr)
243 {
244 	tcon_write(tcon, EBC_WIN_MST0, pre_image_addr);
245 	tcon_write(tcon, EBC_WIN_MST1, cur_image_addr);
246 	tcon_cfg_done(tcon);
247 }
248 
tcon_frame_addr_set(struct ebc_tcon * tcon,u32 frame_addr)249 static void tcon_frame_addr_set(struct ebc_tcon *tcon, u32 frame_addr)
250 {
251 	tcon_write(tcon, EBC_WIN_MST2, frame_addr);
252 	tcon_cfg_done(tcon);
253 }
254 
tcon_lut_data_set(struct ebc_tcon * tcon,unsigned int * lut_data,int frame_count,int lut_32)255 static int tcon_lut_data_set(struct ebc_tcon *tcon, unsigned int *lut_data, int frame_count, int lut_32)
256 {
257 	int i;
258 	int lut_size;
259 
260 	if ((!lut_32 && frame_count > 256) || (lut_32 && frame_count > 64)) {
261 		dev_err(tcon->dev, "frame count over flow\n");
262 		return -1;
263 	}
264 
265 	if (lut_32)
266 		lut_size = frame_count * 64;
267 	else
268 		lut_size = frame_count * 16;
269 
270 	for (i = 0; i < lut_size; i++) {
271 		tcon_write(tcon, EBC_LUT_DATA_ADDR + (i * 4), lut_data[i]);
272 	}
273 	tcon_cfg_done(tcon);
274 
275 	return 0;
276 }
277 
tcon_frame_start(struct ebc_tcon * tcon,int frame_total)278 static void tcon_frame_start(struct ebc_tcon *tcon, int frame_total)
279 {
280 	tcon_write(tcon, EBC_INT_STATUS, LINE_FLAG_INT_MASK | DSP_FRM_INT_MASK | FRM_END_INT_MASK);
281 	/* always set frm start bit 0 before real frame start */
282 	tcon_update_bits(tcon, EBC_DSP_START, DSP_FRM_TOTAL_MASK | DSP_FRM_START_MASK, DSP_FRM_TOTAL(frame_total - 1));
283 	tcon_cfg_done(tcon);
284 
285 	tcon_update_bits(tcon, EBC_DSP_START, DSP_FRM_START_MASK, DSP_FRM_START);
286 }
287 
tcon_irq_hanlder(int irq,void * dev_id)288 static irqreturn_t tcon_irq_hanlder(int irq, void *dev_id)
289 {
290 	struct ebc_tcon *tcon = (struct ebc_tcon *)dev_id;
291 	u32 intr_status;
292 
293 	intr_status = tcon_read(tcon, EBC_INT_STATUS);
294 
295 	if (intr_status & DSP_END_INT) {
296 		tcon_update_bits(tcon, EBC_INT_STATUS, DSP_END_INT_CLR, DSP_END_INT_CLR);
297 
298 		if (tcon->dsp_end_callback)
299 			tcon->dsp_end_callback();
300 	}
301 
302 	return IRQ_HANDLED;
303 }
304 
tcon_is_volatile_reg(struct device * dev,unsigned int reg)305 static bool tcon_is_volatile_reg(struct device *dev, unsigned int reg)
306 {
307 	switch (reg) {
308 	case EBC_DSP_START:
309 	case EBC_EPD_CTRL:
310 	case EBC_DSP_CTRL:
311 		return false;
312 	}
313 
314 	return true;
315 }
316 
317 static struct regmap_config ebc_regmap_config = {
318 	.reg_bits = 32,
319 	.val_bits = 32,
320 	.reg_stride = 4,
321 	.cache_type = REGCACHE_RBTREE,
322 	.volatile_reg = tcon_is_volatile_reg,
323 };
324 
ebc_tcon_probe(struct platform_device * pdev)325 static int ebc_tcon_probe(struct platform_device *pdev)
326 {
327 	struct device *dev = &pdev->dev;
328 	struct ebc_tcon *tcon;
329 	struct resource *res;
330 	int ret;
331 
332 	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
333 	if (!tcon)
334 		return -ENOMEM;
335 
336 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 	tcon->regs = devm_ioremap_resource(dev, res);
338 	if (IS_ERR(tcon->regs))
339 		return PTR_ERR(tcon->regs);
340 
341 	tcon->len = resource_size(res);
342 	ebc_regmap_config.max_register = resource_size(res) - 4;
343 	ebc_regmap_config.name = "rockchip,ebc_tcon";
344 	tcon->regmap_base = devm_regmap_init_mmio(dev, tcon->regs, &ebc_regmap_config);
345 	if (IS_ERR(tcon->regmap_base))
346 		return PTR_ERR(tcon->regmap_base);
347 
348 	tcon->hclk = devm_clk_get(dev, "hclk");
349 	if (IS_ERR(tcon->hclk)) {
350 		ret = PTR_ERR(tcon->hclk);
351 		dev_err(dev, "failed to get hclk clock: %d\n", ret);
352 		return ret;
353 	}
354 
355 	tcon->dclk = devm_clk_get(dev, "dclk");
356 	if (IS_ERR(tcon->dclk)) {
357 		ret = PTR_ERR(tcon->dclk);
358 		dev_err(dev, "failed to get dclk clock: %d\n", ret);
359 		return ret;
360 	}
361 
362 	tcon->irq = platform_get_irq(pdev, 0);
363 	if (tcon->irq < 0) {
364 		dev_err(dev, "No IRQ resource!\n");
365 		return tcon->irq;
366 	}
367 
368 	irq_set_status_flags(tcon->irq, IRQ_NOAUTOEN);
369 	ret = devm_request_irq(dev, tcon->irq, tcon_irq_hanlder,
370 			       0, dev_name(dev), tcon);
371 	if (ret < 0) {
372 		dev_err(dev, "failed to requeset irq: %d\n", ret);
373 		return ret;
374 	}
375 
376 	tcon->dev = dev;
377 	tcon->enable = tcon_enable;
378 	tcon->disable = tcon_disable;
379 	tcon->dsp_mode_set = tcon_dsp_mode_set;
380 	tcon->image_addr_set = tcon_image_addr_set;
381 	tcon->frame_addr_set = tcon_frame_addr_set;
382 	tcon->lut_data_set = tcon_lut_data_set;
383 	tcon->frame_start = tcon_frame_start;
384 	platform_set_drvdata(pdev, tcon);
385 
386 	pm_runtime_enable(dev);
387 
388 	return 0;
389 }
390 
ebc_tcon_remove(struct platform_device * pdev)391 static int ebc_tcon_remove(struct platform_device *pdev)
392 {
393 	pm_runtime_disable(&pdev->dev);
394 
395 	return 0;
396 }
397 
398 static const struct of_device_id ebc_tcon_of_match[] = {
399 	{ .compatible = "rockchip,rk3568-ebc-tcon" },
400 	{}
401 };
402 MODULE_DEVICE_TABLE(of, ebc_tcon_of_match);
403 
404 static struct platform_driver ebc_tcon_driver = {
405 	.driver = {
406 		.name = "rk-ebc-tcon",
407 		.of_match_table = ebc_tcon_of_match,
408 	},
409 	.probe = ebc_tcon_probe,
410 	.remove = ebc_tcon_remove,
411 };
412 module_platform_driver(ebc_tcon_driver);
413 
414 MODULE_AUTHOR("Zorro Liu <zorro.liu@rock-chips.com>");
415 MODULE_DESCRIPTION("ROCKCHIP EBC tcon driver");
416 MODULE_LICENSE("GPL v2");
417